|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)rlogin.c 4.15 (Berkeley) 83/07/02"; ! 3: #endif ! 4: ! 5: /* ! 6: * rlogin - remote login ! 7: */ ! 8: #include <sys/types.h> ! 9: #include <sys/socket.h> ! 10: #include <sys/wait.h> ! 11: ! 12: #include <netinet/in.h> ! 13: ! 14: #include <stdio.h> ! 15: #include <sgtty.h> ! 16: #include <errno.h> ! 17: #include <pwd.h> ! 18: #include <signal.h> ! 19: #include <netdb.h> ! 20: ! 21: char *index(), *rindex(), *malloc(), *getenv(); ! 22: struct passwd *getpwuid(); ! 23: char *name; ! 24: int rem; ! 25: char cmdchar = '~'; ! 26: int eight; ! 27: char *speeds[] = ! 28: { "0", "50", "75", "110", "134", "150", "200", "300", ! 29: "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" }; ! 30: char term[64] = "network"; ! 31: extern int errno; ! 32: int lostpeer(); ! 33: ! 34: main(argc, argv) ! 35: int argc; ! 36: char **argv; ! 37: { ! 38: char *host, *cp; ! 39: struct sgttyb ttyb; ! 40: struct passwd *pwd; ! 41: struct servent *sp; ! 42: int uid, options = 0; ! 43: ! 44: host = rindex(argv[0], '/'); ! 45: if (host) ! 46: host++; ! 47: else ! 48: host = argv[0]; ! 49: argv++, --argc; ! 50: if (!strcmp(host, "rlogin")) ! 51: host = *argv++, --argc; ! 52: another: ! 53: if (argc > 0 && !strcmp(*argv, "-d")) { ! 54: argv++, argc--; ! 55: options |= SO_DEBUG; ! 56: goto another; ! 57: } ! 58: if (argc > 0 && !strcmp(*argv, "-l")) { ! 59: argv++, argc--; ! 60: if (argc == 0) ! 61: goto usage; ! 62: name = *argv++; argc--; ! 63: goto another; ! 64: } ! 65: if (argc > 0 && !strncmp(*argv, "-e", 2)) { ! 66: cmdchar = argv[0][2]; ! 67: argv++, argc--; ! 68: goto another; ! 69: } ! 70: if (argc > 0 && !strcmp(*argv, "-8")) { ! 71: eight = 1; ! 72: argv++, argc--; ! 73: goto another; ! 74: } ! 75: if (host == 0) ! 76: goto usage; ! 77: if (argc > 0) ! 78: goto usage; ! 79: pwd = getpwuid(getuid()); ! 80: if (pwd == 0) { ! 81: fprintf(stderr, "Who are you?\n"); ! 82: exit(1); ! 83: } ! 84: sp = getservbyname("login", "tcp"); ! 85: if (sp == 0) { ! 86: fprintf(stderr, "rlogin: login/tcp: unknown service\n"); ! 87: exit(2); ! 88: } ! 89: cp = getenv("TERM"); ! 90: if (cp) ! 91: strcpy(term, cp); ! 92: if (ioctl(0, TIOCGETP, &ttyb)==0) { ! 93: strcat(term, "/"); ! 94: strcat(term, speeds[ttyb.sg_ospeed]); ! 95: } ! 96: signal(SIGPIPE, lostpeer); ! 97: rem = rcmd(&host, sp->s_port, pwd->pw_name, ! 98: name ? name : pwd->pw_name, term, 0); ! 99: if (rem < 0) ! 100: exit(1); ! 101: if (options & SO_DEBUG && ! 102: setsockopt(rem, SOL_SOCKET, SO_DEBUG, 0, 0) < 0) ! 103: perror("rlogin: setsockopt (SO_DEBUG)"); ! 104: uid = getuid(); ! 105: if (setuid(uid) < 0) { ! 106: perror("rlogin: setuid"); ! 107: exit(1); ! 108: } ! 109: doit(); ! 110: /*NOTREACHED*/ ! 111: usage: ! 112: fprintf(stderr, ! 113: "usage: rlogin host [ -ex ] [ -l username ] [ -8 ]\n"); ! 114: exit(1); ! 115: } ! 116: ! 117: #define CRLF "\r\n" ! 118: ! 119: int child; ! 120: int catchild(); ! 121: ! 122: int defflags, tabflag; ! 123: char deferase, defkill, defstartc, defstopc, defintr; ! 124: struct tchars deftc; ! 125: struct ltchars defltc; ! 126: struct tchars notc = { -1, -1, -1, -1, -1, -1 }; ! 127: struct ltchars noltc = { -1, -1, -1, -1, -1, -1 }; ! 128: ! 129: doit() ! 130: { ! 131: int exit(); ! 132: struct sgttyb sb; ! 133: ! 134: ioctl(0, TIOCGETP, (char *)&sb); ! 135: defflags = sb.sg_flags; ! 136: tabflag = defflags & TBDELAY; ! 137: defflags &= ECHO | CRMOD; ! 138: deferase = sb.sg_erase; ! 139: defkill = sb.sg_kill; ! 140: ioctl(0, TIOCGETC, (char *)&deftc); ! 141: notc.t_startc = defstartc = deftc.t_startc; ! 142: notc.t_stopc = defstopc = deftc.t_stopc; ! 143: defintr = deftc.t_intrc; ! 144: ioctl(0, TIOCGLTC, (char *)&defltc); ! 145: signal(SIGINT, exit); ! 146: signal(SIGHUP, exit); ! 147: signal(SIGQUIT, exit); ! 148: child = fork(); ! 149: if (child == -1) { ! 150: perror("rlogin: fork"); ! 151: done(); ! 152: } ! 153: signal(SIGINT, SIG_IGN); ! 154: mode(1); ! 155: if (child == 0) { ! 156: reader(); ! 157: sleep(1); ! 158: prf("\007Connection closed."); ! 159: exit(3); ! 160: } ! 161: signal(SIGCHLD, catchild); ! 162: writer(); ! 163: prf("Closed connection."); ! 164: done(); ! 165: } ! 166: ! 167: done() ! 168: { ! 169: ! 170: mode(0); ! 171: if (child > 0 && kill(child, SIGKILL) >= 0) ! 172: wait((int *)0); ! 173: exit(0); ! 174: } ! 175: ! 176: catchild() ! 177: { ! 178: union wait status; ! 179: int pid; ! 180: ! 181: again: ! 182: pid = wait3(&status, WNOHANG|WUNTRACED, 0); ! 183: if (pid == 0) ! 184: return; ! 185: /* ! 186: * if the child (reader) dies, just quit ! 187: */ ! 188: if (pid < 0 || pid == child && !WIFSTOPPED(status)) ! 189: done(); ! 190: goto again; ! 191: } ! 192: ! 193: /* ! 194: * writer: write to remote: 0 -> line. ! 195: * ~. terminate ! 196: * ~^Z suspend rlogin process. ! 197: * ~^Y suspend rlogin process, but leave reader alone. ! 198: */ ! 199: writer() ! 200: { ! 201: char b[600], c; ! 202: register char *p; ! 203: register n; ! 204: ! 205: top: ! 206: p = b; ! 207: for (;;) { ! 208: int local; ! 209: ! 210: n = read(0, &c, 1); ! 211: if (n == 0) ! 212: break; ! 213: if (n < 0) ! 214: if (errno == EINTR) ! 215: continue; ! 216: else ! 217: break; ! 218: ! 219: if (eight == 0) ! 220: c &= 0177; ! 221: /* ! 222: * If we're at the beginning of the line ! 223: * and recognize a command character, then ! 224: * we echo locally. Otherwise, characters ! 225: * are echo'd remotely. If the command ! 226: * character is doubled, this acts as a ! 227: * force and local echo is suppressed. ! 228: */ ! 229: if (p == b) ! 230: local = (c == cmdchar); ! 231: if (p == b + 1 && *b == cmdchar) ! 232: local = (c != cmdchar); ! 233: if (!local) { ! 234: if (write(rem, &c, 1) == 0) { ! 235: prf("line gone"); ! 236: return; ! 237: } ! 238: if (eight == 0) ! 239: c &= 0177; ! 240: } else { ! 241: if (c == '\r' || c == '\n') { ! 242: char cmdc = b[1]; ! 243: ! 244: if (cmdc == '.' || cmdc == deftc.t_eofc) { ! 245: write(0, CRLF, sizeof(CRLF)); ! 246: return; ! 247: } ! 248: if (cmdc == defltc.t_suspc || ! 249: cmdc == defltc.t_dsuspc) { ! 250: write(0, CRLF, sizeof(CRLF)); ! 251: mode(0); ! 252: signal(SIGCHLD, SIG_IGN); ! 253: kill(cmdc == defltc.t_suspc ? ! 254: 0 : getpid(), SIGTSTP); ! 255: signal(SIGCHLD, catchild); ! 256: mode(1); ! 257: goto top; ! 258: } ! 259: *p++ = c; ! 260: write(rem, b, p - b); ! 261: goto top; ! 262: } ! 263: write(1, &c, 1); ! 264: } ! 265: *p++ = c; ! 266: #ifdef BOL ! 267: if (c == deferase || c == defstartc || c == defstopc) { ! 268: p -= 2; ! 269: if (p < b) ! 270: goto top; ! 271: } ! 272: if (c == defkill || c == deftc.t_eofc || c == defintr || ! 273: c == '\r' || c == '\n') ! 274: #else BOL ! 275: if (c == '\r' || c == '\n') ! 276: #endif BOL ! 277: goto top; ! 278: if (p >= &b[sizeof b]) ! 279: p--; ! 280: } ! 281: } ! 282: ! 283: oob() ! 284: { ! 285: int out = 1+1, atmark; ! 286: char waste[BUFSIZ], mark; ! 287: ! 288: ioctl(1, TIOCFLUSH, (char *)&out); ! 289: for (;;) { ! 290: if (ioctl(rem, SIOCATMARK, &atmark) < 0) { ! 291: perror("ioctl"); ! 292: break; ! 293: } ! 294: if (atmark) ! 295: break; ! 296: (void) read(rem, waste, sizeof (waste)); ! 297: } ! 298: recv(rem, &mark, 1, MSG_OOB); ! 299: if (mark & TIOCPKT_NOSTOP) { ! 300: notc.t_stopc = -1; ! 301: notc.t_startc = -1; ! 302: ioctl(0, TIOCSETC, (char *)¬c); ! 303: } ! 304: if (mark & TIOCPKT_DOSTOP) { ! 305: notc.t_stopc = deftc.t_stopc; ! 306: notc.t_startc = deftc.t_startc; ! 307: ioctl(0, TIOCSETC, (char *)¬c); ! 308: } ! 309: } ! 310: ! 311: /* ! 312: * reader: read from remote: line -> 1 ! 313: */ ! 314: reader() ! 315: { ! 316: char rb[BUFSIZ]; ! 317: register int cnt; ! 318: ! 319: signal(SIGURG, oob); ! 320: { int pid = -getpid(); ! 321: ioctl(rem, SIOCSPGRP, (char *)&pid); } ! 322: for (;;) { ! 323: cnt = read(rem, rb, sizeof (rb)); ! 324: if (cnt == 0) ! 325: break; ! 326: if (cnt < 0) { ! 327: if (errno == EINTR) ! 328: continue; ! 329: break; ! 330: } ! 331: write(1, rb, cnt); ! 332: } ! 333: } ! 334: ! 335: mode(f) ! 336: { ! 337: struct tchars *tc; ! 338: struct ltchars *ltc; ! 339: struct sgttyb sb; ! 340: ! 341: ioctl(0, TIOCGETP, (char *)&sb); ! 342: switch (f) { ! 343: ! 344: case 0: ! 345: sb.sg_flags &= ~(CBREAK|RAW|TBDELAY); ! 346: sb.sg_flags |= defflags|tabflag; ! 347: tc = &deftc; ! 348: ltc = &defltc; ! 349: sb.sg_kill = defkill; ! 350: sb.sg_erase = deferase; ! 351: break; ! 352: ! 353: case 1: ! 354: sb.sg_flags |= (eight ? RAW : CBREAK); ! 355: sb.sg_flags &= ~defflags; ! 356: /* preserve tab delays, but turn off XTABS */ ! 357: if ((sb.sg_flags & TBDELAY) == XTABS) ! 358: sb.sg_flags &= ~TBDELAY; ! 359: tc = ¬c; ! 360: ltc = &noltc; ! 361: sb.sg_kill = sb.sg_erase = -1; ! 362: break; ! 363: ! 364: default: ! 365: return; ! 366: } ! 367: ioctl(0, TIOCSLTC, (char *)ltc); ! 368: ioctl(0, TIOCSETC, (char *)tc); ! 369: ioctl(0, TIOCSETN, (char *)&sb); ! 370: } ! 371: ! 372: /*VARARGS*/ ! 373: prf(f, a1, a2, a3) ! 374: char *f; ! 375: { ! 376: fprintf(stderr, f, a1, a2, a3); ! 377: fprintf(stderr, CRLF); ! 378: } ! 379: ! 380: lostpeer() ! 381: { ! 382: signal(SIGPIPE, SIG_IGN); ! 383: prf("\007Connection closed (lost peer)."); ! 384: done(); ! 385: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.