16444Swnj #ifndef lint 2*9962Ssam static char sccsid[] = "@(#)rlogin.c 4.7 82/12/25"; 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 rcmdoptions = 0; 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; 429365Ssam int uid; 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: 536444Swnj if (!strcmp(*argv, "-d")) { 546444Swnj argv++, argc--; 556444Swnj rcmdoptions |= SO_DEBUG; 566444Swnj goto another; 576444Swnj } 586444Swnj if (!strcmp(*argv, "-l")) { 596444Swnj argv++, argc--; 606444Swnj if (argc == 0) 616444Swnj goto usage; 626444Swnj name = *argv++; argc--; 636444Swnj goto another; 646444Swnj } 656444Swnj if (!strncmp(*argv, "-e", 2)) { 666444Swnj cmdchar = argv[0][2]; 676444Swnj argv++, argc--; 686444Swnj goto another; 696444Swnj } 706444Swnj if (!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); 92*9962Ssam if (ioctl(0, TIOCGETP, &ttyb)==0) { 936444Swnj strcat(term, "/"); 946444Swnj strcat(term, speeds[ttyb.sg_ospeed]); 956444Swnj } 969365Ssam signal(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); 1019365Ssam uid = getuid(); 1029365Ssam if (setuid(uid) < 0) { 1039365Ssam perror("rlogin: setuid"); 1049365Ssam exit(1); 1059365Ssam } 1069365Ssam doit(); 1079365Ssam /*NOTREACHED*/ 1086444Swnj usage: 1096444Swnj fprintf(stderr, 1106444Swnj "usage: rlogin host [ -ex ] [ -l username ]\n"); 1116444Swnj exit(1); 1126444Swnj } 1136444Swnj 1146444Swnj #define CRLF "\r\n" 1156444Swnj 1169365Ssam int child; 1179365Ssam int done(); 1189365Ssam 119*9962Ssam int defflags; 120*9962Ssam struct ttychars deftc; 121*9962Ssam struct ttychars notc = { 122*9962Ssam -1, -1, -1, -1, -1, 123*9962Ssam -1, -1, -1, -1, -1, 124*9962Ssam -1, -1, -1, -1 125*9962Ssam }; 1266444Swnj 1279365Ssam doit() 1286444Swnj { 1296444Swnj int exit(); 1306444Swnj 131*9962Ssam ioctl(0, TIOCGET, (char *)&defflags); 132*9962Ssam defflags &= ECHO | CRMOD; 133*9962Ssam ioctl(0, TIOCCGET, (char *)&deftc); 134*9962Ssam notc.tc_startc = deftc.tc_startc; 135*9962Ssam notc.tc_stopc = deftc.tc_stopc; 1366444Swnj signal(SIGINT, exit); 1376444Swnj signal(SIGHUP, exit); 1386444Swnj signal(SIGQUIT, exit); 1399365Ssam child = fork(); 1409365Ssam if (child == -1) { 1419365Ssam perror("rlogin: fork"); 1429365Ssam done(); 1439365Ssam } 1449365Ssam signal(SIGINT, SIG_IGN); 1459365Ssam if (child == 0) { 1469365Ssam reader(); 1476444Swnj prf("\007Lost connection."); 1486444Swnj exit(3); 1496444Swnj } 1506444Swnj signal(SIGCHLD, done); 1516444Swnj mode(1); 1529365Ssam writer(); 1536444Swnj prf("Disconnected."); 1546444Swnj done(); 1556444Swnj } 1566444Swnj 1576444Swnj done() 1586444Swnj { 1596444Swnj 1606444Swnj mode(0); 1619365Ssam if (child > 0 && kill(child, SIGKILL) >= 0) 1629365Ssam wait((int *)0); 1636444Swnj exit(0); 1646444Swnj } 1656444Swnj 1666444Swnj /* 1679365Ssam * writer: write to remote: 0 -> line. 1689365Ssam * ~. terminate 1699365Ssam * ~^Z suspend rlogin process. 1706444Swnj */ 1719365Ssam writer() 1726444Swnj { 1739365Ssam char b[600], c; 1749365Ssam register char *p; 1756444Swnj 1769365Ssam top: 1779365Ssam p = b; 1789365Ssam while (read(0, &c, 1) > 0) { 1799365Ssam int local; 1809365Ssam 1819365Ssam if (eight == 0) 1829365Ssam c &= 0177; 1839365Ssam /* 1849365Ssam * If we're at the beginning of the line 1859365Ssam * and recognize a command character, then 1869365Ssam * we echo locally. Otherwise, characters 1879365Ssam * are echo'd remotely. If the command 1889365Ssam * character is doubled, this acts as a 1899365Ssam * force and local echo is suppressed. 1909365Ssam */ 1919365Ssam if (p == b) 1929365Ssam local = (c == cmdchar); 1939365Ssam if (p == b + 1 && *b == cmdchar) 1949365Ssam local = (c != cmdchar); 1959365Ssam if (!local) { 1969365Ssam if (write(rem, &c, 1) == 0) { 1979365Ssam prf("line gone"); 1989365Ssam return; 1996444Swnj } 2009365Ssam if (eight == 0) 2019365Ssam c &= 0177; 2029365Ssam } else { 2039365Ssam if (c == 0177) 204*9962Ssam c = deftc.tc_kill; 2059365Ssam if (c == '\r' || c == '\n') { 206*9962Ssam char cmdc = b[1]; 2076444Swnj 208*9962Ssam if (cmdc == '.' || cmdc == deftc.tc_eofc) { 2099365Ssam write(0, CRLF, sizeof(CRLF)); 2109365Ssam return; 211*9962Ssam } 212*9962Ssam if (cmdc == deftc.tc_suspc || 213*9962Ssam cmdc == deftc.tc_dsuspc) { 2149365Ssam write(0, CRLF, sizeof(CRLF)); 2159365Ssam mode(0); 2169365Ssam signal(SIGCHLD, SIG_IGN); 217*9962Ssam kill(cmdc == deftc.tc_suspc ? 218*9962Ssam 0 : getpid(), SIGTSTP); 2199365Ssam signal(SIGCHLD, done); 2209365Ssam mode(1); 2219365Ssam goto top; 2226444Swnj } 2239365Ssam *p++ = c; 2249365Ssam write(rem, b, p - b); 2259365Ssam goto top; 2266444Swnj } 2279365Ssam write(1, &c, 1); 2286444Swnj } 2299365Ssam *p++ = c; 230*9962Ssam if (c == deftc.tc_erase) { 2319365Ssam p -= 2; 2329365Ssam if (p < b) 2339365Ssam goto top; 2346444Swnj } 235*9962Ssam if (c == deftc.tc_kill || c == 0177 || c == deftc.tc_eofc || 2369365Ssam c == '\r' || c == '\n') 2379365Ssam goto top; 2386444Swnj } 2396444Swnj } 2406444Swnj 2416444Swnj oob() 2426444Swnj { 2439365Ssam int out = 1+1; 2449365Ssam char waste[BUFSIZ], mark; 2456444Swnj 2466444Swnj signal(SIGURG, oob); 2479365Ssam ioctl(1, TIOCFLUSH, (char *)&out); 2486444Swnj for (;;) { 2496444Swnj if (ioctl(rem, SIOCATMARK, &mark) < 0) { 2506444Swnj perror("ioctl"); 2516444Swnj break; 2526444Swnj } 2536444Swnj if (mark) 2546444Swnj break; 2559365Ssam (void) read(rem, waste, sizeof (waste)); 2566444Swnj } 2579207Ssam recv(rem, &mark, 1, SOF_OOB); 2586444Swnj if (mark & TIOCPKT_NOSTOP) { 259*9962Ssam notc.tc_stopc = -1; 260*9962Ssam notc.tc_startc = -1; 261*9962Ssam ioctl(0, TIOCCSET, (char *)¬c); 2626444Swnj } 2636444Swnj if (mark & TIOCPKT_DOSTOP) { 264*9962Ssam notc.tc_stopc = deftc.tc_stopc; 265*9962Ssam notc.tc_startc = deftc.tc_startc; 266*9962Ssam ioctl(0, TIOCCSET, (char *)¬c); 2676444Swnj } 2686444Swnj } 2696444Swnj 2709365Ssam /* 2719365Ssam * reader: read from remote: line -> 1 2729365Ssam */ 2739365Ssam reader() 2746444Swnj { 2759365Ssam char rb[BUFSIZ]; 2769365Ssam register int cnt; 2776444Swnj 2789365Ssam signal(SIGURG, oob); 2796444Swnj { int pid = -getpid(); 2809365Ssam ioctl(rem, SIOCSPGRP, (char *)&pid); } 2816444Swnj for (;;) { 2829365Ssam cnt = read(rem, rb, sizeof (rb)); 2836444Swnj if (cnt <= 0) { 2849365Ssam if (errno == EINTR) 2856444Swnj continue; 2866444Swnj break; 2876444Swnj } 2889365Ssam write(1, rb, cnt); 2896444Swnj } 2906444Swnj } 2916444Swnj 2926444Swnj mode(f) 2936444Swnj { 294*9962Ssam struct ttychars *tc; 295*9962Ssam int flags; 2969365Ssam 297*9962Ssam ioctl(0, TIOCGET, (char *)&flags); 298*9962Ssam switch (f) { 299*9962Ssam 300*9962Ssam case 0: 301*9962Ssam flags &= ~CBREAK; 302*9962Ssam flags |= defflags; 303*9962Ssam tc = &deftc; 304*9962Ssam break; 305*9962Ssam 306*9962Ssam case 1: 307*9962Ssam flags |= CBREAK; 308*9962Ssam flags &= ~defflags; 309*9962Ssam tc = ¬c; 310*9962Ssam break; 311*9962Ssam 312*9962Ssam default: 313*9962Ssam return; 3146444Swnj } 315*9962Ssam ioctl(0, TIOCSET, (char *)&flags); 316*9962Ssam ioctl(0, TIOCCSET, (char *)tc); 3176444Swnj } 3186444Swnj 3199365Ssam /*VARARGS*/ 3206444Swnj prf(f, a1, a2, a3) 3219365Ssam char *f; 3226444Swnj { 3236444Swnj fprintf(stderr, f, a1, a2, a3); 3246444Swnj fprintf(stderr, CRLF); 3256444Swnj } 3266444Swnj 3279365Ssam lostpeer() 3286444Swnj { 3299365Ssam signal(SIGPIPE, SIG_IGN); 3309365Ssam prf("\007Lost connection"); 3319365Ssam done(); 3326444Swnj } 333