|
|
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; ! 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 = deftc.t_startc; ! 142: notc.t_stopc = deftc.t_stopc; ! 143: ioctl(0, TIOCGLTC, (char *)&defltc); ! 144: signal(SIGINT, exit); ! 145: signal(SIGHUP, exit); ! 146: signal(SIGQUIT, exit); ! 147: child = fork(); ! 148: if (child == -1) { ! 149: perror("rlogin: fork"); ! 150: done(); ! 151: } ! 152: signal(SIGINT, SIG_IGN); ! 153: mode(1); ! 154: if (child == 0) { ! 155: reader(); ! 156: sleep(1); ! 157: prf("\007Connection closed."); ! 158: exit(3); ! 159: } ! 160: signal(SIGCHLD, catchild); ! 161: writer(); ! 162: prf("Closed connection."); ! 163: done(); ! 164: } ! 165: ! 166: done() ! 167: { ! 168: ! 169: mode(0); ! 170: if (child > 0 && kill(child, SIGKILL) >= 0) ! 171: wait((int *)0); ! 172: exit(0); ! 173: } ! 174: ! 175: catchild() ! 176: { ! 177: union wait status; ! 178: int pid; ! 179: ! 180: again: ! 181: pid = wait3(&status, WNOHANG|WUNTRACED, 0); ! 182: if (pid == 0) ! 183: return; ! 184: /* ! 185: * if the child (reader) dies, just quit ! 186: */ ! 187: if (pid < 0 || pid == child && !WIFSTOPPED(status)) ! 188: done(); ! 189: goto again; ! 190: } ! 191: ! 192: /* ! 193: * writer: write to remote: 0 -> line. ! 194: * ~. terminate ! 195: * ~^Z suspend rlogin process. ! 196: * ~^Y suspend rlogin process, but leave reader alone. ! 197: */ ! 198: writer() ! 199: { ! 200: char b[600], c; ! 201: register char *p; ! 202: register n; ! 203: ! 204: top: ! 205: p = b; ! 206: for (;;) { ! 207: int local; ! 208: ! 209: n = read(0, &c, 1); ! 210: if (n == 0) ! 211: break; ! 212: if (n < 0) ! 213: if (errno == EINTR) ! 214: continue; ! 215: else ! 216: break; ! 217: ! 218: if (eight == 0) ! 219: c &= 0177; ! 220: /* ! 221: * If we're at the beginning of the line ! 222: * and recognize a command character, then ! 223: * we echo locally. Otherwise, characters ! 224: * are echo'd remotely. If the command ! 225: * character is doubled, this acts as a ! 226: * force and local echo is suppressed. ! 227: */ ! 228: if (p == b) ! 229: local = (c == cmdchar); ! 230: if (p == b + 1 && *b == cmdchar) ! 231: local = (c != cmdchar); ! 232: if (!local) { ! 233: if (write(rem, &c, 1) == 0) { ! 234: prf("line gone"); ! 235: return; ! 236: } ! 237: if (eight == 0) ! 238: c &= 0177; ! 239: } else { ! 240: if (c == '\r' || c == '\n') { ! 241: char cmdc = b[1]; ! 242: ! 243: if (cmdc == '.' || cmdc == deftc.t_eofc) { ! 244: write(0, CRLF, sizeof(CRLF)); ! 245: return; ! 246: } ! 247: if (cmdc == defltc.t_suspc || ! 248: cmdc == defltc.t_dsuspc) { ! 249: write(0, CRLF, sizeof(CRLF)); ! 250: mode(0); ! 251: signal(SIGCHLD, SIG_IGN); ! 252: kill(cmdc == defltc.t_suspc ? ! 253: 0 : getpid(), SIGTSTP); ! 254: signal(SIGCHLD, catchild); ! 255: mode(1); ! 256: goto top; ! 257: } ! 258: *p++ = c; ! 259: write(rem, b, p - b); ! 260: goto top; ! 261: } ! 262: write(1, &c, 1); ! 263: } ! 264: *p++ = c; ! 265: if (c == deferase) { ! 266: p -= 2; ! 267: if (p < b) ! 268: goto top; ! 269: } ! 270: if (c == defkill || c == deftc.t_eofc || ! 271: c == '\r' || c == '\n') ! 272: goto top; ! 273: if (p >= &b[sizeof b]) ! 274: p--; ! 275: } ! 276: } ! 277: ! 278: oob() ! 279: { ! 280: int out = 1+1, atmark; ! 281: char waste[BUFSIZ], mark; ! 282: ! 283: ioctl(1, TIOCFLUSH, (char *)&out); ! 284: for (;;) { ! 285: if (ioctl(rem, SIOCATMARK, &atmark) < 0) { ! 286: perror("ioctl"); ! 287: break; ! 288: } ! 289: if (atmark) ! 290: break; ! 291: (void) read(rem, waste, sizeof (waste)); ! 292: } ! 293: recv(rem, &mark, 1, MSG_OOB); ! 294: if (mark & TIOCPKT_NOSTOP) { ! 295: notc.t_stopc = -1; ! 296: notc.t_startc = -1; ! 297: ioctl(0, TIOCSETC, (char *)¬c); ! 298: } ! 299: if (mark & TIOCPKT_DOSTOP) { ! 300: notc.t_stopc = deftc.t_stopc; ! 301: notc.t_startc = deftc.t_startc; ! 302: ioctl(0, TIOCSETC, (char *)¬c); ! 303: } ! 304: } ! 305: ! 306: /* ! 307: * reader: read from remote: line -> 1 ! 308: */ ! 309: reader() ! 310: { ! 311: char rb[BUFSIZ]; ! 312: register int cnt; ! 313: ! 314: signal(SIGURG, oob); ! 315: { int pid = -getpid(); ! 316: ioctl(rem, SIOCSPGRP, (char *)&pid); } ! 317: for (;;) { ! 318: cnt = read(rem, rb, sizeof (rb)); ! 319: if (cnt == 0) ! 320: break; ! 321: if (cnt < 0) { ! 322: if (errno == EINTR) ! 323: continue; ! 324: break; ! 325: } ! 326: write(1, rb, cnt); ! 327: } ! 328: } ! 329: ! 330: mode(f) ! 331: { ! 332: struct tchars *tc; ! 333: struct ltchars *ltc; ! 334: struct sgttyb sb; ! 335: ! 336: ioctl(0, TIOCGETP, (char *)&sb); ! 337: switch (f) { ! 338: ! 339: case 0: ! 340: sb.sg_flags &= ~(CBREAK|RAW|TBDELAY); ! 341: sb.sg_flags |= defflags|tabflag; ! 342: tc = &deftc; ! 343: ltc = &defltc; ! 344: sb.sg_kill = defkill; ! 345: sb.sg_erase = deferase; ! 346: break; ! 347: ! 348: case 1: ! 349: sb.sg_flags |= (eight ? RAW : CBREAK); ! 350: sb.sg_flags &= ~defflags; ! 351: /* preserve tab delays, but turn off XTABS */ ! 352: if ((sb.sg_flags & TBDELAY) == XTABS) ! 353: sb.sg_flags &= ~TBDELAY; ! 354: tc = ¬c; ! 355: ltc = &noltc; ! 356: sb.sg_kill = sb.sg_erase = -1; ! 357: break; ! 358: ! 359: default: ! 360: return; ! 361: } ! 362: ioctl(0, TIOCSLTC, (char *)ltc); ! 363: ioctl(0, TIOCSETC, (char *)tc); ! 364: ioctl(0, TIOCSETN, (char *)&sb); ! 365: } ! 366: ! 367: /*VARARGS*/ ! 368: prf(f, a1, a2, a3) ! 369: char *f; ! 370: { ! 371: fprintf(stderr, f, a1, a2, a3); ! 372: fprintf(stderr, CRLF); ! 373: } ! 374: ! 375: lostpeer() ! 376: { ! 377: signal(SIGPIPE, SIG_IGN); ! 378: prf("\007Connection closed."); ! 379: done(); ! 380: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.