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

Defined functions

catchild defined in line 243; used 3 times
doit defined in line 177; used 1 times
done defined in line 219; used 4 times
echo defined in line 320; used 2 times
lostpeer defined in line 596; used 2 times
main defined in line 66; never used
mode defined in line 547; used 4 times
oob defined in line 415; used 2 times
prf defined in line 589; used 5 times
reader defined in line 507; used 1 times
sendwindow defined in line 380; used 3 times
sigwinch defined in line 365; used 3 times
stop defined in line 341; used 1 times
writer defined in line 266; used 1 times
writeroob defined in line 233; used 2 times

Defined variables

child defined in line 165; used 6 times
cmdchar defined in line 42; used 5 times
copyright defined in line 8; never used
deferase defined in line 171; used 2 times
defflags defined in line 169; used 3 times
defkill defined in line 171; used 3 times
deflflags defined in line 170; used 2 times
defltc defined in line 173; used 6 times
deftc defined in line 172; used 9 times
dosigwinch defined in line 51; used 4 times
eight defined in line 43; used 4 times
litout defined in line 44; used 2 times
name defined in line 40; used 3 times
noltc defined in line 175; used 1 times
notc defined in line 174; used 9 times
ppid defined in line 412; used 2 times
rcvbuf defined in line 409; used 8 times
rcvcnt defined in line 410; used 9 times
rcvstate defined in line 411; used 3 times
rcvtop defined in line 413; used 3 times
rem defined in line 41; used 13 times
sccsid defined in line 12; never used
speeds defined in line 45; used 1 times
term defined in line 48; used 4 times
winsize defined in line 62; used 12 times

Defined struct's

winsize defined in line 57; used 10 times

Defined macros

CRLF defined in line 163; used 1 times
READING defined in line 406; used 2 times
TIOCPKT_WINDOW defined in line 35; used 2 times
WRITING defined in line 407; used 1 times
sigmask defined in line 53; used 2 times
Last modified: 1997-03-28
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 5179
Valid CSS Valid XHTML 1.0 Strict