16444Swnj #ifndef lint 2*9365Ssam static char sccsid[] = "@(#)rlogin.c 4.5 82/11/27"; 36444Swnj #endif 46444Swnj 56444Swnj #include <sys/types.h> 66444Swnj #include <sys/socket.h> 7*9365Ssam 89207Ssam #include <netinet/in.h> 9*9365Ssam 10*9365Ssam #include <stdio.h> 11*9365Ssam #include <sgtty.h> 126444Swnj #include <errno.h> 136444Swnj #include <pwd.h> 14*9365Ssam #include <signal.h> 15*9365Ssam #include <netdb.h> 166444Swnj 176444Swnj /* 18*9365Ssam * rlogin - remote login 196444Swnj */ 206444Swnj char *index(), *rindex(), *malloc(), *getenv(); 216444Swnj struct passwd *getpwuid(); 22*9365Ssam 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" }; 30*9365Ssam char term[64] = "network"; 31*9365Ssam extern int errno; 32*9365Ssam int lostpeer(); 336444Swnj 34*9365Ssam #define CTRL(c) ('c' & 037) 35*9365Ssam 366444Swnj main(argc, argv) 376444Swnj int argc; 386444Swnj char **argv; 396444Swnj { 40*9365Ssam char *host, *cp; 416444Swnj struct sgttyb ttyb; 426444Swnj struct passwd *pwd; 43*9365Ssam struct servent *sp; 44*9365Ssam int uid; 456444Swnj 466444Swnj host = rindex(argv[0], '/'); 476444Swnj if (host) 486444Swnj host++; 496444Swnj else 506444Swnj host = argv[0]; 516444Swnj argv++, --argc; 526444Swnj if (!strcmp(host, "rlogin")) 536444Swnj host = *argv++, --argc; 546444Swnj another: 556444Swnj if (!strcmp(*argv, "-d")) { 566444Swnj argv++, argc--; 576444Swnj rcmdoptions |= SO_DEBUG; 586444Swnj goto another; 596444Swnj } 606444Swnj if (!strcmp(*argv, "-l")) { 616444Swnj argv++, argc--; 626444Swnj if (argc == 0) 636444Swnj goto usage; 646444Swnj name = *argv++; argc--; 656444Swnj goto another; 666444Swnj } 676444Swnj if (!strncmp(*argv, "-e", 2)) { 686444Swnj cmdchar = argv[0][2]; 696444Swnj argv++, argc--; 706444Swnj goto another; 716444Swnj } 726444Swnj if (!strcmp(*argv, "-8")) { 736444Swnj eight = 1; 746444Swnj argv++, argc--; 756444Swnj goto another; 766444Swnj } 776444Swnj if (host == 0) 786444Swnj goto usage; 796444Swnj if (argc > 0) 806444Swnj goto usage; 816444Swnj pwd = getpwuid(getuid()); 826444Swnj if (pwd == 0) { 836444Swnj fprintf(stderr, "Who are you?\n"); 846444Swnj exit(1); 856444Swnj } 86*9365Ssam sp = getservbyname("login", "tcp"); 87*9365Ssam if (sp == 0) { 88*9365Ssam fprintf(stderr, "rlogin: login/tcp: unknown service\n"); 89*9365Ssam exit(2); 90*9365Ssam } 919241Ssam cp = getenv("TERM"); 929241Ssam if (cp) 939241Ssam strcpy(term, cp); 946444Swnj if (gtty(0, &ttyb)==0) { 956444Swnj strcat(term, "/"); 966444Swnj strcat(term, speeds[ttyb.sg_ospeed]); 976444Swnj } 98*9365Ssam signal(SIGPIPE, lostpeer); 99*9365Ssam rem = rcmd(&host, sp->s_port, pwd->pw_name, 1006444Swnj name ? name : pwd->pw_name, term, 0); 1016444Swnj if (rem < 0) 1026444Swnj exit(1); 103*9365Ssam uid = getuid(); 104*9365Ssam if (setuid(uid) < 0) { 105*9365Ssam perror("rlogin: setuid"); 106*9365Ssam exit(1); 107*9365Ssam } 108*9365Ssam doit(); 109*9365Ssam /*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 118*9365Ssam int child; 119*9365Ssam int done(); 120*9365Ssam 1216444Swnj char tkill, terase; /* current input kill & erase */ 122*9365Ssam char defkill, deferase, defflags; 1236444Swnj 124*9365Ssam struct tchars deftchars; 125*9365Ssam struct tchars notchars = { -1, -1, CTRL(q), CTRL(s), -1, -1 }; 126*9365Ssam struct ltchars defltchars; 127*9365Ssam struct ltchars noltchars = { -1, -1, -1, -1, -1, -1 }; 1286444Swnj 129*9365Ssam doit() 1306444Swnj { 1316444Swnj struct sgttyb stbuf; 1326444Swnj int exit(); 1336444Swnj 134*9365Ssam ioctl(0, TIOCGETP, (char *)&stbuf); 1356444Swnj defkill = stbuf.sg_kill; 1366444Swnj deferase = stbuf.sg_erase; 1376481Sjkf defflags = stbuf.sg_flags & (ECHO | CRMOD); 138*9365Ssam ioctl(0, TIOCGETC, (char *)&deftchars); 139*9365Ssam ioctl(0, TIOCGLTC, (char *)&defltchars); 1406444Swnj signal(SIGINT, exit); 1416444Swnj signal(SIGHUP, exit); 1426444Swnj signal(SIGQUIT, exit); 143*9365Ssam child = fork(); 144*9365Ssam if (child == -1) { 145*9365Ssam perror("rlogin: fork"); 146*9365Ssam done(); 147*9365Ssam } 148*9365Ssam signal(SIGINT, SIG_IGN); 149*9365Ssam if (child == 0) { 150*9365Ssam signal(SIGPIPE, SIG_IGN); 151*9365Ssam reader(); 1526444Swnj prf("\007Lost connection."); 1536444Swnj exit(3); 1546444Swnj } 1556444Swnj signal(SIGCHLD, done); 1566444Swnj mode(1); 157*9365Ssam writer(); 1586444Swnj prf("Disconnected."); 1596444Swnj done(); 1606444Swnj } 1616444Swnj 1626444Swnj done() 1636444Swnj { 1646444Swnj 1656444Swnj mode(0); 166*9365Ssam if (child > 0 && kill(child, SIGKILL) >= 0) 167*9365Ssam wait((int *)0); 1686444Swnj exit(0); 1696444Swnj } 1706444Swnj 1716444Swnj /* 172*9365Ssam * writer: write to remote: 0 -> line. 173*9365Ssam * ~. terminate 174*9365Ssam * ~^Z suspend rlogin process. 1756444Swnj */ 176*9365Ssam writer() 1776444Swnj { 178*9365Ssam char b[600], c; 179*9365Ssam register char *p; 1806444Swnj 181*9365Ssam top: 182*9365Ssam p = b; 183*9365Ssam while (read(0, &c, 1) > 0) { 184*9365Ssam int local; 185*9365Ssam 186*9365Ssam if (eight == 0) 187*9365Ssam c &= 0177; 188*9365Ssam /* 189*9365Ssam * If we're at the beginning of the line 190*9365Ssam * and recognize a command character, then 191*9365Ssam * we echo locally. Otherwise, characters 192*9365Ssam * are echo'd remotely. If the command 193*9365Ssam * character is doubled, this acts as a 194*9365Ssam * force and local echo is suppressed. 195*9365Ssam */ 196*9365Ssam if (p == b) 197*9365Ssam local = (c == cmdchar); 198*9365Ssam if (p == b + 1 && *b == cmdchar) 199*9365Ssam local = (c != cmdchar); 200*9365Ssam if (!local) { 201*9365Ssam if (write(rem, &c, 1) == 0) { 202*9365Ssam prf("line gone"); 203*9365Ssam return; 2046444Swnj } 205*9365Ssam if (eight == 0) 206*9365Ssam c &= 0177; 207*9365Ssam } else { 208*9365Ssam if (c == 0177) 209*9365Ssam c = tkill; 210*9365Ssam if (c == '\r' || c == '\n') { 211*9365Ssam switch (b[1]) { 2126444Swnj 213*9365Ssam case '.': 214*9365Ssam case CTRL(d): 215*9365Ssam write(0, CRLF, sizeof(CRLF)); 216*9365Ssam return; 217*9365Ssam 218*9365Ssam case CTRL(z): 219*9365Ssam write(0, CRLF, sizeof(CRLF)); 220*9365Ssam mode(0); 221*9365Ssam signal(SIGCHLD, SIG_IGN); 222*9365Ssam kill(0, SIGTSTP); 223*9365Ssam signal(SIGCHLD, done); 224*9365Ssam mode(1); 225*9365Ssam goto top; 2266444Swnj } 227*9365Ssam *p++ = c; 228*9365Ssam write(rem, b, p - b); 229*9365Ssam goto top; 2306444Swnj } 231*9365Ssam write(1, &c, 1); 2326444Swnj } 233*9365Ssam *p++ = c; 234*9365Ssam if (c == terase) { 235*9365Ssam p -= 2; 236*9365Ssam if (p < b) 237*9365Ssam goto top; 2386444Swnj } 239*9365Ssam if (c == tkill || c == 0177 || c == CTRL(d) || 240*9365Ssam c == '\r' || c == '\n') 241*9365Ssam goto top; 2426444Swnj } 2436444Swnj } 2446444Swnj 2456444Swnj oob() 2466444Swnj { 247*9365Ssam int out = 1+1; 248*9365Ssam char waste[BUFSIZ], mark; 2496444Swnj 2506444Swnj signal(SIGURG, oob); 251*9365Ssam ioctl(1, TIOCFLUSH, (char *)&out); 2526444Swnj for (;;) { 2536444Swnj if (ioctl(rem, SIOCATMARK, &mark) < 0) { 2546444Swnj perror("ioctl"); 2556444Swnj break; 2566444Swnj } 2576444Swnj if (mark) 2586444Swnj break; 259*9365Ssam (void) read(rem, waste, sizeof (waste)); 2606444Swnj } 2619207Ssam recv(rem, &mark, 1, SOF_OOB); 2626444Swnj if (mark & TIOCPKT_NOSTOP) { 263*9365Ssam notchars.t_stopc = -1; 264*9365Ssam notchars.t_startc = -1; 265*9365Ssam ioctl(0, TIOCSETC, (char *)¬chars); 2666444Swnj } 2676444Swnj if (mark & TIOCPKT_DOSTOP) { 268*9365Ssam notchars.t_stopc = CTRL(s); 269*9365Ssam notchars.t_startc = CTRL(q); 270*9365Ssam ioctl(0, TIOCSETC, (char *)¬chars); 2716444Swnj } 2726444Swnj } 2736444Swnj 274*9365Ssam /* 275*9365Ssam * reader: read from remote: line -> 1 276*9365Ssam */ 277*9365Ssam reader() 2786444Swnj { 279*9365Ssam char rb[BUFSIZ]; 280*9365Ssam register int cnt; 2816444Swnj 282*9365Ssam signal(SIGURG, oob); 283*9365Ssam #ifdef notdef 2846444Swnj { int pid = -getpid(); 285*9365Ssam ioctl(rem, SIOCSPGRP, (char *)&pid); } 286*9365Ssam #endif 2876444Swnj for (;;) { 288*9365Ssam cnt = read(rem, rb, sizeof (rb)); 2896444Swnj if (cnt <= 0) { 290*9365Ssam if (errno == EINTR) 2916444Swnj continue; 2926444Swnj break; 2936444Swnj } 294*9365Ssam write(1, rb, cnt); 2956444Swnj } 2966444Swnj } 2976444Swnj 2986444Swnj mode(f) 2996444Swnj { 3006444Swnj struct sgttyb stbuf; 301*9365Ssam 302*9365Ssam ioctl(0, TIOCGETP, (char *)&stbuf); 3036444Swnj if (f == 0) { 3046444Swnj stbuf.sg_flags &= ~CBREAK; 3056481Sjkf stbuf.sg_flags |= defflags; 306*9365Ssam ioctl(0, TIOCSETC, (char *)&deftchars); 307*9365Ssam ioctl(0, TIOCSLTC, (char *)&defltchars); 3086444Swnj stbuf.sg_kill = defkill; 3096444Swnj stbuf.sg_erase = deferase; 3106444Swnj } 3116444Swnj if (f == 1) { 3126444Swnj stbuf.sg_flags |= CBREAK; 3136444Swnj stbuf.sg_flags &= ~(ECHO|CRMOD); 314*9365Ssam ioctl(0, TIOCSETC, (char *)¬chars); 315*9365Ssam ioctl(0, TIOCSLTC, (char *)&noltchars); 316*9365Ssam stbuf.sg_kill = -1; 317*9365Ssam stbuf.sg_erase = -1; 3186444Swnj } 3196444Swnj if (f == 2) { 3206444Swnj stbuf.sg_flags &= ~CBREAK; 3216444Swnj stbuf.sg_flags &= ~(ECHO|CRMOD); 322*9365Ssam ioctl(0, TIOCSETC, (char *)&deftchars); 323*9365Ssam ioctl(0, TIOCSLTC, (char *)&defltchars); 324*9365Ssam stbuf.sg_kill = -1; 325*9365Ssam stbuf.sg_erase = -1; 3266444Swnj } 327*9365Ssam ioctl(0, TIOCSETN, (char *)&stbuf); 3286444Swnj } 3296444Swnj 330*9365Ssam /*VARARGS*/ 3316444Swnj prf(f, a1, a2, a3) 332*9365Ssam char *f; 3336444Swnj { 3346444Swnj fprintf(stderr, f, a1, a2, a3); 3356444Swnj fprintf(stderr, CRLF); 3366444Swnj } 3376444Swnj 338*9365Ssam lostpeer() 3396444Swnj { 340*9365Ssam signal(SIGPIPE, SIG_IGN); 341*9365Ssam prf("\007Lost connection"); 342*9365Ssam done(); 3436444Swnj } 344