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; 23*6dc4800dSDavid du Colombier char *remuser; /* for BSD rlogin authentication */ 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 { 6422a127bbSDavid du Colombier punt("usage: con [-CdnrRsTv] [-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': 76e40528acSDavid 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 case 'i': 3423e12c5d1SDavid du Colombier buf[0] = 0x1c; 3433e12c5d1SDavid du Colombier if(msgfd <= 0) 3443e12c5d1SDavid du Colombier write(net, buf, 1); 3453e12c5d1SDavid du Colombier else 3463e12c5d1SDavid du Colombier sendctl1(msgfd, M_SIGNAL, SIGQUIT); 3473e12c5d1SDavid du Colombier done = 1; 3483e12c5d1SDavid du Colombier break; 3493e12c5d1SDavid du Colombier case 'b': 3503e12c5d1SDavid du Colombier if(msgfd >= 0) 3513e12c5d1SDavid du Colombier sendctl(msgfd, M_BREAK); 3523e12c5d1SDavid du Colombier else if(ctl >= 0) 353219b2ee8SDavid du Colombier write(ctl, "k", 1); 354219b2ee8SDavid du Colombier done = 1; 355219b2ee8SDavid du Colombier break; 356219b2ee8SDavid du Colombier case 'r': 357219b2ee8SDavid du Colombier returns = 1-returns; 3583e12c5d1SDavid du Colombier done = 1; 3593e12c5d1SDavid du Colombier break; 3603e12c5d1SDavid du Colombier default: 3613e12c5d1SDavid du Colombier fprint(2, STDHELP); 3623e12c5d1SDavid du Colombier break; 3633e12c5d1SDavid du Colombier } 3643e12c5d1SDavid du Colombier if(!done) 3653e12c5d1SDavid du Colombier fprint(2, ">>> "); 3663e12c5d1SDavid du Colombier } 3673e12c5d1SDavid du Colombier 3683e12c5d1SDavid du Colombier if(wasraw) 3693e12c5d1SDavid du Colombier rawon(); 3703e12c5d1SDavid du Colombier else 3713e12c5d1SDavid du Colombier rawoff(); 3723e12c5d1SDavid du Colombier return 0; 3733e12c5d1SDavid du Colombier } 3743e12c5d1SDavid du Colombier 3753e12c5d1SDavid du Colombier /* 3763e12c5d1SDavid du Colombier * the real work. two processes pass bytes back and forth between the 3773e12c5d1SDavid du Colombier * terminal and the network. 3783e12c5d1SDavid du Colombier */ 3793e12c5d1SDavid du Colombier void 3803e12c5d1SDavid du Colombier stdcon(int net) 3813e12c5d1SDavid du Colombier { 3823e12c5d1SDavid du Colombier int netpid; 3833e12c5d1SDavid du Colombier 3843e12c5d1SDavid du Colombier ttypid = getpid(); 3853e12c5d1SDavid du Colombier switch(netpid = rfork(RFMEM|RFPROC)){ 3863e12c5d1SDavid du Colombier case -1: 3873e12c5d1SDavid du Colombier perror("con"); 3883e12c5d1SDavid du Colombier exits("fork"); 3893e12c5d1SDavid du Colombier case 0: 3903e12c5d1SDavid du Colombier notify(notifyf); 3913e12c5d1SDavid du Colombier fromnet(net); 392d3c05884SDavid du Colombier postnote(PNPROC, ttypid, "die yankee dog"); 3933e12c5d1SDavid du Colombier exits(0); 3943e12c5d1SDavid du Colombier default: 3953e12c5d1SDavid du Colombier notify(notifyf); 3963e12c5d1SDavid du Colombier fromkbd(net); 3977dd7cddfSDavid du Colombier if(notkbd) 3987dd7cddfSDavid du Colombier for(;;)sleep(0); 399d3c05884SDavid du Colombier postnote(PNPROC, netpid, "die yankee dog"); 4003e12c5d1SDavid du Colombier exits(0); 4013e12c5d1SDavid du Colombier } 4023e12c5d1SDavid du Colombier } 4033e12c5d1SDavid du Colombier 4043e12c5d1SDavid du Colombier /* 4053e12c5d1SDavid du Colombier * Read the keyboard and write it to the network. '^\' gets us into 4063e12c5d1SDavid du Colombier * the menu. 4073e12c5d1SDavid du Colombier */ 4083e12c5d1SDavid du Colombier void 4093e12c5d1SDavid du Colombier fromkbd(int net) 4103e12c5d1SDavid du Colombier { 4113e12c5d1SDavid du Colombier long n; 4123e12c5d1SDavid du Colombier char buf[MAXMSG]; 4137dd7cddfSDavid du Colombier char *p, *ep; 4147dd7cddfSDavid du Colombier int eofs; 4153e12c5d1SDavid du Colombier 4167dd7cddfSDavid du Colombier eofs = 0; 4173e12c5d1SDavid du Colombier for(;;){ 4183e12c5d1SDavid du Colombier n = read(0, buf, sizeof(buf)); 4193e12c5d1SDavid du Colombier if(n < 0){ 4203e12c5d1SDavid du Colombier if(wasintr()){ 421d3c05884SDavid du Colombier if(!raw){ 4223e12c5d1SDavid du Colombier buf[0] = 0x7f; 4233e12c5d1SDavid du Colombier n = 1; 4243e12c5d1SDavid du Colombier } else 4253e12c5d1SDavid du Colombier continue; 4263e12c5d1SDavid du Colombier } else 4273e12c5d1SDavid du Colombier return; 4283e12c5d1SDavid du Colombier } 4297dd7cddfSDavid du Colombier if(n == 0){ 4307dd7cddfSDavid du Colombier if(++eofs > 32) 4317dd7cddfSDavid du Colombier return; 4327dd7cddfSDavid du Colombier } else 4337dd7cddfSDavid du Colombier eofs = 0; 4343e12c5d1SDavid du Colombier if(n && memchr(buf, 0x1c, n)){ 4353e12c5d1SDavid du Colombier if(menu(net) < 0) 4363e12c5d1SDavid du Colombier return; 4373e12c5d1SDavid du Colombier }else{ 438d3c05884SDavid du Colombier if(!raw && n==0){ 4393e12c5d1SDavid du Colombier buf[0] = 0x4; 4403e12c5d1SDavid du Colombier n = 1; 4413e12c5d1SDavid du Colombier } 4427dd7cddfSDavid du Colombier if(nltocr){ 4437dd7cddfSDavid du Colombier ep = buf+n; 4447dd7cddfSDavid du Colombier for(p = buf; p < ep; p++) 4457dd7cddfSDavid du Colombier switch(*p){ 4467dd7cddfSDavid du Colombier case '\r': 4477dd7cddfSDavid du Colombier *p = '\n'; 4487dd7cddfSDavid du Colombier break; 4497dd7cddfSDavid du Colombier case '\n': 4507dd7cddfSDavid du Colombier *p = '\r'; 4517dd7cddfSDavid du Colombier break; 4527dd7cddfSDavid du Colombier } 4537dd7cddfSDavid du Colombier } 4543e12c5d1SDavid du Colombier if(iwrite(net, buf, n) != n) 4553e12c5d1SDavid du Colombier return; 4563e12c5d1SDavid du Colombier } 4573e12c5d1SDavid du Colombier } 4583e12c5d1SDavid du Colombier } 4593e12c5d1SDavid du Colombier 4603e12c5d1SDavid du Colombier /* 4613e12c5d1SDavid du Colombier * Read from the network and write to the screen. 4623e12c5d1SDavid du Colombier * Filter out spurious carriage returns. 4633e12c5d1SDavid du Colombier */ 4643e12c5d1SDavid du Colombier void 4653e12c5d1SDavid du Colombier fromnet(int net) 4663e12c5d1SDavid du Colombier { 4673e12c5d1SDavid du Colombier long n; 4683e12c5d1SDavid du Colombier char buf[MAXMSG]; 4693e12c5d1SDavid du Colombier char *cp, *ep; 4703e12c5d1SDavid du Colombier 4713e12c5d1SDavid du Colombier for(;;){ 4723e12c5d1SDavid du Colombier n = iread(net, buf, sizeof(buf)); 4733e12c5d1SDavid du Colombier if(n < 0) 4743e12c5d1SDavid du Colombier return; 4753e12c5d1SDavid du Colombier if(n == 0) 4763e12c5d1SDavid du Colombier continue; 4773e12c5d1SDavid du Colombier 478219b2ee8SDavid du Colombier if (strip) 479219b2ee8SDavid du Colombier for (cp=buf; cp<buf+n; cp++) 480219b2ee8SDavid du Colombier *cp &= 0177; 481219b2ee8SDavid du Colombier 4825d459b5aSDavid du Colombier if(crtonl) { 4835d459b5aSDavid du Colombier /* convert cr's to nl's */ 4845d459b5aSDavid du Colombier for (cp = buf; cp < buf + n; cp++) 4855d459b5aSDavid du Colombier if (*cp == '\r') 4865d459b5aSDavid du Colombier *cp = '\n'; 4875d459b5aSDavid du Colombier } 4885d459b5aSDavid du Colombier else if(!returns){ 4893e12c5d1SDavid du Colombier /* convert cr's to null's */ 4903e12c5d1SDavid du Colombier cp = buf; 4913e12c5d1SDavid du Colombier ep = buf + n; 4923e12c5d1SDavid du Colombier while(cp < ep && (cp = memchr(cp, '\r', ep-cp))){ 4933e12c5d1SDavid du Colombier memmove(cp, cp+1, ep-cp-1); 4943e12c5d1SDavid du Colombier ep--; 4953e12c5d1SDavid du Colombier n--; 4963e12c5d1SDavid du Colombier } 4973e12c5d1SDavid du Colombier } 4983e12c5d1SDavid du Colombier 4993e12c5d1SDavid du Colombier if(n > 0 && iwrite(outfd, buf, n) != n){ 5003e12c5d1SDavid du Colombier if(outfd == 1) 5013e12c5d1SDavid du Colombier return; 5023e12c5d1SDavid du Colombier outfd = 1; 5033e12c5d1SDavid du Colombier if(iwrite(1, buf, n) != n) 5043e12c5d1SDavid du Colombier return; 5053e12c5d1SDavid du Colombier } 5063e12c5d1SDavid du Colombier } 5073e12c5d1SDavid du Colombier } 5083e12c5d1SDavid du Colombier 5093e12c5d1SDavid du Colombier /* 5103e12c5d1SDavid du Colombier * dial and return a data connection 5113e12c5d1SDavid du Colombier */ 5123e12c5d1SDavid du Colombier int 5133e12c5d1SDavid du Colombier dodial(char *dest, char *net, char *service) 5143e12c5d1SDavid du Colombier { 5159a747e4fSDavid du Colombier char name[128]; 5169a747e4fSDavid du Colombier char devdir[128]; 5173e12c5d1SDavid du Colombier int data; 5183e12c5d1SDavid du Colombier 5193e12c5d1SDavid du Colombier devdir[0] = 0; 5203e12c5d1SDavid du Colombier strcpy(name, netmkaddr(dest, net, service)); 521bd389b36SDavid du Colombier data = dial(name, 0, devdir, &ctl); 5223e12c5d1SDavid du Colombier if(data < 0){ 523219b2ee8SDavid du Colombier seterr(name); 5243e12c5d1SDavid du Colombier return -1; 5253e12c5d1SDavid du Colombier } 5263e12c5d1SDavid du Colombier fprint(2, "connected to %s on %s\n", name, devdir); 5273e12c5d1SDavid du Colombier return data; 5283e12c5d1SDavid du Colombier } 5293e12c5d1SDavid du Colombier 5303e12c5d1SDavid du Colombier void 5313e12c5d1SDavid du Colombier dosystem(int fd, char *cmd) 5323e12c5d1SDavid du Colombier { 5333e12c5d1SDavid du Colombier char *p; 5343e12c5d1SDavid du Colombier 5353e12c5d1SDavid du Colombier p = system(fd, cmd); 536fbdb243dSDavid du Colombier if(p){ 5377dd7cddfSDavid du Colombier print("con: %s terminated with %s\n", cmd, p); 5383e12c5d1SDavid du Colombier exits(p); 5393e12c5d1SDavid du Colombier } 5403e12c5d1SDavid du Colombier } 5413e12c5d1SDavid du Colombier 5423e12c5d1SDavid du Colombier /* 5433e12c5d1SDavid du Colombier * run a command with the network connection as standard IO 5443e12c5d1SDavid du Colombier */ 5453e12c5d1SDavid du Colombier char * 5463e12c5d1SDavid du Colombier system(int fd, char *cmd) 5473e12c5d1SDavid du Colombier { 5483e12c5d1SDavid du Colombier int pid; 5493e12c5d1SDavid du Colombier int p; 5503e12c5d1SDavid du Colombier static Waitmsg msg; 5513e12c5d1SDavid du Colombier int pfd[2]; 5523e12c5d1SDavid du Colombier int n; 5533e12c5d1SDavid du Colombier char buf[4096]; 5543e12c5d1SDavid du Colombier 5553e12c5d1SDavid du Colombier if(pipe(pfd) < 0){ 5563e12c5d1SDavid du Colombier perror("pipe"); 5573e12c5d1SDavid du Colombier return "pipe failed"; 5583e12c5d1SDavid du Colombier } 5593e12c5d1SDavid du Colombier outfd = pfd[1]; 5603e12c5d1SDavid du Colombier 561219b2ee8SDavid du Colombier close(consctl); 562219b2ee8SDavid du Colombier consctl = -1; 5633e12c5d1SDavid du Colombier switch(pid = fork()){ 5643e12c5d1SDavid du Colombier case -1: 5653e12c5d1SDavid du Colombier perror("con"); 5663e12c5d1SDavid du Colombier return "fork failed"; 5673e12c5d1SDavid du Colombier case 0: 5683e12c5d1SDavid du Colombier close(pfd[1]); 5693e12c5d1SDavid du Colombier dup(pfd[0], 0); 5703ff48bf5SDavid du Colombier dup(fd, 1); 5713e12c5d1SDavid du Colombier close(ctl); 5723e12c5d1SDavid du Colombier close(fd); 5733e12c5d1SDavid du Colombier close(pfd[0]); 5743e12c5d1SDavid du Colombier if(*cmd) 575f19e7b74SDavid du Colombier execl("/bin/rc", "rc", "-c", cmd, nil); 5763e12c5d1SDavid du Colombier else 577f19e7b74SDavid du Colombier execl("/bin/rc", "rc", nil); 5783e12c5d1SDavid du Colombier perror("con"); 5793e12c5d1SDavid du Colombier exits("exec"); 5803e12c5d1SDavid du Colombier break; 5813e12c5d1SDavid du Colombier default: 5823e12c5d1SDavid du Colombier close(pfd[0]); 5833e12c5d1SDavid du Colombier while((n = read(pfd[1], buf, sizeof(buf))) > 0){ 5843e12c5d1SDavid du Colombier if(msgfd >= 0){ 5853e12c5d1SDavid du Colombier if(msgwrite(fd, buf, n) != n) 5863e12c5d1SDavid du Colombier break; 5873e12c5d1SDavid du Colombier } else { 5883e12c5d1SDavid du Colombier if(write(fd, buf, n) != n) 5893e12c5d1SDavid du Colombier break; 5903e12c5d1SDavid du Colombier } 5913e12c5d1SDavid du Colombier } 5929a747e4fSDavid du Colombier p = waitpid(); 5933e12c5d1SDavid du Colombier outfd = 1; 5943e12c5d1SDavid du Colombier close(pfd[1]); 595219b2ee8SDavid du Colombier if(p < 0 || p != pid) 596219b2ee8SDavid du Colombier return "lost child"; 5973e12c5d1SDavid du Colombier break; 5983e12c5d1SDavid du Colombier } 599219b2ee8SDavid du Colombier return msg.msg; 6003e12c5d1SDavid du Colombier } 6013e12c5d1SDavid du Colombier 6023e12c5d1SDavid du Colombier int 6033e12c5d1SDavid du Colombier wasintr(void) 6043e12c5d1SDavid du Colombier { 6053e12c5d1SDavid du Colombier return strcmp(syserr(), "interrupted") == 0; 6063e12c5d1SDavid du Colombier } 6073e12c5d1SDavid du Colombier 6083e12c5d1SDavid du Colombier void 6093e12c5d1SDavid du Colombier punt(char *msg) 6103e12c5d1SDavid du Colombier { 6113e12c5d1SDavid du Colombier if(*msg == 0) 6123e12c5d1SDavid du Colombier msg = transerr; 6133e12c5d1SDavid du Colombier fprint(2, "con: %s\n", msg); 6143e12c5d1SDavid du Colombier exits(msg); 6153e12c5d1SDavid du Colombier } 6163e12c5d1SDavid du Colombier 6173e12c5d1SDavid du Colombier char* 6183e12c5d1SDavid du Colombier syserr(void) 6193e12c5d1SDavid du Colombier { 6209a747e4fSDavid du Colombier static char err[ERRMAX]; 6219a747e4fSDavid du Colombier errstr(err, sizeof err); 6223e12c5d1SDavid du Colombier return err; 6233e12c5d1SDavid du Colombier } 6243e12c5d1SDavid du Colombier 6253e12c5d1SDavid du Colombier void 626219b2ee8SDavid du Colombier seterr(char *addr) 6273e12c5d1SDavid du Colombier { 6283e12c5d1SDavid du Colombier char *se = syserr(); 6293e12c5d1SDavid du Colombier 6303e12c5d1SDavid du Colombier if(verbose) 631219b2ee8SDavid du Colombier fprint(2, "'%s' calling %s\n", se, addr); 6323e12c5d1SDavid du Colombier if(firsterr[0] && (strstr(se, "translate") || 6333e12c5d1SDavid du Colombier strstr(se, "file does not exist") || 6343e12c5d1SDavid du Colombier strstr(se, "unknown address") || 6353e12c5d1SDavid du Colombier strstr(se, "directory entry not found"))) 6363e12c5d1SDavid du Colombier return; 6373e12c5d1SDavid du Colombier strcpy(firsterr, se); 6383e12c5d1SDavid du Colombier } 6393e12c5d1SDavid du Colombier 6403e12c5d1SDavid du Colombier 6413e12c5d1SDavid du Colombier long 6423e12c5d1SDavid du Colombier iread(int f, void *a, int n) 6433e12c5d1SDavid du Colombier { 6443e12c5d1SDavid du Colombier long m; 6453e12c5d1SDavid du Colombier 6463e12c5d1SDavid du Colombier for(;;){ 6473e12c5d1SDavid du Colombier m = read(f, a, n); 6483e12c5d1SDavid du Colombier if(m >= 0 || !wasintr()) 6493e12c5d1SDavid du Colombier break; 6503e12c5d1SDavid du Colombier } 6513e12c5d1SDavid du Colombier return m; 6523e12c5d1SDavid du Colombier } 6533e12c5d1SDavid du Colombier 6543e12c5d1SDavid du Colombier long 6553e12c5d1SDavid du Colombier iwrite(int f, void *a, int n) 6563e12c5d1SDavid du Colombier { 6573e12c5d1SDavid du Colombier long m; 6583e12c5d1SDavid du Colombier 6593e12c5d1SDavid du Colombier m = write(f, a, n); 6603e12c5d1SDavid du Colombier if(m < 0 && wasintr()) 6613e12c5d1SDavid du Colombier return n; 6623e12c5d1SDavid du Colombier return m; 6633e12c5d1SDavid du Colombier } 6643e12c5d1SDavid du Colombier 6653e12c5d1SDavid du Colombier /* 6663e12c5d1SDavid du Colombier * The rest is to support the V10 mesgld protocol. 6673e12c5d1SDavid du Colombier */ 6683e12c5d1SDavid du Colombier 6693e12c5d1SDavid du Colombier /* 6703e12c5d1SDavid du Colombier * network orderings 6713e12c5d1SDavid du Colombier */ 6723e12c5d1SDavid du Colombier #define get2byte(p) ((p)[0] + ((p)[1]<<8)) 6733e12c5d1SDavid du Colombier #define get4byte(p) ((p)[0] + ((p)[1]<<8) + ((p)[2]<<16) + ((p)[3]<<24)) 6743e12c5d1SDavid du Colombier #define put2byte(p, i) ((p)[0]=(i), (p)[1]=(i)>>8) 6753e12c5d1SDavid du Colombier #define put4byte(p, i) ((p)[0]=(i), (p)[1]=(i)>>8, (p)[2]=(i)>>16, (p)[3]=(i)>>24) 6763e12c5d1SDavid du Colombier 6773e12c5d1SDavid du Colombier /* 6783e12c5d1SDavid du Colombier * tty parameters 6793e12c5d1SDavid du Colombier */ 6803e12c5d1SDavid du Colombier int sgflags = ECHO; 6813e12c5d1SDavid du Colombier 6823e12c5d1SDavid du Colombier /* 6833e12c5d1SDavid du Colombier * a mesgld message 6843e12c5d1SDavid du Colombier */ 6853e12c5d1SDavid du Colombier struct Msg { 6863e12c5d1SDavid du Colombier struct mesg h; 6873e12c5d1SDavid du Colombier char b[MAXMSG]; 6883e12c5d1SDavid du Colombier }; 6893e12c5d1SDavid du Colombier 6903e12c5d1SDavid du Colombier 6913e12c5d1SDavid du Colombier /* 6923e12c5d1SDavid du Colombier * send an empty mesgld message 6933e12c5d1SDavid du Colombier */ 6943e12c5d1SDavid du Colombier int 6953e12c5d1SDavid du Colombier sendctl(int net, int type) 6963e12c5d1SDavid du Colombier { 6973e12c5d1SDavid du Colombier Msg m; 6983e12c5d1SDavid du Colombier 6993e12c5d1SDavid du Colombier m.h.type = type; 7003e12c5d1SDavid du Colombier m.h.magic = MSGMAGIC; 7013e12c5d1SDavid du Colombier put2byte(m.h.size, 0); 7023e12c5d1SDavid du Colombier if(iwrite(net, &m, sizeof(struct mesg)) != sizeof(struct mesg)) 7033e12c5d1SDavid du Colombier return -1; 7043e12c5d1SDavid du Colombier return 0; 7053e12c5d1SDavid du Colombier } 7063e12c5d1SDavid du Colombier 7073e12c5d1SDavid du Colombier /* 7083e12c5d1SDavid du Colombier * send a one byte mesgld message 7093e12c5d1SDavid du Colombier */ 7103e12c5d1SDavid du Colombier int 7113e12c5d1SDavid du Colombier sendctl1(int net, int type, int parm) 7123e12c5d1SDavid du Colombier { 7133e12c5d1SDavid du Colombier Msg m; 7143e12c5d1SDavid du Colombier 7153e12c5d1SDavid du Colombier m.h.type = type; 7163e12c5d1SDavid du Colombier m.h.magic = MSGMAGIC; 7173e12c5d1SDavid du Colombier m.b[0] = parm; 7183e12c5d1SDavid du Colombier put2byte(m.h.size, 1); 7193e12c5d1SDavid du Colombier if(iwrite(net, &m, sizeof(struct mesg)+1) != sizeof(struct mesg)+1) 7203e12c5d1SDavid du Colombier return -1; 7213e12c5d1SDavid du Colombier return 0; 7223e12c5d1SDavid du Colombier } 7233e12c5d1SDavid du Colombier 7243e12c5d1SDavid du Colombier /* 7253e12c5d1SDavid du Colombier * read n bytes. return -1 if it fails, 0 otherwise. 7263e12c5d1SDavid du Colombier */ 7273e12c5d1SDavid du Colombier int 7283e12c5d1SDavid du Colombier readupto(int from, char *a, int len) 7293e12c5d1SDavid du Colombier { 7303e12c5d1SDavid du Colombier int n; 7313e12c5d1SDavid du Colombier 7323e12c5d1SDavid du Colombier while(len > 0){ 7333e12c5d1SDavid du Colombier n = iread(from, a, len); 7343e12c5d1SDavid du Colombier if(n < 0) 7353e12c5d1SDavid du Colombier return -1; 7363e12c5d1SDavid du Colombier a += n; 7373e12c5d1SDavid du Colombier len -= n; 7383e12c5d1SDavid du Colombier } 7393e12c5d1SDavid du Colombier return 0; 7403e12c5d1SDavid du Colombier } 7413e12c5d1SDavid du Colombier 7423e12c5d1SDavid du Colombier /* 7433e12c5d1SDavid du Colombier * Decode a mesgld message from the network 7443e12c5d1SDavid du Colombier */ 7453e12c5d1SDavid du Colombier void 7463e12c5d1SDavid du Colombier msgfromnet(int net) 7473e12c5d1SDavid du Colombier { 7483e12c5d1SDavid du Colombier ulong com; 7493e12c5d1SDavid du Colombier struct stioctl *io; 7503e12c5d1SDavid du Colombier struct sgttyb *sg; 7513e12c5d1SDavid du Colombier struct ttydevb *td; 7523e12c5d1SDavid du Colombier struct tchars *tc; 7533e12c5d1SDavid du Colombier int len; 7543e12c5d1SDavid du Colombier Msg m; 7553e12c5d1SDavid du Colombier 7563e12c5d1SDavid du Colombier for(;;){ 7573e12c5d1SDavid du Colombier /* get a complete mesgld message */ 7583e12c5d1SDavid du Colombier if(readupto(net, (char*)&m.h, sizeof(struct mesg)) < 0) 7593e12c5d1SDavid du Colombier break; 7603e12c5d1SDavid du Colombier if(m.h.magic != MSGMAGIC){ 7613e12c5d1SDavid du Colombier fprint(2, "con: bad message magic 0x%ux\n", m.h.magic); 7623e12c5d1SDavid du Colombier break; 7633e12c5d1SDavid du Colombier } 7643e12c5d1SDavid du Colombier len = get2byte(m.h.size); 765219b2ee8SDavid du Colombier if(len > sizeof(m.b)){ 766219b2ee8SDavid du Colombier len = sizeof(m.b); 767219b2ee8SDavid du Colombier fprint(2, "con: mesgld message too long\n"); 768219b2ee8SDavid du Colombier } 7693e12c5d1SDavid du Colombier if(len && readupto(net, m.b, len) < 0) 7703e12c5d1SDavid du Colombier break; 7713e12c5d1SDavid du Colombier 7723e12c5d1SDavid du Colombier /* decode */ 7733e12c5d1SDavid du Colombier switch(m.h.type){ 7743e12c5d1SDavid du Colombier case M_HANGUP: 7753e12c5d1SDavid du Colombier if(debug) 7763e12c5d1SDavid du Colombier fprint(2, "M_HANGUP\n"); 7773e12c5d1SDavid du Colombier return; 7783e12c5d1SDavid du Colombier case M_DATA: 7793e12c5d1SDavid du Colombier if(debug) 7803e12c5d1SDavid du Colombier fprint(2, "M_DATA %d bytes\n", len); 7813e12c5d1SDavid du Colombier if(iwrite(outfd, m.b, len) != len){ 7823e12c5d1SDavid du Colombier if(outfd == 1) 7833e12c5d1SDavid du Colombier return; 7843e12c5d1SDavid du Colombier outfd = 1; 7853e12c5d1SDavid du Colombier if(iwrite(outfd, m.b, len) != len) 7863e12c5d1SDavid du Colombier return; 7873e12c5d1SDavid du Colombier } 7883e12c5d1SDavid du Colombier continue; 7893e12c5d1SDavid du Colombier case M_IOCTL: 7903e12c5d1SDavid du Colombier break; 7913e12c5d1SDavid du Colombier default: 7923e12c5d1SDavid du Colombier /* ignore */ 7933e12c5d1SDavid du Colombier if(debug) 794219b2ee8SDavid du Colombier fprint(2, "con: unknown message\n"); 7953e12c5d1SDavid du Colombier continue; 7963e12c5d1SDavid du Colombier } 7973e12c5d1SDavid du Colombier 7983e12c5d1SDavid du Colombier /* 7993e12c5d1SDavid du Colombier * answer an ioctl 8003e12c5d1SDavid du Colombier */ 8013e12c5d1SDavid du Colombier io = (struct stioctl *)m.b; 8023e12c5d1SDavid du Colombier com = get4byte(io->com); 8033e12c5d1SDavid du Colombier if(debug) 8047dd7cddfSDavid du Colombier fprint(2, "M_IOCTL %lud\n", com); 8053e12c5d1SDavid du Colombier switch(com){ 8063e12c5d1SDavid du Colombier case FIOLOOKLD: 8073e12c5d1SDavid du Colombier put4byte(io->data, tty_ld); 8083e12c5d1SDavid du Colombier len = 0; 8093e12c5d1SDavid du Colombier break; 8103e12c5d1SDavid du Colombier case TIOCGETP: 8113e12c5d1SDavid du Colombier sg = (struct sgttyb *)io->data; 8123e12c5d1SDavid du Colombier sg->sg_ispeed = sg->sg_ospeed = B9600; 8133e12c5d1SDavid du Colombier sg->sg_erase = 0010; /* back space */ 8143e12c5d1SDavid du Colombier sg->sg_kill = 0025; /* CNTL U */ 8153e12c5d1SDavid du Colombier put2byte(sg->sg_flags, sgflags); 8163e12c5d1SDavid du Colombier len = sizeof(struct sgttyb); 8173e12c5d1SDavid du Colombier break; 8183e12c5d1SDavid du Colombier case TIOCSETN: 8193e12c5d1SDavid du Colombier case TIOCSETP: 8203e12c5d1SDavid du Colombier sg = (struct sgttyb *)io->data; 8213e12c5d1SDavid du Colombier sgflags = get2byte(sg->sg_flags); 8223e12c5d1SDavid du Colombier if((sgflags&(RAW|CBREAK)) || !(sgflags&ECHO)) 8233e12c5d1SDavid du Colombier rawon(); 8243e12c5d1SDavid du Colombier else 8253e12c5d1SDavid du Colombier rawoff(); 8263e12c5d1SDavid du Colombier len = 0; 8273e12c5d1SDavid du Colombier break; 8283e12c5d1SDavid du Colombier case TIOCGETC: 8293e12c5d1SDavid du Colombier tc = (struct tchars *)io->data; 8303e12c5d1SDavid du Colombier tc->t_intrc = 0177; 8313e12c5d1SDavid du Colombier tc->t_quitc = 0034; 8323e12c5d1SDavid du Colombier tc->t_startc = 0; 8333e12c5d1SDavid du Colombier tc->t_stopc = 0; 8343e12c5d1SDavid du Colombier tc->t_eofc = 0004; 8353e12c5d1SDavid du Colombier tc->t_brkc = 0; 8363e12c5d1SDavid du Colombier len = sizeof(struct tchars); 8373e12c5d1SDavid du Colombier break; 8383e12c5d1SDavid du Colombier case TIOCSETC: 8393e12c5d1SDavid du Colombier len = 0; 8403e12c5d1SDavid du Colombier break; 8413e12c5d1SDavid du Colombier case TIOCGDEV: 8423e12c5d1SDavid du Colombier td = (struct ttydevb *)io->data; 8433e12c5d1SDavid du Colombier td->ispeed = td->ospeed = B9600; 8443e12c5d1SDavid du Colombier put2byte(td->flags, 0); 8453e12c5d1SDavid du Colombier len = sizeof(struct ttydevb); 8463e12c5d1SDavid du Colombier break; 8473e12c5d1SDavid du Colombier case TIOCSDEV: 8483e12c5d1SDavid du Colombier len = 0; 8493e12c5d1SDavid du Colombier break; 8503e12c5d1SDavid du Colombier default: 8513e12c5d1SDavid du Colombier /* 8523e12c5d1SDavid du Colombier * unimplemented 8533e12c5d1SDavid du Colombier */ 8543e12c5d1SDavid du Colombier m.b[len] = 0; 8553e12c5d1SDavid du Colombier if(sendctl(net, M_IOCNAK) < 0) 8563e12c5d1SDavid du Colombier return; 8573e12c5d1SDavid du Colombier continue; 8583e12c5d1SDavid du Colombier } 8593e12c5d1SDavid du Colombier 8603e12c5d1SDavid du Colombier /* 8613e12c5d1SDavid du Colombier * acknowledge 8623e12c5d1SDavid du Colombier */ 8633e12c5d1SDavid du Colombier m.h.type = M_IOCACK; 8643e12c5d1SDavid du Colombier m.h.magic = MSGMAGIC; 8653e12c5d1SDavid du Colombier len += 4; 8663e12c5d1SDavid du Colombier put2byte(m.h.size, len); 8673e12c5d1SDavid du Colombier len += sizeof(struct mesg); 8683e12c5d1SDavid du Colombier if(iwrite(net, &m, len) != len) 8693e12c5d1SDavid du Colombier return; 8703e12c5d1SDavid du Colombier } 8713e12c5d1SDavid du Colombier } 8723e12c5d1SDavid du Colombier 8733e12c5d1SDavid du Colombier /* 8743e12c5d1SDavid du Colombier * Read the keyboard, convert to mesgld messages, and write it to the network. 8753e12c5d1SDavid du Colombier * '^\' gets us into the menu. 8763e12c5d1SDavid du Colombier */ 8773e12c5d1SDavid du Colombier void 8783e12c5d1SDavid du Colombier msgfromkbd(int net) 8793e12c5d1SDavid du Colombier { 8803e12c5d1SDavid du Colombier long n; 8813e12c5d1SDavid du Colombier char buf[MAXMSG]; 8823e12c5d1SDavid du Colombier 8833e12c5d1SDavid du Colombier for(;;){ 8843e12c5d1SDavid du Colombier n = iread(0, buf, sizeof(buf)); 8853e12c5d1SDavid du Colombier if(n < 0) 8863e12c5d1SDavid du Colombier return; 8873e12c5d1SDavid du Colombier if(n && memchr(buf, 0034, n)){ 8883e12c5d1SDavid du Colombier if(menu(net) < 0) 8893e12c5d1SDavid du Colombier return; 8903e12c5d1SDavid du Colombier } else { 8913e12c5d1SDavid du Colombier if(msgwrite(net, buf, n) != n) 8923e12c5d1SDavid du Colombier return; 8933e12c5d1SDavid du Colombier } 8943e12c5d1SDavid du Colombier } 8953e12c5d1SDavid du Colombier } 8963e12c5d1SDavid du Colombier 8973e12c5d1SDavid du Colombier int 8983e12c5d1SDavid du Colombier msgwrite(int fd, void *buf, int len) 8993e12c5d1SDavid du Colombier { 9003e12c5d1SDavid du Colombier Msg m; 9013e12c5d1SDavid du Colombier int n; 9023e12c5d1SDavid du Colombier 9033e12c5d1SDavid du Colombier n = len; 9043e12c5d1SDavid du Colombier memmove(m.b, buf, n); 9053e12c5d1SDavid du Colombier put2byte(m.h.size, n); 9063e12c5d1SDavid du Colombier m.h.magic = MSGMAGIC; 9073e12c5d1SDavid du Colombier m.h.type = M_DATA; 9083e12c5d1SDavid du Colombier n += sizeof(struct mesg); 9093e12c5d1SDavid du Colombier if(iwrite(fd, &m, n) != n) 9103e12c5d1SDavid du Colombier return -1; 9113e12c5d1SDavid du Colombier 9123e12c5d1SDavid du Colombier put2byte(m.h.size, 0); 9133e12c5d1SDavid du Colombier m.h.magic = MSGMAGIC; 9143e12c5d1SDavid du Colombier m.h.type = M_DELIM; 9153e12c5d1SDavid du Colombier n = sizeof(struct mesg); 9163e12c5d1SDavid du Colombier if(iwrite(fd, &m, n) != n) 9173e12c5d1SDavid du Colombier return -1; 9183e12c5d1SDavid du Colombier 9193e12c5d1SDavid du Colombier return len; 9203e12c5d1SDavid du Colombier } 9213e12c5d1SDavid du Colombier 922