1: /*
   2:  * Copyright (c) 1983 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  */
   6: 
   7: #ifndef lint
   8: char copyright[] =
   9: "@(#) Copyright (c) 1983 Regents of the University of California.\n\
  10:  All rights reserved.\n";
  11: #endif not lint
  12: 
  13: #ifndef lint
  14: static char sccsid[] = "@(#)rlogin.c	5.10 (Berkeley) 3/30/86";
  15: #endif not lint
  16: 
  17: /*
  18:  * rlogin - remote login
  19:  */
  20: #include <sys/param.h>
  21: #include <sys/errno.h>
  22: #include <sys/file.h>
  23: #include <sys/socket.h>
  24: #include <sys/wait.h>
  25: 
  26: #include <netinet/in.h>
  27: 
  28: #include <stdio.h>
  29: #include <sgtty.h>
  30: #include <errno.h>
  31: #include <pwd.h>
  32: #include <signal.h>
  33: #include <setjmp.h>
  34: #include <netdb.h>
  35: 
  36: # ifndef TIOCPKT_WINDOW
  37: # define TIOCPKT_WINDOW 0x80
  38: # endif TIOCPKT_WINDOW
  39: 
  40: char    *index(), *rindex(), *malloc(), *getenv();
  41: struct  passwd *getpwuid();
  42: char    *name;
  43: int rem;
  44: char    cmdchar = '~';
  45: int eight;
  46: int litout;
  47: char    *speeds[] =
  48:     { "0", "50", "75", "110", "134", "150", "200", "300",
  49:       "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" };
  50: char    term[256] = "network";
  51: extern  int errno;
  52: int lostpeer();
  53: int dosigwinch = 0;
  54: #ifndef sigmask
  55: #define sigmask(m)  (1 << ((m)-1))
  56: #endif
  57: #ifdef sun
  58: struct  ttysize winsize;
  59: struct winsize {
  60:     unsigned short ws_row, ws_col;
  61:     unsigned short ws_xpixel, ws_ypixel;
  62: };
  63: #else sun
  64: struct  winsize winsize;
  65: #endif sun
  66: int sigwinch(), oob();
  67: 
  68: main(argc, argv)
  69:     int argc;
  70:     char **argv;
  71: {
  72:     char *host, *cp;
  73:     struct sgttyb ttyb;
  74:     struct passwd *pwd;
  75:     struct servent *sp;
  76:     int uid, options = 0, oldmask;
  77:     int on = 1;
  78: 
  79:     host = rindex(argv[0], '/');
  80:     if (host)
  81:         host++;
  82:     else
  83:         host = argv[0];
  84:     argv++, --argc;
  85:     if (!strcmp(host, "rlogin"))
  86:         host = *argv++, --argc;
  87: another:
  88:     if (argc > 0 && !strcmp(*argv, "-d")) {
  89:         argv++, argc--;
  90:         options |= SO_DEBUG;
  91:         goto another;
  92:     }
  93:     if (argc > 0 && !strcmp(*argv, "-l")) {
  94:         argv++, argc--;
  95:         if (argc == 0)
  96:             goto usage;
  97:         name = *argv++; argc--;
  98:         goto another;
  99:     }
 100:     if (argc > 0 && !strncmp(*argv, "-e", 2)) {
 101:         cmdchar = argv[0][2];
 102:         argv++, argc--;
 103:         goto another;
 104:     }
 105:     if (argc > 0 && !strcmp(*argv, "-8")) {
 106:         eight = 1;
 107:         argv++, argc--;
 108:         goto another;
 109:     }
 110:     if (argc > 0 && !strcmp(*argv, "-L")) {
 111:         litout = 1;
 112:         argv++, argc--;
 113:         goto another;
 114:     }
 115:     if (host == 0)
 116:         goto usage;
 117:     if (argc > 0)
 118:         goto usage;
 119:     pwd = getpwuid(getuid());
 120:     if (pwd == 0) {
 121:         fprintf(stderr, "Who are you?\n");
 122:         exit(1);
 123:     }
 124:     sp = getservbyname("login", "tcp");
 125:     if (sp == 0) {
 126:         fprintf(stderr, "rlogin: login/tcp: unknown service\n");
 127:         exit(2);
 128:     }
 129:     cp = getenv("TERM");
 130:     if (cp)
 131:         strcpy(term, cp);
 132:     if (ioctl(0, TIOCGETP, &ttyb) == 0) {
 133:         strcat(term, "/");
 134:         strcat(term, speeds[ttyb.sg_ospeed]);
 135:     }
 136: #ifdef sun
 137:     (void) ioctl(0, TIOCGSIZE, &winsize);
 138: #else sun
 139:     (void) ioctl(0, TIOCGWINSZ, &winsize);
 140: #endif sun
 141:     signal(SIGPIPE, lostpeer);
 142:     signal(SIGURG, oob);
 143:     oldmask = sigblock(sigmask(SIGURG));
 144:         rem = rcmd(&host, sp->s_port, pwd->pw_name,
 145:         name ? name : pwd->pw_name, term, 0);
 146:         if (rem < 0)
 147:                 exit(1);
 148:     if (options & SO_DEBUG &&
 149:         setsockopt(rem, SOL_SOCKET, SO_DEBUG, &on, sizeof (on)) < 0)
 150:         perror("rlogin: setsockopt (SO_DEBUG)");
 151:     uid = getuid();
 152:     if (setuid(uid) < 0) {
 153:         perror("rlogin: setuid");
 154:         exit(1);
 155:     }
 156:     doit(oldmask);
 157:     /*NOTREACHED*/
 158: usage:
 159:     fprintf(stderr,
 160:         "usage: rlogin host [ -ex ] [ -l username ] [ -8 ] [ -L ]\n");
 161:     exit(1);
 162: }
 163: 
 164: #define CRLF "\r\n"
 165: 
 166: int child;
 167: int catchild();
 168: int writeroob();
 169: 
 170: int defflags, tabflag;
 171: int deflflags;
 172: char    deferase, defkill;
 173: struct  tchars deftc;
 174: struct  ltchars defltc;
 175: struct  tchars notc =   { -1, -1, -1, -1, -1, -1 };
 176: struct  ltchars noltc = { -1, -1, -1, -1, -1, -1 };
 177: 
 178: doit(oldmask)
 179: {
 180:     int exit();
 181:     struct sgttyb sb;
 182: 
 183:     ioctl(0, TIOCGETP, (char *)&sb);
 184:     defflags = sb.sg_flags;
 185:     tabflag = defflags & TBDELAY;
 186:     defflags &= ECHO | CRMOD;
 187:     deferase = sb.sg_erase;
 188:     defkill = sb.sg_kill;
 189:     ioctl(0, TIOCLGET, (char *)&deflflags);
 190:     ioctl(0, TIOCGETC, (char *)&deftc);
 191:     notc.t_startc = deftc.t_startc;
 192:     notc.t_stopc = deftc.t_stopc;
 193:     ioctl(0, TIOCGLTC, (char *)&defltc);
 194:     signal(SIGINT, SIG_IGN);
 195:     signal(SIGHUP, exit);
 196:     signal(SIGQUIT, exit);
 197:     child = fork();
 198:     if (child == -1) {
 199:         perror("rlogin: fork");
 200:         done(1);
 201:     }
 202:     if (child == 0) {
 203:         mode(1);
 204:         sigsetmask(oldmask);
 205:         if (reader() == 0) {
 206:             prf("Connection closed.");
 207:             exit(0);
 208:         }
 209:         sleep(1);
 210:         prf("\007Connection closed.");
 211:         exit(3);
 212:     }
 213:     signal(SIGURG, writeroob);
 214:     sigsetmask(oldmask);
 215:     signal(SIGCHLD, catchild);
 216:     writer();
 217:     prf("Closed connection.");
 218:     done(0);
 219: }
 220: 
 221: done(status)
 222:     int status;
 223: {
 224: 
 225:     mode(0);
 226:     if (child > 0 && kill(child, SIGKILL) >= 0)
 227:         wait((int *)0);
 228:     exit(status);
 229: }
 230: 
 231: /*
 232:  * This is called when the reader process gets the out-of-band (urgent)
 233:  * request to turn on the window-changing protocol.
 234:  */
 235: writeroob()
 236: {
 237: 
 238:     if (dosigwinch == 0) {
 239:         sendwindow();
 240:         signal(SIGWINCH, sigwinch);
 241:     }
 242:     dosigwinch = 1;
 243: }
 244: 
 245: catchild()
 246: {
 247:     union wait status;
 248:     int pid;
 249: 
 250: again:
 251:     pid = wait3(&status, WNOHANG|WUNTRACED, 0);
 252:     if (pid == 0)
 253:         return;
 254:     /*
 255: 	 * if the child (reader) dies, just quit
 256: 	 */
 257:     if (pid < 0 || pid == child && !WIFSTOPPED(status))
 258:         done(status.w_termsig | status.w_retcode);
 259:     goto again;
 260: }
 261: 
 262: /*
 263:  * writer: write to remote: 0 -> line.
 264:  * ~.	terminate
 265:  * ~^Z	suspend rlogin process.
 266:  * ~^Y  suspend rlogin process, but leave reader alone.
 267:  */
 268: writer()
 269: {
 270:     char c;
 271:     register n;
 272:     register bol = 1;               /* beginning of line */
 273:     register local = 0;
 274: 
 275:     for (;;) {
 276:         n = read(0, &c, 1);
 277:         if (n <= 0) {
 278:             if (n < 0 && errno == EINTR)
 279:                 continue;
 280:             break;
 281:         }
 282:         /*
 283: 		 * If we're at the beginning of the line
 284: 		 * and recognize a command character, then
 285: 		 * we echo locally.  Otherwise, characters
 286: 		 * are echo'd remotely.  If the command
 287: 		 * character is doubled, this acts as a
 288: 		 * force and local echo is suppressed.
 289: 		 */
 290:         if (bol) {
 291:             bol = 0;
 292:             if (c == cmdchar) {
 293:                 bol = 0;
 294:                 local = 1;
 295:                 continue;
 296:             }
 297:         } else if (local) {
 298:             local = 0;
 299:             if (c == '.' || c == deftc.t_eofc) {
 300:                 echo(c);
 301:                 break;
 302:             }
 303:             if (c == defltc.t_suspc || c == defltc.t_dsuspc) {
 304:                 bol = 1;
 305:                 echo(c);
 306:                 stop(c);
 307:                 continue;
 308:             }
 309:             if (c != cmdchar)
 310:                 write(rem, &cmdchar, 1);
 311:         }
 312:         if (write(rem, &c, 1) == 0) {
 313:             prf("line gone");
 314:             break;
 315:         }
 316:         bol = c == defkill || c == deftc.t_eofc ||
 317:             c == deftc.t_intrc || c == defltc.t_suspc ||
 318:             c == '\r' || c == '\n';
 319:     }
 320: }
 321: 
 322: echo(c)
 323: register char c;
 324: {
 325:     char buf[8];
 326:     register char *p = buf;
 327: 
 328:     c &= 0177;
 329:     *p++ = cmdchar;
 330:     if (c < ' ') {
 331:         *p++ = '^';
 332:         *p++ = c + '@';
 333:     } else if (c == 0177) {
 334:         *p++ = '^';
 335:         *p++ = '?';
 336:     } else
 337:         *p++ = c;
 338:     *p++ = '\r';
 339:     *p++ = '\n';
 340:     write(1, buf, p - buf);
 341: }
 342: 
 343: stop(cmdc)
 344:     char cmdc;
 345: {
 346:     mode(0);
 347:     signal(SIGCHLD, SIG_IGN);
 348:     kill(cmdc == defltc.t_suspc ? 0 : getpid(), SIGTSTP);
 349:     signal(SIGCHLD, catchild);
 350:     mode(1);
 351:     sigwinch();         /* check for size changes */
 352: }
 353: 
 354: #ifdef sun
 355: sigwinch()
 356: {
 357:     struct ttysize ws;
 358: 
 359:     if (dosigwinch && ioctl(0, TIOCGSIZE, &ws) == 0 &&
 360:         bcmp(&ws, &winsize, sizeof (ws))) {
 361:         winsize = ws;
 362:         sendwindow();
 363:     }
 364: }
 365: 
 366: #else sun
 367: sigwinch()
 368: {
 369:     struct winsize ws;
 370: 
 371:     if (dosigwinch && ioctl(0, TIOCGWINSZ, &ws) == 0 &&
 372:         bcmp(&ws, &winsize, sizeof (ws))) {
 373:         winsize = ws;
 374:         sendwindow();
 375:     }
 376: }
 377: #endif
 378: 
 379: /*
 380:  * Send the window size to the server via the magic escape
 381:  */
 382: sendwindow()
 383: {
 384:     char obuf[4 + sizeof (struct winsize)];
 385:     struct winsize *wp = (struct winsize *)(obuf+4);
 386: 
 387:     obuf[0] = 0377;
 388:     obuf[1] = 0377;
 389:     obuf[2] = 's';
 390:     obuf[3] = 's';
 391: #ifdef sun
 392:     wp->ws_row = htons(winsize.ts_lines);
 393:     wp->ws_col = htons(winsize.ts_cols);
 394:     wp->ws_xpixel = 0;
 395:     wp->ws_ypixel = 0;
 396: #else sun
 397:     wp->ws_row = htons(winsize.ws_row);
 398:     wp->ws_col = htons(winsize.ws_col);
 399:     wp->ws_xpixel = htons(winsize.ws_xpixel);
 400:     wp->ws_ypixel = htons(winsize.ws_ypixel);
 401: #endif sun
 402:     (void) write(rem, obuf, sizeof(obuf));
 403: }
 404: 
 405: /*
 406:  * reader: read from remote: line -> 1
 407:  */
 408: #define READING 1
 409: #define WRITING 2
 410: 
 411: char    rcvbuf[8 * 1024];
 412: int rcvcnt;
 413: int rcvstate;
 414: int ppid;
 415: jmp_buf rcvtop;
 416: 
 417: oob()
 418: {
 419:     int out = FWRITE, atmark, n;
 420:     int rcvd = 0;
 421:     char waste[BUFSIZ], mark;
 422:     struct sgttyb sb;
 423: 
 424:     while (recv(rem, &mark, 1, MSG_OOB) < 0)
 425:         switch (errno) {
 426: 
 427:         case EWOULDBLOCK:
 428:             /*
 429: 			 * Urgent data not here yet.
 430: 			 * It may not be possible to send it yet
 431: 			 * if we are blocked for output
 432: 			 * and our input buffer is full.
 433: 			 */
 434:             if (rcvcnt < sizeof(rcvbuf)) {
 435:                 n = read(rem, rcvbuf + rcvcnt,
 436:                     sizeof(rcvbuf) - rcvcnt);
 437:                 if (n <= 0)
 438:                     return;
 439:                 rcvd += n;
 440:             } else {
 441:                 n = read(rem, waste, sizeof(waste));
 442:                 if (n <= 0)
 443:                     return;
 444:             }
 445:             continue;
 446: 
 447:         default:
 448:             return;
 449:     }
 450:     if (mark & TIOCPKT_WINDOW) {
 451:         /*
 452: 		 * Let server know about window size changes
 453: 		 */
 454:         kill(ppid, SIGURG);
 455:     }
 456:     if (!eight && (mark & TIOCPKT_NOSTOP)) {
 457:         ioctl(0, TIOCGETP, (char *)&sb);
 458:         sb.sg_flags &= ~CBREAK;
 459:         sb.sg_flags |= RAW;
 460:         ioctl(0, TIOCSETN, (char *)&sb);
 461:         notc.t_stopc = -1;
 462:         notc.t_startc = -1;
 463:         ioctl(0, TIOCSETC, (char *)&notc);
 464:     }
 465:     if (!eight && (mark & TIOCPKT_DOSTOP)) {
 466:         ioctl(0, TIOCGETP, (char *)&sb);
 467:         sb.sg_flags &= ~RAW;
 468:         sb.sg_flags |= CBREAK;
 469:         ioctl(0, TIOCSETN, (char *)&sb);
 470:         notc.t_stopc = deftc.t_stopc;
 471:         notc.t_startc = deftc.t_startc;
 472:         ioctl(0, TIOCSETC, (char *)&notc);
 473:     }
 474:     if (mark & TIOCPKT_FLUSHWRITE) {
 475:         ioctl(1, TIOCFLUSH, (char *)&out);
 476:         for (;;) {
 477:             if (ioctl(rem, SIOCATMARK, &atmark) < 0) {
 478:                 perror("ioctl");
 479:                 break;
 480:             }
 481:             if (atmark)
 482:                 break;
 483:             n = read(rem, waste, sizeof (waste));
 484:             if (n <= 0)
 485:                 break;
 486:         }
 487:         /*
 488: 		 * Don't want any pending data to be output,
 489: 		 * so clear the recv buffer.
 490: 		 * If we were hanging on a write when interrupted,
 491: 		 * don't want it to restart.  If we were reading,
 492: 		 * restart anyway.
 493: 		 */
 494:         rcvcnt = 0;
 495:         longjmp(rcvtop, 1);
 496:     }
 497:     /*
 498: 	 * If we filled the receive buffer while a read was pending,
 499: 	 * longjmp to the top to restart appropriately.  Don't abort
 500: 	 * a pending write, however, or we won't know how much was written.
 501: 	 */
 502:     if (rcvd && rcvstate == READING)
 503:         longjmp(rcvtop, 1);
 504: }
 505: 
 506: /*
 507:  * reader: read from remote: line -> 1
 508:  */
 509: reader()
 510: {
 511: #if !defined(BSD) || BSD < 43
 512:     int pid = -getpid();
 513: #else
 514:     int pid = getpid();
 515: #endif
 516:     int n, remaining;
 517:     char *bufp = rcvbuf;
 518: 
 519:     signal(SIGTTOU, SIG_IGN);
 520:     fcntl(rem, F_SETOWN, pid);
 521:     ppid = getppid();
 522:     (void) setjmp(rcvtop);
 523:     for (;;) {
 524:         while ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) {
 525:             rcvstate = WRITING;
 526:             n = write(1, bufp, remaining);
 527:             if (n < 0) {
 528:                 if (errno != EINTR)
 529:                     return (-1);
 530:                 continue;
 531:             }
 532:             bufp += n;
 533:         }
 534:         bufp = rcvbuf;
 535:         rcvcnt = 0;
 536:         rcvstate = READING;
 537:         rcvcnt = read(rem, rcvbuf, sizeof (rcvbuf));
 538:         if (rcvcnt == 0)
 539:             return (0);
 540:         if (rcvcnt < 0) {
 541:             if (errno == EINTR)
 542:                 continue;
 543:             perror("read");
 544:             return (-1);
 545:         }
 546:     }
 547: }
 548: 
 549: mode(f)
 550: {
 551:     struct tchars *tc;
 552:     struct ltchars *ltc;
 553:     struct sgttyb sb;
 554:     int lflags;
 555: 
 556:     ioctl(0, TIOCGETP, (char *)&sb);
 557:     ioctl(0, TIOCLGET, (char *)&lflags);
 558:     switch (f) {
 559: 
 560:     case 0:
 561:         sb.sg_flags &= ~(CBREAK|RAW|TBDELAY);
 562:         sb.sg_flags |= defflags|tabflag;
 563:         tc = &deftc;
 564:         ltc = &defltc;
 565:         sb.sg_kill = defkill;
 566:         sb.sg_erase = deferase;
 567:         lflags = deflflags;
 568:         break;
 569: 
 570:     case 1:
 571:         sb.sg_flags |= (eight ? RAW : CBREAK);
 572:         sb.sg_flags &= ~defflags;
 573:         /* preserve tab delays, but turn off XTABS */
 574:         if ((sb.sg_flags & TBDELAY) == XTABS)
 575:             sb.sg_flags &= ~TBDELAY;
 576:         tc = &notc;
 577:         ltc = &noltc;
 578:         sb.sg_kill = sb.sg_erase = -1;
 579:         if (litout)
 580:             lflags |= LLITOUT;
 581:         break;
 582: 
 583:     default:
 584:         return;
 585:     }
 586:     ioctl(0, TIOCSLTC, (char *)ltc);
 587:     ioctl(0, TIOCSETC, (char *)tc);
 588:     ioctl(0, TIOCSETN, (char *)&sb);
 589:     ioctl(0, TIOCLSET, (char *)&lflags);
 590: }
 591: 
 592: /*VARARGS*/
 593: prf(f, a1, a2, a3, a4, a5)
 594:     char *f;
 595: {
 596:     fprintf(stderr, f, a1, a2, a3, a4, a5);
 597:     fprintf(stderr, CRLF);
 598: }
 599: 
 600: lostpeer()
 601: {
 602:     signal(SIGPIPE, SIG_IGN);
 603:     prf("\007Connection closed.");
 604:     done(1);
 605: }

