13e12c5d1SDavid du Colombier #include <u.h> 23e12c5d1SDavid du Colombier #include <libc.h> 33e12c5d1SDavid du Colombier #include <bio.h> 43e12c5d1SDavid du Colombier #include "telnet.h" 53e12c5d1SDavid du Colombier 63e12c5d1SDavid du Colombier int ctl = -1; /* control fd (for break's) */ 73e12c5d1SDavid du Colombier int consctl = -1; /* consctl fd */ 83e12c5d1SDavid du Colombier 93e12c5d1SDavid du Colombier int ttypid; /* pid's if the 2 processes (used to kill them) */ 103e12c5d1SDavid du Colombier int netpid; 113e12c5d1SDavid du Colombier int interrupted; 123e12c5d1SDavid du Colombier int localecho; 13219b2ee8SDavid du Colombier int notkbd; 14219b2ee8SDavid du Colombier 15*caf4c6fbSDavid du Colombier static char *srv; 16*caf4c6fbSDavid du Colombier 17219b2ee8SDavid du Colombier typedef struct Comm Comm; 18219b2ee8SDavid du Colombier struct Comm { 193e12c5d1SDavid du Colombier int returns; 20219b2ee8SDavid du Colombier int stopped; 21219b2ee8SDavid du Colombier }; 22219b2ee8SDavid du Colombier Comm *comm; 233e12c5d1SDavid du Colombier 243e12c5d1SDavid du Colombier int dodial(char*); 253e12c5d1SDavid du Colombier void fromkbd(int); 263e12c5d1SDavid du Colombier void fromnet(int); 27219b2ee8SDavid du Colombier int menu(Biobuf*, int); 28219b2ee8SDavid du Colombier void notifyf(void*, char*); 293e12c5d1SDavid du Colombier void rawoff(void); 303e12c5d1SDavid du Colombier void rawon(void); 313e12c5d1SDavid du Colombier void telnet(int); 323e12c5d1SDavid du Colombier char* system(int, char*); 333e12c5d1SDavid du Colombier int echochange(Biobuf*, int); 343e12c5d1SDavid du Colombier int termsub(Biobuf*, uchar*, int); 353e12c5d1SDavid du Colombier int xlocsub(Biobuf*, uchar*, int); 3674f16c81SDavid du Colombier void* share(ulong); 37219b2ee8SDavid du Colombier 38219b2ee8SDavid du Colombier static int islikeatty(int); 393e12c5d1SDavid du Colombier 403e12c5d1SDavid du Colombier void 413e12c5d1SDavid du Colombier usage(void) 423e12c5d1SDavid du Colombier { 43*caf4c6fbSDavid du Colombier fatal("usage: telnet [-Cdnr] [-s srv] net!host[!service]", 0, 0); 443e12c5d1SDavid du Colombier } 453e12c5d1SDavid du Colombier 463e12c5d1SDavid du Colombier void 473e12c5d1SDavid du Colombier main(int argc, char *argv[]) 483e12c5d1SDavid du Colombier { 49219b2ee8SDavid du Colombier int returns; 50219b2ee8SDavid du Colombier 513e12c5d1SDavid du Colombier returns = 1; 523e12c5d1SDavid du Colombier ARGBEGIN{ 533e12c5d1SDavid du Colombier case 'C': 543e12c5d1SDavid du Colombier opt[Echo].noway = 1; 553e12c5d1SDavid du Colombier break; 563e12c5d1SDavid du Colombier case 'd': 573e12c5d1SDavid du Colombier debug = 1; 583e12c5d1SDavid du Colombier break; 59219b2ee8SDavid du Colombier case 'n': 60219b2ee8SDavid du Colombier notkbd = 1; 61219b2ee8SDavid du Colombier break; 623e12c5d1SDavid du Colombier case 'r': 633e12c5d1SDavid du Colombier returns = 0; 643e12c5d1SDavid du Colombier break; 65*caf4c6fbSDavid du Colombier case 's': 66*caf4c6fbSDavid du Colombier srv = EARGF(usage()); 67*caf4c6fbSDavid du Colombier break; 683e12c5d1SDavid du Colombier default: 693e12c5d1SDavid du Colombier usage(); 703e12c5d1SDavid du Colombier }ARGEND 713e12c5d1SDavid du Colombier 723e12c5d1SDavid du Colombier if(argc != 1) 733e12c5d1SDavid du Colombier usage(); 743e12c5d1SDavid du Colombier 753e12c5d1SDavid du Colombier /* options we need routines for */ 763e12c5d1SDavid du Colombier opt[Echo].change = echochange; 773e12c5d1SDavid du Colombier opt[Term].sub = termsub; 783e12c5d1SDavid du Colombier opt[Xloc].sub = xlocsub; 793e12c5d1SDavid du Colombier 80219b2ee8SDavid du Colombier comm = share(sizeof(comm)); 81219b2ee8SDavid du Colombier comm->returns = returns; 82219b2ee8SDavid du Colombier 833e12c5d1SDavid du Colombier telnet(dodial(argv[0])); 843e12c5d1SDavid du Colombier } 853e12c5d1SDavid du Colombier 863e12c5d1SDavid du Colombier /* 873e12c5d1SDavid du Colombier * dial and return a data connection 883e12c5d1SDavid du Colombier */ 893e12c5d1SDavid du Colombier int 903e12c5d1SDavid du Colombier dodial(char *dest) 913e12c5d1SDavid du Colombier { 92c66865c7SDavid du Colombier char *name; 933e12c5d1SDavid du Colombier int data; 94c66865c7SDavid du Colombier char devdir[NETPATHLEN]; 953e12c5d1SDavid du Colombier 96c66865c7SDavid du Colombier name = netmkaddr(dest, "tcp", "telnet"); 973e12c5d1SDavid du Colombier data = dial(name, 0, devdir, 0); 983e12c5d1SDavid du Colombier if(data < 0) 99bdd62a84SDavid du Colombier fatal("%s: %r", name, 0); 1003e12c5d1SDavid du Colombier fprint(2, "connected to %s on %s\n", name, devdir); 1013e12c5d1SDavid du Colombier return data; 1023e12c5d1SDavid du Colombier } 1033e12c5d1SDavid du Colombier 104*caf4c6fbSDavid du Colombier void 105*caf4c6fbSDavid du Colombier post(char *srv, int fd) 106*caf4c6fbSDavid du Colombier { 107*caf4c6fbSDavid du Colombier int f; 108*caf4c6fbSDavid du Colombier char buf[32]; 109*caf4c6fbSDavid du Colombier 110*caf4c6fbSDavid du Colombier f = create(srv, OWRITE, 0666); 111*caf4c6fbSDavid du Colombier if(f < 0) 112*caf4c6fbSDavid du Colombier sysfatal("create %s: %r", srv); 113*caf4c6fbSDavid du Colombier snprint(buf, sizeof buf, "%d", fd); 114*caf4c6fbSDavid du Colombier if(write(f, buf, strlen(buf)) != strlen(buf)) 115*caf4c6fbSDavid du Colombier sysfatal("write %s: %r", srv); 116*caf4c6fbSDavid du Colombier close(f); 117*caf4c6fbSDavid du Colombier } 118*caf4c6fbSDavid du Colombier 1193e12c5d1SDavid du Colombier /* 1203e12c5d1SDavid du Colombier * two processes pass bytes back and forth between the 1213e12c5d1SDavid du Colombier * terminal and the network. 1223e12c5d1SDavid du Colombier */ 1233e12c5d1SDavid du Colombier void 1243e12c5d1SDavid du Colombier telnet(int net) 1253e12c5d1SDavid du Colombier { 126219b2ee8SDavid du Colombier int pid; 127*caf4c6fbSDavid du Colombier int p[2]; 128*caf4c6fbSDavid du Colombier char *svc; 129219b2ee8SDavid du Colombier 130219b2ee8SDavid du Colombier rawoff(); 131*caf4c6fbSDavid du Colombier svc = nil; 132*caf4c6fbSDavid du Colombier if (srv) { 133*caf4c6fbSDavid du Colombier if(pipe(p) < 0) 134*caf4c6fbSDavid du Colombier sysfatal("pipe: %r"); 135*caf4c6fbSDavid du Colombier if (srv[0] != '/') 136*caf4c6fbSDavid du Colombier svc = smprint("/srv/%s", srv); 137*caf4c6fbSDavid du Colombier else 138*caf4c6fbSDavid du Colombier svc = srv; 139*caf4c6fbSDavid du Colombier post(svc, p[0]); 140*caf4c6fbSDavid du Colombier close(p[0]); 141*caf4c6fbSDavid du Colombier dup(p[1], 0); 142*caf4c6fbSDavid du Colombier dup(p[1], 1); 143*caf4c6fbSDavid du Colombier /* pipe is now std in & out */ 144*caf4c6fbSDavid du Colombier } 1453e12c5d1SDavid du Colombier ttypid = getpid(); 146219b2ee8SDavid du Colombier switch(pid = rfork(RFPROC|RFFDG|RFMEM)){ 1473e12c5d1SDavid du Colombier case -1: 1483e12c5d1SDavid du Colombier perror("con"); 1493e12c5d1SDavid du Colombier exits("fork"); 1503e12c5d1SDavid du Colombier case 0: 1513e12c5d1SDavid du Colombier rawoff(); 152219b2ee8SDavid du Colombier notify(notifyf); 1533e12c5d1SDavid du Colombier fromnet(net); 154*caf4c6fbSDavid du Colombier if (svc) 155*caf4c6fbSDavid du Colombier remove(svc); 1563e12c5d1SDavid du Colombier sendnote(ttypid, "die"); 1573e12c5d1SDavid du Colombier exits(0); 1583e12c5d1SDavid du Colombier default: 159219b2ee8SDavid du Colombier netpid = pid; 160219b2ee8SDavid du Colombier notify(notifyf); 1613e12c5d1SDavid du Colombier fromkbd(net); 162219b2ee8SDavid du Colombier if(notkbd) 163*caf4c6fbSDavid du Colombier for(;;) 164*caf4c6fbSDavid du Colombier sleep(0); 165*caf4c6fbSDavid du Colombier if (svc) 166*caf4c6fbSDavid du Colombier remove(svc); 1673e12c5d1SDavid du Colombier sendnote(netpid, "die"); 1683e12c5d1SDavid du Colombier exits(0); 1693e12c5d1SDavid du Colombier } 1703e12c5d1SDavid du Colombier } 1713e12c5d1SDavid du Colombier 1723e12c5d1SDavid du Colombier /* 1733e12c5d1SDavid du Colombier * Read the keyboard and write it to the network. '^\' gets us into 1743e12c5d1SDavid du Colombier * the menu. 1753e12c5d1SDavid du Colombier */ 1763e12c5d1SDavid du Colombier void 1773e12c5d1SDavid du Colombier fromkbd(int net) 1783e12c5d1SDavid du Colombier { 1793e12c5d1SDavid du Colombier Biobuf ib, ob; 180219b2ee8SDavid du Colombier int c, likeatty; 1813e12c5d1SDavid du Colombier int eofs; 1823e12c5d1SDavid du Colombier 1833e12c5d1SDavid du Colombier Binit(&ib, 0, OREAD); 1843e12c5d1SDavid du Colombier Binit(&ob, net, OWRITE); 185219b2ee8SDavid du Colombier 186219b2ee8SDavid du Colombier likeatty = islikeatty(0); 1873e12c5d1SDavid du Colombier eofs = 0; 1883e12c5d1SDavid du Colombier for(;;){ 1893e12c5d1SDavid du Colombier c = Bgetc(&ib); 1903e12c5d1SDavid du Colombier 1913e12c5d1SDavid du Colombier /* 1923e12c5d1SDavid du Colombier * with raw off, all ^D's get turned into Eof's. 1933e12c5d1SDavid du Colombier * change them back. 1943e12c5d1SDavid du Colombier * 10 in a row implies that the terminal is really gone so 1953e12c5d1SDavid du Colombier * just hang up. 1963e12c5d1SDavid du Colombier */ 1973e12c5d1SDavid du Colombier if(c < 0){ 198219b2ee8SDavid du Colombier if(notkbd) 199219b2ee8SDavid du Colombier return; 2003e12c5d1SDavid du Colombier if(eofs++ > 10) 2013e12c5d1SDavid du Colombier return; 2023e12c5d1SDavid du Colombier c = 004; 2033e12c5d1SDavid du Colombier } else 2043e12c5d1SDavid du Colombier eofs = 0; 2053e12c5d1SDavid du Colombier 2063e12c5d1SDavid du Colombier /* 2073e12c5d1SDavid du Colombier * if not in binary mode, look for the ^\ escape to menu. 2083e12c5d1SDavid du Colombier * also turn \n into \r\n 2093e12c5d1SDavid du Colombier */ 210219b2ee8SDavid du Colombier if(likeatty || !opt[Binary].local){ 2113e12c5d1SDavid du Colombier if(c == 0034){ /* CTRL \ */ 2123e12c5d1SDavid du Colombier if(Bflush(&ob) < 0) 2133e12c5d1SDavid du Colombier return; 214219b2ee8SDavid du Colombier if(menu(&ib, net) < 0) 2153e12c5d1SDavid du Colombier return; 2163e12c5d1SDavid du Colombier continue; 2173e12c5d1SDavid du Colombier } 218219b2ee8SDavid du Colombier } 219219b2ee8SDavid du Colombier if(!opt[Binary].local){ 220219b2ee8SDavid du Colombier if(c == '\n'){ 221219b2ee8SDavid du Colombier /* 222219b2ee8SDavid du Colombier * This is a very strange use of the SGA option. 223219b2ee8SDavid du Colombier * I did this because some systems that don't 224219b2ee8SDavid du Colombier * announce a willingness to supress-go-ahead 225219b2ee8SDavid du Colombier * need the \r\n sequence to recognize input. 226219b2ee8SDavid du Colombier * If someone can explain this to me, please 227219b2ee8SDavid du Colombier * send me mail. - presotto 228219b2ee8SDavid du Colombier */ 229219b2ee8SDavid du Colombier if(opt[SGA].remote){ 230219b2ee8SDavid du Colombier c = '\r'; 231219b2ee8SDavid du Colombier } else { 2323e12c5d1SDavid du Colombier if(Bputc(&ob, '\r') < 0) 2333e12c5d1SDavid du Colombier return; 2343e12c5d1SDavid du Colombier } 235219b2ee8SDavid du Colombier } 236219b2ee8SDavid du Colombier } 2373e12c5d1SDavid du Colombier if(Bputc(&ob, c) < 0) 2383e12c5d1SDavid du Colombier return; 2393e12c5d1SDavid du Colombier if(Bbuffered(&ib) == 0) 2403e12c5d1SDavid du Colombier if(Bflush(&ob) < 0) 2413e12c5d1SDavid du Colombier return; 2423e12c5d1SDavid du Colombier } 2433e12c5d1SDavid du Colombier } 2443e12c5d1SDavid du Colombier 2453e12c5d1SDavid du Colombier /* 2463e12c5d1SDavid du Colombier * Read from the network and write to the screen. If 'stopped' is set 2473e12c5d1SDavid du Colombier * spin and don't read. Filter out spurious carriage returns. 2483e12c5d1SDavid du Colombier */ 2493e12c5d1SDavid du Colombier void 2503e12c5d1SDavid du Colombier fromnet(int net) 2513e12c5d1SDavid du Colombier { 2523e12c5d1SDavid du Colombier int c; 2537dd7cddfSDavid du Colombier int crnls = 0, freenl = 0, eofs; 2543e12c5d1SDavid du Colombier Biobuf ib, ob; 2553e12c5d1SDavid du Colombier 2563e12c5d1SDavid du Colombier Binit(&ib, net, OREAD); 2573e12c5d1SDavid du Colombier Binit(&ob, 1, OWRITE); 2587dd7cddfSDavid du Colombier eofs = 0; 2597545821fSDavid du Colombier for(;;){ 2607545821fSDavid du Colombier if(Bbuffered(&ib) == 0) 2617545821fSDavid du Colombier Bflush(&ob); 2623e12c5d1SDavid du Colombier if(interrupted){ 2633e12c5d1SDavid du Colombier interrupted = 0; 2643e12c5d1SDavid du Colombier send2(net, Iac, Interrupt); 2653e12c5d1SDavid du Colombier } 2663e12c5d1SDavid du Colombier c = Bgetc(&ib); 2677dd7cddfSDavid du Colombier if(c < 0){ 2687dd7cddfSDavid du Colombier if(eofs++ >= 2) 2693e12c5d1SDavid du Colombier return; 2707dd7cddfSDavid du Colombier continue; 2717dd7cddfSDavid du Colombier } 2727dd7cddfSDavid du Colombier eofs = 0; 2733e12c5d1SDavid du Colombier switch(c){ 274219b2ee8SDavid du Colombier case '\n': /* skip nl after string of cr's */ 275219b2ee8SDavid du Colombier if(!opt[Binary].local && !comm->returns){ 276219b2ee8SDavid du Colombier ++crnls; 277219b2ee8SDavid du Colombier if(freenl == 0) 278219b2ee8SDavid du Colombier break; 279219b2ee8SDavid du Colombier freenl = 0; 2803e12c5d1SDavid du Colombier continue; 2813e12c5d1SDavid du Colombier } 2823e12c5d1SDavid du Colombier break; 283219b2ee8SDavid du Colombier case '\r': /* first cr becomes nl, remainder dropped */ 284219b2ee8SDavid du Colombier if(!opt[Binary].local && !comm->returns){ 285219b2ee8SDavid du Colombier if(crnls++ == 0){ 286219b2ee8SDavid du Colombier freenl = 1; 287219b2ee8SDavid du Colombier c = '\n'; 288219b2ee8SDavid du Colombier break; 289219b2ee8SDavid du Colombier } 2903e12c5d1SDavid du Colombier continue; 2913e12c5d1SDavid du Colombier } 292219b2ee8SDavid du Colombier break; 293219b2ee8SDavid du Colombier case 0: /* remove nulls from crnl string */ 294219b2ee8SDavid du Colombier if(crnls) 295219b2ee8SDavid du Colombier continue; 2963e12c5d1SDavid du Colombier break; 2973e12c5d1SDavid du Colombier 2983e12c5d1SDavid du Colombier case Iac: 299219b2ee8SDavid du Colombier crnls = 0; 300219b2ee8SDavid du Colombier freenl = 0; 3013e12c5d1SDavid du Colombier c = Bgetc(&ib); 3023e12c5d1SDavid du Colombier if(c == Iac) 3033e12c5d1SDavid du Colombier break; 3043e12c5d1SDavid du Colombier if(Bflush(&ob) < 0) 3053e12c5d1SDavid du Colombier return; 3063e12c5d1SDavid du Colombier if(control(&ib, c) < 0) 3073e12c5d1SDavid du Colombier return; 3083e12c5d1SDavid du Colombier continue; 3093e12c5d1SDavid du Colombier 3103e12c5d1SDavid du Colombier default: 311219b2ee8SDavid du Colombier crnls = 0; 312219b2ee8SDavid du Colombier freenl = 0; 3133e12c5d1SDavid du Colombier break; 3143e12c5d1SDavid du Colombier } 3153e12c5d1SDavid du Colombier if(Bputc(&ob, c) < 0) 3163e12c5d1SDavid du Colombier return; 3173e12c5d1SDavid du Colombier } 3183e12c5d1SDavid du Colombier } 3193e12c5d1SDavid du Colombier 3203e12c5d1SDavid du Colombier /* 3213e12c5d1SDavid du Colombier * turn keyboard raw mode on 3223e12c5d1SDavid du Colombier */ 3233e12c5d1SDavid du Colombier void 3243e12c5d1SDavid du Colombier rawon(void) 3253e12c5d1SDavid du Colombier { 3263e12c5d1SDavid du Colombier if(debug) 3273e12c5d1SDavid du Colombier fprint(2, "rawon\n"); 3283e12c5d1SDavid du Colombier if(consctl < 0) 3293e12c5d1SDavid du Colombier consctl = open("/dev/consctl", OWRITE); 3303e12c5d1SDavid du Colombier if(consctl < 0){ 3317dd7cddfSDavid du Colombier fprint(2, "can't open consctl: %r\n"); 3323e12c5d1SDavid du Colombier return; 3333e12c5d1SDavid du Colombier } 3343e12c5d1SDavid du Colombier write(consctl, "rawon", 5); 3353e12c5d1SDavid du Colombier } 3363e12c5d1SDavid du Colombier 3373e12c5d1SDavid du Colombier /* 3383e12c5d1SDavid du Colombier * turn keyboard raw mode off 3393e12c5d1SDavid du Colombier */ 3403e12c5d1SDavid du Colombier void 3413e12c5d1SDavid du Colombier rawoff(void) 3423e12c5d1SDavid du Colombier { 3433e12c5d1SDavid du Colombier if(debug) 3443e12c5d1SDavid du Colombier fprint(2, "rawoff\n"); 3453e12c5d1SDavid du Colombier if(consctl < 0) 3463e12c5d1SDavid du Colombier consctl = open("/dev/consctl", OWRITE); 3473e12c5d1SDavid du Colombier if(consctl < 0){ 3487dd7cddfSDavid du Colombier fprint(2, "can't open consctl: %r\n"); 3493e12c5d1SDavid du Colombier return; 3503e12c5d1SDavid du Colombier } 3513e12c5d1SDavid du Colombier write(consctl, "rawoff", 6); 3523e12c5d1SDavid du Colombier } 3533e12c5d1SDavid du Colombier 3543e12c5d1SDavid du Colombier /* 3553e12c5d1SDavid du Colombier * control menu 3563e12c5d1SDavid du Colombier */ 357219b2ee8SDavid du Colombier #define STDHELP "\t(b)reak, (i)nterrupt, (q)uit, (r)eturns, (!cmd), (.)continue\n" 3583e12c5d1SDavid du Colombier 3593e12c5d1SDavid du Colombier int 360219b2ee8SDavid du Colombier menu(Biobuf *bp, int net) 3613e12c5d1SDavid du Colombier { 3623e12c5d1SDavid du Colombier char *cp; 3633e12c5d1SDavid du Colombier int done; 3643e12c5d1SDavid du Colombier 365219b2ee8SDavid du Colombier comm->stopped = 1; 3663e12c5d1SDavid du Colombier 367219b2ee8SDavid du Colombier rawoff(); 3683e12c5d1SDavid du Colombier fprint(2, ">>> "); 3693e12c5d1SDavid du Colombier for(done = 0; !done; ){ 3703e12c5d1SDavid du Colombier cp = Brdline(bp, '\n'); 371219b2ee8SDavid du Colombier if(cp == 0){ 372219b2ee8SDavid du Colombier comm->stopped = 0; 3733e12c5d1SDavid du Colombier return -1; 374219b2ee8SDavid du Colombier } 3753e12c5d1SDavid du Colombier cp[Blinelen(bp)-1] = 0; 3763e12c5d1SDavid du Colombier switch(*cp){ 3773e12c5d1SDavid du Colombier case '!': 3783e12c5d1SDavid du Colombier system(Bfildes(bp), cp+1); 379219b2ee8SDavid du Colombier done = 1; 3803e12c5d1SDavid du Colombier break; 3813e12c5d1SDavid du Colombier case '.': 3823e12c5d1SDavid du Colombier done = 1; 3833e12c5d1SDavid du Colombier break; 3843e12c5d1SDavid du Colombier case 'q': 385219b2ee8SDavid du Colombier comm->stopped = 0; 3863e12c5d1SDavid du Colombier return -1; 387219b2ee8SDavid du Colombier case 'o': 388219b2ee8SDavid du Colombier switch(*(cp+1)){ 389219b2ee8SDavid du Colombier case 'd': 390219b2ee8SDavid du Colombier send3(net, Iac, Do, atoi(cp+2)); 391219b2ee8SDavid du Colombier break; 392219b2ee8SDavid du Colombier case 'w': 393219b2ee8SDavid du Colombier send3(net, Iac, Will, atoi(cp+2)); 394219b2ee8SDavid du Colombier break; 395219b2ee8SDavid du Colombier } 396219b2ee8SDavid du Colombier break; 397219b2ee8SDavid du Colombier case 'r': 398219b2ee8SDavid du Colombier comm->returns = !comm->returns; 399219b2ee8SDavid du Colombier done = 1; 400219b2ee8SDavid du Colombier break; 4013e12c5d1SDavid du Colombier case 'i': 402219b2ee8SDavid du Colombier send2(net, Iac, Interrupt); 4033e12c5d1SDavid du Colombier break; 4043e12c5d1SDavid du Colombier case 'b': 405219b2ee8SDavid du Colombier send2(net, Iac, Break); 4063e12c5d1SDavid du Colombier break; 4073e12c5d1SDavid du Colombier default: 4083e12c5d1SDavid du Colombier fprint(2, STDHELP); 4093e12c5d1SDavid du Colombier break; 4103e12c5d1SDavid du Colombier } 4113e12c5d1SDavid du Colombier if(!done) 4123e12c5d1SDavid du Colombier fprint(2, ">>> "); 4133e12c5d1SDavid du Colombier } 4143e12c5d1SDavid du Colombier 415219b2ee8SDavid du Colombier rawon(); 416219b2ee8SDavid du Colombier comm->stopped = 0; 4173e12c5d1SDavid du Colombier return 0; 4183e12c5d1SDavid du Colombier } 4193e12c5d1SDavid du Colombier 4203e12c5d1SDavid du Colombier /* 4213e12c5d1SDavid du Colombier * ignore interrupts 4223e12c5d1SDavid du Colombier */ 423219b2ee8SDavid du Colombier void 4243e12c5d1SDavid du Colombier notifyf(void *a, char *msg) 4253e12c5d1SDavid du Colombier { 4263e12c5d1SDavid du Colombier USED(a); 4273e12c5d1SDavid du Colombier if(strcmp(msg, "interrupt") == 0){ 4283e12c5d1SDavid du Colombier interrupted = 1; 429219b2ee8SDavid du Colombier noted(NCONT); 4303e12c5d1SDavid du Colombier } 4313e12c5d1SDavid du Colombier if(strcmp(msg, "hangup") == 0) 432219b2ee8SDavid du Colombier noted(NCONT); 433219b2ee8SDavid du Colombier noted(NDFLT); 4343e12c5d1SDavid du Colombier } 4353e12c5d1SDavid du Colombier 4363e12c5d1SDavid du Colombier /* 4373e12c5d1SDavid du Colombier * run a command with the network connection as standard IO 4383e12c5d1SDavid du Colombier */ 4393e12c5d1SDavid du Colombier char * 4403e12c5d1SDavid du Colombier system(int fd, char *cmd) 4413e12c5d1SDavid du Colombier { 4423e12c5d1SDavid du Colombier int pid; 4433e12c5d1SDavid du Colombier int p; 4443e12c5d1SDavid du Colombier static Waitmsg msg; 4453e12c5d1SDavid du Colombier 4463e12c5d1SDavid du Colombier if((pid = fork()) == -1){ 4473e12c5d1SDavid du Colombier perror("con"); 4483e12c5d1SDavid du Colombier return "fork failed"; 4493e12c5d1SDavid du Colombier } 4503e12c5d1SDavid du Colombier else if(pid == 0){ 4513e12c5d1SDavid du Colombier dup(fd, 0); 4523e12c5d1SDavid du Colombier close(ctl); 4533e12c5d1SDavid du Colombier close(fd); 4543e12c5d1SDavid du Colombier if(*cmd) 455f19e7b74SDavid du Colombier execl("/bin/rc", "rc", "-c", cmd, nil); 4563e12c5d1SDavid du Colombier else 457f19e7b74SDavid du Colombier execl("/bin/rc", "rc", nil); 4583e12c5d1SDavid du Colombier perror("con"); 4593e12c5d1SDavid du Colombier exits("exec"); 4603e12c5d1SDavid du Colombier } 4619a747e4fSDavid du Colombier for(p = waitpid(); p >= 0; p = waitpid()){ 4623e12c5d1SDavid du Colombier if(p == pid) 4633e12c5d1SDavid du Colombier return msg.msg; 4643e12c5d1SDavid du Colombier } 4653e12c5d1SDavid du Colombier return "lost child"; 4663e12c5d1SDavid du Colombier } 4673e12c5d1SDavid du Colombier 4683e12c5d1SDavid du Colombier /* 4693e12c5d1SDavid du Colombier * suppress local echo if the remote side is doing it 4703e12c5d1SDavid du Colombier */ 4713e12c5d1SDavid du Colombier int 4723e12c5d1SDavid du Colombier echochange(Biobuf *bp, int cmd) 4733e12c5d1SDavid du Colombier { 4743e12c5d1SDavid du Colombier USED(bp); 4753e12c5d1SDavid du Colombier 4763e12c5d1SDavid du Colombier switch(cmd){ 4773e12c5d1SDavid du Colombier case Will: 4783e12c5d1SDavid du Colombier rawon(); 4793e12c5d1SDavid du Colombier break; 4803e12c5d1SDavid du Colombier case Wont: 4813e12c5d1SDavid du Colombier rawoff(); 4823e12c5d1SDavid du Colombier break; 4833e12c5d1SDavid du Colombier } 4843e12c5d1SDavid du Colombier return 0; 4853e12c5d1SDavid du Colombier } 4863e12c5d1SDavid du Colombier 4873e12c5d1SDavid du Colombier /* 4883e12c5d1SDavid du Colombier * send terminal type to the other side 4893e12c5d1SDavid du Colombier */ 4903e12c5d1SDavid du Colombier int 4913e12c5d1SDavid du Colombier termsub(Biobuf *bp, uchar *sub, int n) 4923e12c5d1SDavid du Colombier { 4933e12c5d1SDavid du Colombier char buf[64]; 4943e12c5d1SDavid du Colombier char *term; 4953e12c5d1SDavid du Colombier char *p = buf; 4963e12c5d1SDavid du Colombier 4973e12c5d1SDavid du Colombier if(n < 1) 4983e12c5d1SDavid du Colombier return 0; 4993e12c5d1SDavid du Colombier if(sub[0] == 1){ 5003e12c5d1SDavid du Colombier *p++ = Iac; 5013e12c5d1SDavid du Colombier *p++ = Sb; 5023e12c5d1SDavid du Colombier *p++ = opt[Term].code; 5033e12c5d1SDavid du Colombier *p++ = 0; 5043e12c5d1SDavid du Colombier term = getenv("TERM"); 5053e12c5d1SDavid du Colombier if(term == 0 || *term == 0) 5063e12c5d1SDavid du Colombier term = "p9win"; 507bd389b36SDavid du Colombier strncpy(p, term, sizeof(buf) - (p - buf) - 2); 508bd389b36SDavid du Colombier buf[sizeof(buf)-2] = 0; 509bd389b36SDavid du Colombier p += strlen(p); 5103e12c5d1SDavid du Colombier *p++ = Iac; 5113e12c5d1SDavid du Colombier *p++ = Se; 5123e12c5d1SDavid du Colombier return iwrite(Bfildes(bp), buf, p-buf); 5133e12c5d1SDavid du Colombier } 5143e12c5d1SDavid du Colombier return 0; 5153e12c5d1SDavid du Colombier } 5163e12c5d1SDavid du Colombier 5173e12c5d1SDavid du Colombier /* 5183e12c5d1SDavid du Colombier * send an x display location to the other side 5193e12c5d1SDavid du Colombier */ 5203e12c5d1SDavid du Colombier int 5213e12c5d1SDavid du Colombier xlocsub(Biobuf *bp, uchar *sub, int n) 5223e12c5d1SDavid du Colombier { 5233e12c5d1SDavid du Colombier char buf[64]; 5243e12c5d1SDavid du Colombier char *term; 5253e12c5d1SDavid du Colombier char *p = buf; 5263e12c5d1SDavid du Colombier 5273e12c5d1SDavid du Colombier if(n < 1) 5283e12c5d1SDavid du Colombier return 0; 5293e12c5d1SDavid du Colombier if(sub[0] == 1){ 5303e12c5d1SDavid du Colombier *p++ = Iac; 5313e12c5d1SDavid du Colombier *p++ = Sb; 5323e12c5d1SDavid du Colombier *p++ = opt[Xloc].code; 5333e12c5d1SDavid du Colombier *p++ = 0; 5343e12c5d1SDavid du Colombier term = getenv("XDISP"); 5353e12c5d1SDavid du Colombier if(term == 0 || *term == 0) 5363e12c5d1SDavid du Colombier term = "unknown"; 5373e12c5d1SDavid du Colombier strncpy(p, term, p - buf - 2); 5383e12c5d1SDavid du Colombier p += strlen(term); 5393e12c5d1SDavid du Colombier *p++ = Iac; 5403e12c5d1SDavid du Colombier *p++ = Se; 5413e12c5d1SDavid du Colombier return iwrite(Bfildes(bp), buf, p-buf); 5423e12c5d1SDavid du Colombier } 5433e12c5d1SDavid du Colombier return 0; 5443e12c5d1SDavid du Colombier } 545219b2ee8SDavid du Colombier 546219b2ee8SDavid du Colombier static int 547219b2ee8SDavid du Colombier islikeatty(int fd) 548219b2ee8SDavid du Colombier { 5494f281771SDavid du Colombier char buf[64]; 550219b2ee8SDavid du Colombier 5514f281771SDavid du Colombier if(fd2path(fd, buf, sizeof buf) != 0) 552219b2ee8SDavid du Colombier return 0; 5534f281771SDavid du Colombier 5544f281771SDavid du Colombier /* might be /mnt/term/dev/cons */ 5554f281771SDavid du Colombier return strlen(buf) >= 9 && strcmp(buf+strlen(buf)-9, "/dev/cons") == 0; 556219b2ee8SDavid du Colombier } 557219b2ee8SDavid du Colombier 558219b2ee8SDavid du Colombier /* 559219b2ee8SDavid du Colombier * create a shared segment. Make is start 2 meg higher than the current 560219b2ee8SDavid du Colombier * end of process memory. 561219b2ee8SDavid du Colombier */ 562219b2ee8SDavid du Colombier void* 56374f16c81SDavid du Colombier share(ulong len) 564219b2ee8SDavid du Colombier { 5657545821fSDavid du Colombier uchar *vastart; 566219b2ee8SDavid du Colombier 5677545821fSDavid du Colombier vastart = sbrk(0); 56874f16c81SDavid du Colombier if(vastart == (void*)-1) 56974f16c81SDavid du Colombier return 0; 5707545821fSDavid du Colombier vastart += 2*1024*1024; 571219b2ee8SDavid du Colombier 57274f16c81SDavid du Colombier if(segattach(0, "shared", vastart, len) == (void*)-1) 573219b2ee8SDavid du Colombier return 0; 574219b2ee8SDavid du Colombier 5757545821fSDavid du Colombier return vastart; 576219b2ee8SDavid du Colombier } 577