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 */ 185d459b5aSDavid du Colombier int crtonl; /* non-zero forces carriage returns to be converted to nls coming from net */ 19219b2ee8SDavid du Colombier int strip; /* strip off parity bits */ 209a747e4fSDavid du Colombier char firsterr[2*ERRMAX]; 219a747e4fSDavid du Colombier char transerr[2*ERRMAX]; 223e12c5d1SDavid du Colombier int limited; 233e12c5d1SDavid du Colombier char *remuser; 243e12c5d1SDavid du Colombier int verbose; 25219b2ee8SDavid du Colombier int baud; 267dd7cddfSDavid du Colombier int notkbd; 277dd7cddfSDavid du Colombier int nltocr; /* translate kbd nl to cr and vice versa */ 283e12c5d1SDavid du Colombier 293e12c5d1SDavid du Colombier typedef struct Msg Msg; 30219b2ee8SDavid du Colombier #define MAXMSG (2*8192) 313e12c5d1SDavid du Colombier 323e12c5d1SDavid du Colombier int dodial(char*, char*, char*); 333e12c5d1SDavid du Colombier void fromkbd(int); 343e12c5d1SDavid du Colombier void fromnet(int); 353e12c5d1SDavid du Colombier long iread(int, void*, int); 363e12c5d1SDavid du Colombier long iwrite(int, void*, int); 373e12c5d1SDavid du Colombier int menu(int); 383e12c5d1SDavid du Colombier void msgfromkbd(int); 393e12c5d1SDavid du Colombier void msgfromnet(int); 403e12c5d1SDavid du Colombier int msgwrite(int, void*, int); 413e12c5d1SDavid du Colombier void notifyf(void*, char*); 423e12c5d1SDavid du Colombier void pass(int, int, int); 433e12c5d1SDavid du Colombier void rawoff(void); 443e12c5d1SDavid du Colombier void rawon(void); 453e12c5d1SDavid du Colombier int readupto(int, char*, int); 463e12c5d1SDavid du Colombier int sendctl(int, int); 473e12c5d1SDavid du Colombier int sendctl1(int, int, int); 483e12c5d1SDavid du Colombier void stdcon(int); 493e12c5d1SDavid du Colombier char* system(int, char*); 503e12c5d1SDavid du Colombier void dosystem(int, char*); 513e12c5d1SDavid du Colombier int wasintr(void); 523e12c5d1SDavid du Colombier void punt(char*); 533e12c5d1SDavid du Colombier char* syserr(void); 54219b2ee8SDavid du Colombier void seterr(char*); 553e12c5d1SDavid du Colombier 563e12c5d1SDavid du Colombier /* protocols */ 573e12c5d1SDavid du Colombier void device(char*, char*); 583e12c5d1SDavid du Colombier void rlogin(char*, char*); 593e12c5d1SDavid du Colombier void simple(char*, char*); 603e12c5d1SDavid du Colombier 613e12c5d1SDavid du Colombier void 623e12c5d1SDavid du Colombier usage(void) 633e12c5d1SDavid du Colombier { 64*e40528acSDavid du Colombier punt("usage: con [-drCvsn] [-b baud] [-l [user]] [-c cmd] net!host[!service]"); 653e12c5d1SDavid du Colombier } 663e12c5d1SDavid du Colombier 673e12c5d1SDavid du Colombier void 683e12c5d1SDavid du Colombier main(int argc, char *argv[]) 693e12c5d1SDavid du Colombier { 703e12c5d1SDavid du Colombier char *dest; 713e12c5d1SDavid du Colombier char *cmd = 0; 723e12c5d1SDavid du Colombier 733e12c5d1SDavid du Colombier returns = 1; 743e12c5d1SDavid du Colombier ARGBEGIN{ 75219b2ee8SDavid du Colombier case 'b': 76*e40528acSDavid du Colombier baud = atoi(EARGF(usage())); 77219b2ee8SDavid du Colombier break; 783e12c5d1SDavid du Colombier case 'd': 793e12c5d1SDavid du Colombier debug = 1; 803e12c5d1SDavid du Colombier break; 813e12c5d1SDavid du Colombier case 'l': 823e12c5d1SDavid du Colombier limited = 1; 839a747e4fSDavid du Colombier if(argv[1] != nil && argv[1][0] != '-') 843e12c5d1SDavid du Colombier remuser = ARGF(); 853e12c5d1SDavid du Colombier break; 867dd7cddfSDavid du Colombier case 'n': 877dd7cddfSDavid du Colombier notkbd = 1; 887dd7cddfSDavid du Colombier break; 893e12c5d1SDavid du Colombier case 'r': 903e12c5d1SDavid du Colombier returns = 0; 913e12c5d1SDavid du Colombier break; 927dd7cddfSDavid du Colombier case 'R': 937dd7cddfSDavid du Colombier nltocr = 1; 947dd7cddfSDavid du Colombier break; 955d459b5aSDavid du Colombier case 'T': 965d459b5aSDavid du Colombier crtonl = 1; 975d459b5aSDavid du Colombier break; 983e12c5d1SDavid du Colombier case 'C': 993e12c5d1SDavid du Colombier cooked = 1; 1003e12c5d1SDavid du Colombier break; 1013e12c5d1SDavid du Colombier case 'c': 1023e12c5d1SDavid du Colombier cmd = ARGF(); 1033e12c5d1SDavid du Colombier break; 1043e12c5d1SDavid du Colombier case 'v': 1053e12c5d1SDavid du Colombier verbose = 1; 1063e12c5d1SDavid du Colombier break; 107219b2ee8SDavid du Colombier case 's': 108219b2ee8SDavid du Colombier strip = 1; 109219b2ee8SDavid du Colombier break; 1103e12c5d1SDavid du Colombier default: 1113e12c5d1SDavid du Colombier usage(); 1123e12c5d1SDavid du Colombier }ARGEND 1133e12c5d1SDavid du Colombier 1143e12c5d1SDavid du Colombier if(argc != 1){ 1153e12c5d1SDavid du Colombier if(remuser == 0) 1163e12c5d1SDavid du Colombier usage(); 1173e12c5d1SDavid du Colombier dest = remuser; 1183e12c5d1SDavid du Colombier remuser = 0; 1193e12c5d1SDavid du Colombier } else 1203e12c5d1SDavid du Colombier dest = argv[0]; 1217dd7cddfSDavid du Colombier if(*dest == '/' && strchr(dest, '!') == 0) 1223e12c5d1SDavid du Colombier device(dest, cmd); 1233e12c5d1SDavid du Colombier else if(limited){ 1243e12c5d1SDavid du Colombier simple(dest, cmd); /* doesn't return if dialout succeeds */ 1253e12c5d1SDavid du Colombier rlogin(dest, cmd); /* doesn't return if dialout succeeds */ 1263e12c5d1SDavid du Colombier } else { 127219b2ee8SDavid du Colombier rlogin(dest, cmd); /* doesn't return if dialout succeeds */ 1283e12c5d1SDavid du Colombier simple(dest, cmd); /* doesn't return if dialout succeeds */ 1293e12c5d1SDavid du Colombier } 1303e12c5d1SDavid du Colombier punt(firsterr); 1313e12c5d1SDavid du Colombier } 1323e12c5d1SDavid du Colombier 1333e12c5d1SDavid du Colombier /* 1343e12c5d1SDavid du Colombier * just dial and use as a byte stream with remote echo 1353e12c5d1SDavid du Colombier */ 1363e12c5d1SDavid du Colombier void 1373e12c5d1SDavid du Colombier simple(char *dest, char *cmd) 1383e12c5d1SDavid du Colombier { 1393e12c5d1SDavid du Colombier int net; 1403e12c5d1SDavid du Colombier 1413e12c5d1SDavid du Colombier net = dodial(dest, 0, 0); 1423e12c5d1SDavid du Colombier if(net < 0) 1433e12c5d1SDavid du Colombier return; 1443e12c5d1SDavid du Colombier 1453e12c5d1SDavid du Colombier if(cmd) 1463e12c5d1SDavid du Colombier dosystem(net, cmd); 1473e12c5d1SDavid du Colombier 1483e12c5d1SDavid du Colombier if(!cooked) 1493e12c5d1SDavid du Colombier rawon(); 1503e12c5d1SDavid du Colombier stdcon(net); 1513e12c5d1SDavid du Colombier exits(0); 1523e12c5d1SDavid du Colombier } 1533e12c5d1SDavid du Colombier 1543e12c5d1SDavid du Colombier /* 1553e12c5d1SDavid du Colombier * dial, do UCB authentication, use as a byte stream with local echo 1563e12c5d1SDavid du Colombier * 1573e12c5d1SDavid du Colombier * return if dial failed 1583e12c5d1SDavid du Colombier */ 1593e12c5d1SDavid du Colombier void 1603e12c5d1SDavid du Colombier rlogin(char *dest, char *cmd) 1613e12c5d1SDavid du Colombier { 1627dd7cddfSDavid du Colombier int net; 1639a747e4fSDavid du Colombier char buf[128]; 1643e12c5d1SDavid du Colombier char *p; 1653e12c5d1SDavid du Colombier char *localuser; 1663e12c5d1SDavid du Colombier 1673e12c5d1SDavid du Colombier /* only useful on TCP */ 168bd389b36SDavid du Colombier if(strchr(dest, '!') 169bd389b36SDavid du Colombier && (strncmp(dest, "tcp!", 4)!=0 && strncmp(dest, "net!", 4)!=0)) 1703e12c5d1SDavid du Colombier return; 1713e12c5d1SDavid du Colombier 1723e12c5d1SDavid du Colombier net = dodial(dest, "tcp", "login"); 1733e12c5d1SDavid du Colombier if(net < 0) 1743e12c5d1SDavid du Colombier return; 1753e12c5d1SDavid du Colombier 1763e12c5d1SDavid du Colombier /* 1773e12c5d1SDavid du Colombier * do UCB rlogin authentication 1783e12c5d1SDavid du Colombier */ 1797dd7cddfSDavid du Colombier localuser = getuser(); 1803e12c5d1SDavid du Colombier if(remuser == 0){ 1813e12c5d1SDavid du Colombier if(limited) 1823e12c5d1SDavid du Colombier remuser = ":"; 1833e12c5d1SDavid du Colombier else 1843e12c5d1SDavid du Colombier remuser = localuser; 1853e12c5d1SDavid du Colombier } 1863e12c5d1SDavid du Colombier p = getenv("TERM"); 1873e12c5d1SDavid du Colombier if(p == 0) 1883e12c5d1SDavid du Colombier p = "p9"; 1893e12c5d1SDavid du Colombier if(write(net, "", 1)<0 1903e12c5d1SDavid du Colombier || write(net, localuser, strlen(localuser)+1)<0 1913e12c5d1SDavid du Colombier || write(net, remuser, strlen(remuser)+1)<0 1923e12c5d1SDavid du Colombier || write(net, p, strlen(p)+1)<0){ 1933e12c5d1SDavid du Colombier close(net); 1943e12c5d1SDavid du Colombier punt("BSD authentication failed"); 1953e12c5d1SDavid du Colombier } 1963e12c5d1SDavid du Colombier if(read(net, buf, 1) != 1) 1973e12c5d1SDavid du Colombier punt("BSD authentication failed1"); 1983e12c5d1SDavid du Colombier if(buf[0] != 0){ 1993e12c5d1SDavid du Colombier fprint(2, "con: remote error: "); 2003e12c5d1SDavid du Colombier while(read(net, buf, 1) == 1){ 2013e12c5d1SDavid du Colombier write(2, buf, 1); 2023e12c5d1SDavid du Colombier if(buf[0] == '\n') 2033e12c5d1SDavid du Colombier break; 2043e12c5d1SDavid du Colombier } 2053e12c5d1SDavid du Colombier exits("read"); 2063e12c5d1SDavid du Colombier } 2073e12c5d1SDavid du Colombier 2083e12c5d1SDavid du Colombier if(cmd) 2093e12c5d1SDavid du Colombier dosystem(net, cmd); 2103e12c5d1SDavid du Colombier 2113e12c5d1SDavid du Colombier if(!cooked) 2123e12c5d1SDavid du Colombier rawon(); 2137dd7cddfSDavid du Colombier nltocr = 1; 2143e12c5d1SDavid du Colombier stdcon(net); 2153e12c5d1SDavid du Colombier exits(0); 2163e12c5d1SDavid du Colombier } 2173e12c5d1SDavid du Colombier 2183e12c5d1SDavid du Colombier /* 2193e12c5d1SDavid du Colombier * just open a device and use it as a connection 2203e12c5d1SDavid du Colombier */ 2213e12c5d1SDavid du Colombier void 2223e12c5d1SDavid du Colombier device(char *dest, char *cmd) 2233e12c5d1SDavid du Colombier { 2243e12c5d1SDavid du Colombier int net; 2259a747e4fSDavid du Colombier char cname[128]; 2263e12c5d1SDavid du Colombier 2273e12c5d1SDavid du Colombier net = open(dest, ORDWR); 2287dd7cddfSDavid du Colombier if(net < 0) { 2297dd7cddfSDavid du Colombier fprint(2, "con: cannot open %s: %r\n", dest); 2307dd7cddfSDavid du Colombier exits("open"); 2317dd7cddfSDavid du Colombier } 2329a747e4fSDavid du Colombier snprint(cname, sizeof cname, "%sctl", dest); 2333e12c5d1SDavid du Colombier ctl = open(cname, ORDWR); 2349a747e4fSDavid du Colombier if (baud > 0) { 2359a747e4fSDavid du Colombier if(ctl >= 0) 236219b2ee8SDavid du Colombier fprint(ctl, "b%d", baud); 2379a747e4fSDavid du Colombier else 2389a747e4fSDavid du Colombier fprint(2, "con: cannot open %s: %r\n", cname); 2399a747e4fSDavid du Colombier } 2403e12c5d1SDavid du Colombier 2413e12c5d1SDavid du Colombier if(cmd) 2423e12c5d1SDavid du Colombier dosystem(net, cmd); 2433e12c5d1SDavid du Colombier 2443e12c5d1SDavid du Colombier if(!cooked) 2453e12c5d1SDavid du Colombier rawon(); 2463e12c5d1SDavid du Colombier stdcon(net); 2473e12c5d1SDavid du Colombier exits(0); 2483e12c5d1SDavid du Colombier } 2493e12c5d1SDavid du Colombier 2503e12c5d1SDavid du Colombier /* 2513e12c5d1SDavid du Colombier * ignore interrupts 2523e12c5d1SDavid du Colombier */ 2533e12c5d1SDavid du Colombier void 2543e12c5d1SDavid du Colombier notifyf(void *a, char *msg) 2553e12c5d1SDavid du Colombier { 2563e12c5d1SDavid du Colombier USED(a); 2573e12c5d1SDavid du Colombier 258d3c05884SDavid du Colombier if(strstr(msg, "yankee")) 259d3c05884SDavid du Colombier noted(NDFLT); 2603e12c5d1SDavid du Colombier if(strstr(msg, "closed pipe") 2613e12c5d1SDavid du Colombier || strcmp(msg, "interrupt") == 0 2623e12c5d1SDavid du Colombier || strcmp(msg, "hangup") == 0) 2633e12c5d1SDavid du Colombier noted(NCONT); 2643e12c5d1SDavid du Colombier noted(NDFLT); 2653e12c5d1SDavid du Colombier } 2663e12c5d1SDavid du Colombier 2673e12c5d1SDavid du Colombier /* 2683e12c5d1SDavid du Colombier * turn keyboard raw mode on 2693e12c5d1SDavid du Colombier */ 2703e12c5d1SDavid du Colombier void 2713e12c5d1SDavid du Colombier rawon(void) 2723e12c5d1SDavid du Colombier { 2733e12c5d1SDavid du Colombier if(debug) 2743e12c5d1SDavid du Colombier fprint(2, "rawon\n"); 2753e12c5d1SDavid du Colombier if(raw) 2763e12c5d1SDavid du Colombier return; 2773e12c5d1SDavid du Colombier if(consctl < 0) 2783e12c5d1SDavid du Colombier consctl = open("/dev/consctl", OWRITE); 2793e12c5d1SDavid du Colombier if(consctl < 0){ 2809a747e4fSDavid du Colombier // fprint(2, "can't open consctl\n"); 2813e12c5d1SDavid du Colombier return; 2823e12c5d1SDavid du Colombier } 2833e12c5d1SDavid du Colombier write(consctl, "rawon", 5); 2843e12c5d1SDavid du Colombier raw = 1; 2853e12c5d1SDavid du Colombier } 2863e12c5d1SDavid du Colombier 2873e12c5d1SDavid du Colombier /* 2883e12c5d1SDavid du Colombier * turn keyboard raw mode off 2893e12c5d1SDavid du Colombier */ 2903e12c5d1SDavid du Colombier void 2913e12c5d1SDavid du Colombier rawoff(void) 2923e12c5d1SDavid du Colombier { 2933e12c5d1SDavid du Colombier if(debug) 2943e12c5d1SDavid du Colombier fprint(2, "rawoff\n"); 2953e12c5d1SDavid du Colombier if(raw == 0) 2963e12c5d1SDavid du Colombier return; 2973e12c5d1SDavid du Colombier if(consctl < 0) 2983e12c5d1SDavid du Colombier consctl = open("/dev/consctl", OWRITE); 2993e12c5d1SDavid du Colombier if(consctl < 0){ 3009a747e4fSDavid du Colombier // fprint(2, "can't open consctl\n"); 3013e12c5d1SDavid du Colombier return; 3023e12c5d1SDavid du Colombier } 3033e12c5d1SDavid du Colombier write(consctl, "rawoff", 6); 3043e12c5d1SDavid du Colombier raw = 0; 3053e12c5d1SDavid du Colombier } 3063e12c5d1SDavid du Colombier 3073e12c5d1SDavid du Colombier /* 3083e12c5d1SDavid du Colombier * control menu 3093e12c5d1SDavid du Colombier */ 3107dd7cddfSDavid du Colombier #define STDHELP "\t(b)reak, (q)uit, (i)nterrupt, toggle printing (r)eturns, (.)continue, (!cmd)\n" 3113e12c5d1SDavid du Colombier 3123e12c5d1SDavid du Colombier int 3133e12c5d1SDavid du Colombier menu(int net) 3143e12c5d1SDavid du Colombier { 3153e12c5d1SDavid du Colombier char buf[MAXMSG]; 3163e12c5d1SDavid du Colombier long n; 3173e12c5d1SDavid du Colombier int done; 3183e12c5d1SDavid du Colombier int wasraw = raw; 3193e12c5d1SDavid du Colombier 3203e12c5d1SDavid du Colombier if(wasraw) 3213e12c5d1SDavid du Colombier rawoff(); 3223e12c5d1SDavid du Colombier 3233e12c5d1SDavid du Colombier fprint(2, ">>> "); 3243e12c5d1SDavid du Colombier for(done = 0; !done; ){ 3253e12c5d1SDavid du Colombier n = read(0, buf, sizeof(buf)-1); 3263e12c5d1SDavid du Colombier if(n <= 0) 3273e12c5d1SDavid du Colombier return -1; 3283e12c5d1SDavid du Colombier buf[n] = 0; 3293e12c5d1SDavid du Colombier switch(buf[0]){ 3303e12c5d1SDavid du Colombier case '!': 3313e12c5d1SDavid du Colombier print(buf); 3323e12c5d1SDavid du Colombier system(net, buf+1); 3333e12c5d1SDavid du Colombier print("!\n"); 3343e12c5d1SDavid du Colombier done = 1; 3353e12c5d1SDavid du Colombier break; 3363e12c5d1SDavid du Colombier case '.': 3373e12c5d1SDavid du Colombier done = 1; 3383e12c5d1SDavid du Colombier break; 3393e12c5d1SDavid du Colombier case 'q': 3403e12c5d1SDavid du Colombier return -1; 3413e12c5d1SDavid du Colombier break; 3423e12c5d1SDavid du Colombier case 'i': 3433e12c5d1SDavid du Colombier buf[0] = 0x1c; 3443e12c5d1SDavid du Colombier if(msgfd <= 0) 3453e12c5d1SDavid du Colombier write(net, buf, 1); 3463e12c5d1SDavid du Colombier else 3473e12c5d1SDavid du Colombier sendctl1(msgfd, M_SIGNAL, SIGQUIT); 3483e12c5d1SDavid du Colombier done = 1; 3493e12c5d1SDavid du Colombier break; 3503e12c5d1SDavid du Colombier case 'b': 3513e12c5d1SDavid du Colombier if(msgfd >= 0) 3523e12c5d1SDavid du Colombier sendctl(msgfd, M_BREAK); 3533e12c5d1SDavid du Colombier else if(ctl >= 0) 354219b2ee8SDavid du Colombier write(ctl, "k", 1); 355219b2ee8SDavid du Colombier done = 1; 356219b2ee8SDavid du Colombier break; 357219b2ee8SDavid du Colombier case 'r': 358219b2ee8SDavid du Colombier returns = 1-returns; 3593e12c5d1SDavid du Colombier done = 1; 3603e12c5d1SDavid du Colombier break; 3613e12c5d1SDavid du Colombier default: 3623e12c5d1SDavid du Colombier fprint(2, STDHELP); 3633e12c5d1SDavid du Colombier break; 3643e12c5d1SDavid du Colombier } 3653e12c5d1SDavid du Colombier if(!done) 3663e12c5d1SDavid du Colombier fprint(2, ">>> "); 3673e12c5d1SDavid du Colombier } 3683e12c5d1SDavid du Colombier 3693e12c5d1SDavid du Colombier if(wasraw) 3703e12c5d1SDavid du Colombier rawon(); 3713e12c5d1SDavid du Colombier else 3723e12c5d1SDavid du Colombier rawoff(); 3733e12c5d1SDavid du Colombier return 0; 3743e12c5d1SDavid du Colombier } 3753e12c5d1SDavid du Colombier 3763e12c5d1SDavid du Colombier /* 3773e12c5d1SDavid du Colombier * the real work. two processes pass bytes back and forth between the 3783e12c5d1SDavid du Colombier * terminal and the network. 3793e12c5d1SDavid du Colombier */ 3803e12c5d1SDavid du Colombier void 3813e12c5d1SDavid du Colombier stdcon(int net) 3823e12c5d1SDavid du Colombier { 3833e12c5d1SDavid du Colombier int netpid; 3843e12c5d1SDavid du Colombier 3853e12c5d1SDavid du Colombier ttypid = getpid(); 3863e12c5d1SDavid du Colombier switch(netpid = rfork(RFMEM|RFPROC)){ 3873e12c5d1SDavid du Colombier case -1: 3883e12c5d1SDavid du Colombier perror("con"); 3893e12c5d1SDavid du Colombier exits("fork"); 3903e12c5d1SDavid du Colombier case 0: 3913e12c5d1SDavid du Colombier notify(notifyf); 3923e12c5d1SDavid du Colombier fromnet(net); 393d3c05884SDavid du Colombier postnote(PNPROC, ttypid, "die yankee dog"); 3943e12c5d1SDavid du Colombier exits(0); 3953e12c5d1SDavid du Colombier default: 3963e12c5d1SDavid du Colombier notify(notifyf); 3973e12c5d1SDavid du Colombier fromkbd(net); 3987dd7cddfSDavid du Colombier if(notkbd) 3997dd7cddfSDavid du Colombier for(;;)sleep(0); 400d3c05884SDavid du Colombier postnote(PNPROC, netpid, "die yankee dog"); 4013e12c5d1SDavid du Colombier exits(0); 4023e12c5d1SDavid du Colombier } 4033e12c5d1SDavid du Colombier } 4043e12c5d1SDavid du Colombier 4053e12c5d1SDavid du Colombier /* 4063e12c5d1SDavid du Colombier * Read the keyboard and write it to the network. '^\' gets us into 4073e12c5d1SDavid du Colombier * the menu. 4083e12c5d1SDavid du Colombier */ 4093e12c5d1SDavid du Colombier void 4103e12c5d1SDavid du Colombier fromkbd(int net) 4113e12c5d1SDavid du Colombier { 4123e12c5d1SDavid du Colombier long n; 4133e12c5d1SDavid du Colombier char buf[MAXMSG]; 4147dd7cddfSDavid du Colombier char *p, *ep; 4157dd7cddfSDavid du Colombier int eofs; 4163e12c5d1SDavid du Colombier 4177dd7cddfSDavid du Colombier eofs = 0; 4183e12c5d1SDavid du Colombier for(;;){ 4193e12c5d1SDavid du Colombier n = read(0, buf, sizeof(buf)); 4203e12c5d1SDavid du Colombier if(n < 0){ 4213e12c5d1SDavid du Colombier if(wasintr()){ 422d3c05884SDavid du Colombier if(!raw){ 4233e12c5d1SDavid du Colombier buf[0] = 0x7f; 4243e12c5d1SDavid du Colombier n = 1; 4253e12c5d1SDavid du Colombier } else 4263e12c5d1SDavid du Colombier continue; 4273e12c5d1SDavid du Colombier } else 4283e12c5d1SDavid du Colombier return; 4293e12c5d1SDavid du Colombier } 4307dd7cddfSDavid du Colombier if(n == 0){ 4317dd7cddfSDavid du Colombier if(++eofs > 32) 4327dd7cddfSDavid du Colombier return; 4337dd7cddfSDavid du Colombier } else 4347dd7cddfSDavid du Colombier eofs = 0; 4353e12c5d1SDavid du Colombier if(n && memchr(buf, 0x1c, n)){ 4363e12c5d1SDavid du Colombier if(menu(net) < 0) 4373e12c5d1SDavid du Colombier return; 4383e12c5d1SDavid du Colombier }else{ 439d3c05884SDavid du Colombier if(!raw && n==0){ 4403e12c5d1SDavid du Colombier buf[0] = 0x4; 4413e12c5d1SDavid du Colombier n = 1; 4423e12c5d1SDavid du Colombier } 4437dd7cddfSDavid du Colombier if(nltocr){ 4447dd7cddfSDavid du Colombier ep = buf+n; 4457dd7cddfSDavid du Colombier for(p = buf; p < ep; p++) 4467dd7cddfSDavid du Colombier switch(*p){ 4477dd7cddfSDavid du Colombier case '\r': 4487dd7cddfSDavid du Colombier *p = '\n'; 4497dd7cddfSDavid du Colombier break; 4507dd7cddfSDavid du Colombier case '\n': 4517dd7cddfSDavid du Colombier *p = '\r'; 4527dd7cddfSDavid du Colombier break; 4537dd7cddfSDavid du Colombier } 4547dd7cddfSDavid du Colombier } 4553e12c5d1SDavid du Colombier if(iwrite(net, buf, n) != n) 4563e12c5d1SDavid du Colombier return; 4573e12c5d1SDavid du Colombier } 4583e12c5d1SDavid du Colombier } 4593e12c5d1SDavid du Colombier } 4603e12c5d1SDavid du Colombier 4613e12c5d1SDavid du Colombier /* 4623e12c5d1SDavid du Colombier * Read from the network and write to the screen. 4633e12c5d1SDavid du Colombier * Filter out spurious carriage returns. 4643e12c5d1SDavid du Colombier */ 4653e12c5d1SDavid du Colombier void 4663e12c5d1SDavid du Colombier fromnet(int net) 4673e12c5d1SDavid du Colombier { 4683e12c5d1SDavid du Colombier long n; 4693e12c5d1SDavid du Colombier char buf[MAXMSG]; 4703e12c5d1SDavid du Colombier char *cp, *ep; 4713e12c5d1SDavid du Colombier 4723e12c5d1SDavid du Colombier for(;;){ 4733e12c5d1SDavid du Colombier n = iread(net, buf, sizeof(buf)); 4743e12c5d1SDavid du Colombier if(n < 0) 4753e12c5d1SDavid du Colombier return; 4763e12c5d1SDavid du Colombier if(n == 0) 4773e12c5d1SDavid du Colombier continue; 4783e12c5d1SDavid du Colombier 479219b2ee8SDavid du Colombier if (strip) 480219b2ee8SDavid du Colombier for (cp=buf; cp<buf+n; cp++) 481219b2ee8SDavid du Colombier *cp &= 0177; 482219b2ee8SDavid du Colombier 4835d459b5aSDavid du Colombier if(crtonl) { 4845d459b5aSDavid du Colombier /* convert cr's to nl's */ 4855d459b5aSDavid du Colombier for (cp = buf; cp < buf + n; cp++) 4865d459b5aSDavid du Colombier if (*cp == '\r') 4875d459b5aSDavid du Colombier *cp = '\n'; 4885d459b5aSDavid du Colombier } 4895d459b5aSDavid du Colombier else if(!returns){ 4903e12c5d1SDavid du Colombier /* convert cr's to null's */ 4913e12c5d1SDavid du Colombier cp = buf; 4923e12c5d1SDavid du Colombier ep = buf + n; 4933e12c5d1SDavid du Colombier while(cp < ep && (cp = memchr(cp, '\r', ep-cp))){ 4943e12c5d1SDavid du Colombier memmove(cp, cp+1, ep-cp-1); 4953e12c5d1SDavid du Colombier ep--; 4963e12c5d1SDavid du Colombier n--; 4973e12c5d1SDavid du Colombier } 4983e12c5d1SDavid du Colombier } 4993e12c5d1SDavid du Colombier 5003e12c5d1SDavid du Colombier if(n > 0 && iwrite(outfd, buf, n) != n){ 5013e12c5d1SDavid du Colombier if(outfd == 1) 5023e12c5d1SDavid du Colombier return; 5033e12c5d1SDavid du Colombier outfd = 1; 5043e12c5d1SDavid du Colombier if(iwrite(1, buf, n) != n) 5053e12c5d1SDavid du Colombier return; 5063e12c5d1SDavid du Colombier } 5073e12c5d1SDavid du Colombier } 5083e12c5d1SDavid du Colombier } 5093e12c5d1SDavid du Colombier 5103e12c5d1SDavid du Colombier /* 5113e12c5d1SDavid du Colombier * dial and return a data connection 5123e12c5d1SDavid du Colombier */ 5133e12c5d1SDavid du Colombier int 5143e12c5d1SDavid du Colombier dodial(char *dest, char *net, char *service) 5153e12c5d1SDavid du Colombier { 5169a747e4fSDavid du Colombier char name[128]; 5179a747e4fSDavid du Colombier char devdir[128]; 5183e12c5d1SDavid du Colombier int data; 5193e12c5d1SDavid du Colombier 5203e12c5d1SDavid du Colombier devdir[0] = 0; 5213e12c5d1SDavid du Colombier strcpy(name, netmkaddr(dest, net, service)); 522bd389b36SDavid du Colombier data = dial(name, 0, devdir, &ctl); 5233e12c5d1SDavid du Colombier if(data < 0){ 524219b2ee8SDavid du Colombier seterr(name); 5253e12c5d1SDavid du Colombier return -1; 5263e12c5d1SDavid du Colombier } 5273e12c5d1SDavid du Colombier fprint(2, "connected to %s on %s\n", name, devdir); 5283e12c5d1SDavid du Colombier return data; 5293e12c5d1SDavid du Colombier } 5303e12c5d1SDavid du Colombier 5313e12c5d1SDavid du Colombier void 5323e12c5d1SDavid du Colombier dosystem(int fd, char *cmd) 5333e12c5d1SDavid du Colombier { 5343e12c5d1SDavid du Colombier char *p; 5353e12c5d1SDavid du Colombier 5363e12c5d1SDavid du Colombier p = system(fd, cmd); 537fbdb243dSDavid du Colombier if(p){ 5387dd7cddfSDavid du Colombier print("con: %s terminated with %s\n", cmd, p); 5393e12c5d1SDavid du Colombier exits(p); 5403e12c5d1SDavid du Colombier } 5413e12c5d1SDavid du Colombier } 5423e12c5d1SDavid du Colombier 5433e12c5d1SDavid du Colombier /* 5443e12c5d1SDavid du Colombier * run a command with the network connection as standard IO 5453e12c5d1SDavid du Colombier */ 5463e12c5d1SDavid du Colombier char * 5473e12c5d1SDavid du Colombier system(int fd, char *cmd) 5483e12c5d1SDavid du Colombier { 5493e12c5d1SDavid du Colombier int pid; 5503e12c5d1SDavid du Colombier int p; 5513e12c5d1SDavid du Colombier static Waitmsg msg; 5523e12c5d1SDavid du Colombier int pfd[2]; 5533e12c5d1SDavid du Colombier int n; 5543e12c5d1SDavid du Colombier char buf[4096]; 5553e12c5d1SDavid du Colombier 5563e12c5d1SDavid du Colombier if(pipe(pfd) < 0){ 5573e12c5d1SDavid du Colombier perror("pipe"); 5583e12c5d1SDavid du Colombier return "pipe failed"; 5593e12c5d1SDavid du Colombier } 5603e12c5d1SDavid du Colombier outfd = pfd[1]; 5613e12c5d1SDavid du Colombier 562219b2ee8SDavid du Colombier close(consctl); 563219b2ee8SDavid du Colombier consctl = -1; 5643e12c5d1SDavid du Colombier switch(pid = fork()){ 5653e12c5d1SDavid du Colombier case -1: 5663e12c5d1SDavid du Colombier perror("con"); 5673e12c5d1SDavid du Colombier return "fork failed"; 5683e12c5d1SDavid du Colombier case 0: 5693e12c5d1SDavid du Colombier close(pfd[1]); 5703e12c5d1SDavid du Colombier dup(pfd[0], 0); 5713ff48bf5SDavid du Colombier dup(fd, 1); 5723e12c5d1SDavid du Colombier close(ctl); 5733e12c5d1SDavid du Colombier close(fd); 5743e12c5d1SDavid du Colombier close(pfd[0]); 5753e12c5d1SDavid du Colombier if(*cmd) 5763e12c5d1SDavid du Colombier execl("/bin/rc", "rc", "-c", cmd, 0); 5773e12c5d1SDavid du Colombier else 5783e12c5d1SDavid du Colombier execl("/bin/rc", "rc", 0); 5793e12c5d1SDavid du Colombier perror("con"); 5803e12c5d1SDavid du Colombier exits("exec"); 5813e12c5d1SDavid du Colombier break; 5823e12c5d1SDavid du Colombier default: 5833e12c5d1SDavid du Colombier close(pfd[0]); 5843e12c5d1SDavid du Colombier while((n = read(pfd[1], buf, sizeof(buf))) > 0){ 5853e12c5d1SDavid du Colombier if(msgfd >= 0){ 5863e12c5d1SDavid du Colombier if(msgwrite(fd, buf, n) != n) 5873e12c5d1SDavid du Colombier break; 5883e12c5d1SDavid du Colombier } else { 5893e12c5d1SDavid du Colombier if(write(fd, buf, n) != n) 5903e12c5d1SDavid du Colombier break; 5913e12c5d1SDavid du Colombier } 5923e12c5d1SDavid du Colombier } 5939a747e4fSDavid du Colombier p = waitpid(); 5943e12c5d1SDavid du Colombier outfd = 1; 5953e12c5d1SDavid du Colombier close(pfd[1]); 596219b2ee8SDavid du Colombier if(p < 0 || p != pid) 597219b2ee8SDavid du Colombier return "lost child"; 5983e12c5d1SDavid du Colombier break; 5993e12c5d1SDavid du Colombier } 600219b2ee8SDavid du Colombier return msg.msg; 6013e12c5d1SDavid du Colombier } 6023e12c5d1SDavid du Colombier 6033e12c5d1SDavid du Colombier int 6043e12c5d1SDavid du Colombier wasintr(void) 6053e12c5d1SDavid du Colombier { 6063e12c5d1SDavid du Colombier return strcmp(syserr(), "interrupted") == 0; 6073e12c5d1SDavid du Colombier } 6083e12c5d1SDavid du Colombier 6093e12c5d1SDavid du Colombier void 6103e12c5d1SDavid du Colombier punt(char *msg) 6113e12c5d1SDavid du Colombier { 6123e12c5d1SDavid du Colombier if(*msg == 0) 6133e12c5d1SDavid du Colombier msg = transerr; 6143e12c5d1SDavid du Colombier fprint(2, "con: %s\n", msg); 6153e12c5d1SDavid du Colombier exits(msg); 6163e12c5d1SDavid du Colombier } 6173e12c5d1SDavid du Colombier 6183e12c5d1SDavid du Colombier char* 6193e12c5d1SDavid du Colombier syserr(void) 6203e12c5d1SDavid du Colombier { 6219a747e4fSDavid du Colombier static char err[ERRMAX]; 6229a747e4fSDavid du Colombier errstr(err, sizeof err); 6233e12c5d1SDavid du Colombier return err; 6243e12c5d1SDavid du Colombier } 6253e12c5d1SDavid du Colombier 6263e12c5d1SDavid du Colombier void 627219b2ee8SDavid du Colombier seterr(char *addr) 6283e12c5d1SDavid du Colombier { 6293e12c5d1SDavid du Colombier char *se = syserr(); 6303e12c5d1SDavid du Colombier 6313e12c5d1SDavid du Colombier if(verbose) 632219b2ee8SDavid du Colombier fprint(2, "'%s' calling %s\n", se, addr); 6333e12c5d1SDavid du Colombier if(firsterr[0] && (strstr(se, "translate") || 6343e12c5d1SDavid du Colombier strstr(se, "file does not exist") || 6353e12c5d1SDavid du Colombier strstr(se, "unknown address") || 6363e12c5d1SDavid du Colombier strstr(se, "directory entry not found"))) 6373e12c5d1SDavid du Colombier return; 6383e12c5d1SDavid du Colombier strcpy(firsterr, se); 6393e12c5d1SDavid du Colombier } 6403e12c5d1SDavid du Colombier 6413e12c5d1SDavid du Colombier 6423e12c5d1SDavid du Colombier long 6433e12c5d1SDavid du Colombier iread(int f, void *a, int n) 6443e12c5d1SDavid du Colombier { 6453e12c5d1SDavid du Colombier long m; 6463e12c5d1SDavid du Colombier 6473e12c5d1SDavid du Colombier for(;;){ 6483e12c5d1SDavid du Colombier m = read(f, a, n); 6493e12c5d1SDavid du Colombier if(m >= 0 || !wasintr()) 6503e12c5d1SDavid du Colombier break; 6513e12c5d1SDavid du Colombier } 6523e12c5d1SDavid du Colombier return m; 6533e12c5d1SDavid du Colombier } 6543e12c5d1SDavid du Colombier 6553e12c5d1SDavid du Colombier long 6563e12c5d1SDavid du Colombier iwrite(int f, void *a, int n) 6573e12c5d1SDavid du Colombier { 6583e12c5d1SDavid du Colombier long m; 6593e12c5d1SDavid du Colombier 6603e12c5d1SDavid du Colombier m = write(f, a, n); 6613e12c5d1SDavid du Colombier if(m < 0 && wasintr()) 6623e12c5d1SDavid du Colombier return n; 6633e12c5d1SDavid du Colombier return m; 6643e12c5d1SDavid du Colombier } 6653e12c5d1SDavid du Colombier 6663e12c5d1SDavid du Colombier /* 6673e12c5d1SDavid du Colombier * The rest is to support the V10 mesgld protocol. 6683e12c5d1SDavid du Colombier */ 6693e12c5d1SDavid du Colombier 6703e12c5d1SDavid du Colombier /* 6713e12c5d1SDavid du Colombier * network orderings 6723e12c5d1SDavid du Colombier */ 6733e12c5d1SDavid du Colombier #define get2byte(p) ((p)[0] + ((p)[1]<<8)) 6743e12c5d1SDavid du Colombier #define get4byte(p) ((p)[0] + ((p)[1]<<8) + ((p)[2]<<16) + ((p)[3]<<24)) 6753e12c5d1SDavid du Colombier #define put2byte(p, i) ((p)[0]=(i), (p)[1]=(i)>>8) 6763e12c5d1SDavid du Colombier #define put4byte(p, i) ((p)[0]=(i), (p)[1]=(i)>>8, (p)[2]=(i)>>16, (p)[3]=(i)>>24) 6773e12c5d1SDavid du Colombier 6783e12c5d1SDavid du Colombier /* 6793e12c5d1SDavid du Colombier * tty parameters 6803e12c5d1SDavid du Colombier */ 6813e12c5d1SDavid du Colombier int sgflags = ECHO; 6823e12c5d1SDavid du Colombier 6833e12c5d1SDavid du Colombier /* 6843e12c5d1SDavid du Colombier * a mesgld message 6853e12c5d1SDavid du Colombier */ 6863e12c5d1SDavid du Colombier struct Msg { 6873e12c5d1SDavid du Colombier struct mesg h; 6883e12c5d1SDavid du Colombier char b[MAXMSG]; 6893e12c5d1SDavid du Colombier }; 6903e12c5d1SDavid du Colombier 6913e12c5d1SDavid du Colombier 6923e12c5d1SDavid du Colombier /* 6933e12c5d1SDavid du Colombier * send an empty mesgld message 6943e12c5d1SDavid du Colombier */ 6953e12c5d1SDavid du Colombier int 6963e12c5d1SDavid du Colombier sendctl(int net, int type) 6973e12c5d1SDavid du Colombier { 6983e12c5d1SDavid du Colombier Msg m; 6993e12c5d1SDavid du Colombier 7003e12c5d1SDavid du Colombier m.h.type = type; 7013e12c5d1SDavid du Colombier m.h.magic = MSGMAGIC; 7023e12c5d1SDavid du Colombier put2byte(m.h.size, 0); 7033e12c5d1SDavid du Colombier if(iwrite(net, &m, sizeof(struct mesg)) != sizeof(struct mesg)) 7043e12c5d1SDavid du Colombier return -1; 7053e12c5d1SDavid du Colombier return 0; 7063e12c5d1SDavid du Colombier } 7073e12c5d1SDavid du Colombier 7083e12c5d1SDavid du Colombier /* 7093e12c5d1SDavid du Colombier * send a one byte mesgld message 7103e12c5d1SDavid du Colombier */ 7113e12c5d1SDavid du Colombier int 7123e12c5d1SDavid du Colombier sendctl1(int net, int type, int parm) 7133e12c5d1SDavid du Colombier { 7143e12c5d1SDavid du Colombier Msg m; 7153e12c5d1SDavid du Colombier 7163e12c5d1SDavid du Colombier m.h.type = type; 7173e12c5d1SDavid du Colombier m.h.magic = MSGMAGIC; 7183e12c5d1SDavid du Colombier m.b[0] = parm; 7193e12c5d1SDavid du Colombier put2byte(m.h.size, 1); 7203e12c5d1SDavid du Colombier if(iwrite(net, &m, sizeof(struct mesg)+1) != sizeof(struct mesg)+1) 7213e12c5d1SDavid du Colombier return -1; 7223e12c5d1SDavid du Colombier return 0; 7233e12c5d1SDavid du Colombier } 7243e12c5d1SDavid du Colombier 7253e12c5d1SDavid du Colombier /* 7263e12c5d1SDavid du Colombier * read n bytes. return -1 if it fails, 0 otherwise. 7273e12c5d1SDavid du Colombier */ 7283e12c5d1SDavid du Colombier int 7293e12c5d1SDavid du Colombier readupto(int from, char *a, int len) 7303e12c5d1SDavid du Colombier { 7313e12c5d1SDavid du Colombier int n; 7323e12c5d1SDavid du Colombier 7333e12c5d1SDavid du Colombier while(len > 0){ 7343e12c5d1SDavid du Colombier n = iread(from, a, len); 7353e12c5d1SDavid du Colombier if(n < 0) 7363e12c5d1SDavid du Colombier return -1; 7373e12c5d1SDavid du Colombier a += n; 7383e12c5d1SDavid du Colombier len -= n; 7393e12c5d1SDavid du Colombier } 7403e12c5d1SDavid du Colombier return 0; 7413e12c5d1SDavid du Colombier } 7423e12c5d1SDavid du Colombier 7433e12c5d1SDavid du Colombier /* 7443e12c5d1SDavid du Colombier * Decode a mesgld message from the network 7453e12c5d1SDavid du Colombier */ 7463e12c5d1SDavid du Colombier void 7473e12c5d1SDavid du Colombier msgfromnet(int net) 7483e12c5d1SDavid du Colombier { 7493e12c5d1SDavid du Colombier ulong com; 7503e12c5d1SDavid du Colombier struct stioctl *io; 7513e12c5d1SDavid du Colombier struct sgttyb *sg; 7523e12c5d1SDavid du Colombier struct ttydevb *td; 7533e12c5d1SDavid du Colombier struct tchars *tc; 7543e12c5d1SDavid du Colombier int len; 7553e12c5d1SDavid du Colombier Msg m; 7563e12c5d1SDavid du Colombier 7573e12c5d1SDavid du Colombier for(;;){ 7583e12c5d1SDavid du Colombier /* get a complete mesgld message */ 7593e12c5d1SDavid du Colombier if(readupto(net, (char*)&m.h, sizeof(struct mesg)) < 0) 7603e12c5d1SDavid du Colombier break; 7613e12c5d1SDavid du Colombier if(m.h.magic != MSGMAGIC){ 7623e12c5d1SDavid du Colombier fprint(2, "con: bad message magic 0x%ux\n", m.h.magic); 7633e12c5d1SDavid du Colombier break; 7643e12c5d1SDavid du Colombier } 7653e12c5d1SDavid du Colombier len = get2byte(m.h.size); 766219b2ee8SDavid du Colombier if(len > sizeof(m.b)){ 767219b2ee8SDavid du Colombier len = sizeof(m.b); 768219b2ee8SDavid du Colombier fprint(2, "con: mesgld message too long\n"); 769219b2ee8SDavid du Colombier } 7703e12c5d1SDavid du Colombier if(len && readupto(net, m.b, len) < 0) 7713e12c5d1SDavid du Colombier break; 7723e12c5d1SDavid du Colombier 7733e12c5d1SDavid du Colombier /* decode */ 7743e12c5d1SDavid du Colombier switch(m.h.type){ 7753e12c5d1SDavid du Colombier case M_HANGUP: 7763e12c5d1SDavid du Colombier if(debug) 7773e12c5d1SDavid du Colombier fprint(2, "M_HANGUP\n"); 7783e12c5d1SDavid du Colombier return; 7793e12c5d1SDavid du Colombier case M_DATA: 7803e12c5d1SDavid du Colombier if(debug) 7813e12c5d1SDavid du Colombier fprint(2, "M_DATA %d bytes\n", len); 7823e12c5d1SDavid du Colombier if(iwrite(outfd, m.b, len) != len){ 7833e12c5d1SDavid du Colombier if(outfd == 1) 7843e12c5d1SDavid du Colombier return; 7853e12c5d1SDavid du Colombier outfd = 1; 7863e12c5d1SDavid du Colombier if(iwrite(outfd, m.b, len) != len) 7873e12c5d1SDavid du Colombier return; 7883e12c5d1SDavid du Colombier } 7893e12c5d1SDavid du Colombier continue; 7903e12c5d1SDavid du Colombier case M_IOCTL: 7913e12c5d1SDavid du Colombier break; 7923e12c5d1SDavid du Colombier default: 7933e12c5d1SDavid du Colombier /* ignore */ 7943e12c5d1SDavid du Colombier if(debug) 795219b2ee8SDavid du Colombier fprint(2, "con: unknown message\n"); 7963e12c5d1SDavid du Colombier continue; 7973e12c5d1SDavid du Colombier } 7983e12c5d1SDavid du Colombier 7993e12c5d1SDavid du Colombier /* 8003e12c5d1SDavid du Colombier * answer an ioctl 8013e12c5d1SDavid du Colombier */ 8023e12c5d1SDavid du Colombier io = (struct stioctl *)m.b; 8033e12c5d1SDavid du Colombier com = get4byte(io->com); 8043e12c5d1SDavid du Colombier if(debug) 8057dd7cddfSDavid du Colombier fprint(2, "M_IOCTL %lud\n", com); 8063e12c5d1SDavid du Colombier switch(com){ 8073e12c5d1SDavid du Colombier case FIOLOOKLD: 8083e12c5d1SDavid du Colombier put4byte(io->data, tty_ld); 8093e12c5d1SDavid du Colombier len = 0; 8103e12c5d1SDavid du Colombier break; 8113e12c5d1SDavid du Colombier case TIOCGETP: 8123e12c5d1SDavid du Colombier sg = (struct sgttyb *)io->data; 8133e12c5d1SDavid du Colombier sg->sg_ispeed = sg->sg_ospeed = B9600; 8143e12c5d1SDavid du Colombier sg->sg_erase = 0010; /* back space */ 8153e12c5d1SDavid du Colombier sg->sg_kill = 0025; /* CNTL U */ 8163e12c5d1SDavid du Colombier put2byte(sg->sg_flags, sgflags); 8173e12c5d1SDavid du Colombier len = sizeof(struct sgttyb); 8183e12c5d1SDavid du Colombier break; 8193e12c5d1SDavid du Colombier case TIOCSETN: 8203e12c5d1SDavid du Colombier case TIOCSETP: 8213e12c5d1SDavid du Colombier sg = (struct sgttyb *)io->data; 8223e12c5d1SDavid du Colombier sgflags = get2byte(sg->sg_flags); 8233e12c5d1SDavid du Colombier if((sgflags&(RAW|CBREAK)) || !(sgflags&ECHO)) 8243e12c5d1SDavid du Colombier rawon(); 8253e12c5d1SDavid du Colombier else 8263e12c5d1SDavid du Colombier rawoff(); 8273e12c5d1SDavid du Colombier len = 0; 8283e12c5d1SDavid du Colombier break; 8293e12c5d1SDavid du Colombier case TIOCGETC: 8303e12c5d1SDavid du Colombier tc = (struct tchars *)io->data; 8313e12c5d1SDavid du Colombier tc->t_intrc = 0177; 8323e12c5d1SDavid du Colombier tc->t_quitc = 0034; 8333e12c5d1SDavid du Colombier tc->t_startc = 0; 8343e12c5d1SDavid du Colombier tc->t_stopc = 0; 8353e12c5d1SDavid du Colombier tc->t_eofc = 0004; 8363e12c5d1SDavid du Colombier tc->t_brkc = 0; 8373e12c5d1SDavid du Colombier len = sizeof(struct tchars); 8383e12c5d1SDavid du Colombier break; 8393e12c5d1SDavid du Colombier case TIOCSETC: 8403e12c5d1SDavid du Colombier len = 0; 8413e12c5d1SDavid du Colombier break; 8423e12c5d1SDavid du Colombier case TIOCGDEV: 8433e12c5d1SDavid du Colombier td = (struct ttydevb *)io->data; 8443e12c5d1SDavid du Colombier td->ispeed = td->ospeed = B9600; 8453e12c5d1SDavid du Colombier put2byte(td->flags, 0); 8463e12c5d1SDavid du Colombier len = sizeof(struct ttydevb); 8473e12c5d1SDavid du Colombier break; 8483e12c5d1SDavid du Colombier case TIOCSDEV: 8493e12c5d1SDavid du Colombier len = 0; 8503e12c5d1SDavid du Colombier break; 8513e12c5d1SDavid du Colombier default: 8523e12c5d1SDavid du Colombier /* 8533e12c5d1SDavid du Colombier * unimplemented 8543e12c5d1SDavid du Colombier */ 8553e12c5d1SDavid du Colombier m.b[len] = 0; 8563e12c5d1SDavid du Colombier if(sendctl(net, M_IOCNAK) < 0) 8573e12c5d1SDavid du Colombier return; 8583e12c5d1SDavid du Colombier continue; 8593e12c5d1SDavid du Colombier } 8603e12c5d1SDavid du Colombier 8613e12c5d1SDavid du Colombier /* 8623e12c5d1SDavid du Colombier * acknowledge 8633e12c5d1SDavid du Colombier */ 8643e12c5d1SDavid du Colombier m.h.type = M_IOCACK; 8653e12c5d1SDavid du Colombier m.h.magic = MSGMAGIC; 8663e12c5d1SDavid du Colombier len += 4; 8673e12c5d1SDavid du Colombier put2byte(m.h.size, len); 8683e12c5d1SDavid du Colombier len += sizeof(struct mesg); 8693e12c5d1SDavid du Colombier if(iwrite(net, &m, len) != len) 8703e12c5d1SDavid du Colombier return; 8713e12c5d1SDavid du Colombier } 8723e12c5d1SDavid du Colombier } 8733e12c5d1SDavid du Colombier 8743e12c5d1SDavid du Colombier /* 8753e12c5d1SDavid du Colombier * Read the keyboard, convert to mesgld messages, and write it to the network. 8763e12c5d1SDavid du Colombier * '^\' gets us into the menu. 8773e12c5d1SDavid du Colombier */ 8783e12c5d1SDavid du Colombier void 8793e12c5d1SDavid du Colombier msgfromkbd(int net) 8803e12c5d1SDavid du Colombier { 8813e12c5d1SDavid du Colombier long n; 8823e12c5d1SDavid du Colombier char buf[MAXMSG]; 8833e12c5d1SDavid du Colombier 8843e12c5d1SDavid du Colombier for(;;){ 8853e12c5d1SDavid du Colombier n = iread(0, buf, sizeof(buf)); 8863e12c5d1SDavid du Colombier if(n < 0) 8873e12c5d1SDavid du Colombier return; 8883e12c5d1SDavid du Colombier if(n && memchr(buf, 0034, n)){ 8893e12c5d1SDavid du Colombier if(menu(net) < 0) 8903e12c5d1SDavid du Colombier return; 8913e12c5d1SDavid du Colombier } else { 8923e12c5d1SDavid du Colombier if(msgwrite(net, buf, n) != n) 8933e12c5d1SDavid du Colombier return; 8943e12c5d1SDavid du Colombier } 8953e12c5d1SDavid du Colombier } 8963e12c5d1SDavid du Colombier } 8973e12c5d1SDavid du Colombier 8983e12c5d1SDavid du Colombier int 8993e12c5d1SDavid du Colombier msgwrite(int fd, void *buf, int len) 9003e12c5d1SDavid du Colombier { 9013e12c5d1SDavid du Colombier Msg m; 9023e12c5d1SDavid du Colombier int n; 9033e12c5d1SDavid du Colombier 9043e12c5d1SDavid du Colombier n = len; 9053e12c5d1SDavid du Colombier memmove(m.b, buf, n); 9063e12c5d1SDavid du Colombier put2byte(m.h.size, n); 9073e12c5d1SDavid du Colombier m.h.magic = MSGMAGIC; 9083e12c5d1SDavid du Colombier m.h.type = M_DATA; 9093e12c5d1SDavid du Colombier n += sizeof(struct mesg); 9103e12c5d1SDavid du Colombier if(iwrite(fd, &m, n) != n) 9113e12c5d1SDavid du Colombier return -1; 9123e12c5d1SDavid du Colombier 9133e12c5d1SDavid du Colombier put2byte(m.h.size, 0); 9143e12c5d1SDavid du Colombier m.h.magic = MSGMAGIC; 9153e12c5d1SDavid du Colombier m.h.type = M_DELIM; 9163e12c5d1SDavid du Colombier n = sizeof(struct mesg); 9173e12c5d1SDavid du Colombier if(iwrite(fd, &m, n) != n) 9183e12c5d1SDavid du Colombier return -1; 9193e12c5d1SDavid du Colombier 9203e12c5d1SDavid du Colombier return len; 9213e12c5d1SDavid du Colombier } 9223e12c5d1SDavid du Colombier 923