16444Swnj #ifndef lint 2*11803Sedward static char sccsid[] = "@(#)rlogin.c 4.11 83/03/31"; 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> 16*11803Sedward #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 } 96*11803Sedward 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, 1136444Swnj "usage: rlogin host [ -ex ] [ -l username ]\n"); 1146444Swnj exit(1); 1156444Swnj } 1166444Swnj 1176444Swnj #define CRLF "\r\n" 1186444Swnj 1199365Ssam int child; 120*11803Sedward int catchild(); 1219365Ssam 1229962Ssam int defflags; 1239962Ssam struct ttychars deftc; 1249962Ssam struct ttychars notc = { 1259962Ssam -1, -1, -1, -1, -1, 1269962Ssam -1, -1, -1, -1, -1, 1279962Ssam -1, -1, -1, -1 1289962Ssam }; 1296444Swnj 1309365Ssam doit() 1316444Swnj { 1326444Swnj int exit(); 1336444Swnj 1349962Ssam ioctl(0, TIOCGET, (char *)&defflags); 1359962Ssam defflags &= ECHO | CRMOD; 1369962Ssam ioctl(0, TIOCCGET, (char *)&deftc); 1379962Ssam notc.tc_startc = deftc.tc_startc; 1389962Ssam notc.tc_stopc = deftc.tc_stopc; 139*11803Sedward sigset(SIGINT, exit); 140*11803Sedward sigset(SIGHUP, exit); 141*11803Sedward sigset(SIGQUIT, exit); 1429365Ssam child = fork(); 1439365Ssam if (child == -1) { 1449365Ssam perror("rlogin: fork"); 1459365Ssam done(); 1469365Ssam } 147*11803Sedward sigignore(SIGINT); 148*11803Sedward mode(1); 1499365Ssam if (child == 0) { 1509365Ssam reader(); 1516444Swnj prf("\007Lost connection."); 1526444Swnj exit(3); 1536444Swnj } 154*11803Sedward sigset(SIGCHLD, catchild); 1559365Ssam writer(); 1566444Swnj prf("Disconnected."); 1576444Swnj done(); 1586444Swnj } 1596444Swnj 1606444Swnj done() 1616444Swnj { 1626444Swnj 1636444Swnj mode(0); 1649365Ssam if (child > 0 && kill(child, SIGKILL) >= 0) 1659365Ssam wait((int *)0); 1666444Swnj exit(0); 1676444Swnj } 1686444Swnj 169*11803Sedward catchild() 170*11803Sedward { 171*11803Sedward union wait status; 172*11803Sedward int pid; 173*11803Sedward 174*11803Sedward again: 175*11803Sedward pid = wait3(&status, WNOHANG|WUNTRACED, 0); 176*11803Sedward if (pid == 0) 177*11803Sedward return; 178*11803Sedward /* 179*11803Sedward * if the child (reader) dies, just quit 180*11803Sedward */ 181*11803Sedward if (pid < 0 || pid == child && !WIFSTOPPED(status)) 182*11803Sedward done(); 183*11803Sedward goto again; 184*11803Sedward } 185*11803Sedward 1866444Swnj /* 1879365Ssam * writer: write to remote: 0 -> line. 1889365Ssam * ~. terminate 1899365Ssam * ~^Z suspend rlogin process. 19010415Ssam * ~^Y suspend rlogin process, but leave reader alone. 1916444Swnj */ 1929365Ssam writer() 1936444Swnj { 1949365Ssam char b[600], c; 1959365Ssam register char *p; 196*11803Sedward register n; 1976444Swnj 1989365Ssam top: 1999365Ssam p = b; 200*11803Sedward for (;;) { 2019365Ssam int local; 2029365Ssam 203*11803Sedward n = read(0, &c, 1); 204*11803Sedward if (n == 0) 205*11803Sedward break; 206*11803Sedward if (n < 0) 207*11803Sedward if (errno == EINTR) 208*11803Sedward continue; 209*11803Sedward else 210*11803Sedward break; 211*11803Sedward 2129365Ssam if (eight == 0) 2139365Ssam c &= 0177; 2149365Ssam /* 2159365Ssam * If we're at the beginning of the line 2169365Ssam * and recognize a command character, then 2179365Ssam * we echo locally. Otherwise, characters 2189365Ssam * are echo'd remotely. If the command 2199365Ssam * character is doubled, this acts as a 2209365Ssam * force and local echo is suppressed. 2219365Ssam */ 2229365Ssam if (p == b) 2239365Ssam local = (c == cmdchar); 2249365Ssam if (p == b + 1 && *b == cmdchar) 2259365Ssam local = (c != cmdchar); 2269365Ssam if (!local) { 2279365Ssam if (write(rem, &c, 1) == 0) { 2289365Ssam prf("line gone"); 2299365Ssam return; 2306444Swnj } 2319365Ssam if (eight == 0) 2329365Ssam c &= 0177; 2339365Ssam } else { 2349365Ssam if (c == 0177) 2359962Ssam c = deftc.tc_kill; 2369365Ssam if (c == '\r' || c == '\n') { 2379962Ssam char cmdc = b[1]; 2386444Swnj 2399962Ssam if (cmdc == '.' || cmdc == deftc.tc_eofc) { 2409365Ssam write(0, CRLF, sizeof(CRLF)); 2419365Ssam return; 2429962Ssam } 2439962Ssam if (cmdc == deftc.tc_suspc || 2449962Ssam cmdc == deftc.tc_dsuspc) { 2459365Ssam write(0, CRLF, sizeof(CRLF)); 2469365Ssam mode(0); 247*11803Sedward sigignore(SIGCHLD); 2489962Ssam kill(cmdc == deftc.tc_suspc ? 2499962Ssam 0 : getpid(), SIGTSTP); 250*11803Sedward sigrelse(SIGCHLD); 2519365Ssam mode(1); 2529365Ssam goto top; 2536444Swnj } 2549365Ssam *p++ = c; 2559365Ssam write(rem, b, p - b); 2569365Ssam goto top; 2576444Swnj } 2589365Ssam write(1, &c, 1); 2596444Swnj } 2609365Ssam *p++ = c; 2619962Ssam if (c == deftc.tc_erase) { 2629365Ssam p -= 2; 2639365Ssam if (p < b) 2649365Ssam goto top; 2656444Swnj } 2669962Ssam if (c == deftc.tc_kill || c == 0177 || c == deftc.tc_eofc || 2679365Ssam c == '\r' || c == '\n') 2689365Ssam goto top; 269*11803Sedward if (p >= &b[sizeof b]) 270*11803Sedward p--; 2716444Swnj } 2726444Swnj } 2736444Swnj 2746444Swnj oob() 2756444Swnj { 27610839Ssam int out = 1+1, atmark; 2779365Ssam char waste[BUFSIZ], mark; 2786444Swnj 2799365Ssam ioctl(1, TIOCFLUSH, (char *)&out); 2806444Swnj for (;;) { 28110839Ssam if (ioctl(rem, SIOCATMARK, &atmark) < 0) { 2826444Swnj perror("ioctl"); 2836444Swnj break; 2846444Swnj } 28510839Ssam if (atmark) 2866444Swnj break; 2879365Ssam (void) read(rem, waste, sizeof (waste)); 2886444Swnj } 2899207Ssam recv(rem, &mark, 1, SOF_OOB); 2906444Swnj if (mark & TIOCPKT_NOSTOP) { 2919962Ssam notc.tc_stopc = -1; 2929962Ssam notc.tc_startc = -1; 2939962Ssam ioctl(0, TIOCCSET, (char *)¬c); 2946444Swnj } 2956444Swnj if (mark & TIOCPKT_DOSTOP) { 2969962Ssam notc.tc_stopc = deftc.tc_stopc; 2979962Ssam notc.tc_startc = deftc.tc_startc; 2989962Ssam ioctl(0, TIOCCSET, (char *)¬c); 2996444Swnj } 3006444Swnj } 3016444Swnj 3029365Ssam /* 3039365Ssam * reader: read from remote: line -> 1 3049365Ssam */ 3059365Ssam reader() 3066444Swnj { 3079365Ssam char rb[BUFSIZ]; 3089365Ssam register int cnt; 3096444Swnj 310*11803Sedward sigset(SIGURG, oob); 3116444Swnj { int pid = -getpid(); 3129365Ssam ioctl(rem, SIOCSPGRP, (char *)&pid); } 3136444Swnj for (;;) { 3149365Ssam cnt = read(rem, rb, sizeof (rb)); 31511396Ssam if (cnt == 0) 31611396Ssam break; 31711396Ssam if (cnt < 0) { 3189365Ssam if (errno == EINTR) 3196444Swnj continue; 3206444Swnj break; 3216444Swnj } 3229365Ssam write(1, rb, cnt); 3236444Swnj } 3246444Swnj } 3256444Swnj 3266444Swnj mode(f) 3276444Swnj { 3289962Ssam struct ttychars *tc; 3299962Ssam int flags; 3309365Ssam 3319962Ssam ioctl(0, TIOCGET, (char *)&flags); 3329962Ssam switch (f) { 3339962Ssam 3349962Ssam case 0: 3359962Ssam flags &= ~CBREAK; 3369962Ssam flags |= defflags; 3379962Ssam tc = &deftc; 3389962Ssam break; 3399962Ssam 3409962Ssam case 1: 3419962Ssam flags |= CBREAK; 3429962Ssam flags &= ~defflags; 3439962Ssam tc = ¬c; 3449962Ssam break; 3459962Ssam 3469962Ssam default: 3479962Ssam return; 3486444Swnj } 3499962Ssam ioctl(0, TIOCSET, (char *)&flags); 3509962Ssam ioctl(0, TIOCCSET, (char *)tc); 3516444Swnj } 3526444Swnj 3539365Ssam /*VARARGS*/ 3546444Swnj prf(f, a1, a2, a3) 3559365Ssam char *f; 3566444Swnj { 3576444Swnj fprintf(stderr, f, a1, a2, a3); 3586444Swnj fprintf(stderr, CRLF); 3596444Swnj } 3606444Swnj 3619365Ssam lostpeer() 3626444Swnj { 363*11803Sedward sigignore(SIGPIPE); 3649365Ssam prf("\007Lost connection"); 3659365Ssam done(); 3666444Swnj } 367