#ifndef lint static char sccsid[] = "@(#)rlogin.c 4.7 82/12/25"; #endif #include #include #include #include #include #include #include #include #include /* * rlogin - remote login */ char *index(), *rindex(), *malloc(), *getenv(); struct passwd *getpwuid(); char *name; int rem; char cmdchar = '~'; int rcmdoptions = 0; int eight; char *speeds[] = { "0", "50", "75", "110", "134", "150", "200", "300", "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" }; char term[64] = "network"; extern int errno; int lostpeer(); main(argc, argv) int argc; char **argv; { char *host, *cp; struct sgttyb ttyb; struct passwd *pwd; struct servent *sp; int uid; host = rindex(argv[0], '/'); if (host) host++; else host = argv[0]; argv++, --argc; if (!strcmp(host, "rlogin")) host = *argv++, --argc; another: if (!strcmp(*argv, "-d")) { argv++, argc--; rcmdoptions |= SO_DEBUG; goto another; } if (!strcmp(*argv, "-l")) { argv++, argc--; if (argc == 0) goto usage; name = *argv++; argc--; goto another; } if (!strncmp(*argv, "-e", 2)) { cmdchar = argv[0][2]; argv++, argc--; goto another; } if (!strcmp(*argv, "-8")) { eight = 1; argv++, argc--; goto another; } if (host == 0) goto usage; if (argc > 0) goto usage; pwd = getpwuid(getuid()); if (pwd == 0) { fprintf(stderr, "Who are you?\n"); exit(1); } sp = getservbyname("login", "tcp"); if (sp == 0) { fprintf(stderr, "rlogin: login/tcp: unknown service\n"); exit(2); } cp = getenv("TERM"); if (cp) strcpy(term, cp); if (ioctl(0, TIOCGETP, &ttyb)==0) { strcat(term, "/"); strcat(term, speeds[ttyb.sg_ospeed]); } signal(SIGPIPE, lostpeer); rem = rcmd(&host, sp->s_port, pwd->pw_name, name ? name : pwd->pw_name, term, 0); if (rem < 0) exit(1); uid = getuid(); if (setuid(uid) < 0) { perror("rlogin: setuid"); exit(1); } doit(); /*NOTREACHED*/ usage: fprintf(stderr, "usage: rlogin host [ -ex ] [ -l username ]\n"); exit(1); } #define CRLF "\r\n" int child; int done(); int defflags; struct ttychars deftc; struct ttychars notc = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; doit() { int exit(); ioctl(0, TIOCGET, (char *)&defflags); defflags &= ECHO | CRMOD; ioctl(0, TIOCCGET, (char *)&deftc); notc.tc_startc = deftc.tc_startc; notc.tc_stopc = deftc.tc_stopc; signal(SIGINT, exit); signal(SIGHUP, exit); signal(SIGQUIT, exit); child = fork(); if (child == -1) { perror("rlogin: fork"); done(); } signal(SIGINT, SIG_IGN); if (child == 0) { reader(); prf("\007Lost connection."); exit(3); } signal(SIGCHLD, done); mode(1); writer(); prf("Disconnected."); done(); } done() { mode(0); if (child > 0 && kill(child, SIGKILL) >= 0) wait((int *)0); exit(0); } /* * writer: write to remote: 0 -> line. * ~. terminate * ~^Z suspend rlogin process. */ writer() { char b[600], c; register char *p; top: p = b; while (read(0, &c, 1) > 0) { int local; if (eight == 0) c &= 0177; /* * If we're at the beginning of the line * and recognize a command character, then * we echo locally. Otherwise, characters * are echo'd remotely. If the command * character is doubled, this acts as a * force and local echo is suppressed. */ if (p == b) local = (c == cmdchar); if (p == b + 1 && *b == cmdchar) local = (c != cmdchar); if (!local) { if (write(rem, &c, 1) == 0) { prf("line gone"); return; } if (eight == 0) c &= 0177; } else { if (c == 0177) c = deftc.tc_kill; if (c == '\r' || c == '\n') { char cmdc = b[1]; if (cmdc == '.' || cmdc == deftc.tc_eofc) { write(0, CRLF, sizeof(CRLF)); return; } if (cmdc == deftc.tc_suspc || cmdc == deftc.tc_dsuspc) { write(0, CRLF, sizeof(CRLF)); mode(0); signal(SIGCHLD, SIG_IGN); kill(cmdc == deftc.tc_suspc ? 0 : getpid(), SIGTSTP); signal(SIGCHLD, done); mode(1); goto top; } *p++ = c; write(rem, b, p - b); goto top; } write(1, &c, 1); } *p++ = c; if (c == deftc.tc_erase) { p -= 2; if (p < b) goto top; } if (c == deftc.tc_kill || c == 0177 || c == deftc.tc_eofc || c == '\r' || c == '\n') goto top; } } oob() { int out = 1+1; char waste[BUFSIZ], mark; signal(SIGURG, oob); ioctl(1, TIOCFLUSH, (char *)&out); for (;;) { if (ioctl(rem, SIOCATMARK, &mark) < 0) { perror("ioctl"); break; } if (mark) break; (void) read(rem, waste, sizeof (waste)); } recv(rem, &mark, 1, SOF_OOB); if (mark & TIOCPKT_NOSTOP) { notc.tc_stopc = -1; notc.tc_startc = -1; ioctl(0, TIOCCSET, (char *)¬c); } if (mark & TIOCPKT_DOSTOP) { notc.tc_stopc = deftc.tc_stopc; notc.tc_startc = deftc.tc_startc; ioctl(0, TIOCCSET, (char *)¬c); } } /* * reader: read from remote: line -> 1 */ reader() { char rb[BUFSIZ]; register int cnt; signal(SIGURG, oob); { int pid = -getpid(); ioctl(rem, SIOCSPGRP, (char *)&pid); } for (;;) { cnt = read(rem, rb, sizeof (rb)); if (cnt <= 0) { if (errno == EINTR) continue; break; } write(1, rb, cnt); } } mode(f) { struct ttychars *tc; int flags; ioctl(0, TIOCGET, (char *)&flags); switch (f) { case 0: flags &= ~CBREAK; flags |= defflags; tc = &deftc; break; case 1: flags |= CBREAK; flags &= ~defflags; tc = ¬c; break; default: return; } ioctl(0, TIOCSET, (char *)&flags); ioctl(0, TIOCCSET, (char *)tc); } /*VARARGS*/ prf(f, a1, a2, a3) char *f; { fprintf(stderr, f, a1, a2, a3); fprintf(stderr, CRLF); } lostpeer() { signal(SIGPIPE, SIG_IGN); prf("\007Lost connection"); done(); }