16446Swnj #ifndef lint 2*8380Ssam static char sccsid[] = "@(#)rlogind.c 4.2 82/10/07"; 36446Swnj #endif 46446Swnj 56446Swnj #include <stdio.h> 66446Swnj #include <sys/types.h> 76446Swnj #include <sys/stat.h> 86446Swnj #include <sys/socket.h> 96446Swnj #include <net/in.h> 106446Swnj #include <errno.h> 116446Swnj #include <pwd.h> 126446Swnj #include <wait.h> 136446Swnj #include <signal.h> 146446Swnj #include <sgtty.h> 156446Swnj #include <stdio.h> 16*8380Ssam #include <netdb.h> 176446Swnj 186446Swnj extern errno; 196446Swnj struct passwd *getpwnam(); 20*8380Ssam char *crypt(), *rindex(), *index(), *malloc(); 216446Swnj int options = SO_ACCEPTCONN|SO_KEEPALIVE; 22*8380Ssam struct sockaddr_in sin = { AF_INET }; 236446Swnj /* 246446Swnj * remote login server: 256446Swnj * remuser\0 266446Swnj * locuser\0 276446Swnj * terminal type\0 286446Swnj * data 296446Swnj */ 306446Swnj main(argc, argv) 316446Swnj int argc; 326446Swnj char **argv; 336446Swnj { 346446Swnj union wait status; 356446Swnj int f, debug = 0; 366446Swnj struct sockaddr_in from; 37*8380Ssam struct servent *sp; 386446Swnj 39*8380Ssam sp = getservbyname("login", "tcp"); 40*8380Ssam if (sp == 0) { 41*8380Ssam fprintf(stderr, "rlogind: tcp/rlogin: unknown service\n"); 42*8380Ssam exit(1); 43*8380Ssam } 446446Swnj #ifndef DEBUG 456446Swnj if (fork()) 466446Swnj exit(0); 476446Swnj for (f = 0; f < 10; f++) 486446Swnj (void) close(f); 496446Swnj (void) open("/", 0); 506446Swnj (void) dup2(0, 1); 516446Swnj (void) dup2(0, 2); 526446Swnj { int tt = open("/dev/tty", 2); 536446Swnj if (tt > 0) { 546446Swnj ioctl(tt, TIOCNOTTY, 0); 556446Swnj close(tt); 566446Swnj } 576446Swnj } 586446Swnj #endif 59*8380Ssam sin.sin_port = htons(sp->s_port); 606446Swnj argc--, argv++; 616446Swnj if (argc > 0 && !strcmp(argv[0], "-d")) 62*8380Ssam options |= SO_DEBUG, argv++, argc--; 63*8380Ssam if (argc > 0) { 64*8380Ssam int port = atoi(argv[0]); 65*8380Ssam 66*8380Ssam if (port < 0) { 67*8380Ssam fprintf(stderr, "%s: bad port #\n", argv[0]); 68*8380Ssam exit(1); 69*8380Ssam } 70*8380Ssam sin.sin_port = htons(port); 71*8380Ssam argv++, argc--; 72*8380Ssam } 736446Swnj for (;;) { 746446Swnj f = socket(SOCK_STREAM, 0, &sin, options); 756446Swnj if (f < 0) { 766446Swnj perror("socket"); 776446Swnj sleep(5); 786446Swnj continue; 796446Swnj } 806446Swnj if (accept(f, &from) < 0) { 816446Swnj perror("accept"); 826446Swnj close(f); 836446Swnj sleep(1); 846446Swnj continue; 856446Swnj } 866446Swnj if (fork() == 0) 876446Swnj doit(f, &from); 886446Swnj close(f); 896446Swnj while (wait3(status, WNOHANG, 0) > 0) 906446Swnj continue; 916446Swnj } 926446Swnj } 936446Swnj 946446Swnj char locuser[32], remuser[32]; 956446Swnj char buf[BUFSIZ]; 966446Swnj int child; 976446Swnj int cleanup(); 986446Swnj int netf; 996446Swnj extern errno; 1006446Swnj char *line; 1016446Swnj 1026446Swnj doit(f, fromp) 1036446Swnj int f; 1046446Swnj struct sockaddr_in *fromp; 1056446Swnj { 106*8380Ssam char c; 1076446Swnj int i, p, cc, t; 1086446Swnj int stop = TIOCPKT_DOSTOP; 109*8380Ssam register struct hostent *hp; 1106446Swnj 1116446Swnj alarm(60); 1126446Swnj read(f, &c, 1); 1136446Swnj if (c != 0) 1146446Swnj exit(1); 1156446Swnj alarm(0); 1166446Swnj fromp->sin_port = htons(fromp->sin_port); 117*8380Ssam hp = gethostbyaddr(&fromp->sin_addr, sizeof (struct in_addr), 118*8380Ssam fromp->sin_family); 1196446Swnj if (fromp->sin_family != AF_INET || 1206446Swnj fromp->sin_port >= IPPORT_RESERVED || 121*8380Ssam hp == 0) { 1226446Swnj write(f, "\01Permission denied.\n", 20); 1236446Swnj exit(1); 1246446Swnj } 1256446Swnj write(f, "", 1); 1266446Swnj for (c = 'p'; c <= 's'; c++) { 1276446Swnj struct stat stb; 1286446Swnj line = "/dev/ptyXX"; 1296446Swnj line[strlen("/dev/pty")] = c; 1306446Swnj line[strlen("/dev/ptyp")] = '0'; 1316446Swnj if (stat(line, &stb) < 0) 1326446Swnj break; 1336446Swnj for (i = 0; i < 16; i++) { 1346446Swnj line[strlen("/dev/ptyp")] = "0123456789abcdef"[i]; 1356446Swnj p = open(line, 2); 1366446Swnj if (p > 0) 1376446Swnj goto gotpty; 1386446Swnj } 1396446Swnj } 1406446Swnj dup2(f, 1); 1416446Swnj printf("All network ports in use.\r\n"); 1426446Swnj exit(1); 1436446Swnj gotpty: 1446446Swnj dup2(f, 0); 1456446Swnj line[strlen("/dev/")] = 't'; 1466446Swnj #ifdef DEBUG 1476446Swnj { int tt = open("/dev/tty", 2); 1486446Swnj if (tt > 0) { 1496446Swnj ioctl(tt, TIOCNOTTY, 0); 1506446Swnj close(tt); 1516446Swnj } 1526446Swnj } 1536446Swnj #endif 1546446Swnj t = open(line, 2); 1556446Swnj if (t < 0) { 1566446Swnj dup2(f, 2); 1576446Swnj perror(line); 1586446Swnj exit(1); 1596446Swnj } 1606446Swnj { struct sgttyb b; 1616446Swnj gtty(t, &b); b.sg_flags = RAW|ANYP; stty(t, &b); 1626446Swnj } 1636446Swnj if (fork()) { 1646446Swnj char pibuf[1024], fibuf[1024], *pbp, *fbp; 1656446Swnj int pcc = 0, fcc = 0, on = 1; 1666446Swnj /* FILE *console = fopen("/dev/console", "w"); */ 1676446Swnj /* setbuf(console, 0); */ 1686446Swnj 1696446Swnj /* fprintf(console, "f %d p %d\r\n", f, p); */ 1706446Swnj ioctl(f, FIONBIO, &on); 1716446Swnj ioctl(p, FIONBIO, &on); 1726446Swnj ioctl(p, TIOCPKT, &on); 1736446Swnj signal(SIGTSTP, SIG_IGN); 1746446Swnj sigset(SIGCHLD, cleanup); 1756446Swnj for (;;) { 1766446Swnj int ibits = 0, obits = 0; 1776446Swnj if (fcc) obits |= (1<<p); else ibits |= (1<<f); 1786446Swnj if (pcc >= 0) 1796446Swnj if (pcc) obits |= (1<<f); else ibits |= (1<<p); 1806446Swnj if (fcc < 0 && pcc < 0) break; 1816446Swnj /* fprintf(console, "ibits from %d obits from %d\r\n", ibits, obits); */ 1826446Swnj select(32, &ibits, &obits, 10000000); 1836446Swnj /* fprintf(console, "ibits %d obits %d\r\n", ibits, obits); */ 1846446Swnj if (ibits == 0 && obits == 0) { 1856446Swnj sleep(5); 1866446Swnj continue; 1876446Swnj } 1886446Swnj if (ibits & (1<<f)) { 1896446Swnj fcc = read(f, fibuf, sizeof (fibuf)); 1906446Swnj /* fprintf(console, "%d from f\r\n", fcc); */ 1916446Swnj if (fcc < 0 && errno == EWOULDBLOCK) 1926446Swnj fcc = 0; 1936446Swnj else { 1946446Swnj if (fcc <= 0) 1956446Swnj break; 1966446Swnj fbp = fibuf; 1976446Swnj } 1986446Swnj } 1996446Swnj if (ibits & (1<<p)) { 2006446Swnj pcc = read(p, pibuf, sizeof (pibuf)); 2016446Swnj /* fprintf(console, "%d from p, buf[0] %x, errno %d\r\n", pcc, buf[0], errno); */ 2026446Swnj pbp = pibuf; 2036446Swnj if (pcc < 0 && errno == EWOULDBLOCK) 2046446Swnj pcc = 0; 2056446Swnj else if (pcc <= 0) 2066446Swnj pcc = -1; 2076446Swnj else if (pibuf[0] == 0) 2086446Swnj pbp++, pcc--; 2096446Swnj else { 2106446Swnj if (pibuf[0]&(TIOCPKT_FLUSHWRITE| 2116446Swnj TIOCPKT_NOSTOP| 2126446Swnj TIOCPKT_DOSTOP)) { 2136446Swnj int nstop = pibuf[0] & 2146446Swnj (TIOCPKT_NOSTOP| 2156446Swnj TIOCPKT_DOSTOP); 2166446Swnj if (nstop) 2176446Swnj stop = nstop; 2186446Swnj pibuf[0] |= nstop; 2196446Swnj ioctl(f,SIOCSENDOOB,&pibuf[0]); 2206446Swnj } 2216446Swnj pcc = 0; 2226446Swnj } 2236446Swnj } 2246446Swnj if ((obits & (1<<f)) && pcc > 0) { 2256446Swnj cc = write(f, pbp, pcc); 2266446Swnj /* fprintf(console, "%d of %d to f\r\n", cc, pcc); */ 2276446Swnj if (cc > 0) { 2286446Swnj pcc -= cc; 2296446Swnj pbp += cc; 2306446Swnj } 2316446Swnj } 2326446Swnj if ((obits & (1<<p)) && fcc > 0) { 2336446Swnj cc = write(p, fbp, fcc); 2346446Swnj /* fprintf(console, "%d of %d to p\r\n", cc, fcc); */ 2356446Swnj if (cc > 0) { 2366446Swnj fcc -= cc; 2376446Swnj fbp += cc; 2386446Swnj } 2396446Swnj } 2406446Swnj } 2416446Swnj cleanup(); 2426446Swnj } 2436446Swnj close(f); 2446446Swnj close(p); 2456446Swnj dup2(t, 0); 2466446Swnj dup2(t, 1); 2476446Swnj dup2(t, 2); 2486446Swnj close(t); 249*8380Ssam execl("/bin/login", "login", "-r", hp->h_name, 0); 2506446Swnj perror("/bin/login"); 2516446Swnj exit(1); 2526446Swnj } 2536446Swnj 2546446Swnj cleanup() 2556446Swnj { 2566446Swnj int how = 2; 2576446Swnj 2586446Swnj rmut(); 2596446Swnj ioctl(netf, SIOCDONE, &how); 2606446Swnj kill(0, SIGKILL); 2616446Swnj exit(1); 2626446Swnj } 2636446Swnj 2646446Swnj #include <utmp.h> 2656446Swnj 2666446Swnj struct utmp wtmp; 2676446Swnj char wtmpf[] = "/usr/adm/wtmp"; 2686446Swnj char utmp[] = "/etc/utmp"; 2696446Swnj #define SCPYN(a, b) strncpy(a, b, sizeof(a)) 2706446Swnj #define SCMPN(a, b) strncmp(a, b, sizeof(a)) 2716446Swnj 2726446Swnj rmut() 2736446Swnj { 2746446Swnj register f; 2756446Swnj int found = 0; 2766446Swnj 2776446Swnj f = open(utmp, 2); 2786446Swnj if (f >= 0) { 2796446Swnj while(read(f, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp)) { 2806446Swnj if (SCMPN(wtmp.ut_line, line+5) || wtmp.ut_name[0]==0) 2816446Swnj continue; 2826446Swnj lseek(f, -(long)sizeof(wtmp), 1); 2836446Swnj SCPYN(wtmp.ut_name, ""); 2846446Swnj time(&wtmp.ut_time); 2856446Swnj write(f, (char *)&wtmp, sizeof(wtmp)); 2866446Swnj found++; 2876446Swnj } 2886446Swnj close(f); 2896446Swnj } 2906446Swnj if (found) { 2916446Swnj f = open(wtmpf, 1); 2926446Swnj if (f >= 0) { 2936446Swnj SCPYN(wtmp.ut_line, line+5); 2946446Swnj SCPYN(wtmp.ut_name, ""); 2956446Swnj time(&wtmp.ut_time); 2966446Swnj lseek(f, (long)0, 2); 2976446Swnj write(f, (char *)&wtmp, sizeof(wtmp)); 2986446Swnj close(f); 2996446Swnj } 3006446Swnj } 3016446Swnj chmod(line, 0666); 3026446Swnj chown(line, 0, 0); 3036446Swnj line[strlen("/dev/")] = 'p'; 3046446Swnj chmod(line, 0666); 3056446Swnj chown(line, 0, 0); 3066446Swnj } 307