16460Swnj #ifndef lint 2*6577Ssam static char sccsid[] = "@(#)rwhod.c 4.3 82/04/20"; 36460Swnj #endif 46460Swnj 56460Swnj #include <stdio.h> 66460Swnj #include <signal.h> 76460Swnj #include <sys/types.h> 86460Swnj #include <net/in.h> 96460Swnj #include <sys/socket.h> 106460Swnj #include <errno.h> 116460Swnj #include <utmp.h> 126460Swnj #include "rwhod.h" 136460Swnj #include <sys/stat.h> 146460Swnj #include <nlist.h> 156460Swnj #include <sys/ioctl.h> 166460Swnj 176460Swnj struct sockaddr_in sin = { AF_INET, IPPORT_WHOSERVER }; 186460Swnj 196460Swnj extern errno; 206460Swnj 216460Swnj char *localnet = "localnet"; 226460Swnj char *myname = "myname"; 236460Swnj 246460Swnj struct nlist nl[] = { 256460Swnj #define NL_AVENRUN 0 266460Swnj { "_avenrun" }, 276460Swnj #define NL_BOOTIME 1 286460Swnj { "_bootime" }, 296460Swnj 0 306460Swnj }; 316460Swnj 326460Swnj struct whod mywd; 336460Swnj int s, utmpf, kmemf = -1; 346460Swnj 356460Swnj int onalrm(); 366460Swnj char *strcpy(), *sprintf(); 376460Swnj long lseek(); 386460Swnj int getkmem(); 396460Swnj 406460Swnj main() 416460Swnj { 426460Swnj struct sockaddr_in from; 436460Swnj char path[64]; 446460Swnj int addr; 456460Swnj 466460Swnj #ifndef DEBUG 476460Swnj if (fork()) 486460Swnj exit(0); 496460Swnj { int s; 506460Swnj for (s = 0; s < 10; s++) 516460Swnj (void) close(s); 526460Swnj (void) open("/", 0); 536460Swnj (void) dup2(0, 1); 546460Swnj (void) dup2(0, 2); 556460Swnj s = open("/dev/tty", 2); 566460Swnj if (s >= 0) { 576460Swnj ioctl(s, TIOCNOTTY, 0); 586460Swnj (void) close(s); 596460Swnj } 606460Swnj } 616460Swnj #endif 626460Swnj (void) chdir("/dev"); 636460Swnj (void) signal(SIGHUP, getkmem); 646460Swnj if (getuid()) { 656460Swnj fprintf(stderr, "not super user\n"); 666460Swnj exit(1); 676460Swnj } 686460Swnj addr = rhost(&localnet); 696460Swnj if (addr == -1) { 706460Swnj fprintf(stderr, "no localnet for whod\n"); 716460Swnj exit(1); 726460Swnj } 736460Swnj sin.sin_addr.s_addr = addr; 746460Swnj if (rhost(&myname) == -1) { 756460Swnj fprintf(stderr, "don't know my name\n"); 766460Swnj exit(1); 776460Swnj } 786460Swnj strncpy(mywd.wd_hostname, myname, sizeof (mywd.wd_hostname) - 1); 796460Swnj utmpf = open("/etc/utmp", 0); 806460Swnj if (utmpf < 0) { 816460Swnj (void) close(creat("/etc/utmp", 0644)); 826460Swnj utmpf = open("/etc/utmp", 0); 836460Swnj } 846460Swnj if (utmpf < 0) { 856460Swnj perror("/etc/utmp"); 866460Swnj exit(1); 876460Swnj } 886460Swnj getkmem(); 896460Swnj #ifdef vax 906460Swnj sin.sin_port = htons(sin.sin_port); 916460Swnj #endif 926460Swnj again: 936460Swnj if ((s = socket(SOCK_DGRAM, 0, &sin, 0)) < 0) { 946460Swnj perror("socket"); 956460Swnj sleep(5); 966460Swnj goto again; 976460Swnj } 986460Swnj sigset(SIGALRM, onalrm); 996460Swnj onalrm(); 1006460Swnj for (;;) { 1016460Swnj struct whod wd; 1026460Swnj int cc, whod; 1036460Swnj 1046460Swnj cc = receive(s, &from, (char *)&wd, sizeof (struct whod)); 1056460Swnj if (cc <= 0) { 1066460Swnj if (cc < 0 && errno != EINTR) 1076460Swnj perror("receive"); 1086460Swnj continue; 1096460Swnj } 1106460Swnj #ifdef vax 1116460Swnj from.sin_port = ntohs(from.sin_port); 1126460Swnj #endif 1136460Swnj if (from.sin_port != IPPORT_WHOSERVER) { 1146460Swnj printf("bad from port %d\n", from.sin_port); 1156460Swnj continue; 1166460Swnj } 1176460Swnj /* 1186460Swnj if (rhost(&wd.wd_hostname) == -1) { 1196460Swnj printf("unknown host %s\n", wd.wd_hostname); 1206460Swnj continue; 1216460Swnj } 1226460Swnj */ 1236460Swnj (void) sprintf(path, "/etc/whod.%s", wd.wd_hostname); 1246460Swnj whod = creat(path, 0666); 1256460Swnj if (whod < 0) { 1266460Swnj printf("can't create %s\n", path); 1276460Swnj continue; 1286460Swnj } 1296460Swnj (void) time(&wd.wd_recvtime); 1306460Swnj (void) write(whod, (char *)&wd, cc); 1316460Swnj (void) close(whod); 1326460Swnj } 1336460Swnj } 1346460Swnj 1356460Swnj int utmptime; 1366460Swnj int utmpent; 137*6577Ssam struct utmp utmp[100]; 1386460Swnj int alarmcount; 1396460Swnj 1406460Swnj onalrm() 1416460Swnj { 1426460Swnj register int i; 1436460Swnj struct stat stb; 144*6577Ssam register struct whoent *we = mywd.wd_we, *wlast; 1456460Swnj int cc; 1466460Swnj double avenrun[3]; 1476460Swnj time_t now = time(0); 1486460Swnj 1496460Swnj if (alarmcount % 10 == 0) 1506460Swnj getkmem(); 1516460Swnj alarmcount++; 1526460Swnj (void) fstat(utmpf, &stb); 1536460Swnj if (stb.st_mtime != utmptime) { 1546460Swnj (void) lseek(utmpf, (long)0, 0); 1556460Swnj cc = read(utmpf, (char *)utmp, sizeof (utmp)); 1566460Swnj if (cc < 0) { 1576460Swnj perror("/etc/utmp"); 1586460Swnj return; 1596460Swnj } 160*6577Ssam wlast = &mywd.wd_we[(1024 / sizeof (struct whoent)) - 1]; 1616460Swnj utmpent = cc / sizeof (struct utmp); 1626460Swnj for (i = 0; i < utmpent; i++) 1636460Swnj if (utmp[i].ut_name[0]) { 1646460Swnj we->we_utmp = utmp[i]; 165*6577Ssam if (we >= wlast) 166*6577Ssam break; 1676460Swnj we++; 1686460Swnj } 1696460Swnj utmpent = we - mywd.wd_we; 1706460Swnj } 1716460Swnj we = mywd.wd_we; 1726460Swnj for (i = 0; i < utmpent; i++) { 1736460Swnj if (stat(we->we_utmp.ut_line, &stb) >= 0) 1746460Swnj we->we_idle = now - stb.st_atime; 1756460Swnj we++; 1766460Swnj } 1776460Swnj (void) lseek(kmemf, (long)nl[NL_AVENRUN].n_value, 0); 1786460Swnj (void) read(kmemf, (char *)avenrun, sizeof (avenrun)); 1796460Swnj for (i = 0; i < 3; i++) 1806460Swnj mywd.wd_loadav[i] = avenrun[i] * 100; 1816460Swnj cc = (char *)we - (char *)&mywd; 1826460Swnj (void) time(&mywd.wd_sendtime); 1836460Swnj send(s, &sin, (char *)&mywd, cc); 1846460Swnj (void) alarm(60); 1856460Swnj } 1866460Swnj 1876460Swnj getkmem() 1886460Swnj { 1896460Swnj struct nlist *nlp; 1906460Swnj 1916460Swnj signal(SIGHUP, getkmem); 1926460Swnj if (kmemf >= 0) 1936460Swnj (void) close(kmemf); 1946460Swnj loop: 1956460Swnj for (nlp = &nl[sizeof (nl) / sizeof (nl[0])]; --nlp >= nl; ) { 1966460Swnj nlp->n_value = 0; 1976460Swnj nlp->n_type = 0; 1986460Swnj } 1996460Swnj nlist("/vmunix", nl); 2006460Swnj if (nl[0].n_value == 0) { 2016460Swnj fprintf(stderr, "/vmunix namelist botch\n"); 2026460Swnj sleep(300); 2036460Swnj goto loop; 2046460Swnj } 2056460Swnj kmemf = open("/dev/kmem", 0); 2066460Swnj if (kmemf < 0) { 2076460Swnj perror("/dev/kmem"); 2086460Swnj sleep(300); 2096460Swnj goto loop; 2106460Swnj } 2116460Swnj (void) lseek(kmemf, (long)nl[NL_BOOTIME].n_value, 0); 2126460Swnj (void) read(kmemf, (char *)&mywd.wd_bootime, sizeof (mywd.wd_bootime)); 2136460Swnj } 214