16444Swnj #ifndef lint 2*12155Ssam static char sccsid[] = "@(#)rlogin.c 4.12 83/04/30"; 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> 1611803Sedward #include <wait.h> 176444Swnj 186444Swnj /* 199365Ssam * rlogin - remote login 206444Swnj */ 216444Swnj char *index(), *rindex(), *malloc(), *getenv(); 226444Swnj struct passwd *getpwuid(); 239365Ssam char *name; 246444Swnj int rem; 256444Swnj char cmdchar = '~'; 266444Swnj int eight; 276444Swnj char *speeds[] = 286444Swnj { "0", "50", "75", "110", "134", "150", "200", "300", 296444Swnj "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" }; 309365Ssam char term[64] = "network"; 319365Ssam extern int errno; 329365Ssam int lostpeer(); 336444Swnj 346444Swnj main(argc, argv) 356444Swnj int argc; 366444Swnj char **argv; 376444Swnj { 389365Ssam char *host, *cp; 396444Swnj struct sgttyb ttyb; 406444Swnj struct passwd *pwd; 419365Ssam struct servent *sp; 4210415Ssam int uid, options = 0; 436444Swnj 446444Swnj host = rindex(argv[0], '/'); 456444Swnj if (host) 466444Swnj host++; 476444Swnj else 486444Swnj host = argv[0]; 496444Swnj argv++, --argc; 506444Swnj if (!strcmp(host, "rlogin")) 516444Swnj host = *argv++, --argc; 526444Swnj another: 5310839Ssam if (argc > 0 && !strcmp(*argv, "-d")) { 546444Swnj argv++, argc--; 5510415Ssam options |= SO_DEBUG; 566444Swnj goto another; 576444Swnj } 5810839Ssam if (argc > 0 && !strcmp(*argv, "-l")) { 596444Swnj argv++, argc--; 606444Swnj if (argc == 0) 616444Swnj goto usage; 626444Swnj name = *argv++; argc--; 636444Swnj goto another; 646444Swnj } 6510839Ssam if (argc > 0 && !strncmp(*argv, "-e", 2)) { 666444Swnj cmdchar = argv[0][2]; 676444Swnj argv++, argc--; 686444Swnj goto another; 696444Swnj } 7010839Ssam if (argc > 0 && !strcmp(*argv, "-8")) { 716444Swnj eight = 1; 726444Swnj argv++, argc--; 736444Swnj goto another; 746444Swnj } 756444Swnj if (host == 0) 766444Swnj goto usage; 776444Swnj if (argc > 0) 786444Swnj goto usage; 796444Swnj pwd = getpwuid(getuid()); 806444Swnj if (pwd == 0) { 816444Swnj fprintf(stderr, "Who are you?\n"); 826444Swnj exit(1); 836444Swnj } 849365Ssam sp = getservbyname("login", "tcp"); 859365Ssam if (sp == 0) { 869365Ssam fprintf(stderr, "rlogin: login/tcp: unknown service\n"); 879365Ssam exit(2); 889365Ssam } 899241Ssam cp = getenv("TERM"); 909241Ssam if (cp) 919241Ssam strcpy(term, cp); 929962Ssam if (ioctl(0, TIOCGETP, &ttyb)==0) { 936444Swnj strcat(term, "/"); 946444Swnj strcat(term, speeds[ttyb.sg_ospeed]); 956444Swnj } 9611803Sedward sigset(SIGPIPE, lostpeer); 979365Ssam rem = rcmd(&host, sp->s_port, pwd->pw_name, 986444Swnj name ? name : pwd->pw_name, term, 0); 996444Swnj if (rem < 0) 1006444Swnj exit(1); 10110415Ssam if (options & SO_DEBUG && 10210415Ssam setsockopt(rem, SOL_SOCKET, SO_DEBUG, 0, 0) < 0) 10310415Ssam perror("rlogin: setsockopt (SO_DEBUG)"); 1049365Ssam uid = getuid(); 1059365Ssam if (setuid(uid) < 0) { 1069365Ssam perror("rlogin: setuid"); 1079365Ssam exit(1); 1089365Ssam } 1099365Ssam doit(); 1109365Ssam /*NOTREACHED*/ 1116444Swnj usage: 1126444Swnj fprintf(stderr, 113*12155Ssam "usage: rlogin host [ -ex ] [ -l username ] [ -8 ]\n"); 1146444Swnj exit(1); 1156444Swnj } 1166444Swnj 1176444Swnj #define CRLF "\r\n" 1186444Swnj 1199365Ssam int child; 12011803Sedward int catchild(); 1219365Ssam 1229962Ssam int defflags; 123*12155Ssam int tabflag; 1249962Ssam struct ttychars deftc; 1259962Ssam struct ttychars notc = { 1269962Ssam -1, -1, -1, -1, -1, 1279962Ssam -1, -1, -1, -1, -1, 1289962Ssam -1, -1, -1, -1 1299962Ssam }; 1306444Swnj 1319365Ssam doit() 1326444Swnj { 1336444Swnj int exit(); 1346444Swnj 1359962Ssam ioctl(0, TIOCGET, (char *)&defflags); 136*12155Ssam tabflag = defflags & TBDELAY; 1379962Ssam defflags &= ECHO | CRMOD; 1389962Ssam ioctl(0, TIOCCGET, (char *)&deftc); 1399962Ssam notc.tc_startc = deftc.tc_startc; 1409962Ssam notc.tc_stopc = deftc.tc_stopc; 14111803Sedward sigset(SIGINT, exit); 14211803Sedward sigset(SIGHUP, exit); 14311803Sedward sigset(SIGQUIT, exit); 1449365Ssam child = fork(); 1459365Ssam if (child == -1) { 1469365Ssam perror("rlogin: fork"); 1479365Ssam done(); 1489365Ssam } 14911803Sedward sigignore(SIGINT); 15011803Sedward mode(1); 1519365Ssam if (child == 0) { 1529365Ssam reader(); 153*12155Ssam sleep(1); 154*12155Ssam prf("\007Connection closed."); 1556444Swnj exit(3); 1566444Swnj } 15711803Sedward sigset(SIGCHLD, catchild); 1589365Ssam writer(); 159*12155Ssam prf("Closed connection."); 1606444Swnj done(); 1616444Swnj } 1626444Swnj 1636444Swnj done() 1646444Swnj { 1656444Swnj 1666444Swnj mode(0); 1679365Ssam if (child > 0 && kill(child, SIGKILL) >= 0) 1689365Ssam wait((int *)0); 1696444Swnj exit(0); 1706444Swnj } 1716444Swnj 17211803Sedward catchild() 17311803Sedward { 17411803Sedward union wait status; 17511803Sedward int pid; 17611803Sedward 17711803Sedward again: 17811803Sedward pid = wait3(&status, WNOHANG|WUNTRACED, 0); 17911803Sedward if (pid == 0) 18011803Sedward return; 18111803Sedward /* 18211803Sedward * if the child (reader) dies, just quit 18311803Sedward */ 18411803Sedward if (pid < 0 || pid == child && !WIFSTOPPED(status)) 18511803Sedward done(); 18611803Sedward goto again; 18711803Sedward } 18811803Sedward 1896444Swnj /* 1909365Ssam * writer: write to remote: 0 -> line. 1919365Ssam * ~. terminate 1929365Ssam * ~^Z suspend rlogin process. 19310415Ssam * ~^Y suspend rlogin process, but leave reader alone. 1946444Swnj */ 1959365Ssam writer() 1966444Swnj { 1979365Ssam char b[600], c; 1989365Ssam register char *p; 19911803Sedward register n; 2006444Swnj 2019365Ssam top: 2029365Ssam p = b; 20311803Sedward for (;;) { 2049365Ssam int local; 2059365Ssam 20611803Sedward n = read(0, &c, 1); 20711803Sedward if (n == 0) 20811803Sedward break; 20911803Sedward if (n < 0) 21011803Sedward if (errno == EINTR) 21111803Sedward continue; 21211803Sedward else 21311803Sedward break; 21411803Sedward 2159365Ssam if (eight == 0) 2169365Ssam c &= 0177; 2179365Ssam /* 2189365Ssam * If we're at the beginning of the line 2199365Ssam * and recognize a command character, then 2209365Ssam * we echo locally. Otherwise, characters 2219365Ssam * are echo'd remotely. If the command 2229365Ssam * character is doubled, this acts as a 2239365Ssam * force and local echo is suppressed. 2249365Ssam */ 2259365Ssam if (p == b) 2269365Ssam local = (c == cmdchar); 2279365Ssam if (p == b + 1 && *b == cmdchar) 2289365Ssam local = (c != cmdchar); 2299365Ssam if (!local) { 2309365Ssam if (write(rem, &c, 1) == 0) { 2319365Ssam prf("line gone"); 2329365Ssam return; 2336444Swnj } 2349365Ssam if (eight == 0) 2359365Ssam c &= 0177; 2369365Ssam } else { 2379365Ssam if (c == '\r' || c == '\n') { 2389962Ssam char cmdc = b[1]; 2396444Swnj 2409962Ssam if (cmdc == '.' || cmdc == deftc.tc_eofc) { 2419365Ssam write(0, CRLF, sizeof(CRLF)); 2429365Ssam return; 2439962Ssam } 2449962Ssam if (cmdc == deftc.tc_suspc || 2459962Ssam cmdc == deftc.tc_dsuspc) { 2469365Ssam write(0, CRLF, sizeof(CRLF)); 2479365Ssam mode(0); 24811803Sedward sigignore(SIGCHLD); 2499962Ssam kill(cmdc == deftc.tc_suspc ? 2509962Ssam 0 : getpid(), SIGTSTP); 25111803Sedward sigrelse(SIGCHLD); 2529365Ssam mode(1); 2539365Ssam goto top; 2546444Swnj } 2559365Ssam *p++ = c; 2569365Ssam write(rem, b, p - b); 2579365Ssam goto top; 2586444Swnj } 2599365Ssam write(1, &c, 1); 2606444Swnj } 2619365Ssam *p++ = c; 2629962Ssam if (c == deftc.tc_erase) { 2639365Ssam p -= 2; 2649365Ssam if (p < b) 2659365Ssam goto top; 2666444Swnj } 267*12155Ssam if (c == deftc.tc_kill || c == deftc.tc_eofc || 2689365Ssam c == '\r' || c == '\n') 2699365Ssam goto top; 27011803Sedward if (p >= &b[sizeof b]) 27111803Sedward p--; 2726444Swnj } 2736444Swnj } 2746444Swnj 2756444Swnj oob() 2766444Swnj { 27710839Ssam int out = 1+1, atmark; 2789365Ssam char waste[BUFSIZ], mark; 2796444Swnj 2809365Ssam ioctl(1, TIOCFLUSH, (char *)&out); 2816444Swnj for (;;) { 28210839Ssam if (ioctl(rem, SIOCATMARK, &atmark) < 0) { 2836444Swnj perror("ioctl"); 2846444Swnj break; 2856444Swnj } 28610839Ssam if (atmark) 2876444Swnj break; 2889365Ssam (void) read(rem, waste, sizeof (waste)); 2896444Swnj } 2909207Ssam recv(rem, &mark, 1, SOF_OOB); 2916444Swnj if (mark & TIOCPKT_NOSTOP) { 2929962Ssam notc.tc_stopc = -1; 2939962Ssam notc.tc_startc = -1; 2949962Ssam ioctl(0, TIOCCSET, (char *)¬c); 2956444Swnj } 2966444Swnj if (mark & TIOCPKT_DOSTOP) { 2979962Ssam notc.tc_stopc = deftc.tc_stopc; 2989962Ssam notc.tc_startc = deftc.tc_startc; 2999962Ssam ioctl(0, TIOCCSET, (char *)¬c); 3006444Swnj } 3016444Swnj } 3026444Swnj 3039365Ssam /* 3049365Ssam * reader: read from remote: line -> 1 3059365Ssam */ 3069365Ssam reader() 3076444Swnj { 3089365Ssam char rb[BUFSIZ]; 3099365Ssam register int cnt; 3106444Swnj 31111803Sedward sigset(SIGURG, oob); 3126444Swnj { int pid = -getpid(); 3139365Ssam ioctl(rem, SIOCSPGRP, (char *)&pid); } 3146444Swnj for (;;) { 3159365Ssam cnt = read(rem, rb, sizeof (rb)); 31611396Ssam if (cnt == 0) 31711396Ssam break; 31811396Ssam if (cnt < 0) { 3199365Ssam if (errno == EINTR) 3206444Swnj continue; 3216444Swnj break; 3226444Swnj } 3239365Ssam write(1, rb, cnt); 3246444Swnj } 3256444Swnj } 3266444Swnj 3276444Swnj mode(f) 3286444Swnj { 3299962Ssam struct ttychars *tc; 3309962Ssam int flags; 3319365Ssam 3329962Ssam ioctl(0, TIOCGET, (char *)&flags); 3339962Ssam switch (f) { 3349962Ssam 3359962Ssam case 0: 336*12155Ssam flags &= ~(CBREAK|RAW|TBDELAY); 337*12155Ssam flags |= defflags|tabflag; 3389962Ssam tc = &deftc; 3399962Ssam break; 3409962Ssam 3419962Ssam case 1: 342*12155Ssam flags |= (eight ? RAW : CBREAK); 3439962Ssam flags &= ~defflags; 344*12155Ssam /* preserve tab delays, but turn off XTABS */ 345*12155Ssam if ((flags & TBDELAY) == XTABS) 346*12155Ssam flags &= ~TBDELAY; 3479962Ssam tc = ¬c; 3489962Ssam break; 3499962Ssam 3509962Ssam default: 3519962Ssam return; 3526444Swnj } 3539962Ssam ioctl(0, TIOCSET, (char *)&flags); 3549962Ssam ioctl(0, TIOCCSET, (char *)tc); 3556444Swnj } 3566444Swnj 3579365Ssam /*VARARGS*/ 3586444Swnj prf(f, a1, a2, a3) 3599365Ssam char *f; 3606444Swnj { 3616444Swnj fprintf(stderr, f, a1, a2, a3); 3626444Swnj fprintf(stderr, CRLF); 3636444Swnj } 3646444Swnj 3659365Ssam lostpeer() 3666444Swnj { 36711803Sedward sigignore(SIGPIPE); 368*12155Ssam prf("\007Connection closed."); 3699365Ssam done(); 3706444Swnj } 371