henesyinit from p9fce6d0435 years agoHistory
345 lines · 5.3 KB · C
RawDownload
#include <u.h>#include <libc.h> enum{	CtrlD	= 4,	View	= 0x80,	Cr	= 13,}; void	error(char *);void	sendmsg(int, char *);void	connect(int, int);void	kill(int);int	asyncconfig(char*, char*, char*, int, int, int, char*);int	muxconfig(char*, char*, int, int, int);void	dkconfig(int, char*, int, int, int);char*	system(int, char*);void	csaddnet(char*); /* *  default is: *	dev == #h *	csc == 4 *	chans == 16 *	baud == 9600 *	net == dk *	ws == 7 (2K) */ voidmain(int argc, char *argv[]){	char brate[32];	int baud;	Dir dir;	char *net;	char *dev;	int csc, chans, ws;	int i, async, incon;	char *cmd; 	csc = 0;	chans = 0;	cmd = 0;	incon = 0;	async = 0;	net = 0;	dev = 0;	baud = 9600;	ws = 7;	ARGBEGIN{	case 'C':		cmd = ARGF();		break;	case 'a':		async = 1;		break;	case 'i':		incon = 1;		break;	case 'c':		csc = atoi(ARGF());		chans = atoi(ARGF());		break;	case 'b':		baud = atoi(ARGF());		break;	case 'd':		dev = ARGF();		break;	case 'n':	/* ignore it (for dk232config) */		net = ARGF();		break;	case 'w':		ws = atoi(ARGF());		break;	}ARGEND 	if(ws > 017){		for(i=0; i<020; i++)			if(ws == 1<<(i+4)){				ws = i;				break;			}	}	if(ws < 0 || ws > 017){		fprint(2, "illegal window size\n");		exits("ws");	} 	if(async){		if(net == 0){			if(dirstat("/net/dk/clone", &dir) == 0)				net = "dk232";			else				net = "dk";		}		if(csc == 0)			csc = 1;		if(chans == 0)			chans = 16;		if(dev == 0)			dev = "/dev/eia0";		sprint(brate, "B%d", baud);		asyncconfig(net, dev, brate, csc, chans, ws, cmd);	} else if(incon){		if(net == 0)			net = "dk";		if(csc == 0)			csc = 1;		if(chans == 0)			chans = 16;		if(dev == 0)			dev = "#i";		muxconfig(net, dev, csc, chans, ws);	} else {		if(net == 0)			net = "dk";		if(csc == 0)			csc = 4;		if(chans == 0)			chans = 256;		if(dev == 0)			dev = "#h";		muxconfig(net, dev, csc, chans, ws);	}	csaddnet(net);	exits(0);} /* *  configure the datakit */voiddkconfig(int cfd, char* net, int csc, int chans, int ws){	char buf[64]; 	sendmsg(cfd, "push dkmux");	sprint(buf, "config %d %d restart %s %d", csc, chans, net, ws);	sendmsg(cfd, buf); 	/*	 *  fork a process to hold the device channel open forever	 */	switch(fork()){	case -1:		break;	case 0:		for(;;)			sleep(60*1000);		exits(0);	default:		break;	}	sprint(buf, "#k%s", net);	bind(buf, "/net", MBEFORE);	close(cfd);} /* *  connect to a file system over the serial line */intasyncconfig(char *net, char *dev, char *baud, int csc, int chans, int ws, char *cmd){	int cfd, dfd;	char buf[NAMELEN+3];  	if(strchr(dev, '!')){		dfd = dial(dev, 0, 0, &cfd);	} else {		sprint(buf, "%sctl", dev);		cfd = open(buf, ORDWR);		if(cfd < 0)			error(buf);		sendmsg(cfd, baud);		dfd = open(dev, ORDWR);		if(dfd < 0)			error(dev);		if(cmd)			system(dfd, cmd);	}	connect(dfd, cfd);	close(dfd);	sendmsg(cfd, "push async"); 	dkconfig(cfd, net, csc, chans, ws);	return 0;} /* *  connect to a file system over a multiplexed device */intmuxconfig(char *net, char *dev, int csc, int chans, int ws){	int cfd;	char buf[NAMELEN+3]; 	sprint(buf, "%s/ctl", dev);	cfd = open(buf, ORDWR);	if(cfd < 0)		error(buf); 	dkconfig(cfd, net, csc, chans, ws);	return 0;} voidsendmsg(int fd, char *msg){	int n; 	n = strlen(msg);	if(write(fd, msg, n) != n)		error(msg);} /* *  print error and exit */voiderror(char *s){	fprint(2, "%s: %s: %r\n", argv0, s);	exits(0);} voidconnect(int fd, int cfd){	char xbuf[128];	int i, pid, n, ctl; 	print("Connect to file system now, type ctrl-d when done.\n");	print("(Use the view or down arrow key to send a break)\n"); 	switch(pid = fork()) {	case -1:		error("fork failed");	case 0:		for(;;) {			n = read(fd, xbuf, sizeof(xbuf));			if(n < 0) {				errstr(xbuf);				print("[remote read error (%s)]\n", xbuf);				for(;;);			}			for(i = 0; i < n; i++)				if(xbuf[i] == Cr)					xbuf[i] = ' ';			write(1, xbuf, n);		}	default:		ctl = open("/dev/consctl", OWRITE);		if(ctl < 0)			error("opening consctl");		write(ctl, "rawon", 5); 		for(;;) {			read(0, xbuf, 1);			switch(xbuf[0]&0xff) {			case CtrlD:				kill(pid);				close(ctl);				return;			case View:	/* send a break */				write(cfd, "k250", 4);				break;			default:				n = write(fd, xbuf, 1);				if(n < 0) {					errstr(xbuf);					kill(pid);					close(ctl);					print("[remote write error (%s)]\n", xbuf);				}			}		}	}} voidkill(int pid){	char xbuf[32];	int f; 	sprint(xbuf, "/proc/%d/note", pid);	f = open(xbuf, OWRITE);	write(f, "die", 3);	close(f);} /* *  run a command with the network connection as standard IO */char *system(int fd, char *cmd){	int pid;	int p;	static Waitmsg msg; 	switch(pid = fork()){	case -1:		fprint(2, "%s: can't fork: %r\n", argv0);		return "fork failed";	case 0:		dup(fd, 0);		dup(fd, 1);		close(fd);		execl("/bin/rc", "rc", "-c", cmd, 0);		fprint(2, "%s: can't exec /bin/rc: %r\n", argv0);		exits("exec");		return 0;	default:		for(;;){			p = wait(&msg);			if(p < 0)				return "lost child";			if(p == pid)				return msg.msg;			}		break;	}	return 0;} voidcsaddnet(char *name){	int fd;	char buf[NAMELEN+6]; 	sprint(buf, "add %s", name);	fd = open("/net/cs", OWRITE);	if(fd < 0)		return;	write(fd, buf, strlen(buf));	close(fd);}