4 int debug; /* true if debugging */
5 int ctl = -1; /* control fd (for break's) */
6 int raw; /* true if raw is on */
7 int consctl = -1; /* control fd for cons */
8 int ttypid; /* pid's if the 2 processes (used to kill them) */
9 int outfd = 1; /* local output file descriptor */
10 int cooked; /* non-zero forces cooked mode */
11 int returns; /* non-zero forces carriage returns not to be filtered out */
12 int crtonl; /* non-zero forces carriage returns to be converted to nls coming from net */
13 int strip; /* strip off parity bits */
14 char firsterr[2*ERRMAX];
15 char transerr[2*ERRMAX];
17 char *remuser; /* for BSD rlogin authentication */
21 int nltocr; /* translate kbd nl to cr and vice versa */
25 #define MAXMSG (2*8192)
27 int dodial(char*, char*, char*);
30 long iread(int, void*, int);
31 long iwrite(int, void*, int);
33 void notifyf(void*, char*);
34 void pass(int, int, int);
38 char* system(int, char*);
39 void dosystem(int, char*);
46 void device(char*, char*);
47 void rlogin(char*, char*);
48 void simple(char*, char*);
53 punt("usage: con [-CdnrRsTv] [-b baud] [-l [user]] [-c cmd] [-S svc] "
54 "net!host[!service]");
58 main(int argc, char *argv[])
66 baud = atoi(EARGF(usage()));
79 if(argv[1] != nil && argv[1][0] != '-')
80 remuser = EARGF(usage());
114 if(*dest == '/' && strchr(dest, '!') == 0)
117 simple(dest, cmd); /* doesn't return if dialout succeeds */
118 rlogin(dest, cmd); /* doesn't return if dialout succeeds */
120 rlogin(dest, cmd); /* doesn't return if dialout succeeds */
121 simple(dest, cmd); /* doesn't return if dialout succeeds */
127 * just dial and use as a byte stream with remote echo
130 simple(char *dest, char *cmd)
134 net = dodial(dest, 0, 0);
148 * dial, do UCB authentication, use as a byte stream with local echo
150 * return if dial failed
153 rlogin(char *dest, char *cmd)
160 /* only useful on TCP */
162 && (strncmp(dest, "tcp!", 4)!=0 && strncmp(dest, "net!", 4)!=0))
165 net = dodial(dest, "tcp", "login");
170 * do UCB rlogin authentication
172 localuser = getuser();
182 if(write(net, "", 1)<0
183 || write(net, localuser, strlen(localuser)+1)<0
184 || write(net, remuser, strlen(remuser)+1)<0
185 || write(net, p, strlen(p)+1)<0){
187 punt("BSD authentication failed");
189 if(read(net, buf, 1) != 1)
190 punt("BSD authentication failed1");
192 fprint(2, "con: remote error: ");
193 while(read(net, buf, 1) == 1){
212 * just open a device and use it as a connection
215 device(char *dest, char *cmd)
220 net = open(dest, ORDWR);
222 fprint(2, "con: cannot open %s: %r\n", dest);
225 snprint(cname, sizeof cname, "%sctl", dest);
226 ctl = open(cname, ORDWR);
229 /* set speed and use fifos if available */
230 fprint(ctl, "b%d i1", baud);
233 fprint(2, "con: cannot open %s: %r\n", cname);
249 notifyf(void *a, char *msg)
253 if(strstr(msg, "yankee"))
255 if(strstr(msg, "closed pipe")
256 || strcmp(msg, "interrupt") == 0
257 || strcmp(msg, "hangup") == 0)
263 * turn keyboard raw mode on
269 fprint(2, "rawon\n");
273 consctl = open("/dev/consctl", OWRITE);
275 // fprint(2, "can't open consctl\n");
278 write(consctl, "rawon", 5);
283 * turn keyboard raw mode off
289 fprint(2, "rawoff\n");
293 consctl = open("/dev/consctl", OWRITE);
295 // fprint(2, "can't open consctl\n");
298 write(consctl, "rawoff", 6);
305 #define STDHELP "\t(b)reak, (q)uit, (i)nterrupt, toggle printing (r)eturns, (.)continue, (!cmd)\n"
319 for(done = 0; !done; ){
320 n = read(0, buf, sizeof(buf)-1);
366 post(char *srv, int fd)
371 f = create(srv, OWRITE /* |ORCLOSE */ , 0666);
373 sysfatal("create %s: %r", srv);
374 snprint(buf, sizeof buf, "%d", fd);
375 if(write(f, buf, strlen(buf)) != strlen(buf))
376 sysfatal("write %s: %r", srv);
381 * the real work. two processes pass bytes back and forth between the
382 * terminal and the network.
394 sysfatal("pipe: %r");
396 svc = smprint("/srv/%s", srv);
403 /* pipe is now std in & out */
406 switch(netpid = rfork(RFMEM|RFPROC)){
415 postnote(PNPROC, ttypid, "die yankee dog");
425 postnote(PNPROC, netpid, "die yankee dog");
431 * Read the keyboard and write it to the network. '^\' gets us into
444 n = read(0, buf, sizeof(buf));
460 if(n && memchr(buf, 0x1c, n)){
470 for(p = buf; p < ep; p++)
480 if(iwrite(net, buf, n) != n)
487 * Read from the network and write to the screen.
488 * Filter out spurious carriage returns.
498 n = iread(net, buf, sizeof(buf));
505 for (cp=buf; cp<buf+n; cp++)
509 /* convert cr's to nl's */
510 for (cp = buf; cp < buf + n; cp++)
515 /* convert cr's to null's */
518 while(cp < ep && (cp = memchr(cp, '\r', ep-cp))){
519 memmove(cp, cp+1, ep-cp-1);
525 if(n > 0 && iwrite(outfd, buf, n) != n){
529 if(iwrite(1, buf, n) != n)
536 * dial and return a data connection
539 dodial(char *dest, char *net, char *service)
546 strcpy(name, netmkaddr(dest, net, service));
547 data = dial(name, 0, devdir, &ctl);
552 fprint(2, "connected to %s on %s\n", name, devdir);
557 dosystem(int fd, char *cmd)
563 print("con: %s terminated with %s\n", cmd, p);
569 * run a command with the network connection as standard IO
572 system(int fd, char *cmd)
583 return "pipe failed";
589 switch(pid = fork()){
592 return "fork failed";
601 execl("/bin/rc", "rc", "-c", cmd, nil);
603 execl("/bin/rc", "rc", nil);
609 while((n = read(pfd[1], buf, sizeof(buf))) > 0)
610 if(write(fd, buf, n) != n)
615 if(p < 0 || p != pid)
625 return strcmp(syserr(), "interrupted") == 0;
633 fprint(2, "con: %s\n", msg);
640 static char err[ERRMAX];
641 errstr(err, sizeof err);
651 fprint(2, "'%s' calling %s\n", se, addr);
652 if(firsterr[0] && (strstr(se, "translate") ||
653 strstr(se, "file does not exist") ||
654 strstr(se, "unknown address") ||
655 strstr(se, "directory entry not found")))
657 strcpy(firsterr, se);
662 iread(int f, void *a, int n)
668 if(m >= 0 || !wasintr())
675 iwrite(int f, void *a, int n)
680 if(m < 0 && wasintr())