Defined functions

catchild defined in line 245; used 3 times
doit defined in line 178; used 1 times
done defined in line 221; used 4 times
echo defined in line 322; used 2 times
lostpeer defined in line 600; used 2 times
main defined in line 68; never used
mode defined in line 549; used 4 times
oob defined in line 417; used 2 times
prf defined in line 593; used 5 times
reader defined in line 509; used 1 times
sendwindow defined in line 382; used 3 times
sigwinch defined in line 367; used 3 times
stop defined in line 343; used 1 times
writer defined in line 268; used 1 times
writeroob defined in line 235; used 2 times

Defined variables

child defined in line 166; used 6 times
cmdchar defined in line 44; used 5 times
copyright defined in line 8; never used
deferase defined in line 172; used 2 times
defflags defined in line 170; used 5 times
defkill defined in line 172; used 3 times
deflflags defined in line 171; used 2 times
defltc defined in line 174; used 6 times
deftc defined in line 173; used 9 times
dosigwinch defined in line 53; used 4 times
eight defined in line 45; used 4 times
litout defined in line 46; used 2 times
name defined in line 42; used 3 times
noltc defined in line 176; used 1 times
notc defined in line 175; used 9 times
ppid defined in line 414; used 2 times
rcvbuf defined in line 411; used 8 times
rcvcnt defined in line 412; used 9 times
rcvstate defined in line 413; used 3 times
rcvtop defined in line 415; used 3 times
rem defined in line 43; used 13 times
sccsid defined in line 14; never used
speeds defined in line 47; used 1 times
tabflag defined in line 170; used 2 times
term defined in line 50; used 4 times
winsize defined in line 64; used 12 times

Defined struct's

winsize defined in line 59; used 10 times

Defined macros

CRLF defined in line 164; used 1 times
READING defined in line 408; used 2 times
TIOCPKT_WINDOW defined in line 37; used 2 times
WRITING defined in line 409; used 1 times
sigmask defined in line 55; used 2 times
Last modified: 1986-03-31
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2390
Valid CSS Valid XHTML 1.0 Strict