|
|
1.1 ! root 1: #include <sys/types.h> ! 2: #include <sys/stream.h> ! 3: #include <sys/stat.h> ! 4: #include <sys/ttyio.h> ! 5: #include <sys/filio.h> ! 6: #include <sys/dkio.h> ! 7: #include <stdio.h> ! 8: #include <errno.h> ! 9: #include <signal.h> ! 10: #include <ipc.h> ! 11: #include <libc.h> ! 12: #include <utsname.h> ! 13: ! 14: /* ! 15: * program to connect to ! 16: * another cpu on Datakit w/ transparent ioctls ! 17: */ ! 18: ! 19: int rem=-1; /* remote file descriptor */ ! 20: extern int mesg_ld; ! 21: struct sgttyb sgbuf; ! 22: struct tchars tcbuf; ! 23: int ttyrem=0; /* true if tty ld is remote */ ! 24: char *ttyn; ! 25: int perms; ! 26: ! 27: struct sigmsg { ! 28: struct mesg m; ! 29: char sig[1]; ! 30: }; ! 31: ! 32: struct buffer { ! 33: int rfd,wfd; ! 34: int rmesgld; ! 35: int wmesgld; ! 36: char *rptr; ! 37: char *wptr; ! 38: char data[4096+MSGHLEN]; ! 39: }; ! 40: static struct buffer ttyb; ! 41: static struct buffer netb; ! 42: ! 43: struct mesg *getmsg(); ! 44: int fillbuf(); ! 45: ! 46: #define msglen(mp) ((mp)->losize + ((mp)->hisize<<8)) ! 47: ! 48: int lfd; ! 49: char *av0; ! 50: int notdef; ! 51: int (*quitsig)(); ! 52: int debug; ! 53: ! 54: usage() ! 55: { ! 56: fprintf(stderr, "usage: %s [-l] host\n", av0); ! 57: exit(1); ! 58: } ! 59: ! 60: main(argc, argv) ! 61: char **argv; ! 62: { ! 63: char *host; ! 64: struct stat sb; ! 65: int all, ld, nold; ! 66: extern int hupcatch(); ! 67: char *ttyname(); ! 68: ! 69: nold = 0; ! 70: av0 = strrchr(argv[0], '/'); ! 71: av0 = av0==NULL ? argv[0] : av0+1; ! 72: while(argc>1 && argv[1][0]=='-'){ ! 73: char *cp; ! 74: for(cp=&argv[1][1]; *cp; cp++) ! 75: switch (*cp) { ! 76: case 'l': ! 77: av0 = "con -l"; ! 78: break; ! 79: case 'd': ! 80: debug = 1; ! 81: close(2); ! 82: creat("/tmp/con.debug", 0666); ! 83: break; ! 84: case 'n': ! 85: nold = 1; ! 86: break; ! 87: default: ! 88: usage(); ! 89: } ! 90: argv++; ! 91: argc--; ! 92: } ! 93: host=argv[1]; ! 94: if(strcmp(host, "helix")==0 ! 95: || strcmp(host, "spindle")==0 ! 96: || strcmp(host, "hobocpu")==0 ! 97: || strcmp(host, "fornax")==0) ! 98: av0 = "dcon"; ! 99: /* ! 100: if (host==NULL) ! 101: usage(); ! 102: */ ! 103: ioctl(0, TIOCGETP, &sgbuf); ! 104: ioctl(0, TIOCGETC, &tcbuf); ! 105: quitsig = signal(SIGQUIT, hupcatch); ! 106: ! 107: all = strcmp(av0, "con")==0; ! 108: if (strcmp(av0, "nogin")==0) ! 109: rem = trynogin(host); ! 110: if (all || strcmp(av0, "ndcon")==0) ! 111: rem = trymesg(host); ! 112: if (rem<0 && (all || strcmp(av0, "dcon")==0)) ! 113: rem = trynomesg(host); ! 114: /* ! 115: if (rem<0 && (all || strcmp(av0, "9con")==0)) ! 116: rem = try9con(host); ! 117: */ ! 118: if (rem<0 && (all || strcmp(av0, "rogin")==0 || strcmp(av0, "rlogin")==0)) ! 119: rem = tryrogin(host); ! 120: if (rem<0 && (all || strcmp(av0, "con -l")==0)) ! 121: rem = trysimple(host); ! 122: if (rem<0) { ! 123: fprintf(stderr, "%s: %s connecting to %s\n", av0, errstr, host); ! 124: exit(1); ! 125: } ! 126: ! 127: /* ! 128: * we really have to avoid leaving mesg_ld's pushed ! 129: */ ! 130: signal(SIGHUP, hupcatch); ! 131: signal(SIGPIPE, hupcatch); ! 132: if ((ttyn = ttyname(0)) != NULL ! 133: && stat(ttyn, &sb) >= 0) { ! 134: perms = sb.st_mode & ~S_IFMT; ! 135: chmod(ttyn, 0); ! 136: } ! 137: ! 138: /* ! 139: * push mesg_ld onto stdin and stdout if possible ! 140: */ ! 141: ttyb.rmesgld = ttyb.wmesgld = netb.rmesgld = netb.wmesgld = 0; ! 142: if (!nold){ ! 143: /* race ahead possible */ ! 144: ioctl(0, TIOCFLUSH, (char *)0); ! 145: if(ioctl(0, FIOPUSHLD, &mesg_ld)>=0) ! 146: ttyb.rmesgld=1; ! 147: if(ioctl(1, FIOLOOKLD, &ld)>=0 ! 148: && (ld==mesg_ld || ioctl(1, FIOPUSHLD, &mesg_ld)>=0)) ! 149: ttyb.wmesgld=1; ! 150: } ! 151: ! 152: /* ! 153: * see if remote side accepts mesg_ld packets ! 154: */ ! 155: netb.rmesgld = netb.wmesgld = ttyrem==0; ! 156: if(debug) ! 157: fprintf(stderr, "connected\n"); ! 158: go(rem); ! 159: finish(0); ! 160: /* NOTREACHED */ ! 161: } ! 162: ! 163: /* try to set up a message line discipline connection */ ! 164: trymesg(host) ! 165: char *host; ! 166: { ! 167: int fd; ! 168: ! 169: fd = ipcopen(ipcpath(host, "dk", "mesgdcon"), "light hup"); ! 170: if (fd<0) ! 171: return fd; ! 172: if (ipclogin(fd)<0) { ! 173: fprintf(stderr, "%s: can't log in\n", av0); ! 174: exit(1); ! 175: } ! 176: return fd; ! 177: } ! 178: ! 179: /* try to set up a no line discipline connection */ ! 180: trynomesg(host) ! 181: char *host; ! 182: { ! 183: int fd; ! 184: ! 185: fd = ipcopen(ipcpath(host, "dk", "dcon"), "light hup"); ! 186: if (fd<0) ! 187: return fd; ! 188: if (ipclogin(fd)<0) { ! 189: fprintf(stderr, "%s: can't log in\n", av0); ! 190: exit(1); ! 191: } ! 192: remtty(fd); ! 193: return fd; ! 194: } ! 195: ! 196: /* ! 197: * try to set up an dcon-like connection with local echo ! 198: */ ! 199: try9con(host) ! 200: char *host; ! 201: { ! 202: int fd; ! 203: char service[256]; ! 204: ! 205: sprintf(service, "nonet!%s", host); ! 206: fd = ipcopen(ipcpath("r70", "dk", service), "light hup bsdauth"); ! 207: if (fd<0) ! 208: return fd; ! 209: ttyrem = 1; ! 210: return fd; ! 211: } ! 212: ! 213: /* ! 214: * try to set up an rlogin-like connection with local echo ! 215: * ! 216: * the authentication string is passwd by ipcopen because of the bsdauth ! 217: * parameter. The ipcrogin passes the terminal type and gets the authentication ! 218: * reply. ! 219: */ ! 220: trynogin(host) ! 221: char *host; ! 222: { ! 223: int fd; ! 224: char *term; ! 225: ! 226: fd = ipcopen(ipcpath(host, "tcp", "login"), "light hup bsdauth"); ! 227: if (fd<0) ! 228: return fd; ! 229: term = getenv("TERM"); ! 230: ipcrogin(fd, term?term:""); ! 231: ttyrem = 1; ! 232: return fd; ! 233: } ! 234: ! 235: /* ! 236: * try to set up a rlogin-like connection with remote echo ! 237: */ ! 238: tryrogin(host) ! 239: char *host; ! 240: { ! 241: int fd; ! 242: char *term; ! 243: ! 244: fd = ipcopen(ipcpath(host, "tcp", "login"), "light hup bsdauth"); ! 245: if (fd<0) ! 246: return fd; ! 247: term = getenv("TERM"); ! 248: ipcrogin(fd, term?term:""); ! 249: remtty(fd); ! 250: return fd; ! 251: } ! 252: ! 253: /* try to set up a non-authenticated connection */ ! 254: trysimple(host) ! 255: char *host; ! 256: { ! 257: int fd; ! 258: ! 259: fd = ipcopen(ipcpath(host, "dk", ""), "light hup 1200"); ! 260: if (fd<0) ! 261: return fd; ! 262: remtty(fd); ! 263: return fd; ! 264: } ! 265: ! 266: /* set up for tty control to be remote */ ! 267: remtty(fd) ! 268: { ! 269: struct sgttyb sg; ! 270: struct tchars tc; ! 271: ! 272: sg = sgbuf; ! 273: sg.sg_flags &= ~(CRMOD|ECHO|XTABS); ! 274: sg.sg_flags |= CBREAK; ! 275: ioctl(0, TIOCSETP, &sg); ! 276: tc.t_quitc = tcbuf.t_quitc; ! 277: tc.t_intrc = tc.t_startc = tc.t_stopc = tc.t_eofc = tc.t_brkc = -1; ! 278: ioctl(0, TIOCSETC, &tc); ! 279: ttyrem = 1; ! 280: /* ! 281: * HACK!!!! to make select work when connected to a ! 282: * delimited stream --- turn off delimiters. ! 283: */ ! 284: ioctl(fd, DIOCSTREAM, 0); ! 285: } ! 286: ! 287: ! 288: go(fd) ! 289: { ! 290: int rbits, wbits; ! 291: struct mesg *mp; ! 292: int dgenerated=0; ! 293: int lasttype=0; ! 294: ! 295: wbits = 0; ! 296: ttyb.rptr = ttyb.wptr = ttyb.data; ! 297: ttyb.rfd = 0; ! 298: ttyb.wfd = 1; ! 299: netb.rptr = netb.wptr = netb.data; ! 300: netb.rfd = fd; ! 301: netb.wfd = fd; ! 302: while(1){ ! 303: rbits = 1 | (1<<fd); ! 304: if(select(20, (fd_set*)&rbits, (fd_set*)&wbits, 20000) < 0){ ! 305: if(errno != EINTR) ! 306: return; ! 307: continue; ! 308: } ! 309: if(rbits & 1) ! 310: if (fillbuf(&ttyb)<0) ! 311: return; ! 312: if(rbits & (1<<fd)) ! 313: if (fillbuf(&netb)<0) ! 314: return; ! 315: while(mp = getmsg(&ttyb)) { ! 316: if (mp->type==M_DELIM) { ! 317: if (ttyrem && lasttype==M_DELIM) { ! 318: sendmsg(&netb, M_DATA, &tcbuf.t_eofc, 1); ! 319: continue; ! 320: } ! 321: } ! 322: lasttype = mp->type; ! 323: if (mp->type==M_SIGNAL) ! 324: switch(((struct sigmsg *)mp)->sig[0]) { ! 325: case SIGQUIT: ! 326: dolocal(mp); ! 327: continue; ! 328: case SIGINT: ! 329: if(!ttyrem) ! 330: break; ! 331: sendmsg(&netb, M_DATA, &tcbuf.t_intrc, 1); ! 332: continue; ! 333: } ! 334: mp->magic = MSGMAGIC; /* temp safety */ ! 335: if(writemsg(&netb, mp)<0) ! 336: return; ! 337: if(!ttyrem && mp->type == M_FLUSH) { ! 338: remflush(); ! 339: rbits = 0; ! 340: } ! 341: } ! 342: while(mp = getmsg(&netb)){ ! 343: if(mp->type == M_HANGUP) ! 344: return; ! 345: if(mp->type == M_IOCTL){ ! 346: doioctl(mp); ! 347: } else if(dgenerated && mp->type==M_DELIM){ ! 348: dgenerated = 0; ! 349: } else { ! 350: if(writemsg(&ttyb, mp)<0) ! 351: return; ! 352: if(mp->type==M_DATA) { ! 353: sendmsg(&ttyb, M_DELIM, (char *)mp, 0); ! 354: dgenerated = 1; ! 355: } ! 356: } ! 357: } ! 358: } ! 359: } ! 360: ! 361: /* read in at least a complete message */ ! 362: fillbuf(bp) ! 363: register struct buffer *bp; ! 364: { ! 365: register int n; ! 366: struct mesg *mp; ! 367: static int neofs; ! 368: ! 369: if(!bp->rmesgld) { ! 370: bp->rptr = bp->data; ! 371: bp->wptr = bp->data+MSGHLEN; ! 372: mp = (struct mesg *)bp->rptr; ! 373: } else { ! 374: /* compact */ ! 375: n = bp->wptr-bp->rptr; ! 376: if (n > 0 && bp->rptr!=bp->data) ! 377: memcpy(bp->data, bp->rptr, n); ! 378: bp->rptr = bp->data; ! 379: bp->wptr = bp->rptr + n; ! 380: } ! 381: ! 382: /* try reading */ ! 383: n = bp->data+sizeof(bp->data) - bp->wptr; ! 384: if (n > 0) { ! 385: if(debug) ! 386: fprintf(stderr, "read(%d)\n", bp->rfd); ! 387: n = read(bp->rfd, bp->wptr, n); ! 388: if(debug){ ! 389: char *cp; ! 390: fprintf(stderr, "read(%d) returns %d\n", bp->rfd, n); ! 391: for(cp = bp->wptr; cp < bp->wptr+n; cp++) ! 392: fprintf(stderr, "<%o>\n", *cp); ! 393: } ! 394: if(n<=0){ ! 395: if(n<0 || ++neofs>4) ! 396: return -1; ! 397: if(!bp->rmesgld) ! 398: bp->wptr-=MSGHLEN; ! 399: } ! 400: bp->wptr += n; ! 401: } else ! 402: neofs = 0; ! 403: ! 404: if(!bp->rmesgld) { ! 405: mp->type = M_DATA; ! 406: mp->magic = MSGMAGIC; ! 407: setmsgl(mp, n); ! 408: } ! 409: return 0; ! 410: } ! 411: ! 412: /* get the next (buffered) message */ ! 413: struct mesg * ! 414: getmsg(bp) ! 415: struct buffer *bp; ! 416: { ! 417: struct mesg *mp = (struct mesg *)bp->rptr; ! 418: int n = bp->wptr - bp->rptr; ! 419: ! 420: if (n<MSGHLEN || n<MSGHLEN+msglen(mp)) { ! 421: if (msglen(mp)+MSGHLEN > sizeof(bp->data)) ! 422: bp->rptr = bp->wptr = bp->data; ! 423: return NULL; ! 424: } ! 425: bp->rptr += MSGHLEN + msglen(mp); ! 426: mp->magic = MSGMAGIC; ! 427: return mp; ! 428: } ! 429: ! 430: int ! 431: writemsg(bp, mp) ! 432: struct buffer *bp; ! 433: struct mesg *mp; ! 434: { ! 435: int len,n; ! 436: char *cp; ! 437: ! 438: if(bp->wmesgld) { ! 439: len = MSGHLEN + msglen(mp); ! 440: cp = (char *)mp; ! 441: } else if(mp->type==M_DATA){ ! 442: len = msglen(mp); ! 443: cp = ((char *)mp)+MSGHLEN; ! 444: } else ! 445: return 0; ! 446: if(debug) ! 447: fprintf(stderr, "write(%d)\n", bp->wfd); ! 448: n=write(bp->wfd, cp, len); ! 449: if(debug) ! 450: fprintf(stderr, "write(%d) returns %d\n", bp->wfd, n); ! 451: if(n!=len) ! 452: return -1; ! 453: return 0; ! 454: } ! 455: ! 456: doioctl(mp) ! 457: struct mesg *mp; ! 458: { ! 459: struct iofoo{ ! 460: int cmd; ! 461: union{ ! 462: int i; ! 463: char errno; ! 464: struct insld insld; ! 465: } u; ! 466: } *iop; ! 467: int cmd, ld; ! 468: int n; ! 469: ! 470: iop = (struct iofoo *)(((char*)mp) + MSGHLEN); ! 471: cmd = iop->cmd; ! 472: n = msglen(mp); ! 473: n -= sizeof(iop->cmd); ! 474: switch(cmd){ ! 475: case FIOLOOKLD: ! 476: if(n > 0) ! 477: ld = iop->u.i; ! 478: else ! 479: ld = 0; ! 480: ld++; ! 481: if(ioctl(1, FIOLOOKLD, &ld) < 0) ! 482: goto bad; ! 483: iop->cmd = ld; ! 484: n = sizeof(iop->cmd); ! 485: break; ! 486: ! 487: case FIOPOPLD: ! 488: if(n > 0) ! 489: ld = iop->u.i; ! 490: else ! 491: ld = 0; ! 492: ld++; ! 493: if(ioctl(1, FIOPOPLD, &ld) < 0) ! 494: goto bad; ! 495: n = 0; ! 496: break; ! 497: ! 498: case FIOPUSHLD: ! 499: iop->u.insld.level = 0; ! 500: /* fall through... */ ! 501: case FIOINSLD: ! 502: iop->u.insld.level++; ! 503: if(ioctl(1, FIOINSLD, &(iop->u.insld)) < 0) ! 504: goto bad; ! 505: n = 0; ! 506: break; ! 507: ! 508: default: ! 509: mp->magic = MSGMAGIC; /* safety */ ! 510: writemsg(&ttyb, mp); ! 511: return; ! 512: } ! 513: /* locally successful */ ! 514: mp->type = M_IOCACK; ! 515: mp->magic = MSGMAGIC; ! 516: setmsgl(mp, n); ! 517: writemsg(&netb, mp); ! 518: return; ! 519: bad: ! 520: mp->type = M_IOCNAK; ! 521: mp->magic = MSGMAGIC; ! 522: setmsgl(mp, sizeof(struct iofoo)); ! 523: iop->u.errno = errno; ! 524: writemsg(&netb, mp); ! 525: } ! 526: ! 527: remflush() ! 528: { ! 529: char buf[5000]; ! 530: struct mesg *mp; ! 531: ! 532: mp = (struct mesg *) buf; ! 533: mp->type = M_IOCTL; ! 534: setmsgl(mp, sizeof(int)); ! 535: mp->magic = MSGMAGIC; ! 536: writemsg(&netb, (struct mesg *)buf); ! 537: ! 538: while(read(rem, buf, sizeof(buf)) > 0){ ! 539: if(mp->type == M_HANGUP){ ! 540: close(rem); ! 541: return; ! 542: } ! 543: if(mp->type == M_IOCNAK || mp->type == M_IOCACK) ! 544: return; ! 545: } ! 546: } ! 547: ! 548: setmsgl(mp, n) ! 549: register struct mesg *mp; ! 550: int n; ! 551: { ! 552: mp->losize = n; ! 553: mp->hisize = n >> 8; ! 554: } ! 555: ! 556: hupcatch() ! 557: { ! 558: finish(0); ! 559: } ! 560: ! 561: finish(sts) ! 562: { ! 563: struct mesg m; ! 564: ! 565: if(ioctl(0, FIOLOOKLD, 0) == mesg_ld) { ! 566: ioctl(0, FIOPOPLD, 0); ! 567: ioctl(0, TIOCFLUSH, (char *)0); ! 568: } ! 569: if(ioctl(1, FIOLOOKLD, 0) == mesg_ld) ! 570: ioctl(1, FIOPOPLD, 0); ! 571: if (ttyn) ! 572: chmod(ttyn, perms); ! 573: ioctl(0, TIOCSETP, &sgbuf); ! 574: ioctl(0, TIOCSETC, &tcbuf); ! 575: signal(SIGQUIT, quitsig); ! 576: if(sts==0) ! 577: write(2, "Eof\n", 4); ! 578: exit(sts); ! 579: } ! 580: ! 581: dolocal(mp) ! 582: register struct mesg *mp; ! 583: { ! 584: char lbuf[128+1]; ! 585: register char *lp; ! 586: struct sgttyb nsgbuf; ! 587: struct tchars ntcbuf; ! 588: int done; ! 589: static char prompt[32]; ! 590: struct utsname uts; ! 591: ! 592: ! 593: ioctl(0, FIOPOPLD, (char *)0); ! 594: signal(SIGQUIT, quitsig); ! 595: ioctl(0, TIOCFLUSH, (char *)0); ! 596: ioctl(0, TIOCGETP, &nsgbuf); ! 597: ioctl(0, TIOCSETP, &sgbuf); ! 598: ioctl(0, TIOCGETC, &ntcbuf); ! 599: ioctl(0, TIOCSETC, &tcbuf); ! 600: if(prompt[0]==0){ ! 601: uname(&uts); ! 602: strncpy(prompt, uts.nodename, sizeof(uts.nodename)); ! 603: prompt[sizeof(uts.nodename)] = 0; ! 604: strcat(prompt, ">> "); ! 605: } ! 606: if (ttyn) ! 607: chmod(ttyn, perms); ! 608: for (done=0;!done;) { ! 609: lp = lbuf; ! 610: printf(prompt); ! 611: fflush(stdout); ! 612: while (lp < &lbuf[128] && read(0, lp, 1)>0 && *lp!='\n') ! 613: lp++; ! 614: *lp = '\0'; ! 615: switch(*lbuf) { ! 616: case 'b': ! 617: if (ttyrem) ! 618: ioctl(netb.wfd, TIOCSBRK, 0); ! 619: else ! 620: sendmsg(&netb, M_BREAK, (char *)NULL, 0); ! 621: mp->type = 0; ! 622: done = 1; ! 623: break; ! 624: case 'i': ! 625: if (ttyrem) { ! 626: sendmsg(&netb, M_DATA, &tcbuf.t_quitc, 1); ! 627: mp->type = 0; ! 628: } ! 629: done = 1; ! 630: break; ! 631: case 'q': ! 632: case 'x': ! 633: case '.': ! 634: finish(1); ! 635: case '!': ! 636: system(lbuf+1); ! 637: printf("!!\n"); ! 638: fflush(stdout); ! 639: mp->type = 0; ! 640: done = 1; ! 641: break; ! 642: case '\0': ! 643: mp->type = 0; ! 644: done = 1; ! 645: break; ! 646: default: ! 647: printf("[qx.] to exit, i for quit signal, b for break, !cmd for shell\n"); ! 648: fflush(stdout); ! 649: } ! 650: } ! 651: ioctl(0, TIOCSETP, &nsgbuf); ! 652: ioctl(0, TIOCSETC, &ntcbuf); ! 653: signal(SIGQUIT, hupcatch); ! 654: ioctl(0, FIOPUSHLD, &mesg_ld); ! 655: if (ttyn) ! 656: chmod(ttyn, 0); ! 657: if (mp->type) { ! 658: mp->magic = MSGMAGIC; /* safety */ ! 659: writemsg(&netb, mp); ! 660: } ! 661: } ! 662: ! 663: sendmsg(bp, type, cp, len) ! 664: struct buffer *bp; ! 665: int type, len; ! 666: char *cp; ! 667: { ! 668: struct amesg { ! 669: struct mesg m; ! 670: char body[128]; ! 671: } am; ! 672: ! 673: am.m.magic = MSGMAGIC; ! 674: am.m.type = type; ! 675: setmsgl(&am.m, len); ! 676: if (cp!=NULL && len>0) ! 677: memcpy(am.body, cp, len); ! 678: writemsg(bp, (struct mesg *)&am); ! 679: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.