13e12c5d1SDavid du Colombier #include <u.h> 23e12c5d1SDavid du Colombier #include <libc.h> 33e12c5d1SDavid du Colombier 43e12c5d1SDavid du Colombier #include "rustream.h" 53e12c5d1SDavid du Colombier #include "ruttyio.h" 63e12c5d1SDavid du Colombier #include "rusignal.h" 73e12c5d1SDavid du Colombier #include "rufilio.h" 83e12c5d1SDavid du Colombier 93e12c5d1SDavid du Colombier int debug; /* true if debugging */ 103e12c5d1SDavid du Colombier int ctl = -1; /* control fd (for break's) */ 113e12c5d1SDavid du Colombier int raw; /* true if raw is on */ 123e12c5d1SDavid du Colombier int consctl = -1; /* control fd for cons */ 133e12c5d1SDavid du Colombier int ttypid; /* pid's if the 2 processes (used to kill them) */ 143e12c5d1SDavid du Colombier int msgfd = -1; /* mesgld file descriptor (for signals to be written to) */ 153e12c5d1SDavid du Colombier int outfd = 1; /* local output file descriptor */ 163e12c5d1SDavid du Colombier int cooked; /* non-zero forces cooked mode */ 173e12c5d1SDavid du Colombier int returns; /* non-zero forces carriage returns not to be filtered out */ 18*219b2ee8SDavid du Colombier int strip; /* strip off parity bits */ 193e12c5d1SDavid du Colombier char firsterr[2*ERRLEN]; 203e12c5d1SDavid du Colombier char transerr[2*ERRLEN]; 213e12c5d1SDavid du Colombier int limited; 223e12c5d1SDavid du Colombier char *remuser; 233e12c5d1SDavid du Colombier int verbose; 24*219b2ee8SDavid du Colombier int baud; 253e12c5d1SDavid du Colombier 263e12c5d1SDavid du Colombier typedef struct Msg Msg; 27*219b2ee8SDavid du Colombier #define MAXMSG (2*8192) 283e12c5d1SDavid du Colombier 293e12c5d1SDavid du Colombier int dkauth(int); 303e12c5d1SDavid du Colombier int dodial(char*, char*, char*); 313e12c5d1SDavid du Colombier void fromkbd(int); 323e12c5d1SDavid du Colombier void fromnet(int); 333e12c5d1SDavid du Colombier long iread(int, void*, int); 343e12c5d1SDavid du Colombier long iwrite(int, void*, int); 353e12c5d1SDavid du Colombier int menu(int); 363e12c5d1SDavid du Colombier void msgfromkbd(int); 373e12c5d1SDavid du Colombier void msgfromnet(int); 383e12c5d1SDavid du Colombier void msgnotifyf(void*, char*); 393e12c5d1SDavid du Colombier int msgwrite(int, void*, int); 403e12c5d1SDavid du Colombier void notifyf(void*, char*); 413e12c5d1SDavid du Colombier void pass(int, int, int); 423e12c5d1SDavid du Colombier void rawoff(void); 433e12c5d1SDavid du Colombier void rawon(void); 443e12c5d1SDavid du Colombier int readupto(int, char*, int); 453e12c5d1SDavid du Colombier int sendctl(int, int); 463e12c5d1SDavid du Colombier int sendctl1(int, int, int); 473e12c5d1SDavid du Colombier void stdcon(int); 483e12c5d1SDavid du Colombier char* system(int, char*); 493e12c5d1SDavid du Colombier void dosystem(int, char*); 503e12c5d1SDavid du Colombier int wasintr(void); 513e12c5d1SDavid du Colombier void punt(char*); 523e12c5d1SDavid du Colombier char* syserr(void); 53*219b2ee8SDavid du Colombier void seterr(char*); 543e12c5d1SDavid du Colombier 553e12c5d1SDavid du Colombier /* protocols */ 563e12c5d1SDavid du Colombier void dcon(char*, char*); 573e12c5d1SDavid du Colombier void device(char*, char*); 583e12c5d1SDavid du Colombier void mesgdcon(char*, char*); 593e12c5d1SDavid du Colombier void rlogin(char*, char*); 603e12c5d1SDavid du Colombier void simple(char*, char*); 613e12c5d1SDavid du Colombier 623e12c5d1SDavid du Colombier void 633e12c5d1SDavid du Colombier usage(void) 643e12c5d1SDavid du Colombier { 65*219b2ee8SDavid du Colombier punt("usage: con [-drCvs] [-l [user]] [-c cmd] net!host[!service]"); 663e12c5d1SDavid du Colombier } 673e12c5d1SDavid du Colombier 683e12c5d1SDavid du Colombier void 693e12c5d1SDavid du Colombier main(int argc, char *argv[]) 703e12c5d1SDavid du Colombier { 713e12c5d1SDavid du Colombier char *dest; 723e12c5d1SDavid du Colombier char *cmd = 0; 733e12c5d1SDavid du Colombier 743e12c5d1SDavid du Colombier returns = 1; 753e12c5d1SDavid du Colombier ARGBEGIN{ 76*219b2ee8SDavid du Colombier case 'b': 77*219b2ee8SDavid du Colombier baud = atoi(ARGF()); 78*219b2ee8SDavid du Colombier break; 793e12c5d1SDavid du Colombier case 'd': 803e12c5d1SDavid du Colombier debug = 1; 813e12c5d1SDavid du Colombier break; 823e12c5d1SDavid du Colombier case 'l': 833e12c5d1SDavid du Colombier limited = 1; 843e12c5d1SDavid du Colombier if(argv[1][0] != '-') 853e12c5d1SDavid du Colombier remuser = ARGF(); 863e12c5d1SDavid du Colombier break; 873e12c5d1SDavid du Colombier case 'r': 883e12c5d1SDavid du Colombier returns = 0; 893e12c5d1SDavid du Colombier break; 903e12c5d1SDavid du Colombier case 'C': 913e12c5d1SDavid du Colombier cooked = 1; 923e12c5d1SDavid du Colombier break; 933e12c5d1SDavid du Colombier case 'c': 943e12c5d1SDavid du Colombier cmd = ARGF(); 953e12c5d1SDavid du Colombier break; 963e12c5d1SDavid du Colombier case 'v': 973e12c5d1SDavid du Colombier verbose = 1; 983e12c5d1SDavid du Colombier break; 99*219b2ee8SDavid du Colombier case 's': 100*219b2ee8SDavid du Colombier strip = 1; 101*219b2ee8SDavid du Colombier break; 1023e12c5d1SDavid du Colombier default: 1033e12c5d1SDavid du Colombier usage(); 1043e12c5d1SDavid du Colombier }ARGEND 1053e12c5d1SDavid du Colombier 1063e12c5d1SDavid du Colombier if(argc != 1){ 1073e12c5d1SDavid du Colombier if(remuser == 0) 1083e12c5d1SDavid du Colombier usage(); 1093e12c5d1SDavid du Colombier dest = remuser; 1103e12c5d1SDavid du Colombier remuser = 0; 1113e12c5d1SDavid du Colombier } else 1123e12c5d1SDavid du Colombier dest = argv[0]; 1133e12c5d1SDavid du Colombier if(*dest == '/') 1143e12c5d1SDavid du Colombier device(dest, cmd); 1153e12c5d1SDavid du Colombier else if(limited){ 1163e12c5d1SDavid du Colombier simple(dest, cmd); /* doesn't return if dialout succeeds */ 1173e12c5d1SDavid du Colombier rlogin(dest, cmd); /* doesn't return if dialout succeeds */ 1183e12c5d1SDavid du Colombier } else { 119*219b2ee8SDavid du Colombier rlogin(dest, cmd); /* doesn't return if dialout succeeds */ 1203e12c5d1SDavid du Colombier mesgdcon(dest, cmd); /* doesn't return if dialout succeeds */ 1213e12c5d1SDavid du Colombier dcon(dest, cmd); /* doesn't return if dialout succeeds */ 1223e12c5d1SDavid du Colombier simple(dest, cmd); /* doesn't return if dialout succeeds */ 1233e12c5d1SDavid du Colombier } 1243e12c5d1SDavid du Colombier punt(firsterr); 1253e12c5d1SDavid du Colombier } 1263e12c5d1SDavid du Colombier 1273e12c5d1SDavid du Colombier /* 1283e12c5d1SDavid du Colombier * just dial and use as a byte stream with remote echo 1293e12c5d1SDavid du Colombier */ 1303e12c5d1SDavid du Colombier void 1313e12c5d1SDavid du Colombier simple(char *dest, char *cmd) 1323e12c5d1SDavid du Colombier { 1333e12c5d1SDavid du Colombier int net; 1343e12c5d1SDavid du Colombier 1353e12c5d1SDavid du Colombier net = dodial(dest, 0, 0); 1363e12c5d1SDavid du Colombier if(net < 0) 1373e12c5d1SDavid du Colombier return; 1383e12c5d1SDavid du Colombier 1393e12c5d1SDavid du Colombier if(cmd) 1403e12c5d1SDavid du Colombier dosystem(net, cmd); 1413e12c5d1SDavid du Colombier 1423e12c5d1SDavid du Colombier if(!cooked) 1433e12c5d1SDavid du Colombier rawon(); 1443e12c5d1SDavid du Colombier stdcon(net); 1453e12c5d1SDavid du Colombier exits(0); 1463e12c5d1SDavid du Colombier } 1473e12c5d1SDavid du Colombier 1483e12c5d1SDavid du Colombier /* 1493e12c5d1SDavid du Colombier * dial, do UCB authentication, use as a byte stream with local echo 1503e12c5d1SDavid du Colombier * 1513e12c5d1SDavid du Colombier * return if dial failed 1523e12c5d1SDavid du Colombier */ 1533e12c5d1SDavid du Colombier void 1543e12c5d1SDavid du Colombier rlogin(char *dest, char *cmd) 1553e12c5d1SDavid du Colombier { 1563e12c5d1SDavid du Colombier int net, fd; 1573e12c5d1SDavid du Colombier long n; 1583e12c5d1SDavid du Colombier char buf[2*NAMELEN]; 1593e12c5d1SDavid du Colombier char *p; 1603e12c5d1SDavid du Colombier char *localuser; 1613e12c5d1SDavid du Colombier 1623e12c5d1SDavid du Colombier /* only useful on TCP */ 163bd389b36SDavid du Colombier if(strchr(dest, '!') 164bd389b36SDavid du Colombier && (strncmp(dest, "tcp!", 4)!=0 && strncmp(dest, "net!", 4)!=0)) 1653e12c5d1SDavid du Colombier return; 1663e12c5d1SDavid du Colombier 1673e12c5d1SDavid du Colombier net = dodial(dest, "tcp", "login"); 1683e12c5d1SDavid du Colombier if(net < 0) 1693e12c5d1SDavid du Colombier return; 1703e12c5d1SDavid du Colombier 1713e12c5d1SDavid du Colombier /* 1723e12c5d1SDavid du Colombier * do UCB rlogin authentication 1733e12c5d1SDavid du Colombier */ 1743e12c5d1SDavid du Colombier fd = open("/dev/user", OREAD); 1753e12c5d1SDavid du Colombier n = read(fd, buf, sizeof(buf)); 1763e12c5d1SDavid du Colombier close(fd); 1773e12c5d1SDavid du Colombier buf[n] = 0; 1783e12c5d1SDavid du Colombier localuser = buf; 1793e12c5d1SDavid du Colombier if(remuser == 0){ 1803e12c5d1SDavid du Colombier if(limited) 1813e12c5d1SDavid du Colombier remuser = ":"; 1823e12c5d1SDavid du Colombier else 1833e12c5d1SDavid du Colombier remuser = localuser; 1843e12c5d1SDavid du Colombier } 1853e12c5d1SDavid du Colombier p = getenv("TERM"); 1863e12c5d1SDavid du Colombier if(p == 0) 1873e12c5d1SDavid du Colombier p = "p9"; 1883e12c5d1SDavid du Colombier if(write(net, "", 1)<0 1893e12c5d1SDavid du Colombier || write(net, localuser, strlen(localuser)+1)<0 1903e12c5d1SDavid du Colombier || write(net, remuser, strlen(remuser)+1)<0 1913e12c5d1SDavid du Colombier || write(net, p, strlen(p)+1)<0){ 1923e12c5d1SDavid du Colombier close(net); 1933e12c5d1SDavid du Colombier punt("BSD authentication failed"); 1943e12c5d1SDavid du Colombier } 1953e12c5d1SDavid du Colombier if(read(net, buf, 1) != 1) 1963e12c5d1SDavid du Colombier punt("BSD authentication failed1"); 1973e12c5d1SDavid du Colombier if(buf[0] != 0){ 1983e12c5d1SDavid du Colombier fprint(2, "con: remote error: "); 1993e12c5d1SDavid du Colombier while(read(net, buf, 1) == 1){ 2003e12c5d1SDavid du Colombier write(2, buf, 1); 2013e12c5d1SDavid du Colombier if(buf[0] == '\n') 2023e12c5d1SDavid du Colombier break; 2033e12c5d1SDavid du Colombier } 2043e12c5d1SDavid du Colombier exits("read"); 2053e12c5d1SDavid du Colombier } 2063e12c5d1SDavid du Colombier 2073e12c5d1SDavid du Colombier if(cmd) 2083e12c5d1SDavid du Colombier dosystem(net, cmd); 2093e12c5d1SDavid du Colombier 2103e12c5d1SDavid du Colombier if(!cooked) 2113e12c5d1SDavid du Colombier rawon(); 2123e12c5d1SDavid du Colombier stdcon(net); 2133e12c5d1SDavid du Colombier exits(0); 2143e12c5d1SDavid du Colombier } 2153e12c5d1SDavid du Colombier 2163e12c5d1SDavid du Colombier /* 2173e12c5d1SDavid du Colombier * dial, do DK authentication, use as a byte stream with remote echo 2183e12c5d1SDavid du Colombier * 2193e12c5d1SDavid du Colombier * return if dial failed 2203e12c5d1SDavid du Colombier */ 2213e12c5d1SDavid du Colombier void 2223e12c5d1SDavid du Colombier dcon(char *dest, char *cmd) 2233e12c5d1SDavid du Colombier { 2243e12c5d1SDavid du Colombier int net; 2253e12c5d1SDavid du Colombier 2263e12c5d1SDavid du Colombier net = dodial(dest, 0, "dcon"); 2273e12c5d1SDavid du Colombier if(net < 0) 2283e12c5d1SDavid du Colombier return; 2293e12c5d1SDavid du Colombier 2303e12c5d1SDavid du Colombier if(dkauth(net) < 0) 2313e12c5d1SDavid du Colombier punt("can't authenticate across datakit"); 2323e12c5d1SDavid du Colombier 2333e12c5d1SDavid du Colombier if(cmd) 2343e12c5d1SDavid du Colombier dosystem(net, cmd); 2353e12c5d1SDavid du Colombier 2363e12c5d1SDavid du Colombier if(!cooked) 2373e12c5d1SDavid du Colombier rawon(); 2383e12c5d1SDavid du Colombier stdcon(net); 2393e12c5d1SDavid du Colombier exits(0); 2403e12c5d1SDavid du Colombier } 2413e12c5d1SDavid du Colombier 2423e12c5d1SDavid du Colombier /* 2433e12c5d1SDavid du Colombier * just open a device and use it as a connection 2443e12c5d1SDavid du Colombier */ 2453e12c5d1SDavid du Colombier void 2463e12c5d1SDavid du Colombier device(char *dest, char *cmd) 2473e12c5d1SDavid du Colombier { 2483e12c5d1SDavid du Colombier int net; 2493e12c5d1SDavid du Colombier char cname[3*NAMELEN]; 2503e12c5d1SDavid du Colombier 2513e12c5d1SDavid du Colombier net = open(dest, ORDWR); 2523e12c5d1SDavid du Colombier if(net < 0) 253*219b2ee8SDavid du Colombier punt(syserr()); 2543e12c5d1SDavid du Colombier sprint(cname, "%sctl", dest); 2553e12c5d1SDavid du Colombier ctl = open(cname, ORDWR); 256*219b2ee8SDavid du Colombier if(ctl >= 0 && baud > 0) 257*219b2ee8SDavid du Colombier fprint(ctl, "b%d", baud); 2583e12c5d1SDavid du Colombier 2593e12c5d1SDavid du Colombier if(cmd) 2603e12c5d1SDavid du Colombier dosystem(net, cmd); 2613e12c5d1SDavid du Colombier 2623e12c5d1SDavid du Colombier if(!cooked) 2633e12c5d1SDavid du Colombier rawon(); 2643e12c5d1SDavid du Colombier stdcon(net); 2653e12c5d1SDavid du Colombier exits(0); 2663e12c5d1SDavid du Colombier } 2673e12c5d1SDavid du Colombier 2683e12c5d1SDavid du Colombier /* 2693e12c5d1SDavid du Colombier * ignore interrupts 2703e12c5d1SDavid du Colombier */ 2713e12c5d1SDavid du Colombier void 2723e12c5d1SDavid du Colombier notifyf(void *a, char *msg) 2733e12c5d1SDavid du Colombier { 2743e12c5d1SDavid du Colombier USED(a); 2753e12c5d1SDavid du Colombier 2763e12c5d1SDavid du Colombier if(strstr(msg, "closed pipe") 2773e12c5d1SDavid du Colombier || strcmp(msg, "interrupt") == 0 2783e12c5d1SDavid du Colombier || strcmp(msg, "hangup") == 0) 2793e12c5d1SDavid du Colombier noted(NCONT); 2803e12c5d1SDavid du Colombier noted(NDFLT); 2813e12c5d1SDavid du Colombier } 2823e12c5d1SDavid du Colombier 2833e12c5d1SDavid du Colombier /* 2843e12c5d1SDavid du Colombier * turn keyboard raw mode on 2853e12c5d1SDavid du Colombier */ 2863e12c5d1SDavid du Colombier void 2873e12c5d1SDavid du Colombier rawon(void) 2883e12c5d1SDavid du Colombier { 2893e12c5d1SDavid du Colombier if(debug) 2903e12c5d1SDavid du Colombier fprint(2, "rawon\n"); 2913e12c5d1SDavid du Colombier if(raw) 2923e12c5d1SDavid du Colombier return; 2933e12c5d1SDavid du Colombier if(consctl < 0) 2943e12c5d1SDavid du Colombier consctl = open("/dev/consctl", OWRITE); 2953e12c5d1SDavid du Colombier if(consctl < 0){ 2963e12c5d1SDavid du Colombier fprint(2, "can't open consctl\n"); 2973e12c5d1SDavid du Colombier return; 2983e12c5d1SDavid du Colombier } 2993e12c5d1SDavid du Colombier write(consctl, "rawon", 5); 3003e12c5d1SDavid du Colombier raw = 1; 3013e12c5d1SDavid du Colombier } 3023e12c5d1SDavid du Colombier 3033e12c5d1SDavid du Colombier /* 3043e12c5d1SDavid du Colombier * turn keyboard raw mode off 3053e12c5d1SDavid du Colombier */ 3063e12c5d1SDavid du Colombier void 3073e12c5d1SDavid du Colombier rawoff(void) 3083e12c5d1SDavid du Colombier { 3093e12c5d1SDavid du Colombier if(debug) 3103e12c5d1SDavid du Colombier fprint(2, "rawoff\n"); 3113e12c5d1SDavid du Colombier if(raw == 0) 3123e12c5d1SDavid du Colombier return; 3133e12c5d1SDavid du Colombier if(consctl < 0) 3143e12c5d1SDavid du Colombier consctl = open("/dev/consctl", OWRITE); 3153e12c5d1SDavid du Colombier if(consctl < 0){ 3163e12c5d1SDavid du Colombier fprint(2, "can't open consctl\n"); 3173e12c5d1SDavid du Colombier return; 3183e12c5d1SDavid du Colombier } 3193e12c5d1SDavid du Colombier write(consctl, "rawoff", 6); 3203e12c5d1SDavid du Colombier raw = 0; 3213e12c5d1SDavid du Colombier } 3223e12c5d1SDavid du Colombier 3233e12c5d1SDavid du Colombier /* 3243e12c5d1SDavid du Colombier * control menu 3253e12c5d1SDavid du Colombier */ 326*219b2ee8SDavid du Colombier #define STDHELP "\t(b)reak, (q)uit, (i)nterrupt, (r)eturns, (.)continue, (!cmd)\n" 3273e12c5d1SDavid du Colombier 3283e12c5d1SDavid du Colombier int 3293e12c5d1SDavid du Colombier menu(int net) 3303e12c5d1SDavid du Colombier { 3313e12c5d1SDavid du Colombier char buf[MAXMSG]; 3323e12c5d1SDavid du Colombier long n; 3333e12c5d1SDavid du Colombier int done; 3343e12c5d1SDavid du Colombier int wasraw = raw; 3353e12c5d1SDavid du Colombier 3363e12c5d1SDavid du Colombier if(wasraw) 3373e12c5d1SDavid du Colombier rawoff(); 3383e12c5d1SDavid du Colombier 3393e12c5d1SDavid du Colombier fprint(2, ">>> "); 3403e12c5d1SDavid du Colombier for(done = 0; !done; ){ 3413e12c5d1SDavid du Colombier n = read(0, buf, sizeof(buf)-1); 3423e12c5d1SDavid du Colombier if(n <= 0) 3433e12c5d1SDavid du Colombier return -1; 3443e12c5d1SDavid du Colombier buf[n] = 0; 3453e12c5d1SDavid du Colombier switch(buf[0]){ 3463e12c5d1SDavid du Colombier case '!': 3473e12c5d1SDavid du Colombier print(buf); 3483e12c5d1SDavid du Colombier system(net, buf+1); 3493e12c5d1SDavid du Colombier print("!\n"); 3503e12c5d1SDavid du Colombier done = 1; 3513e12c5d1SDavid du Colombier break; 3523e12c5d1SDavid du Colombier case '.': 3533e12c5d1SDavid du Colombier done = 1; 3543e12c5d1SDavid du Colombier break; 3553e12c5d1SDavid du Colombier case 'q': 3563e12c5d1SDavid du Colombier return -1; 3573e12c5d1SDavid du Colombier break; 3583e12c5d1SDavid du Colombier case 'i': 3593e12c5d1SDavid du Colombier buf[0] = 0x1c; 3603e12c5d1SDavid du Colombier if(msgfd <= 0) 3613e12c5d1SDavid du Colombier write(net, buf, 1); 3623e12c5d1SDavid du Colombier else 3633e12c5d1SDavid du Colombier sendctl1(msgfd, M_SIGNAL, SIGQUIT); 3643e12c5d1SDavid du Colombier done = 1; 3653e12c5d1SDavid du Colombier break; 3663e12c5d1SDavid du Colombier case 'b': 3673e12c5d1SDavid du Colombier if(msgfd >= 0) 3683e12c5d1SDavid du Colombier sendctl(msgfd, M_BREAK); 3693e12c5d1SDavid du Colombier else if(ctl >= 0) 370*219b2ee8SDavid du Colombier write(ctl, "k", 1); 371*219b2ee8SDavid du Colombier done = 1; 372*219b2ee8SDavid du Colombier break; 373*219b2ee8SDavid du Colombier case 'r': 374*219b2ee8SDavid du Colombier returns = 1-returns; 3753e12c5d1SDavid du Colombier done = 1; 3763e12c5d1SDavid du Colombier break; 3773e12c5d1SDavid du Colombier default: 3783e12c5d1SDavid du Colombier fprint(2, STDHELP); 3793e12c5d1SDavid du Colombier break; 3803e12c5d1SDavid du Colombier } 3813e12c5d1SDavid du Colombier if(!done) 3823e12c5d1SDavid du Colombier fprint(2, ">>> "); 3833e12c5d1SDavid du Colombier } 3843e12c5d1SDavid du Colombier 3853e12c5d1SDavid du Colombier if(wasraw) 3863e12c5d1SDavid du Colombier rawon(); 3873e12c5d1SDavid du Colombier else 3883e12c5d1SDavid du Colombier rawoff(); 3893e12c5d1SDavid du Colombier return 0; 3903e12c5d1SDavid du Colombier } 3913e12c5d1SDavid du Colombier 3923e12c5d1SDavid du Colombier /* 3933e12c5d1SDavid du Colombier * the real work. two processes pass bytes back and forth between the 3943e12c5d1SDavid du Colombier * terminal and the network. 3953e12c5d1SDavid du Colombier */ 3963e12c5d1SDavid du Colombier void 3973e12c5d1SDavid du Colombier stdcon(int net) 3983e12c5d1SDavid du Colombier { 3993e12c5d1SDavid du Colombier int netpid; 4003e12c5d1SDavid du Colombier 4013e12c5d1SDavid du Colombier ttypid = getpid(); 4023e12c5d1SDavid du Colombier switch(netpid = rfork(RFMEM|RFPROC)){ 4033e12c5d1SDavid du Colombier case -1: 4043e12c5d1SDavid du Colombier perror("con"); 4053e12c5d1SDavid du Colombier exits("fork"); 4063e12c5d1SDavid du Colombier case 0: 4073e12c5d1SDavid du Colombier notify(notifyf); 4083e12c5d1SDavid du Colombier fromnet(net); 409*219b2ee8SDavid du Colombier postnote(PNPROC, ttypid, "kill"); 4103e12c5d1SDavid du Colombier exits(0); 4113e12c5d1SDavid du Colombier default: 4123e12c5d1SDavid du Colombier notify(notifyf); 4133e12c5d1SDavid du Colombier fromkbd(net); 414*219b2ee8SDavid du Colombier postnote(PNPROC, netpid, "kill"); 4153e12c5d1SDavid du Colombier exits(0); 4163e12c5d1SDavid du Colombier } 4173e12c5d1SDavid du Colombier } 4183e12c5d1SDavid du Colombier 4193e12c5d1SDavid du Colombier /* 4203e12c5d1SDavid du Colombier * Read the keyboard and write it to the network. '^\' gets us into 4213e12c5d1SDavid du Colombier * the menu. 4223e12c5d1SDavid du Colombier */ 4233e12c5d1SDavid du Colombier void 4243e12c5d1SDavid du Colombier fromkbd(int net) 4253e12c5d1SDavid du Colombier { 4263e12c5d1SDavid du Colombier long n; 4273e12c5d1SDavid du Colombier char buf[MAXMSG]; 4283e12c5d1SDavid du Colombier 4293e12c5d1SDavid du Colombier for(;;){ 4303e12c5d1SDavid du Colombier n = read(0, buf, sizeof(buf)); 4313e12c5d1SDavid du Colombier if(n < 0){ 4323e12c5d1SDavid du Colombier if(wasintr()){ 4333e12c5d1SDavid du Colombier if(cooked){ 4343e12c5d1SDavid du Colombier buf[0] = 0x7f; 4353e12c5d1SDavid du Colombier n = 1; 4363e12c5d1SDavid du Colombier } else 4373e12c5d1SDavid du Colombier continue; 4383e12c5d1SDavid du Colombier } else 4393e12c5d1SDavid du Colombier return; 4403e12c5d1SDavid du Colombier } 4413e12c5d1SDavid du Colombier if(n && memchr(buf, 0x1c, n)){ 4423e12c5d1SDavid du Colombier if(menu(net) < 0) 4433e12c5d1SDavid du Colombier return; 4443e12c5d1SDavid du Colombier }else{ 4453e12c5d1SDavid du Colombier if(cooked && n==0){ 4463e12c5d1SDavid du Colombier buf[0] = 0x4; 4473e12c5d1SDavid du Colombier n = 1; 4483e12c5d1SDavid du Colombier } 4493e12c5d1SDavid du Colombier if(iwrite(net, buf, n) != n) 4503e12c5d1SDavid du Colombier return; 4513e12c5d1SDavid du Colombier } 4523e12c5d1SDavid du Colombier } 4533e12c5d1SDavid du Colombier } 4543e12c5d1SDavid du Colombier 4553e12c5d1SDavid du Colombier /* 4563e12c5d1SDavid du Colombier * Read from the network and write to the screen. 4573e12c5d1SDavid du Colombier * Filter out spurious carriage returns. 4583e12c5d1SDavid du Colombier */ 4593e12c5d1SDavid du Colombier void 4603e12c5d1SDavid du Colombier fromnet(int net) 4613e12c5d1SDavid du Colombier { 4623e12c5d1SDavid du Colombier long n; 4633e12c5d1SDavid du Colombier char buf[MAXMSG]; 4643e12c5d1SDavid du Colombier char *cp, *ep; 4653e12c5d1SDavid du Colombier 4663e12c5d1SDavid du Colombier for(;;){ 4673e12c5d1SDavid du Colombier n = iread(net, buf, sizeof(buf)); 4683e12c5d1SDavid du Colombier if(n < 0) 4693e12c5d1SDavid du Colombier return; 4703e12c5d1SDavid du Colombier if(n == 0) 4713e12c5d1SDavid du Colombier continue; 4723e12c5d1SDavid du Colombier 473*219b2ee8SDavid du Colombier if (strip) 474*219b2ee8SDavid du Colombier for (cp=buf; cp<buf+n; cp++) 475*219b2ee8SDavid du Colombier *cp &= 0177; 476*219b2ee8SDavid du Colombier 4773e12c5d1SDavid du Colombier if(!returns){ 4783e12c5d1SDavid du Colombier /* convert cr's to null's */ 4793e12c5d1SDavid du Colombier cp = buf; 4803e12c5d1SDavid du Colombier ep = buf + n; 4813e12c5d1SDavid du Colombier while(cp < ep && (cp = memchr(cp, '\r', ep-cp))){ 4823e12c5d1SDavid du Colombier memmove(cp, cp+1, ep-cp-1); 4833e12c5d1SDavid du Colombier ep--; 4843e12c5d1SDavid du Colombier n--; 4853e12c5d1SDavid du Colombier } 4863e12c5d1SDavid du Colombier } 4873e12c5d1SDavid du Colombier 4883e12c5d1SDavid du Colombier if(n > 0 && iwrite(outfd, buf, n) != n){ 4893e12c5d1SDavid du Colombier if(outfd == 1) 4903e12c5d1SDavid du Colombier return; 4913e12c5d1SDavid du Colombier outfd = 1; 4923e12c5d1SDavid du Colombier if(iwrite(1, buf, n) != n) 4933e12c5d1SDavid du Colombier return; 4943e12c5d1SDavid du Colombier } 4953e12c5d1SDavid du Colombier } 4963e12c5d1SDavid du Colombier } 4973e12c5d1SDavid du Colombier 4983e12c5d1SDavid du Colombier /* 4993e12c5d1SDavid du Colombier * dial and return a data connection 5003e12c5d1SDavid du Colombier */ 5013e12c5d1SDavid du Colombier int 5023e12c5d1SDavid du Colombier dodial(char *dest, char *net, char *service) 5033e12c5d1SDavid du Colombier { 5043e12c5d1SDavid du Colombier char name[3*NAMELEN]; 5053e12c5d1SDavid du Colombier char devdir[3*NAMELEN]; 5063e12c5d1SDavid du Colombier int data; 5073e12c5d1SDavid du Colombier 5083e12c5d1SDavid du Colombier devdir[0] = 0; 5093e12c5d1SDavid du Colombier strcpy(name, netmkaddr(dest, net, service)); 510bd389b36SDavid du Colombier data = dial(name, 0, devdir, &ctl); 5113e12c5d1SDavid du Colombier if(data < 0){ 512*219b2ee8SDavid du Colombier seterr(name); 5133e12c5d1SDavid du Colombier return -1; 5143e12c5d1SDavid du Colombier } 5153e12c5d1SDavid du Colombier fprint(2, "connected to %s on %s\n", name, devdir); 5163e12c5d1SDavid du Colombier return data; 5173e12c5d1SDavid du Colombier } 5183e12c5d1SDavid du Colombier 5193e12c5d1SDavid du Colombier /* 5203e12c5d1SDavid du Colombier * send a note to a process 5213e12c5d1SDavid du Colombier */ 5223e12c5d1SDavid du Colombier /* 5233e12c5d1SDavid du Colombier * datakit authentication 5243e12c5d1SDavid du Colombier */ 5253e12c5d1SDavid du Colombier int 5263e12c5d1SDavid du Colombier dkauth(int net) 5273e12c5d1SDavid du Colombier { 5283e12c5d1SDavid du Colombier char buf[128]; 5293e12c5d1SDavid du Colombier long n; 5303e12c5d1SDavid du Colombier char *p; 5313e12c5d1SDavid du Colombier 5323e12c5d1SDavid du Colombier for(;;){ 5333e12c5d1SDavid du Colombier if(read(net, buf, 2)!=2) 5343e12c5d1SDavid du Colombier return -1; 5353e12c5d1SDavid du Colombier if(buf[0]=='O' && buf[1]=='K') 5363e12c5d1SDavid du Colombier break; 5373e12c5d1SDavid du Colombier if(buf[0]!='N' || buf[1]!='O') 5383e12c5d1SDavid du Colombier return -1; 5393e12c5d1SDavid du Colombier print("please login: "); 5403e12c5d1SDavid du Colombier n = read(0, buf, sizeof(buf)-1); 5413e12c5d1SDavid du Colombier if(n<=0) 5423e12c5d1SDavid du Colombier exits("login"); 5433e12c5d1SDavid du Colombier buf[n-1] = ','; 5443e12c5d1SDavid du Colombier rawon(); 5453e12c5d1SDavid du Colombier print("password: "); 5463e12c5d1SDavid du Colombier for(p = &buf[n]; p<&buf[127];p++){ 5473e12c5d1SDavid du Colombier if(read(0, p, 1)!=1) 5483e12c5d1SDavid du Colombier return -1; 5493e12c5d1SDavid du Colombier if(*p=='\r' || *p=='\n'){ 5503e12c5d1SDavid du Colombier *p++ = 0; 5513e12c5d1SDavid du Colombier break; 5523e12c5d1SDavid du Colombier } 5533e12c5d1SDavid du Colombier } 5543e12c5d1SDavid du Colombier n = p-buf; 5553e12c5d1SDavid du Colombier rawoff(); 5563e12c5d1SDavid du Colombier if(write(net, buf, n)!=n) 5573e12c5d1SDavid du Colombier return -1; 5583e12c5d1SDavid du Colombier } 5593e12c5d1SDavid du Colombier return 0; 5603e12c5d1SDavid du Colombier } 5613e12c5d1SDavid du Colombier 5623e12c5d1SDavid du Colombier void 5633e12c5d1SDavid du Colombier dosystem(int fd, char *cmd) 5643e12c5d1SDavid du Colombier { 5653e12c5d1SDavid du Colombier char *p; 5663e12c5d1SDavid du Colombier 5673e12c5d1SDavid du Colombier p = system(fd, cmd); 5683e12c5d1SDavid du Colombier if(*p){ 5693e12c5d1SDavid du Colombier print("con: %s terminated with %s\n", p); 5703e12c5d1SDavid du Colombier exits(p); 5713e12c5d1SDavid du Colombier } 5723e12c5d1SDavid du Colombier } 5733e12c5d1SDavid du Colombier 5743e12c5d1SDavid du Colombier /* 5753e12c5d1SDavid du Colombier * run a command with the network connection as standard IO 5763e12c5d1SDavid du Colombier */ 5773e12c5d1SDavid du Colombier char * 5783e12c5d1SDavid du Colombier system(int fd, char *cmd) 5793e12c5d1SDavid du Colombier { 5803e12c5d1SDavid du Colombier int pid; 5813e12c5d1SDavid du Colombier int p; 5823e12c5d1SDavid du Colombier static Waitmsg msg; 5833e12c5d1SDavid du Colombier int pfd[2]; 5843e12c5d1SDavid du Colombier int n; 5853e12c5d1SDavid du Colombier char buf[4096]; 5863e12c5d1SDavid du Colombier 5873e12c5d1SDavid du Colombier if(pipe(pfd) < 0){ 5883e12c5d1SDavid du Colombier perror("pipe"); 5893e12c5d1SDavid du Colombier return "pipe failed"; 5903e12c5d1SDavid du Colombier } 5913e12c5d1SDavid du Colombier outfd = pfd[1]; 5923e12c5d1SDavid du Colombier 593*219b2ee8SDavid du Colombier close(consctl); 594*219b2ee8SDavid du Colombier consctl = -1; 5953e12c5d1SDavid du Colombier switch(pid = fork()){ 5963e12c5d1SDavid du Colombier case -1: 5973e12c5d1SDavid du Colombier perror("con"); 5983e12c5d1SDavid du Colombier return "fork failed"; 5993e12c5d1SDavid du Colombier case 0: 6003e12c5d1SDavid du Colombier close(pfd[1]); 6013e12c5d1SDavid du Colombier dup(pfd[0], 0); 6023e12c5d1SDavid du Colombier dup(pfd[0], 1); 6033e12c5d1SDavid du Colombier close(ctl); 6043e12c5d1SDavid du Colombier close(fd); 6053e12c5d1SDavid du Colombier close(pfd[0]); 6063e12c5d1SDavid du Colombier if(*cmd) 6073e12c5d1SDavid du Colombier execl("/bin/rc", "rc", "-c", cmd, 0); 6083e12c5d1SDavid du Colombier else 6093e12c5d1SDavid du Colombier execl("/bin/rc", "rc", 0); 6103e12c5d1SDavid du Colombier perror("con"); 6113e12c5d1SDavid du Colombier exits("exec"); 6123e12c5d1SDavid du Colombier break; 6133e12c5d1SDavid du Colombier default: 6143e12c5d1SDavid du Colombier close(pfd[0]); 6153e12c5d1SDavid du Colombier while((n = read(pfd[1], buf, sizeof(buf))) > 0){ 6163e12c5d1SDavid du Colombier if(msgfd >= 0){ 6173e12c5d1SDavid du Colombier if(msgwrite(fd, buf, n) != n) 6183e12c5d1SDavid du Colombier break; 6193e12c5d1SDavid du Colombier } else { 6203e12c5d1SDavid du Colombier if(write(fd, buf, n) != n) 6213e12c5d1SDavid du Colombier break; 6223e12c5d1SDavid du Colombier } 6233e12c5d1SDavid du Colombier } 6243e12c5d1SDavid du Colombier p = wait(&msg); 6253e12c5d1SDavid du Colombier outfd = 1; 6263e12c5d1SDavid du Colombier close(pfd[1]); 627*219b2ee8SDavid du Colombier if(p < 0 || p != pid) 628*219b2ee8SDavid du Colombier return "lost child"; 6293e12c5d1SDavid du Colombier break; 6303e12c5d1SDavid du Colombier } 631*219b2ee8SDavid du Colombier return msg.msg; 6323e12c5d1SDavid du Colombier } 6333e12c5d1SDavid du Colombier 6343e12c5d1SDavid du Colombier int 6353e12c5d1SDavid du Colombier wasintr(void) 6363e12c5d1SDavid du Colombier { 6373e12c5d1SDavid du Colombier return strcmp(syserr(), "interrupted") == 0; 6383e12c5d1SDavid du Colombier } 6393e12c5d1SDavid du Colombier 6403e12c5d1SDavid du Colombier void 6413e12c5d1SDavid du Colombier punt(char *msg) 6423e12c5d1SDavid du Colombier { 6433e12c5d1SDavid du Colombier if(*msg == 0) 6443e12c5d1SDavid du Colombier msg = transerr; 6453e12c5d1SDavid du Colombier fprint(2, "con: %s\n", msg); 6463e12c5d1SDavid du Colombier exits(msg); 6473e12c5d1SDavid du Colombier } 6483e12c5d1SDavid du Colombier 6493e12c5d1SDavid du Colombier char* 6503e12c5d1SDavid du Colombier syserr(void) 6513e12c5d1SDavid du Colombier { 6523e12c5d1SDavid du Colombier static char err[ERRLEN]; 6533e12c5d1SDavid du Colombier errstr(err); 6543e12c5d1SDavid du Colombier return err; 6553e12c5d1SDavid du Colombier } 6563e12c5d1SDavid du Colombier 6573e12c5d1SDavid du Colombier void 658*219b2ee8SDavid du Colombier seterr(char *addr) 6593e12c5d1SDavid du Colombier { 6603e12c5d1SDavid du Colombier char *se = syserr(); 6613e12c5d1SDavid du Colombier 6623e12c5d1SDavid du Colombier if(verbose) 663*219b2ee8SDavid du Colombier fprint(2, "'%s' calling %s\n", se, addr); 6643e12c5d1SDavid du Colombier if(firsterr[0] && (strstr(se, "translate") || 6653e12c5d1SDavid du Colombier strstr(se, "file does not exist") || 6663e12c5d1SDavid du Colombier strstr(se, "unknown address") || 6673e12c5d1SDavid du Colombier strstr(se, "directory entry not found"))) 6683e12c5d1SDavid du Colombier return; 6693e12c5d1SDavid du Colombier strcpy(firsterr, se); 6703e12c5d1SDavid du Colombier } 6713e12c5d1SDavid du Colombier 6723e12c5d1SDavid du Colombier 6733e12c5d1SDavid du Colombier long 6743e12c5d1SDavid du Colombier iread(int f, void *a, int n) 6753e12c5d1SDavid du Colombier { 6763e12c5d1SDavid du Colombier long m; 6773e12c5d1SDavid du Colombier 6783e12c5d1SDavid du Colombier for(;;){ 6793e12c5d1SDavid du Colombier m = read(f, a, n); 6803e12c5d1SDavid du Colombier if(m >= 0 || !wasintr()) 6813e12c5d1SDavid du Colombier break; 6823e12c5d1SDavid du Colombier } 6833e12c5d1SDavid du Colombier return m; 6843e12c5d1SDavid du Colombier } 6853e12c5d1SDavid du Colombier 6863e12c5d1SDavid du Colombier long 6873e12c5d1SDavid du Colombier iwrite(int f, void *a, int n) 6883e12c5d1SDavid du Colombier { 6893e12c5d1SDavid du Colombier long m; 6903e12c5d1SDavid du Colombier 6913e12c5d1SDavid du Colombier m = write(f, a, n); 6923e12c5d1SDavid du Colombier if(m < 0 && wasintr()) 6933e12c5d1SDavid du Colombier return n; 6943e12c5d1SDavid du Colombier return m; 6953e12c5d1SDavid du Colombier } 6963e12c5d1SDavid du Colombier 6973e12c5d1SDavid du Colombier /* 6983e12c5d1SDavid du Colombier * The rest is to support the V10 mesgld protocol. 6993e12c5d1SDavid du Colombier */ 7003e12c5d1SDavid du Colombier 7013e12c5d1SDavid du Colombier /* 7023e12c5d1SDavid du Colombier * network orderings 7033e12c5d1SDavid du Colombier */ 7043e12c5d1SDavid du Colombier #define get2byte(p) ((p)[0] + ((p)[1]<<8)) 7053e12c5d1SDavid du Colombier #define get4byte(p) ((p)[0] + ((p)[1]<<8) + ((p)[2]<<16) + ((p)[3]<<24)) 7063e12c5d1SDavid du Colombier #define put2byte(p, i) ((p)[0]=(i), (p)[1]=(i)>>8) 7073e12c5d1SDavid du Colombier #define put4byte(p, i) ((p)[0]=(i), (p)[1]=(i)>>8, (p)[2]=(i)>>16, (p)[3]=(i)>>24) 7083e12c5d1SDavid du Colombier 7093e12c5d1SDavid du Colombier /* 7103e12c5d1SDavid du Colombier * tty parameters 7113e12c5d1SDavid du Colombier */ 7123e12c5d1SDavid du Colombier int sgflags = ECHO; 7133e12c5d1SDavid du Colombier 7143e12c5d1SDavid du Colombier /* 7153e12c5d1SDavid du Colombier * a mesgld message 7163e12c5d1SDavid du Colombier */ 7173e12c5d1SDavid du Colombier struct Msg { 7183e12c5d1SDavid du Colombier struct mesg h; 7193e12c5d1SDavid du Colombier char b[MAXMSG]; 7203e12c5d1SDavid du Colombier }; 7213e12c5d1SDavid du Colombier 7223e12c5d1SDavid du Colombier /* 7233e12c5d1SDavid du Colombier * connect using the mesgdcon protocol. infinite ugliness to talk to a V10 7243e12c5d1SDavid du Colombier * system. 7253e12c5d1SDavid du Colombier */ 7263e12c5d1SDavid du Colombier void 7273e12c5d1SDavid du Colombier mesgdcon(char *dest, char *cmd) 7283e12c5d1SDavid du Colombier { 7293e12c5d1SDavid du Colombier int net; 7303e12c5d1SDavid du Colombier int netpid; 7313e12c5d1SDavid du Colombier 732*219b2ee8SDavid du Colombier net = dodial(dest, "dk", "mesgdcon"); 7333e12c5d1SDavid du Colombier if(net < 0) 7343e12c5d1SDavid du Colombier return; 7353e12c5d1SDavid du Colombier 7363e12c5d1SDavid du Colombier if(dkauth(net) < 0) 7373e12c5d1SDavid du Colombier punt("can't authenticate across datakit"); 7383e12c5d1SDavid du Colombier 7393e12c5d1SDavid du Colombier if(cmd) 7403e12c5d1SDavid du Colombier dosystem(net, cmd); 7413e12c5d1SDavid du Colombier 7423e12c5d1SDavid du Colombier msgfd = net; 7433e12c5d1SDavid du Colombier ttypid = getpid(); 7443e12c5d1SDavid du Colombier switch(netpid = rfork(RFMEM|RFPROC)){ 7453e12c5d1SDavid du Colombier case -1: 7463e12c5d1SDavid du Colombier perror("con"); 7473e12c5d1SDavid du Colombier exits("fork"); 7483e12c5d1SDavid du Colombier case 0: 7493e12c5d1SDavid du Colombier notify(notifyf); 7503e12c5d1SDavid du Colombier msgfromnet(net); 751*219b2ee8SDavid du Colombier postnote(PNPROC, ttypid, "kill"); 7523e12c5d1SDavid du Colombier exits(0); 7533e12c5d1SDavid du Colombier default: 7543e12c5d1SDavid du Colombier notify(msgnotifyf); 7553e12c5d1SDavid du Colombier msgfromkbd(net); 756*219b2ee8SDavid du Colombier postnote(PNPROC, netpid, "kill"); 7573e12c5d1SDavid du Colombier exits(0); 7583e12c5d1SDavid du Colombier } 7593e12c5d1SDavid du Colombier } 7603e12c5d1SDavid du Colombier 7613e12c5d1SDavid du Colombier /* 7623e12c5d1SDavid du Colombier * convert certain interrupts into mesgld messages 7633e12c5d1SDavid du Colombier */ 7643e12c5d1SDavid du Colombier void 7653e12c5d1SDavid du Colombier msgnotifyf(void *a, char *msg) 7663e12c5d1SDavid du Colombier { 7673e12c5d1SDavid du Colombier USED(a); 7683e12c5d1SDavid du Colombier 7693e12c5d1SDavid du Colombier if(strstr(msg, "closed pipe")) 7703e12c5d1SDavid du Colombier noted(NCONT); 7713e12c5d1SDavid du Colombier if(strcmp(msg, "interrupt") == 0){ 7723e12c5d1SDavid du Colombier sendctl1(msgfd, M_SIGNAL, SIGINT); 7733e12c5d1SDavid du Colombier noted(NCONT); 7743e12c5d1SDavid du Colombier } 7753e12c5d1SDavid du Colombier if(strcmp(msg, "hangup") == 0){ 7763e12c5d1SDavid du Colombier sendctl(msgfd, M_HANGUP); 7773e12c5d1SDavid du Colombier noted(NCONT); 7783e12c5d1SDavid du Colombier } 7793e12c5d1SDavid du Colombier noted(NDFLT); 7803e12c5d1SDavid du Colombier } 7813e12c5d1SDavid du Colombier 7823e12c5d1SDavid du Colombier /* 7833e12c5d1SDavid du Colombier * send an empty mesgld message 7843e12c5d1SDavid du Colombier */ 7853e12c5d1SDavid du Colombier int 7863e12c5d1SDavid du Colombier sendctl(int net, int type) 7873e12c5d1SDavid du Colombier { 7883e12c5d1SDavid du Colombier Msg m; 7893e12c5d1SDavid du Colombier 7903e12c5d1SDavid du Colombier m.h.type = type; 7913e12c5d1SDavid du Colombier m.h.magic = MSGMAGIC; 7923e12c5d1SDavid du Colombier put2byte(m.h.size, 0); 7933e12c5d1SDavid du Colombier if(iwrite(net, &m, sizeof(struct mesg)) != sizeof(struct mesg)) 7943e12c5d1SDavid du Colombier return -1; 7953e12c5d1SDavid du Colombier return 0; 7963e12c5d1SDavid du Colombier } 7973e12c5d1SDavid du Colombier 7983e12c5d1SDavid du Colombier /* 7993e12c5d1SDavid du Colombier * send a one byte mesgld message 8003e12c5d1SDavid du Colombier */ 8013e12c5d1SDavid du Colombier int 8023e12c5d1SDavid du Colombier sendctl1(int net, int type, int parm) 8033e12c5d1SDavid du Colombier { 8043e12c5d1SDavid du Colombier Msg m; 8053e12c5d1SDavid du Colombier 8063e12c5d1SDavid du Colombier m.h.type = type; 8073e12c5d1SDavid du Colombier m.h.magic = MSGMAGIC; 8083e12c5d1SDavid du Colombier m.b[0] = parm; 8093e12c5d1SDavid du Colombier put2byte(m.h.size, 1); 8103e12c5d1SDavid du Colombier if(iwrite(net, &m, sizeof(struct mesg)+1) != sizeof(struct mesg)+1) 8113e12c5d1SDavid du Colombier return -1; 8123e12c5d1SDavid du Colombier return 0; 8133e12c5d1SDavid du Colombier } 8143e12c5d1SDavid du Colombier 8153e12c5d1SDavid du Colombier /* 8163e12c5d1SDavid du Colombier * read n bytes. return -1 if it fails, 0 otherwise. 8173e12c5d1SDavid du Colombier */ 8183e12c5d1SDavid du Colombier int 8193e12c5d1SDavid du Colombier readupto(int from, char *a, int len) 8203e12c5d1SDavid du Colombier { 8213e12c5d1SDavid du Colombier int n; 8223e12c5d1SDavid du Colombier 8233e12c5d1SDavid du Colombier while(len > 0){ 8243e12c5d1SDavid du Colombier n = iread(from, a, len); 8253e12c5d1SDavid du Colombier if(n < 0) 8263e12c5d1SDavid du Colombier return -1; 8273e12c5d1SDavid du Colombier a += n; 8283e12c5d1SDavid du Colombier len -= n; 8293e12c5d1SDavid du Colombier } 8303e12c5d1SDavid du Colombier return 0; 8313e12c5d1SDavid du Colombier } 8323e12c5d1SDavid du Colombier 8333e12c5d1SDavid du Colombier /* 8343e12c5d1SDavid du Colombier * Decode a mesgld message from the network 8353e12c5d1SDavid du Colombier */ 8363e12c5d1SDavid du Colombier void 8373e12c5d1SDavid du Colombier msgfromnet(int net) 8383e12c5d1SDavid du Colombier { 8393e12c5d1SDavid du Colombier ulong com; 8403e12c5d1SDavid du Colombier struct stioctl *io; 8413e12c5d1SDavid du Colombier struct sgttyb *sg; 8423e12c5d1SDavid du Colombier struct ttydevb *td; 8433e12c5d1SDavid du Colombier struct tchars *tc; 8443e12c5d1SDavid du Colombier int len; 8453e12c5d1SDavid du Colombier Msg m; 8463e12c5d1SDavid du Colombier 8473e12c5d1SDavid du Colombier for(;;){ 8483e12c5d1SDavid du Colombier /* get a complete mesgld message */ 8493e12c5d1SDavid du Colombier if(readupto(net, (char*)&m.h, sizeof(struct mesg)) < 0) 8503e12c5d1SDavid du Colombier break; 8513e12c5d1SDavid du Colombier if(m.h.magic != MSGMAGIC){ 8523e12c5d1SDavid du Colombier fprint(2, "con: bad message magic 0x%ux\n", m.h.magic); 8533e12c5d1SDavid du Colombier break; 8543e12c5d1SDavid du Colombier } 8553e12c5d1SDavid du Colombier len = get2byte(m.h.size); 856*219b2ee8SDavid du Colombier if(len > sizeof(m.b)){ 857*219b2ee8SDavid du Colombier len = sizeof(m.b); 858*219b2ee8SDavid du Colombier fprint(2, "con: mesgld message too long\n"); 859*219b2ee8SDavid du Colombier } 8603e12c5d1SDavid du Colombier if(len && readupto(net, m.b, len) < 0) 8613e12c5d1SDavid du Colombier break; 8623e12c5d1SDavid du Colombier 8633e12c5d1SDavid du Colombier /* decode */ 8643e12c5d1SDavid du Colombier switch(m.h.type){ 8653e12c5d1SDavid du Colombier case M_HANGUP: 8663e12c5d1SDavid du Colombier if(debug) 8673e12c5d1SDavid du Colombier fprint(2, "M_HANGUP\n"); 8683e12c5d1SDavid du Colombier return; 8693e12c5d1SDavid du Colombier case M_DATA: 8703e12c5d1SDavid du Colombier if(debug) 8713e12c5d1SDavid du Colombier fprint(2, "M_DATA %d bytes\n", len); 8723e12c5d1SDavid du Colombier if(iwrite(outfd, m.b, len) != len){ 8733e12c5d1SDavid du Colombier if(outfd == 1) 8743e12c5d1SDavid du Colombier return; 8753e12c5d1SDavid du Colombier outfd = 1; 8763e12c5d1SDavid du Colombier if(iwrite(outfd, m.b, len) != len) 8773e12c5d1SDavid du Colombier return; 8783e12c5d1SDavid du Colombier } 8793e12c5d1SDavid du Colombier continue; 8803e12c5d1SDavid du Colombier case M_IOCTL: 8813e12c5d1SDavid du Colombier break; 8823e12c5d1SDavid du Colombier default: 8833e12c5d1SDavid du Colombier /* ignore */ 8843e12c5d1SDavid du Colombier if(debug) 885*219b2ee8SDavid du Colombier fprint(2, "con: unknown message\n"); 8863e12c5d1SDavid du Colombier continue; 8873e12c5d1SDavid du Colombier } 8883e12c5d1SDavid du Colombier 8893e12c5d1SDavid du Colombier /* 8903e12c5d1SDavid du Colombier * answer an ioctl 8913e12c5d1SDavid du Colombier */ 8923e12c5d1SDavid du Colombier io = (struct stioctl *)m.b; 8933e12c5d1SDavid du Colombier com = get4byte(io->com); 8943e12c5d1SDavid du Colombier if(debug) 8953e12c5d1SDavid du Colombier fprint(2, "M_IOCTL %d\n", com); 8963e12c5d1SDavid du Colombier switch(com){ 8973e12c5d1SDavid du Colombier case FIOLOOKLD: 8983e12c5d1SDavid du Colombier put4byte(io->data, tty_ld); 8993e12c5d1SDavid du Colombier len = 0; 9003e12c5d1SDavid du Colombier break; 9013e12c5d1SDavid du Colombier case TIOCGETP: 9023e12c5d1SDavid du Colombier sg = (struct sgttyb *)io->data; 9033e12c5d1SDavid du Colombier sg->sg_ispeed = sg->sg_ospeed = B9600; 9043e12c5d1SDavid du Colombier sg->sg_erase = 0010; /* back space */ 9053e12c5d1SDavid du Colombier sg->sg_kill = 0025; /* CNTL U */ 9063e12c5d1SDavid du Colombier put2byte(sg->sg_flags, sgflags); 9073e12c5d1SDavid du Colombier len = sizeof(struct sgttyb); 9083e12c5d1SDavid du Colombier break; 9093e12c5d1SDavid du Colombier case TIOCSETN: 9103e12c5d1SDavid du Colombier case TIOCSETP: 9113e12c5d1SDavid du Colombier sg = (struct sgttyb *)io->data; 9123e12c5d1SDavid du Colombier sgflags = get2byte(sg->sg_flags); 9133e12c5d1SDavid du Colombier if((sgflags&(RAW|CBREAK)) || !(sgflags&ECHO)) 9143e12c5d1SDavid du Colombier rawon(); 9153e12c5d1SDavid du Colombier else 9163e12c5d1SDavid du Colombier rawoff(); 9173e12c5d1SDavid du Colombier len = 0; 9183e12c5d1SDavid du Colombier break; 9193e12c5d1SDavid du Colombier case TIOCGETC: 9203e12c5d1SDavid du Colombier tc = (struct tchars *)io->data; 9213e12c5d1SDavid du Colombier tc->t_intrc = 0177; 9223e12c5d1SDavid du Colombier tc->t_quitc = 0034; 9233e12c5d1SDavid du Colombier tc->t_startc = 0; 9243e12c5d1SDavid du Colombier tc->t_stopc = 0; 9253e12c5d1SDavid du Colombier tc->t_eofc = 0004; 9263e12c5d1SDavid du Colombier tc->t_brkc = 0; 9273e12c5d1SDavid du Colombier len = sizeof(struct tchars); 9283e12c5d1SDavid du Colombier break; 9293e12c5d1SDavid du Colombier case TIOCSETC: 9303e12c5d1SDavid du Colombier len = 0; 9313e12c5d1SDavid du Colombier break; 9323e12c5d1SDavid du Colombier case TIOCGDEV: 9333e12c5d1SDavid du Colombier td = (struct ttydevb *)io->data; 9343e12c5d1SDavid du Colombier td->ispeed = td->ospeed = B9600; 9353e12c5d1SDavid du Colombier put2byte(td->flags, 0); 9363e12c5d1SDavid du Colombier len = sizeof(struct ttydevb); 9373e12c5d1SDavid du Colombier break; 9383e12c5d1SDavid du Colombier case TIOCSDEV: 9393e12c5d1SDavid du Colombier len = 0; 9403e12c5d1SDavid du Colombier break; 9413e12c5d1SDavid du Colombier default: 9423e12c5d1SDavid du Colombier /* 9433e12c5d1SDavid du Colombier * unimplemented 9443e12c5d1SDavid du Colombier */ 9453e12c5d1SDavid du Colombier m.b[len] = 0; 9463e12c5d1SDavid du Colombier if(sendctl(net, M_IOCNAK) < 0) 9473e12c5d1SDavid du Colombier return; 9483e12c5d1SDavid du Colombier continue; 9493e12c5d1SDavid du Colombier } 9503e12c5d1SDavid du Colombier 9513e12c5d1SDavid du Colombier /* 9523e12c5d1SDavid du Colombier * acknowledge 9533e12c5d1SDavid du Colombier */ 9543e12c5d1SDavid du Colombier m.h.type = M_IOCACK; 9553e12c5d1SDavid du Colombier m.h.magic = MSGMAGIC; 9563e12c5d1SDavid du Colombier len += 4; 9573e12c5d1SDavid du Colombier put2byte(m.h.size, len); 9583e12c5d1SDavid du Colombier len += sizeof(struct mesg); 9593e12c5d1SDavid du Colombier if(iwrite(net, &m, len) != len) 9603e12c5d1SDavid du Colombier return; 9613e12c5d1SDavid du Colombier } 9623e12c5d1SDavid du Colombier } 9633e12c5d1SDavid du Colombier 9643e12c5d1SDavid du Colombier /* 9653e12c5d1SDavid du Colombier * Read the keyboard, convert to mesgld messages, and write it to the network. 9663e12c5d1SDavid du Colombier * '^\' gets us into the menu. 9673e12c5d1SDavid du Colombier */ 9683e12c5d1SDavid du Colombier void 9693e12c5d1SDavid du Colombier msgfromkbd(int net) 9703e12c5d1SDavid du Colombier { 9713e12c5d1SDavid du Colombier long n; 9723e12c5d1SDavid du Colombier char buf[MAXMSG]; 9733e12c5d1SDavid du Colombier 9743e12c5d1SDavid du Colombier for(;;){ 9753e12c5d1SDavid du Colombier n = iread(0, buf, sizeof(buf)); 9763e12c5d1SDavid du Colombier if(n < 0) 9773e12c5d1SDavid du Colombier return; 9783e12c5d1SDavid du Colombier if(n && memchr(buf, 0034, n)){ 9793e12c5d1SDavid du Colombier if(menu(net) < 0) 9803e12c5d1SDavid du Colombier return; 9813e12c5d1SDavid du Colombier } else { 9823e12c5d1SDavid du Colombier if(msgwrite(net, buf, n) != n) 9833e12c5d1SDavid du Colombier return; 9843e12c5d1SDavid du Colombier } 9853e12c5d1SDavid du Colombier } 9863e12c5d1SDavid du Colombier } 9873e12c5d1SDavid du Colombier 9883e12c5d1SDavid du Colombier int 9893e12c5d1SDavid du Colombier msgwrite(int fd, void *buf, int len) 9903e12c5d1SDavid du Colombier { 9913e12c5d1SDavid du Colombier Msg m; 9923e12c5d1SDavid du Colombier int n; 9933e12c5d1SDavid du Colombier 9943e12c5d1SDavid du Colombier n = len; 9953e12c5d1SDavid du Colombier memmove(m.b, buf, n); 9963e12c5d1SDavid du Colombier put2byte(m.h.size, n); 9973e12c5d1SDavid du Colombier m.h.magic = MSGMAGIC; 9983e12c5d1SDavid du Colombier m.h.type = M_DATA; 9993e12c5d1SDavid du Colombier n += sizeof(struct mesg); 10003e12c5d1SDavid du Colombier if(iwrite(fd, &m, n) != n) 10013e12c5d1SDavid du Colombier return -1; 10023e12c5d1SDavid du Colombier 10033e12c5d1SDavid du Colombier put2byte(m.h.size, 0); 10043e12c5d1SDavid du Colombier m.h.magic = MSGMAGIC; 10053e12c5d1SDavid du Colombier m.h.type = M_DELIM; 10063e12c5d1SDavid du Colombier n = sizeof(struct mesg); 10073e12c5d1SDavid du Colombier if(iwrite(fd, &m, n) != n) 10083e12c5d1SDavid du Colombier return -1; 10093e12c5d1SDavid du Colombier 10103e12c5d1SDavid du Colombier return len; 10113e12c5d1SDavid du Colombier } 10123e12c5d1SDavid du Colombier 1013