13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier
43e12c5d1SDavid du Colombier int debug; /* true if debugging */
53e12c5d1SDavid du Colombier int ctl = -1; /* control fd (for break's) */
63e12c5d1SDavid du Colombier int raw; /* true if raw is on */
73e12c5d1SDavid du Colombier int consctl = -1; /* control fd for cons */
83e12c5d1SDavid du Colombier int ttypid; /* pid's if the 2 processes (used to kill them) */
93e12c5d1SDavid du Colombier int outfd = 1; /* local output file descriptor */
103e12c5d1SDavid du Colombier int cooked; /* non-zero forces cooked mode */
113e12c5d1SDavid du Colombier int returns; /* non-zero forces carriage returns not to be filtered out */
125d459b5aSDavid du Colombier int crtonl; /* non-zero forces carriage returns to be converted to nls coming from net */
13219b2ee8SDavid du Colombier int strip; /* strip off parity bits */
149a747e4fSDavid du Colombier char firsterr[2*ERRMAX];
159a747e4fSDavid du Colombier char transerr[2*ERRMAX];
163e12c5d1SDavid du Colombier int limited;
176dc4800dSDavid du Colombier char *remuser; /* for BSD rlogin authentication */
183e12c5d1SDavid du Colombier int verbose;
19219b2ee8SDavid du Colombier int baud;
207dd7cddfSDavid du Colombier int notkbd;
217dd7cddfSDavid du Colombier int nltocr; /* translate kbd nl to cr and vice versa */
223e12c5d1SDavid du Colombier
23*3b86f2f8SDavid du Colombier static char *srv;
24*3b86f2f8SDavid du Colombier
25219b2ee8SDavid du Colombier #define MAXMSG (2*8192)
263e12c5d1SDavid du Colombier
273e12c5d1SDavid du Colombier int dodial(char*, char*, char*);
283e12c5d1SDavid du Colombier void fromkbd(int);
293e12c5d1SDavid du Colombier void fromnet(int);
303e12c5d1SDavid du Colombier long iread(int, void*, int);
313e12c5d1SDavid du Colombier long iwrite(int, void*, int);
323e12c5d1SDavid du Colombier int menu(int);
333e12c5d1SDavid du Colombier void notifyf(void*, char*);
343e12c5d1SDavid du Colombier void pass(int, int, int);
353e12c5d1SDavid du Colombier void rawoff(void);
363e12c5d1SDavid du Colombier void rawon(void);
373e12c5d1SDavid du Colombier void stdcon(int);
383e12c5d1SDavid du Colombier char* system(int, char*);
393e12c5d1SDavid du Colombier void dosystem(int, char*);
403e12c5d1SDavid du Colombier int wasintr(void);
413e12c5d1SDavid du Colombier void punt(char*);
423e12c5d1SDavid du Colombier char* syserr(void);
43219b2ee8SDavid du Colombier void seterr(char*);
443e12c5d1SDavid du Colombier
453e12c5d1SDavid du Colombier /* protocols */
463e12c5d1SDavid du Colombier void device(char*, char*);
473e12c5d1SDavid du Colombier void rlogin(char*, char*);
483e12c5d1SDavid du Colombier void simple(char*, char*);
493e12c5d1SDavid du Colombier
503e12c5d1SDavid du Colombier void
usage(void)513e12c5d1SDavid du Colombier usage(void)
523e12c5d1SDavid du Colombier {
53*3b86f2f8SDavid du Colombier punt("usage: con [-CdnrRsTv] [-b baud] [-l [user]] [-c cmd] [-S svc] "
54*3b86f2f8SDavid du Colombier "net!host[!service]");
553e12c5d1SDavid du Colombier }
563e12c5d1SDavid du Colombier
573e12c5d1SDavid du Colombier void
main(int argc,char * argv[])583e12c5d1SDavid du Colombier main(int argc, char *argv[])
593e12c5d1SDavid du Colombier {
603e12c5d1SDavid du Colombier char *dest;
613e12c5d1SDavid du Colombier char *cmd = 0;
623e12c5d1SDavid du Colombier
633e12c5d1SDavid du Colombier returns = 1;
643e12c5d1SDavid du Colombier ARGBEGIN{
65219b2ee8SDavid du Colombier case 'b':
66e40528acSDavid du Colombier baud = atoi(EARGF(usage()));
67219b2ee8SDavid du Colombier break;
68*3b86f2f8SDavid du Colombier case 'C':
69*3b86f2f8SDavid du Colombier cooked = 1;
70*3b86f2f8SDavid du Colombier break;
71*3b86f2f8SDavid du Colombier case 'c':
72*3b86f2f8SDavid du Colombier cmd = EARGF(usage());
73*3b86f2f8SDavid du Colombier break;
743e12c5d1SDavid du Colombier case 'd':
753e12c5d1SDavid du Colombier debug = 1;
763e12c5d1SDavid du Colombier break;
773e12c5d1SDavid du Colombier case 'l':
783e12c5d1SDavid du Colombier limited = 1;
799a747e4fSDavid du Colombier if(argv[1] != nil && argv[1][0] != '-')
80*3b86f2f8SDavid du Colombier remuser = EARGF(usage());
813e12c5d1SDavid du Colombier break;
827dd7cddfSDavid du Colombier case 'n':
837dd7cddfSDavid du Colombier notkbd = 1;
847dd7cddfSDavid du Colombier break;
853e12c5d1SDavid du Colombier case 'r':
863e12c5d1SDavid du Colombier returns = 0;
873e12c5d1SDavid du Colombier break;
88*3b86f2f8SDavid du Colombier case 's':
89*3b86f2f8SDavid du Colombier strip = 1;
90*3b86f2f8SDavid du Colombier break;
91*3b86f2f8SDavid du Colombier case 'S':
92*3b86f2f8SDavid du Colombier srv = EARGF(usage());
93*3b86f2f8SDavid du Colombier break;
947dd7cddfSDavid du Colombier case 'R':
957dd7cddfSDavid du Colombier nltocr = 1;
967dd7cddfSDavid du Colombier break;
975d459b5aSDavid du Colombier case 'T':
985d459b5aSDavid du Colombier crtonl = 1;
995d459b5aSDavid du Colombier break;
1003e12c5d1SDavid du Colombier case 'v':
1013e12c5d1SDavid du Colombier verbose = 1;
1023e12c5d1SDavid du Colombier break;
1033e12c5d1SDavid du Colombier default:
1043e12c5d1SDavid du Colombier usage();
1053e12c5d1SDavid du Colombier }ARGEND
1063e12c5d1SDavid du Colombier
1073e12c5d1SDavid du Colombier if(argc != 1){
1083e12c5d1SDavid du Colombier if(remuser == 0)
1093e12c5d1SDavid du Colombier usage();
1103e12c5d1SDavid du Colombier dest = remuser;
1113e12c5d1SDavid du Colombier remuser = 0;
1123e12c5d1SDavid du Colombier } else
1133e12c5d1SDavid du Colombier dest = argv[0];
1147dd7cddfSDavid du Colombier if(*dest == '/' && strchr(dest, '!') == 0)
1153e12c5d1SDavid du Colombier device(dest, cmd);
1163e12c5d1SDavid du Colombier else if(limited){
1173e12c5d1SDavid du Colombier simple(dest, cmd); /* doesn't return if dialout succeeds */
1183e12c5d1SDavid du Colombier rlogin(dest, cmd); /* doesn't return if dialout succeeds */
1193e12c5d1SDavid du Colombier } else {
120219b2ee8SDavid du Colombier rlogin(dest, cmd); /* doesn't return if dialout succeeds */
1213e12c5d1SDavid du Colombier simple(dest, cmd); /* doesn't return if dialout succeeds */
1223e12c5d1SDavid du Colombier }
1233e12c5d1SDavid du Colombier punt(firsterr);
1243e12c5d1SDavid du Colombier }
1253e12c5d1SDavid du Colombier
1263e12c5d1SDavid du Colombier /*
1273e12c5d1SDavid du Colombier * just dial and use as a byte stream with remote echo
1283e12c5d1SDavid du Colombier */
1293e12c5d1SDavid du Colombier void
simple(char * dest,char * cmd)1303e12c5d1SDavid du Colombier simple(char *dest, char *cmd)
1313e12c5d1SDavid du Colombier {
1323e12c5d1SDavid du Colombier int net;
1333e12c5d1SDavid du Colombier
1343e12c5d1SDavid du Colombier net = dodial(dest, 0, 0);
1353e12c5d1SDavid du Colombier if(net < 0)
1363e12c5d1SDavid du Colombier return;
1373e12c5d1SDavid du Colombier
1383e12c5d1SDavid du Colombier if(cmd)
1393e12c5d1SDavid du Colombier dosystem(net, cmd);
1403e12c5d1SDavid du Colombier
1413e12c5d1SDavid du Colombier if(!cooked)
1423e12c5d1SDavid du Colombier rawon();
1433e12c5d1SDavid du Colombier stdcon(net);
1443e12c5d1SDavid du Colombier exits(0);
1453e12c5d1SDavid du Colombier }
1463e12c5d1SDavid du Colombier
1473e12c5d1SDavid du Colombier /*
1483e12c5d1SDavid du Colombier * dial, do UCB authentication, use as a byte stream with local echo
1493e12c5d1SDavid du Colombier *
1503e12c5d1SDavid du Colombier * return if dial failed
1513e12c5d1SDavid du Colombier */
1523e12c5d1SDavid du Colombier void
rlogin(char * dest,char * cmd)1533e12c5d1SDavid du Colombier rlogin(char *dest, char *cmd)
1543e12c5d1SDavid du Colombier {
1557dd7cddfSDavid du Colombier int net;
1569a747e4fSDavid du Colombier char buf[128];
1573e12c5d1SDavid du Colombier char *p;
1583e12c5d1SDavid du Colombier char *localuser;
1593e12c5d1SDavid du Colombier
1603e12c5d1SDavid du Colombier /* only useful on TCP */
161bd389b36SDavid du Colombier if(strchr(dest, '!')
162bd389b36SDavid du Colombier && (strncmp(dest, "tcp!", 4)!=0 && strncmp(dest, "net!", 4)!=0))
1633e12c5d1SDavid du Colombier return;
1643e12c5d1SDavid du Colombier
1653e12c5d1SDavid du Colombier net = dodial(dest, "tcp", "login");
1663e12c5d1SDavid du Colombier if(net < 0)
1673e12c5d1SDavid du Colombier return;
1683e12c5d1SDavid du Colombier
1693e12c5d1SDavid du Colombier /*
1703e12c5d1SDavid du Colombier * do UCB rlogin authentication
1713e12c5d1SDavid du Colombier */
1727dd7cddfSDavid du Colombier localuser = getuser();
1733e12c5d1SDavid du Colombier if(remuser == 0){
1743e12c5d1SDavid du Colombier if(limited)
1753e12c5d1SDavid du Colombier remuser = ":";
1763e12c5d1SDavid du Colombier else
1773e12c5d1SDavid du Colombier remuser = localuser;
1783e12c5d1SDavid du Colombier }
1793e12c5d1SDavid du Colombier p = getenv("TERM");
1803e12c5d1SDavid du Colombier if(p == 0)
1813e12c5d1SDavid du Colombier p = "p9";
1823e12c5d1SDavid du Colombier if(write(net, "", 1)<0
1833e12c5d1SDavid du Colombier || write(net, localuser, strlen(localuser)+1)<0
1843e12c5d1SDavid du Colombier || write(net, remuser, strlen(remuser)+1)<0
1853e12c5d1SDavid du Colombier || write(net, p, strlen(p)+1)<0){
1863e12c5d1SDavid du Colombier close(net);
1873e12c5d1SDavid du Colombier punt("BSD authentication failed");
1883e12c5d1SDavid du Colombier }
1893e12c5d1SDavid du Colombier if(read(net, buf, 1) != 1)
1903e12c5d1SDavid du Colombier punt("BSD authentication failed1");
1913e12c5d1SDavid du Colombier if(buf[0] != 0){
1923e12c5d1SDavid du Colombier fprint(2, "con: remote error: ");
1933e12c5d1SDavid du Colombier while(read(net, buf, 1) == 1){
1943e12c5d1SDavid du Colombier write(2, buf, 1);
1953e12c5d1SDavid du Colombier if(buf[0] == '\n')
1963e12c5d1SDavid du Colombier break;
1973e12c5d1SDavid du Colombier }
1983e12c5d1SDavid du Colombier exits("read");
1993e12c5d1SDavid du Colombier }
2003e12c5d1SDavid du Colombier
2013e12c5d1SDavid du Colombier if(cmd)
2023e12c5d1SDavid du Colombier dosystem(net, cmd);
2033e12c5d1SDavid du Colombier
2043e12c5d1SDavid du Colombier if(!cooked)
2053e12c5d1SDavid du Colombier rawon();
2067dd7cddfSDavid du Colombier nltocr = 1;
2073e12c5d1SDavid du Colombier stdcon(net);
2083e12c5d1SDavid du Colombier exits(0);
2093e12c5d1SDavid du Colombier }
2103e12c5d1SDavid du Colombier
2113e12c5d1SDavid du Colombier /*
2123e12c5d1SDavid du Colombier * just open a device and use it as a connection
2133e12c5d1SDavid du Colombier */
2143e12c5d1SDavid du Colombier void
device(char * dest,char * cmd)2153e12c5d1SDavid du Colombier device(char *dest, char *cmd)
2163e12c5d1SDavid du Colombier {
2173e12c5d1SDavid du Colombier int net;
2189a747e4fSDavid du Colombier char cname[128];
2193e12c5d1SDavid du Colombier
2203e12c5d1SDavid du Colombier net = open(dest, ORDWR);
2217dd7cddfSDavid du Colombier if(net < 0) {
2227dd7cddfSDavid du Colombier fprint(2, "con: cannot open %s: %r\n", dest);
2237dd7cddfSDavid du Colombier exits("open");
2247dd7cddfSDavid du Colombier }
2259a747e4fSDavid du Colombier snprint(cname, sizeof cname, "%sctl", dest);
2263e12c5d1SDavid du Colombier ctl = open(cname, ORDWR);
2279a747e4fSDavid du Colombier if (baud > 0) {
228f845c312SDavid du Colombier if(ctl >= 0){
229f845c312SDavid du Colombier /* set speed and use fifos if available */
230f845c312SDavid du Colombier fprint(ctl, "b%d i1", baud);
231f845c312SDavid du Colombier }
2329a747e4fSDavid du Colombier else
2339a747e4fSDavid du Colombier fprint(2, "con: cannot open %s: %r\n", cname);
2349a747e4fSDavid du Colombier }
2353e12c5d1SDavid du Colombier
2363e12c5d1SDavid du Colombier if(cmd)
2373e12c5d1SDavid du Colombier dosystem(net, cmd);
2383e12c5d1SDavid du Colombier
2393e12c5d1SDavid du Colombier if(!cooked)
2403e12c5d1SDavid du Colombier rawon();
2413e12c5d1SDavid du Colombier stdcon(net);
2423e12c5d1SDavid du Colombier exits(0);
2433e12c5d1SDavid du Colombier }
2443e12c5d1SDavid du Colombier
2453e12c5d1SDavid du Colombier /*
2463e12c5d1SDavid du Colombier * ignore interrupts
2473e12c5d1SDavid du Colombier */
2483e12c5d1SDavid du Colombier void
notifyf(void * a,char * msg)2493e12c5d1SDavid du Colombier notifyf(void *a, char *msg)
2503e12c5d1SDavid du Colombier {
2513e12c5d1SDavid du Colombier USED(a);
2523e12c5d1SDavid du Colombier
253d3c05884SDavid du Colombier if(strstr(msg, "yankee"))
254d3c05884SDavid du Colombier noted(NDFLT);
2553e12c5d1SDavid du Colombier if(strstr(msg, "closed pipe")
2563e12c5d1SDavid du Colombier || strcmp(msg, "interrupt") == 0
2573e12c5d1SDavid du Colombier || strcmp(msg, "hangup") == 0)
2583e12c5d1SDavid du Colombier noted(NCONT);
2593e12c5d1SDavid du Colombier noted(NDFLT);
2603e12c5d1SDavid du Colombier }
2613e12c5d1SDavid du Colombier
2623e12c5d1SDavid du Colombier /*
2633e12c5d1SDavid du Colombier * turn keyboard raw mode on
2643e12c5d1SDavid du Colombier */
2653e12c5d1SDavid du Colombier void
rawon(void)2663e12c5d1SDavid du Colombier rawon(void)
2673e12c5d1SDavid du Colombier {
2683e12c5d1SDavid du Colombier if(debug)
2693e12c5d1SDavid du Colombier fprint(2, "rawon\n");
2703e12c5d1SDavid du Colombier if(raw)
2713e12c5d1SDavid du Colombier return;
2723e12c5d1SDavid du Colombier if(consctl < 0)
2733e12c5d1SDavid du Colombier consctl = open("/dev/consctl", OWRITE);
2743e12c5d1SDavid du Colombier if(consctl < 0){
2759a747e4fSDavid du Colombier // fprint(2, "can't open consctl\n");
2763e12c5d1SDavid du Colombier return;
2773e12c5d1SDavid du Colombier }
2783e12c5d1SDavid du Colombier write(consctl, "rawon", 5);
2793e12c5d1SDavid du Colombier raw = 1;
2803e12c5d1SDavid du Colombier }
2813e12c5d1SDavid du Colombier
2823e12c5d1SDavid du Colombier /*
2833e12c5d1SDavid du Colombier * turn keyboard raw mode off
2843e12c5d1SDavid du Colombier */
2853e12c5d1SDavid du Colombier void
rawoff(void)2863e12c5d1SDavid du Colombier rawoff(void)
2873e12c5d1SDavid du Colombier {
2883e12c5d1SDavid du Colombier if(debug)
2893e12c5d1SDavid du Colombier fprint(2, "rawoff\n");
2903e12c5d1SDavid du Colombier if(raw == 0)
2913e12c5d1SDavid du Colombier return;
2923e12c5d1SDavid du Colombier if(consctl < 0)
2933e12c5d1SDavid du Colombier consctl = open("/dev/consctl", OWRITE);
2943e12c5d1SDavid du Colombier if(consctl < 0){
2959a747e4fSDavid du Colombier // fprint(2, "can't open consctl\n");
2963e12c5d1SDavid du Colombier return;
2973e12c5d1SDavid du Colombier }
2983e12c5d1SDavid du Colombier write(consctl, "rawoff", 6);
2993e12c5d1SDavid du Colombier raw = 0;
3003e12c5d1SDavid du Colombier }
3013e12c5d1SDavid du Colombier
3023e12c5d1SDavid du Colombier /*
3033e12c5d1SDavid du Colombier * control menu
3043e12c5d1SDavid du Colombier */
3057dd7cddfSDavid du Colombier #define STDHELP "\t(b)reak, (q)uit, (i)nterrupt, toggle printing (r)eturns, (.)continue, (!cmd)\n"
3063e12c5d1SDavid du Colombier
3073e12c5d1SDavid du Colombier int
menu(int net)3083e12c5d1SDavid du Colombier menu(int net)
3093e12c5d1SDavid du Colombier {
3103e12c5d1SDavid du Colombier char buf[MAXMSG];
3113e12c5d1SDavid du Colombier long n;
3123e12c5d1SDavid du Colombier int done;
3133e12c5d1SDavid du Colombier int wasraw = raw;
3143e12c5d1SDavid du Colombier
3153e12c5d1SDavid du Colombier if(wasraw)
3163e12c5d1SDavid du Colombier rawoff();
3173e12c5d1SDavid du Colombier
3183e12c5d1SDavid du Colombier fprint(2, ">>> ");
3193e12c5d1SDavid du Colombier for(done = 0; !done; ){
3203e12c5d1SDavid du Colombier n = read(0, buf, sizeof(buf)-1);
3213e12c5d1SDavid du Colombier if(n <= 0)
3223e12c5d1SDavid du Colombier return -1;
3233e12c5d1SDavid du Colombier buf[n] = 0;
3243e12c5d1SDavid du Colombier switch(buf[0]){
3253e12c5d1SDavid du Colombier case '!':
3263e12c5d1SDavid du Colombier print(buf);
3273e12c5d1SDavid du Colombier system(net, buf+1);
3283e12c5d1SDavid du Colombier print("!\n");
3293e12c5d1SDavid du Colombier done = 1;
3303e12c5d1SDavid du Colombier break;
3313e12c5d1SDavid du Colombier case '.':
3323e12c5d1SDavid du Colombier done = 1;
3333e12c5d1SDavid du Colombier break;
3343e12c5d1SDavid du Colombier case 'q':
3353e12c5d1SDavid du Colombier return -1;
3363e12c5d1SDavid du Colombier case 'i':
3373e12c5d1SDavid du Colombier buf[0] = 0x1c;
3383e12c5d1SDavid du Colombier write(net, buf, 1);
3393e12c5d1SDavid du Colombier done = 1;
3403e12c5d1SDavid du Colombier break;
3413e12c5d1SDavid du Colombier case 'b':
342*3b86f2f8SDavid du Colombier if(ctl >= 0)
343219b2ee8SDavid du Colombier write(ctl, "k", 1);
344219b2ee8SDavid du Colombier done = 1;
345219b2ee8SDavid du Colombier break;
346219b2ee8SDavid du Colombier case 'r':
347219b2ee8SDavid du Colombier returns = 1-returns;
3483e12c5d1SDavid du Colombier done = 1;
3493e12c5d1SDavid du Colombier break;
3503e12c5d1SDavid du Colombier default:
3513e12c5d1SDavid du Colombier fprint(2, STDHELP);
3523e12c5d1SDavid du Colombier break;
3533e12c5d1SDavid du Colombier }
3543e12c5d1SDavid du Colombier if(!done)
3553e12c5d1SDavid du Colombier fprint(2, ">>> ");
3563e12c5d1SDavid du Colombier }
3573e12c5d1SDavid du Colombier
3583e12c5d1SDavid du Colombier if(wasraw)
3593e12c5d1SDavid du Colombier rawon();
3603e12c5d1SDavid du Colombier else
3613e12c5d1SDavid du Colombier rawoff();
3623e12c5d1SDavid du Colombier return 0;
3633e12c5d1SDavid du Colombier }
3643e12c5d1SDavid du Colombier
365*3b86f2f8SDavid du Colombier void
post(char * srv,int fd)366*3b86f2f8SDavid du Colombier post(char *srv, int fd)
367*3b86f2f8SDavid du Colombier {
368*3b86f2f8SDavid du Colombier int f;
369*3b86f2f8SDavid du Colombier char buf[32];
370*3b86f2f8SDavid du Colombier
371*3b86f2f8SDavid du Colombier f = create(srv, OWRITE /* |ORCLOSE */ , 0666);
372*3b86f2f8SDavid du Colombier if(f < 0)
373*3b86f2f8SDavid du Colombier sysfatal("create %s: %r", srv);
374*3b86f2f8SDavid du Colombier snprint(buf, sizeof buf, "%d", fd);
375*3b86f2f8SDavid du Colombier if(write(f, buf, strlen(buf)) != strlen(buf))
376*3b86f2f8SDavid du Colombier sysfatal("write %s: %r", srv);
377*3b86f2f8SDavid du Colombier close(f);
378*3b86f2f8SDavid du Colombier }
379*3b86f2f8SDavid du Colombier
3803e12c5d1SDavid du Colombier /*
3813e12c5d1SDavid du Colombier * the real work. two processes pass bytes back and forth between the
3823e12c5d1SDavid du Colombier * terminal and the network.
3833e12c5d1SDavid du Colombier */
3843e12c5d1SDavid du Colombier void
stdcon(int net)3853e12c5d1SDavid du Colombier stdcon(int net)
3863e12c5d1SDavid du Colombier {
3873e12c5d1SDavid du Colombier int netpid;
388*3b86f2f8SDavid du Colombier int p[2];
389*3b86f2f8SDavid du Colombier char *svc;
3903e12c5d1SDavid du Colombier
391*3b86f2f8SDavid du Colombier svc = nil;
392*3b86f2f8SDavid du Colombier if (srv) {
393*3b86f2f8SDavid du Colombier if(pipe(p) < 0)
394*3b86f2f8SDavid du Colombier sysfatal("pipe: %r");
395*3b86f2f8SDavid du Colombier if (srv[0] != '/')
396*3b86f2f8SDavid du Colombier svc = smprint("/srv/%s", srv);
397*3b86f2f8SDavid du Colombier else
398*3b86f2f8SDavid du Colombier svc = srv;
399*3b86f2f8SDavid du Colombier post(svc, p[0]);
400*3b86f2f8SDavid du Colombier close(p[0]);
401*3b86f2f8SDavid du Colombier dup(p[1], 0);
402*3b86f2f8SDavid du Colombier dup(p[1], 1);
403*3b86f2f8SDavid du Colombier /* pipe is now std in & out */
404*3b86f2f8SDavid du Colombier }
4053e12c5d1SDavid du Colombier ttypid = getpid();
4063e12c5d1SDavid du Colombier switch(netpid = rfork(RFMEM|RFPROC)){
4073e12c5d1SDavid du Colombier case -1:
4083e12c5d1SDavid du Colombier perror("con");
4093e12c5d1SDavid du Colombier exits("fork");
4103e12c5d1SDavid du Colombier case 0:
4113e12c5d1SDavid du Colombier notify(notifyf);
4123e12c5d1SDavid du Colombier fromnet(net);
413*3b86f2f8SDavid du Colombier if (svc)
414*3b86f2f8SDavid du Colombier remove(svc);
415d3c05884SDavid du Colombier postnote(PNPROC, ttypid, "die yankee dog");
4163e12c5d1SDavid du Colombier exits(0);
4173e12c5d1SDavid du Colombier default:
4183e12c5d1SDavid du Colombier notify(notifyf);
4193e12c5d1SDavid du Colombier fromkbd(net);
420*3b86f2f8SDavid du Colombier if (svc)
421*3b86f2f8SDavid du Colombier remove(svc);
4227dd7cddfSDavid du Colombier if(notkbd)
423*3b86f2f8SDavid du Colombier for(;;)
424*3b86f2f8SDavid du Colombier sleep(0);
425d3c05884SDavid du Colombier postnote(PNPROC, netpid, "die yankee dog");
4263e12c5d1SDavid du Colombier exits(0);
4273e12c5d1SDavid du Colombier }
4283e12c5d1SDavid du Colombier }
4293e12c5d1SDavid du Colombier
4303e12c5d1SDavid du Colombier /*
4313e12c5d1SDavid du Colombier * Read the keyboard and write it to the network. '^\' gets us into
4323e12c5d1SDavid du Colombier * the menu.
4333e12c5d1SDavid du Colombier */
4343e12c5d1SDavid du Colombier void
fromkbd(int net)4353e12c5d1SDavid du Colombier fromkbd(int net)
4363e12c5d1SDavid du Colombier {
4373e12c5d1SDavid du Colombier long n;
4383e12c5d1SDavid du Colombier char buf[MAXMSG];
4397dd7cddfSDavid du Colombier char *p, *ep;
4407dd7cddfSDavid du Colombier int eofs;
4413e12c5d1SDavid du Colombier
4427dd7cddfSDavid du Colombier eofs = 0;
4433e12c5d1SDavid du Colombier for(;;){
4443e12c5d1SDavid du Colombier n = read(0, buf, sizeof(buf));
4453e12c5d1SDavid du Colombier if(n < 0){
4463e12c5d1SDavid du Colombier if(wasintr()){
447d3c05884SDavid du Colombier if(!raw){
4483e12c5d1SDavid du Colombier buf[0] = 0x7f;
4493e12c5d1SDavid du Colombier n = 1;
4503e12c5d1SDavid du Colombier } else
4513e12c5d1SDavid du Colombier continue;
4523e12c5d1SDavid du Colombier } else
4533e12c5d1SDavid du Colombier return;
4543e12c5d1SDavid du Colombier }
4557dd7cddfSDavid du Colombier if(n == 0){
4567dd7cddfSDavid du Colombier if(++eofs > 32)
4577dd7cddfSDavid du Colombier return;
4587dd7cddfSDavid du Colombier } else
4597dd7cddfSDavid du Colombier eofs = 0;
4603e12c5d1SDavid du Colombier if(n && memchr(buf, 0x1c, n)){
4613e12c5d1SDavid du Colombier if(menu(net) < 0)
4623e12c5d1SDavid du Colombier return;
4633e12c5d1SDavid du Colombier }else{
464d3c05884SDavid du Colombier if(!raw && n==0){
4653e12c5d1SDavid du Colombier buf[0] = 0x4;
4663e12c5d1SDavid du Colombier n = 1;
4673e12c5d1SDavid du Colombier }
4687dd7cddfSDavid du Colombier if(nltocr){
4697dd7cddfSDavid du Colombier ep = buf+n;
4707dd7cddfSDavid du Colombier for(p = buf; p < ep; p++)
4717dd7cddfSDavid du Colombier switch(*p){
4727dd7cddfSDavid du Colombier case '\r':
4737dd7cddfSDavid du Colombier *p = '\n';
4747dd7cddfSDavid du Colombier break;
4757dd7cddfSDavid du Colombier case '\n':
4767dd7cddfSDavid du Colombier *p = '\r';
4777dd7cddfSDavid du Colombier break;
4787dd7cddfSDavid du Colombier }
4797dd7cddfSDavid du Colombier }
4803e12c5d1SDavid du Colombier if(iwrite(net, buf, n) != n)
4813e12c5d1SDavid du Colombier return;
4823e12c5d1SDavid du Colombier }
4833e12c5d1SDavid du Colombier }
4843e12c5d1SDavid du Colombier }
4853e12c5d1SDavid du Colombier
4863e12c5d1SDavid du Colombier /*
4873e12c5d1SDavid du Colombier * Read from the network and write to the screen.
4883e12c5d1SDavid du Colombier * Filter out spurious carriage returns.
4893e12c5d1SDavid du Colombier */
4903e12c5d1SDavid du Colombier void
fromnet(int net)4913e12c5d1SDavid du Colombier fromnet(int net)
4923e12c5d1SDavid du Colombier {
4933e12c5d1SDavid du Colombier long n;
4943e12c5d1SDavid du Colombier char buf[MAXMSG];
4953e12c5d1SDavid du Colombier char *cp, *ep;
4963e12c5d1SDavid du Colombier
4973e12c5d1SDavid du Colombier for(;;){
4983e12c5d1SDavid du Colombier n = iread(net, buf, sizeof(buf));
4993e12c5d1SDavid du Colombier if(n < 0)
5003e12c5d1SDavid du Colombier return;
5013e12c5d1SDavid du Colombier if(n == 0)
5023e12c5d1SDavid du Colombier continue;
5033e12c5d1SDavid du Colombier
504219b2ee8SDavid du Colombier if (strip)
505219b2ee8SDavid du Colombier for (cp=buf; cp<buf+n; cp++)
506219b2ee8SDavid du Colombier *cp &= 0177;
507219b2ee8SDavid du Colombier
5085d459b5aSDavid du Colombier if(crtonl) {
5095d459b5aSDavid du Colombier /* convert cr's to nl's */
5105d459b5aSDavid du Colombier for (cp = buf; cp < buf + n; cp++)
5115d459b5aSDavid du Colombier if (*cp == '\r')
5125d459b5aSDavid du Colombier *cp = '\n';
5135d459b5aSDavid du Colombier }
5145d459b5aSDavid du Colombier else if(!returns){
5153e12c5d1SDavid du Colombier /* convert cr's to null's */
5163e12c5d1SDavid du Colombier cp = buf;
5173e12c5d1SDavid du Colombier ep = buf + n;
5183e12c5d1SDavid du Colombier while(cp < ep && (cp = memchr(cp, '\r', ep-cp))){
5193e12c5d1SDavid du Colombier memmove(cp, cp+1, ep-cp-1);
5203e12c5d1SDavid du Colombier ep--;
5213e12c5d1SDavid du Colombier n--;
5223e12c5d1SDavid du Colombier }
5233e12c5d1SDavid du Colombier }
5243e12c5d1SDavid du Colombier
5253e12c5d1SDavid du Colombier if(n > 0 && iwrite(outfd, buf, n) != n){
5263e12c5d1SDavid du Colombier if(outfd == 1)
5273e12c5d1SDavid du Colombier return;
5283e12c5d1SDavid du Colombier outfd = 1;
5293e12c5d1SDavid du Colombier if(iwrite(1, buf, n) != n)
5303e12c5d1SDavid du Colombier return;
5313e12c5d1SDavid du Colombier }
5323e12c5d1SDavid du Colombier }
5333e12c5d1SDavid du Colombier }
5343e12c5d1SDavid du Colombier
5353e12c5d1SDavid du Colombier /*
5363e12c5d1SDavid du Colombier * dial and return a data connection
5373e12c5d1SDavid du Colombier */
5383e12c5d1SDavid du Colombier int
dodial(char * dest,char * net,char * service)5393e12c5d1SDavid du Colombier dodial(char *dest, char *net, char *service)
5403e12c5d1SDavid du Colombier {
5419a747e4fSDavid du Colombier char name[128];
5429a747e4fSDavid du Colombier char devdir[128];
5433e12c5d1SDavid du Colombier int data;
5443e12c5d1SDavid du Colombier
5453e12c5d1SDavid du Colombier devdir[0] = 0;
5463e12c5d1SDavid du Colombier strcpy(name, netmkaddr(dest, net, service));
547bd389b36SDavid du Colombier data = dial(name, 0, devdir, &ctl);
5483e12c5d1SDavid du Colombier if(data < 0){
549219b2ee8SDavid du Colombier seterr(name);
5503e12c5d1SDavid du Colombier return -1;
5513e12c5d1SDavid du Colombier }
5523e12c5d1SDavid du Colombier fprint(2, "connected to %s on %s\n", name, devdir);
5533e12c5d1SDavid du Colombier return data;
5543e12c5d1SDavid du Colombier }
5553e12c5d1SDavid du Colombier
5563e12c5d1SDavid du Colombier void
dosystem(int fd,char * cmd)5573e12c5d1SDavid du Colombier dosystem(int fd, char *cmd)
5583e12c5d1SDavid du Colombier {
5593e12c5d1SDavid du Colombier char *p;
5603e12c5d1SDavid du Colombier
5613e12c5d1SDavid du Colombier p = system(fd, cmd);
562fbdb243dSDavid du Colombier if(p){
5637dd7cddfSDavid du Colombier print("con: %s terminated with %s\n", cmd, p);
5643e12c5d1SDavid du Colombier exits(p);
5653e12c5d1SDavid du Colombier }
5663e12c5d1SDavid du Colombier }
5673e12c5d1SDavid du Colombier
5683e12c5d1SDavid du Colombier /*
5693e12c5d1SDavid du Colombier * run a command with the network connection as standard IO
5703e12c5d1SDavid du Colombier */
5713e12c5d1SDavid du Colombier char *
system(int fd,char * cmd)5723e12c5d1SDavid du Colombier system(int fd, char *cmd)
5733e12c5d1SDavid du Colombier {
5743e12c5d1SDavid du Colombier int pid;
5753e12c5d1SDavid du Colombier int p;
5763e12c5d1SDavid du Colombier static Waitmsg msg;
5773e12c5d1SDavid du Colombier int pfd[2];
5783e12c5d1SDavid du Colombier int n;
5793e12c5d1SDavid du Colombier char buf[4096];
5803e12c5d1SDavid du Colombier
5813e12c5d1SDavid du Colombier if(pipe(pfd) < 0){
5823e12c5d1SDavid du Colombier perror("pipe");
5833e12c5d1SDavid du Colombier return "pipe failed";
5843e12c5d1SDavid du Colombier }
5853e12c5d1SDavid du Colombier outfd = pfd[1];
5863e12c5d1SDavid du Colombier
587219b2ee8SDavid du Colombier close(consctl);
588219b2ee8SDavid du Colombier consctl = -1;
5893e12c5d1SDavid du Colombier switch(pid = fork()){
5903e12c5d1SDavid du Colombier case -1:
5913e12c5d1SDavid du Colombier perror("con");
5923e12c5d1SDavid du Colombier return "fork failed";
5933e12c5d1SDavid du Colombier case 0:
5943e12c5d1SDavid du Colombier close(pfd[1]);
5953e12c5d1SDavid du Colombier dup(pfd[0], 0);
5963ff48bf5SDavid du Colombier dup(fd, 1);
5973e12c5d1SDavid du Colombier close(ctl);
5983e12c5d1SDavid du Colombier close(fd);
5993e12c5d1SDavid du Colombier close(pfd[0]);
6003e12c5d1SDavid du Colombier if(*cmd)
601f19e7b74SDavid du Colombier execl("/bin/rc", "rc", "-c", cmd, nil);
6023e12c5d1SDavid du Colombier else
603f19e7b74SDavid du Colombier execl("/bin/rc", "rc", nil);
6043e12c5d1SDavid du Colombier perror("con");
6053e12c5d1SDavid du Colombier exits("exec");
6063e12c5d1SDavid du Colombier break;
6073e12c5d1SDavid du Colombier default:
6083e12c5d1SDavid du Colombier close(pfd[0]);
609*3b86f2f8SDavid du Colombier while((n = read(pfd[1], buf, sizeof(buf))) > 0)
6103e12c5d1SDavid du Colombier if(write(fd, buf, n) != n)
6113e12c5d1SDavid du Colombier break;
6129a747e4fSDavid du Colombier p = waitpid();
6133e12c5d1SDavid du Colombier outfd = 1;
6143e12c5d1SDavid du Colombier close(pfd[1]);
615219b2ee8SDavid du Colombier if(p < 0 || p != pid)
616219b2ee8SDavid du Colombier return "lost child";
6173e12c5d1SDavid du Colombier break;
6183e12c5d1SDavid du Colombier }
619219b2ee8SDavid du Colombier return msg.msg;
6203e12c5d1SDavid du Colombier }
6213e12c5d1SDavid du Colombier
6223e12c5d1SDavid du Colombier int
wasintr(void)6233e12c5d1SDavid du Colombier wasintr(void)
6243e12c5d1SDavid du Colombier {
6253e12c5d1SDavid du Colombier return strcmp(syserr(), "interrupted") == 0;
6263e12c5d1SDavid du Colombier }
6273e12c5d1SDavid du Colombier
6283e12c5d1SDavid du Colombier void
punt(char * msg)6293e12c5d1SDavid du Colombier punt(char *msg)
6303e12c5d1SDavid du Colombier {
6313e12c5d1SDavid du Colombier if(*msg == 0)
6323e12c5d1SDavid du Colombier msg = transerr;
6333e12c5d1SDavid du Colombier fprint(2, "con: %s\n", msg);
6343e12c5d1SDavid du Colombier exits(msg);
6353e12c5d1SDavid du Colombier }
6363e12c5d1SDavid du Colombier
6373e12c5d1SDavid du Colombier char*
syserr(void)6383e12c5d1SDavid du Colombier syserr(void)
6393e12c5d1SDavid du Colombier {
6409a747e4fSDavid du Colombier static char err[ERRMAX];
6419a747e4fSDavid du Colombier errstr(err, sizeof err);
6423e12c5d1SDavid du Colombier return err;
6433e12c5d1SDavid du Colombier }
6443e12c5d1SDavid du Colombier
6453e12c5d1SDavid du Colombier void
seterr(char * addr)646219b2ee8SDavid du Colombier seterr(char *addr)
6473e12c5d1SDavid du Colombier {
6483e12c5d1SDavid du Colombier char *se = syserr();
6493e12c5d1SDavid du Colombier
6503e12c5d1SDavid du Colombier if(verbose)
651219b2ee8SDavid du Colombier fprint(2, "'%s' calling %s\n", se, addr);
6523e12c5d1SDavid du Colombier if(firsterr[0] && (strstr(se, "translate") ||
6533e12c5d1SDavid du Colombier strstr(se, "file does not exist") ||
6543e12c5d1SDavid du Colombier strstr(se, "unknown address") ||
6553e12c5d1SDavid du Colombier strstr(se, "directory entry not found")))
6563e12c5d1SDavid du Colombier return;
6573e12c5d1SDavid du Colombier strcpy(firsterr, se);
6583e12c5d1SDavid du Colombier }
6593e12c5d1SDavid du Colombier
6603e12c5d1SDavid du Colombier
6613e12c5d1SDavid du Colombier long
iread(int f,void * a,int n)6623e12c5d1SDavid du Colombier iread(int f, void *a, int n)
6633e12c5d1SDavid du Colombier {
6643e12c5d1SDavid du Colombier long m;
6653e12c5d1SDavid du Colombier
6663e12c5d1SDavid du Colombier for(;;){
6673e12c5d1SDavid du Colombier m = read(f, a, n);
6683e12c5d1SDavid du Colombier if(m >= 0 || !wasintr())
6693e12c5d1SDavid du Colombier break;
6703e12c5d1SDavid du Colombier }
6713e12c5d1SDavid du Colombier return m;
6723e12c5d1SDavid du Colombier }
6733e12c5d1SDavid du Colombier
6743e12c5d1SDavid du Colombier long
iwrite(int f,void * a,int n)6753e12c5d1SDavid du Colombier iwrite(int f, void *a, int n)
6763e12c5d1SDavid du Colombier {
6773e12c5d1SDavid du Colombier long m;
6783e12c5d1SDavid du Colombier
6793e12c5d1SDavid du Colombier m = write(f, a, n);
6803e12c5d1SDavid du Colombier if(m < 0 && wasintr())
6813e12c5d1SDavid du Colombier return n;
6823e12c5d1SDavid du Colombier return m;
6833e12c5d1SDavid du Colombier }
684