16444Swnj #ifndef lint 2*10839Ssam static char sccsid[] = "@(#)rlogin.c 4.9 83/02/09"; 36444Swnj #endif 46444Swnj 56444Swnj #include <sys/types.h> 66444Swnj #include <sys/socket.h> 79365Ssam 89207Ssam #include <netinet/in.h> 99365Ssam 109365Ssam #include <stdio.h> 119365Ssam #include <sgtty.h> 126444Swnj #include <errno.h> 136444Swnj #include <pwd.h> 149365Ssam #include <signal.h> 159365Ssam #include <netdb.h> 166444Swnj 176444Swnj /* 189365Ssam * rlogin - remote login 196444Swnj */ 206444Swnj char *index(), *rindex(), *malloc(), *getenv(); 216444Swnj struct passwd *getpwuid(); 229365Ssam char *name; 236444Swnj int rem; 246444Swnj char cmdchar = '~'; 256444Swnj int eight; 266444Swnj char *speeds[] = 276444Swnj { "0", "50", "75", "110", "134", "150", "200", "300", 286444Swnj "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" }; 299365Ssam char term[64] = "network"; 309365Ssam extern int errno; 319365Ssam int lostpeer(); 326444Swnj 336444Swnj main(argc, argv) 346444Swnj int argc; 356444Swnj char **argv; 366444Swnj { 379365Ssam char *host, *cp; 386444Swnj struct sgttyb ttyb; 396444Swnj struct passwd *pwd; 409365Ssam struct servent *sp; 4110415Ssam int uid, options = 0; 426444Swnj 436444Swnj host = rindex(argv[0], '/'); 446444Swnj if (host) 456444Swnj host++; 466444Swnj else 476444Swnj host = argv[0]; 486444Swnj argv++, --argc; 496444Swnj if (!strcmp(host, "rlogin")) 506444Swnj host = *argv++, --argc; 516444Swnj another: 52*10839Ssam if (argc > 0 && !strcmp(*argv, "-d")) { 536444Swnj argv++, argc--; 5410415Ssam options |= SO_DEBUG; 556444Swnj goto another; 566444Swnj } 57*10839Ssam if (argc > 0 && !strcmp(*argv, "-l")) { 586444Swnj argv++, argc--; 596444Swnj if (argc == 0) 606444Swnj goto usage; 616444Swnj name = *argv++; argc--; 626444Swnj goto another; 636444Swnj } 64*10839Ssam if (argc > 0 && !strncmp(*argv, "-e", 2)) { 656444Swnj cmdchar = argv[0][2]; 666444Swnj argv++, argc--; 676444Swnj goto another; 686444Swnj } 69*10839Ssam if (argc > 0 && !strcmp(*argv, "-8")) { 706444Swnj eight = 1; 716444Swnj argv++, argc--; 726444Swnj goto another; 736444Swnj } 746444Swnj if (host == 0) 756444Swnj goto usage; 766444Swnj if (argc > 0) 776444Swnj goto usage; 786444Swnj pwd = getpwuid(getuid()); 796444Swnj if (pwd == 0) { 806444Swnj fprintf(stderr, "Who are you?\n"); 816444Swnj exit(1); 826444Swnj } 839365Ssam sp = getservbyname("login", "tcp"); 849365Ssam if (sp == 0) { 859365Ssam fprintf(stderr, "rlogin: login/tcp: unknown service\n"); 869365Ssam exit(2); 879365Ssam } 889241Ssam cp = getenv("TERM"); 899241Ssam if (cp) 909241Ssam strcpy(term, cp); 919962Ssam if (ioctl(0, TIOCGETP, &ttyb)==0) { 926444Swnj strcat(term, "/"); 936444Swnj strcat(term, speeds[ttyb.sg_ospeed]); 946444Swnj } 959365Ssam signal(SIGPIPE, lostpeer); 969365Ssam rem = rcmd(&host, sp->s_port, pwd->pw_name, 976444Swnj name ? name : pwd->pw_name, term, 0); 986444Swnj if (rem < 0) 996444Swnj exit(1); 10010415Ssam if (options & SO_DEBUG && 10110415Ssam setsockopt(rem, SOL_SOCKET, SO_DEBUG, 0, 0) < 0) 10210415Ssam perror("rlogin: setsockopt (SO_DEBUG)"); 1039365Ssam uid = getuid(); 1049365Ssam if (setuid(uid) < 0) { 1059365Ssam perror("rlogin: setuid"); 1069365Ssam exit(1); 1079365Ssam } 1089365Ssam doit(); 1099365Ssam /*NOTREACHED*/ 1106444Swnj usage: 1116444Swnj fprintf(stderr, 1126444Swnj "usage: rlogin host [ -ex ] [ -l username ]\n"); 1136444Swnj exit(1); 1146444Swnj } 1156444Swnj 1166444Swnj #define CRLF "\r\n" 1176444Swnj 1189365Ssam int child; 1199365Ssam int done(); 1209365Ssam 1219962Ssam int defflags; 1229962Ssam struct ttychars deftc; 1239962Ssam struct ttychars notc = { 1249962Ssam -1, -1, -1, -1, -1, 1259962Ssam -1, -1, -1, -1, -1, 1269962Ssam -1, -1, -1, -1 1279962Ssam }; 1286444Swnj 1299365Ssam doit() 1306444Swnj { 1316444Swnj int exit(); 1326444Swnj 1339962Ssam ioctl(0, TIOCGET, (char *)&defflags); 1349962Ssam defflags &= ECHO | CRMOD; 1359962Ssam ioctl(0, TIOCCGET, (char *)&deftc); 1369962Ssam notc.tc_startc = deftc.tc_startc; 1379962Ssam notc.tc_stopc = deftc.tc_stopc; 1386444Swnj signal(SIGINT, exit); 1396444Swnj signal(SIGHUP, exit); 1406444Swnj signal(SIGQUIT, exit); 1419365Ssam child = fork(); 1429365Ssam if (child == -1) { 1439365Ssam perror("rlogin: fork"); 1449365Ssam done(); 1459365Ssam } 1469365Ssam signal(SIGINT, SIG_IGN); 1479365Ssam if (child == 0) { 1489365Ssam reader(); 1496444Swnj prf("\007Lost connection."); 1506444Swnj exit(3); 1516444Swnj } 1526444Swnj signal(SIGCHLD, done); 1536444Swnj mode(1); 1549365Ssam writer(); 1556444Swnj prf("Disconnected."); 1566444Swnj done(); 1576444Swnj } 1586444Swnj 1596444Swnj done() 1606444Swnj { 1616444Swnj 1626444Swnj mode(0); 1639365Ssam if (child > 0 && kill(child, SIGKILL) >= 0) 1649365Ssam wait((int *)0); 1656444Swnj exit(0); 1666444Swnj } 1676444Swnj 1686444Swnj /* 1699365Ssam * writer: write to remote: 0 -> line. 1709365Ssam * ~. terminate 1719365Ssam * ~^Z suspend rlogin process. 17210415Ssam * ~^Y suspend rlogin process, but leave reader alone. 1736444Swnj */ 1749365Ssam writer() 1756444Swnj { 1769365Ssam char b[600], c; 1779365Ssam register char *p; 1786444Swnj 1799365Ssam top: 1809365Ssam p = b; 1819365Ssam while (read(0, &c, 1) > 0) { 1829365Ssam int local; 1839365Ssam 1849365Ssam if (eight == 0) 1859365Ssam c &= 0177; 1869365Ssam /* 1879365Ssam * If we're at the beginning of the line 1889365Ssam * and recognize a command character, then 1899365Ssam * we echo locally. Otherwise, characters 1909365Ssam * are echo'd remotely. If the command 1919365Ssam * character is doubled, this acts as a 1929365Ssam * force and local echo is suppressed. 1939365Ssam */ 1949365Ssam if (p == b) 1959365Ssam local = (c == cmdchar); 1969365Ssam if (p == b + 1 && *b == cmdchar) 1979365Ssam local = (c != cmdchar); 1989365Ssam if (!local) { 1999365Ssam if (write(rem, &c, 1) == 0) { 2009365Ssam prf("line gone"); 2019365Ssam return; 2026444Swnj } 2039365Ssam if (eight == 0) 2049365Ssam c &= 0177; 2059365Ssam } else { 2069365Ssam if (c == 0177) 2079962Ssam c = deftc.tc_kill; 2089365Ssam if (c == '\r' || c == '\n') { 2099962Ssam char cmdc = b[1]; 2106444Swnj 2119962Ssam if (cmdc == '.' || cmdc == deftc.tc_eofc) { 2129365Ssam write(0, CRLF, sizeof(CRLF)); 2139365Ssam return; 2149962Ssam } 2159962Ssam if (cmdc == deftc.tc_suspc || 2169962Ssam cmdc == deftc.tc_dsuspc) { 2179365Ssam write(0, CRLF, sizeof(CRLF)); 2189365Ssam mode(0); 2199365Ssam signal(SIGCHLD, SIG_IGN); 2209962Ssam kill(cmdc == deftc.tc_suspc ? 2219962Ssam 0 : getpid(), SIGTSTP); 2229365Ssam signal(SIGCHLD, done); 2239365Ssam mode(1); 2249365Ssam goto top; 2256444Swnj } 2269365Ssam *p++ = c; 2279365Ssam write(rem, b, p - b); 2289365Ssam goto top; 2296444Swnj } 2309365Ssam write(1, &c, 1); 2316444Swnj } 2329365Ssam *p++ = c; 2339962Ssam if (c == deftc.tc_erase) { 2349365Ssam p -= 2; 2359365Ssam if (p < b) 2369365Ssam goto top; 2376444Swnj } 2389962Ssam if (c == deftc.tc_kill || c == 0177 || c == deftc.tc_eofc || 2399365Ssam c == '\r' || c == '\n') 2409365Ssam goto top; 2416444Swnj } 2426444Swnj } 2436444Swnj 2446444Swnj oob() 2456444Swnj { 246*10839Ssam int out = 1+1, atmark; 2479365Ssam char waste[BUFSIZ], mark; 2486444Swnj 2496444Swnj signal(SIGURG, oob); 2509365Ssam ioctl(1, TIOCFLUSH, (char *)&out); 2516444Swnj for (;;) { 252*10839Ssam if (ioctl(rem, SIOCATMARK, &atmark) < 0) { 2536444Swnj perror("ioctl"); 2546444Swnj break; 2556444Swnj } 256*10839Ssam if (atmark) 2576444Swnj break; 2589365Ssam (void) read(rem, waste, sizeof (waste)); 2596444Swnj } 2609207Ssam recv(rem, &mark, 1, SOF_OOB); 2616444Swnj if (mark & TIOCPKT_NOSTOP) { 2629962Ssam notc.tc_stopc = -1; 2639962Ssam notc.tc_startc = -1; 2649962Ssam ioctl(0, TIOCCSET, (char *)¬c); 2656444Swnj } 2666444Swnj if (mark & TIOCPKT_DOSTOP) { 2679962Ssam notc.tc_stopc = deftc.tc_stopc; 2689962Ssam notc.tc_startc = deftc.tc_startc; 2699962Ssam ioctl(0, TIOCCSET, (char *)¬c); 2706444Swnj } 2716444Swnj } 2726444Swnj 2739365Ssam /* 2749365Ssam * reader: read from remote: line -> 1 2759365Ssam */ 2769365Ssam reader() 2776444Swnj { 2789365Ssam char rb[BUFSIZ]; 2799365Ssam register int cnt; 2806444Swnj 2819365Ssam signal(SIGURG, oob); 2826444Swnj { int pid = -getpid(); 2839365Ssam ioctl(rem, SIOCSPGRP, (char *)&pid); } 2846444Swnj for (;;) { 2859365Ssam cnt = read(rem, rb, sizeof (rb)); 2866444Swnj if (cnt <= 0) { 2879365Ssam if (errno == EINTR) 2886444Swnj continue; 2896444Swnj break; 2906444Swnj } 2919365Ssam write(1, rb, cnt); 2926444Swnj } 2936444Swnj } 2946444Swnj 2956444Swnj mode(f) 2966444Swnj { 2979962Ssam struct ttychars *tc; 2989962Ssam int flags; 2999365Ssam 3009962Ssam ioctl(0, TIOCGET, (char *)&flags); 3019962Ssam switch (f) { 3029962Ssam 3039962Ssam case 0: 3049962Ssam flags &= ~CBREAK; 3059962Ssam flags |= defflags; 3069962Ssam tc = &deftc; 3079962Ssam break; 3089962Ssam 3099962Ssam case 1: 3109962Ssam flags |= CBREAK; 3119962Ssam flags &= ~defflags; 3129962Ssam tc = ¬c; 3139962Ssam break; 3149962Ssam 3159962Ssam default: 3169962Ssam return; 3176444Swnj } 3189962Ssam ioctl(0, TIOCSET, (char *)&flags); 3199962Ssam ioctl(0, TIOCCSET, (char *)tc); 3206444Swnj } 3216444Swnj 3229365Ssam /*VARARGS*/ 3236444Swnj prf(f, a1, a2, a3) 3249365Ssam char *f; 3256444Swnj { 3266444Swnj fprintf(stderr, f, a1, a2, a3); 3276444Swnj fprintf(stderr, CRLF); 3286444Swnj } 3296444Swnj 3309365Ssam lostpeer() 3316444Swnj { 3329365Ssam signal(SIGPIPE, SIG_IGN); 3339365Ssam prf("\007Lost connection"); 3349365Ssam done(); 3356444Swnj } 336