1 #ifndef lint 2 static char sccsid[] = "@(#)rwhod.c 4.3 82/04/20"; 3 #endif 4 5 #include <stdio.h> 6 #include <signal.h> 7 #include <sys/types.h> 8 #include <net/in.h> 9 #include <sys/socket.h> 10 #include <errno.h> 11 #include <utmp.h> 12 #include "rwhod.h" 13 #include <sys/stat.h> 14 #include <nlist.h> 15 #include <sys/ioctl.h> 16 17 struct sockaddr_in sin = { AF_INET, IPPORT_WHOSERVER }; 18 19 extern errno; 20 21 char *localnet = "localnet"; 22 char *myname = "myname"; 23 24 struct nlist nl[] = { 25 #define NL_AVENRUN 0 26 { "_avenrun" }, 27 #define NL_BOOTIME 1 28 { "_bootime" }, 29 0 30 }; 31 32 struct whod mywd; 33 int s, utmpf, kmemf = -1; 34 35 int onalrm(); 36 char *strcpy(), *sprintf(); 37 long lseek(); 38 int getkmem(); 39 40 main() 41 { 42 struct sockaddr_in from; 43 char path[64]; 44 int addr; 45 46 #ifndef DEBUG 47 if (fork()) 48 exit(0); 49 { int s; 50 for (s = 0; s < 10; s++) 51 (void) close(s); 52 (void) open("/", 0); 53 (void) dup2(0, 1); 54 (void) dup2(0, 2); 55 s = open("/dev/tty", 2); 56 if (s >= 0) { 57 ioctl(s, TIOCNOTTY, 0); 58 (void) close(s); 59 } 60 } 61 #endif 62 (void) chdir("/dev"); 63 (void) signal(SIGHUP, getkmem); 64 if (getuid()) { 65 fprintf(stderr, "not super user\n"); 66 exit(1); 67 } 68 addr = rhost(&localnet); 69 if (addr == -1) { 70 fprintf(stderr, "no localnet for whod\n"); 71 exit(1); 72 } 73 sin.sin_addr.s_addr = addr; 74 if (rhost(&myname) == -1) { 75 fprintf(stderr, "don't know my name\n"); 76 exit(1); 77 } 78 strncpy(mywd.wd_hostname, myname, sizeof (mywd.wd_hostname) - 1); 79 utmpf = open("/etc/utmp", 0); 80 if (utmpf < 0) { 81 (void) close(creat("/etc/utmp", 0644)); 82 utmpf = open("/etc/utmp", 0); 83 } 84 if (utmpf < 0) { 85 perror("/etc/utmp"); 86 exit(1); 87 } 88 getkmem(); 89 #ifdef vax 90 sin.sin_port = htons(sin.sin_port); 91 #endif 92 again: 93 if ((s = socket(SOCK_DGRAM, 0, &sin, 0)) < 0) { 94 perror("socket"); 95 sleep(5); 96 goto again; 97 } 98 sigset(SIGALRM, onalrm); 99 onalrm(); 100 for (;;) { 101 struct whod wd; 102 int cc, whod; 103 104 cc = receive(s, &from, (char *)&wd, sizeof (struct whod)); 105 if (cc <= 0) { 106 if (cc < 0 && errno != EINTR) 107 perror("receive"); 108 continue; 109 } 110 #ifdef vax 111 from.sin_port = ntohs(from.sin_port); 112 #endif 113 if (from.sin_port != IPPORT_WHOSERVER) { 114 printf("bad from port %d\n", from.sin_port); 115 continue; 116 } 117 /* 118 if (rhost(&wd.wd_hostname) == -1) { 119 printf("unknown host %s\n", wd.wd_hostname); 120 continue; 121 } 122 */ 123 (void) sprintf(path, "/etc/whod.%s", wd.wd_hostname); 124 whod = creat(path, 0666); 125 if (whod < 0) { 126 printf("can't create %s\n", path); 127 continue; 128 } 129 (void) time(&wd.wd_recvtime); 130 (void) write(whod, (char *)&wd, cc); 131 (void) close(whod); 132 } 133 } 134 135 int utmptime; 136 int utmpent; 137 struct utmp utmp[100]; 138 int alarmcount; 139 140 onalrm() 141 { 142 register int i; 143 struct stat stb; 144 register struct whoent *we = mywd.wd_we, *wlast; 145 int cc; 146 double avenrun[3]; 147 time_t now = time(0); 148 149 if (alarmcount % 10 == 0) 150 getkmem(); 151 alarmcount++; 152 (void) fstat(utmpf, &stb); 153 if (stb.st_mtime != utmptime) { 154 (void) lseek(utmpf, (long)0, 0); 155 cc = read(utmpf, (char *)utmp, sizeof (utmp)); 156 if (cc < 0) { 157 perror("/etc/utmp"); 158 return; 159 } 160 wlast = &mywd.wd_we[(1024 / sizeof (struct whoent)) - 1]; 161 utmpent = cc / sizeof (struct utmp); 162 for (i = 0; i < utmpent; i++) 163 if (utmp[i].ut_name[0]) { 164 we->we_utmp = utmp[i]; 165 if (we >= wlast) 166 break; 167 we++; 168 } 169 utmpent = we - mywd.wd_we; 170 } 171 we = mywd.wd_we; 172 for (i = 0; i < utmpent; i++) { 173 if (stat(we->we_utmp.ut_line, &stb) >= 0) 174 we->we_idle = now - stb.st_atime; 175 we++; 176 } 177 (void) lseek(kmemf, (long)nl[NL_AVENRUN].n_value, 0); 178 (void) read(kmemf, (char *)avenrun, sizeof (avenrun)); 179 for (i = 0; i < 3; i++) 180 mywd.wd_loadav[i] = avenrun[i] * 100; 181 cc = (char *)we - (char *)&mywd; 182 (void) time(&mywd.wd_sendtime); 183 send(s, &sin, (char *)&mywd, cc); 184 (void) alarm(60); 185 } 186 187 getkmem() 188 { 189 struct nlist *nlp; 190 191 signal(SIGHUP, getkmem); 192 if (kmemf >= 0) 193 (void) close(kmemf); 194 loop: 195 for (nlp = &nl[sizeof (nl) / sizeof (nl[0])]; --nlp >= nl; ) { 196 nlp->n_value = 0; 197 nlp->n_type = 0; 198 } 199 nlist("/vmunix", nl); 200 if (nl[0].n_value == 0) { 201 fprintf(stderr, "/vmunix namelist botch\n"); 202 sleep(300); 203 goto loop; 204 } 205 kmemf = open("/dev/kmem", 0); 206 if (kmemf < 0) { 207 perror("/dev/kmem"); 208 sleep(300); 209 goto loop; 210 } 211 (void) lseek(kmemf, (long)nl[NL_BOOTIME].n_value, 0); 212 (void) read(kmemf, (char *)&mywd.wd_bootime, sizeof (mywd.wd_bootime)); 213 } 214