|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)rwhod.c 4.19 (Berkeley) 83/07/01"; ! 3: #endif ! 4: ! 5: #include <sys/types.h> ! 6: #include <sys/socket.h> ! 7: #include <sys/stat.h> ! 8: #include <sys/ioctl.h> ! 9: #include <sys/file.h> ! 10: ! 11: #include <net/if.h> ! 12: #include <netinet/in.h> ! 13: ! 14: #include <nlist.h> ! 15: #include <stdio.h> ! 16: #include <signal.h> ! 17: #include <errno.h> ! 18: #include <utmp.h> ! 19: #include <ctype.h> ! 20: #include <netdb.h> ! 21: #include "rwhod.h" ! 22: ! 23: struct sockaddr_in sin = { AF_INET }; ! 24: ! 25: extern errno; ! 26: ! 27: char myname[32]; ! 28: ! 29: struct nlist nl[] = { ! 30: #define NL_AVENRUN 0 ! 31: { "_avenrun" }, ! 32: #define NL_BOOTTIME 1 ! 33: { "_boottime" }, ! 34: 0 ! 35: }; ! 36: ! 37: /* ! 38: * We communicate with each neighbor in ! 39: * a list constructed at the time we're ! 40: * started up. Neighbors are currently ! 41: * directly connected via a hardware interface. ! 42: */ ! 43: struct neighbor { ! 44: struct neighbor *n_next; ! 45: char *n_name; /* interface name */ ! 46: char *n_addr; /* who to send to */ ! 47: int n_addrlen; /* size of address */ ! 48: int n_flags; /* should forward?, interface flags */ ! 49: }; ! 50: ! 51: struct neighbor *neighbors; ! 52: struct whod mywd; ! 53: struct servent *sp; ! 54: int s, utmpf, kmemf = -1; ! 55: ! 56: #define WHDRSIZE (sizeof (mywd) - sizeof (mywd.wd_we)) ! 57: #define RWHODIR "/usr/spool/rwho" ! 58: ! 59: int onalrm(); ! 60: char *strcpy(), *sprintf(), *malloc(); ! 61: long lseek(); ! 62: int getkmem(); ! 63: struct in_addr inet_makeaddr(); ! 64: ! 65: main() ! 66: { ! 67: struct sockaddr_in from; ! 68: char path[64]; ! 69: int addr; ! 70: struct hostent *hp; ! 71: ! 72: sp = getservbyname("who", "udp"); ! 73: if (sp == 0) { ! 74: fprintf(stderr, "rwhod: udp/who: unknown service\n"); ! 75: exit(1); ! 76: } ! 77: #ifndef DEBUG ! 78: if (fork()) ! 79: exit(0); ! 80: { int s; ! 81: for (s = 0; s < 10; s++) ! 82: (void) close(s); ! 83: (void) open("/", 0); ! 84: (void) dup2(0, 1); ! 85: (void) dup2(0, 2); ! 86: s = open("/dev/tty", 2); ! 87: if (s >= 0) { ! 88: ioctl(s, TIOCNOTTY, 0); ! 89: (void) close(s); ! 90: } ! 91: } ! 92: #endif ! 93: (void) chdir("/dev"); ! 94: (void) signal(SIGHUP, getkmem); ! 95: if (getuid()) { ! 96: fprintf(stderr, "rwhod: not super user\n"); ! 97: exit(1); ! 98: } ! 99: /* ! 100: * Establish host name as returned by system. ! 101: */ ! 102: if (gethostname(myname, sizeof (myname) - 1) < 0) { ! 103: perror("gethostname"); ! 104: exit(1); ! 105: } ! 106: strncpy(mywd.wd_hostname, myname, sizeof (myname) - 1); ! 107: utmpf = open("/etc/utmp", O_RDONLY); ! 108: if (utmpf < 0) { ! 109: (void) close(creat("/etc/utmp", 0644)); ! 110: utmpf = open("/etc/utmp", O_RDONLY); ! 111: } ! 112: if (utmpf < 0) { ! 113: perror("rwhod: /etc/utmp"); ! 114: exit(1); ! 115: } ! 116: getkmem(); ! 117: if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { ! 118: perror("rwhod: socket"); ! 119: exit(1); ! 120: } ! 121: hp = gethostbyname(myname); ! 122: if (hp == NULL) { ! 123: fprintf(stderr, "%s: don't know my own name\n", myname); ! 124: exit(1); ! 125: } ! 126: sin.sin_family = hp->h_addrtype; ! 127: sin.sin_port = sp->s_port; ! 128: if (bind(s, &sin, sizeof (sin)) < 0) { ! 129: perror("rwhod: bind"); ! 130: exit(1); ! 131: } ! 132: if (!configure(s)) ! 133: exit(1); ! 134: signal(SIGALRM, onalrm); ! 135: onalrm(); ! 136: for (;;) { ! 137: struct whod wd; ! 138: int cc, whod, len = sizeof (from); ! 139: ! 140: cc = recvfrom(s, (char *)&wd, sizeof (struct whod), 0, ! 141: &from, &len); ! 142: if (cc <= 0) { ! 143: if (cc < 0 && errno != EINTR) ! 144: perror("rwhod: recv"); ! 145: continue; ! 146: } ! 147: if (from.sin_port != sp->s_port) { ! 148: fprintf(stderr, "rwhod: %d: bad from port\n", ! 149: ntohs(from.sin_port)); ! 150: continue; ! 151: } ! 152: #ifdef notdef ! 153: if (gethostbyname(wd.wd_hostname) == 0) { ! 154: fprintf(stderr, "rwhod: %s: unknown host\n", ! 155: wd.wd_hostname); ! 156: continue; ! 157: } ! 158: #endif ! 159: if (wd.wd_vers != WHODVERSION) ! 160: continue; ! 161: if (wd.wd_type != WHODTYPE_STATUS) ! 162: continue; ! 163: if (!verify(wd.wd_hostname)) { ! 164: fprintf(stderr, "rwhod: malformed host name from %x\n", ! 165: from.sin_addr); ! 166: continue; ! 167: } ! 168: (void) sprintf(path, "%s/whod.%s", RWHODIR, wd.wd_hostname); ! 169: whod = creat(path, 0666); ! 170: if (whod < 0) { ! 171: fprintf(stderr, "rwhod: "); ! 172: perror(path); ! 173: continue; ! 174: } ! 175: #if vax || pdp11 ! 176: { ! 177: int i, n = (cc - WHDRSIZE)/sizeof(struct whoent); ! 178: struct whoent *we; ! 179: ! 180: /* undo header byte swapping before writing to file */ ! 181: wd.wd_sendtime = ntohl(wd.wd_sendtime); ! 182: for (i = 0; i < 3; i++) ! 183: wd.wd_loadav[i] = ntohl(wd.wd_loadav[i]); ! 184: wd.wd_boottime = ntohl(wd.wd_boottime); ! 185: we = wd.wd_we; ! 186: for (i = 0; i < n; i++) { ! 187: we->we_idle = ntohl(we->we_idle); ! 188: we->we_utmp.out_time = ! 189: ntohl(we->we_utmp.out_time); ! 190: we++; ! 191: } ! 192: } ! 193: #endif ! 194: (void) time(&wd.wd_recvtime); ! 195: (void) write(whod, (char *)&wd, cc); ! 196: (void) close(whod); ! 197: } ! 198: } ! 199: ! 200: /* ! 201: * Check out host name for unprintables ! 202: * and other funnies before allowing a file ! 203: * to be created. Sorry, but blanks aren't allowed. ! 204: */ ! 205: verify(name) ! 206: register char *name; ! 207: { ! 208: register int size = 0; ! 209: ! 210: while (*name) { ! 211: if (!isascii(*name) || !isalnum(*name)) ! 212: return (0); ! 213: name++, size++; ! 214: } ! 215: return (size > 0); ! 216: } ! 217: ! 218: int utmptime; ! 219: int utmpent; ! 220: struct utmp utmp[100]; ! 221: int alarmcount; ! 222: ! 223: onalrm() ! 224: { ! 225: register int i; ! 226: struct stat stb; ! 227: register struct whoent *we = mywd.wd_we, *wlast; ! 228: int cc; ! 229: double avenrun[3]; ! 230: time_t now = time(0); ! 231: register struct neighbor *np; ! 232: ! 233: if (alarmcount % 10 == 0) ! 234: getkmem(); ! 235: alarmcount++; ! 236: (void) fstat(utmpf, &stb); ! 237: if (stb.st_mtime != utmptime) { ! 238: (void) lseek(utmpf, (long)0, L_SET); ! 239: cc = read(utmpf, (char *)utmp, sizeof (utmp)); ! 240: if (cc < 0) { ! 241: perror("/etc/utmp"); ! 242: goto done; ! 243: } ! 244: wlast = &mywd.wd_we[1024 / sizeof (struct whoent) - 1]; ! 245: utmpent = cc / sizeof (struct utmp); ! 246: for (i = 0; i < utmpent; i++) ! 247: if (utmp[i].ut_name[0]) { ! 248: bcopy(utmp[i].ut_line, we->we_utmp.out_line, ! 249: sizeof (utmp[i].ut_line)); ! 250: bcopy(utmp[i].ut_name, we->we_utmp.out_name, ! 251: sizeof (utmp[i].ut_name)); ! 252: we->we_utmp.out_time = htonl(utmp[i].ut_time); ! 253: if (we >= wlast) ! 254: break; ! 255: we++; ! 256: } ! 257: utmpent = we - mywd.wd_we; ! 258: } ! 259: we = mywd.wd_we; ! 260: for (i = 0; i < utmpent; i++) { ! 261: if (stat(we->we_utmp.out_line, &stb) >= 0) ! 262: we->we_idle = htonl(now - stb.st_atime); ! 263: we++; ! 264: } ! 265: (void) lseek(kmemf, (long)nl[NL_AVENRUN].n_value, L_SET); ! 266: (void) read(kmemf, (char *)avenrun, sizeof (avenrun)); ! 267: for (i = 0; i < 3; i++) ! 268: mywd.wd_loadav[i] = htonl((u_long)(avenrun[i] * 100)); ! 269: cc = (char *)we - (char *)&mywd; ! 270: mywd.wd_sendtime = htonl(time(0)); ! 271: mywd.wd_vers = WHODVERSION; ! 272: mywd.wd_type = WHODTYPE_STATUS; ! 273: for (np = neighbors; np != NULL; np = np->n_next) ! 274: (void) sendto(s, (char *)&mywd, cc, 0, ! 275: np->n_addr, np->n_addrlen); ! 276: done: ! 277: (void) alarm(60); ! 278: } ! 279: ! 280: getkmem() ! 281: { ! 282: struct nlist *nlp; ! 283: ! 284: if (kmemf >= 0) ! 285: (void) close(kmemf); ! 286: loop: ! 287: for (nlp = &nl[sizeof (nl) / sizeof (nl[0])]; --nlp >= nl; ) { ! 288: nlp->n_value = 0; ! 289: nlp->n_type = 0; ! 290: } ! 291: nlist("/vmunix", nl); ! 292: if (nl[0].n_value == 0) { ! 293: fprintf(stderr, "/vmunix namelist botch\n"); ! 294: sleep(300); ! 295: goto loop; ! 296: } ! 297: kmemf = open("/dev/kmem", O_RDONLY); ! 298: if (kmemf < 0) { ! 299: perror("/dev/kmem"); ! 300: sleep(300); ! 301: goto loop; ! 302: } ! 303: (void) lseek(kmemf, (long)nl[NL_BOOTTIME].n_value, L_SET); ! 304: (void) read(kmemf, (char *)&mywd.wd_boottime, ! 305: sizeof (mywd.wd_boottime)); ! 306: mywd.wd_boottime = htonl(mywd.wd_boottime); ! 307: } ! 308: ! 309: /* ! 310: * Figure out device configuration and select ! 311: * networks which deserve status information. ! 312: */ ! 313: configure(s) ! 314: int s; ! 315: { ! 316: char buf[BUFSIZ]; ! 317: struct ifconf ifc; ! 318: struct ifreq ifreq, *ifr; ! 319: struct sockaddr_in *sin; ! 320: register struct neighbor *np; ! 321: int n; ! 322: ! 323: ifc.ifc_len = sizeof (buf); ! 324: ifc.ifc_buf = buf; ! 325: if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) { ! 326: perror("rwhod: ioctl (get interface configuration)"); ! 327: return (0); ! 328: } ! 329: ifr = ifc.ifc_req; ! 330: for (n = ifc.ifc_len / sizeof (struct ifreq); n > 0; n--, ifr++) { ! 331: for (np = neighbors; np != NULL; np = np->n_next) ! 332: if (np->n_name && ! 333: strcmp(ifr->ifr_name, np->n_name) == 0) ! 334: break; ! 335: if (np != NULL) ! 336: continue; ! 337: ifreq = *ifr; ! 338: np = (struct neighbor *)malloc(sizeof (*np)); ! 339: if (np == NULL) ! 340: continue; ! 341: np->n_name = malloc(strlen(ifr->ifr_name) + 1); ! 342: if (np->n_name == NULL) { ! 343: free((char *)np); ! 344: continue; ! 345: } ! 346: strcpy(np->n_name, ifr->ifr_name); ! 347: np->n_addrlen = sizeof (ifr->ifr_addr); ! 348: np->n_addr = malloc(np->n_addrlen); ! 349: if (np->n_addr == NULL) { ! 350: free(np->n_name); ! 351: free((char *)np); ! 352: continue; ! 353: } ! 354: bcopy((char *)&ifr->ifr_addr, np->n_addr, np->n_addrlen); ! 355: if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) { ! 356: perror("rwhod: ioctl (get interface flags)"); ! 357: free((char *)np); ! 358: continue; ! 359: } ! 360: if ((ifreq.ifr_flags & (IFF_BROADCAST|IFF_POINTOPOINT)) == 0) { ! 361: free((char *)np); ! 362: continue; ! 363: } ! 364: np->n_flags = ifreq.ifr_flags; ! 365: if (np->n_flags & IFF_POINTOPOINT) { ! 366: if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) { ! 367: perror("rwhod: ioctl (get dstaddr)"); ! 368: free((char *)np); ! 369: continue; ! 370: } ! 371: /* we assume addresses are all the same size */ ! 372: bcopy((char *)&ifreq.ifr_dstaddr, ! 373: np->n_addr, np->n_addrlen); ! 374: } ! 375: if (np->n_flags & IFF_BROADCAST) { ! 376: /* we assume addresses are all the same size */ ! 377: sin = (struct sockaddr_in *)np->n_addr; ! 378: sin->sin_addr = ! 379: inet_makeaddr(inet_netof(sin->sin_addr), INADDR_ANY); ! 380: } ! 381: /* gag, wish we could get rid of Internet dependencies */ ! 382: sin = (struct sockaddr_in *)np->n_addr; ! 383: sin->sin_port = sp->s_port; ! 384: np->n_next = neighbors; ! 385: neighbors = np; ! 386: } ! 387: return (1); ! 388: } ! 389: ! 390: #ifdef DEBUG ! 391: sendto(s, buf, cc, flags, to, tolen) ! 392: int s; ! 393: char *buf; ! 394: int cc, flags; ! 395: char *to; ! 396: int tolen; ! 397: { ! 398: register struct whod *w = (struct whod *)buf; ! 399: register struct whoent *we; ! 400: struct sockaddr_in *sin = (struct sockaddr_in *)to; ! 401: char *interval(); ! 402: ! 403: printf("sendto %x.%d\n", ntohl(sin->sin_addr), ntohs(sin->sin_port)); ! 404: printf("hostname %s %s\n", w->wd_hostname, ! 405: interval(ntohl(w->wd_sendtime) - ntohl(w->wd_boottime), " up")); ! 406: printf("load %4.2f, %4.2f, %4.2f\n", ! 407: ntohl(w->wd_loadav[0]) / 100.0, ntohl(w->wd_loadav[1]) / 100.0, ! 408: ntohl(w->wd_loadav[2]) / 100.0); ! 409: cc -= WHDRSIZE; ! 410: for (we = w->wd_we, cc /= sizeof (struct whoent); cc > 0; cc--, we++) { ! 411: time_t t = ntohl(we->we_utmp.out_time); ! 412: printf("%-8.8s %s:%s %.12s", ! 413: we->we_utmp.out_name, ! 414: w->wd_hostname, we->we_utmp.out_line, ! 415: ctime(&t)+4); ! 416: we->we_idle = ntohl(we->we_idle) / 60; ! 417: if (we->we_idle) { ! 418: if (we->we_idle >= 100*60) ! 419: we->we_idle = 100*60 - 1; ! 420: if (we->we_idle >= 60) ! 421: printf(" %2d", we->we_idle / 60); ! 422: else ! 423: printf(" "); ! 424: printf(":%02d", we->we_idle % 60); ! 425: } ! 426: printf("\n"); ! 427: } ! 428: } ! 429: ! 430: char * ! 431: interval(time, updown) ! 432: int time; ! 433: char *updown; ! 434: { ! 435: static char resbuf[32]; ! 436: int days, hours, minutes; ! 437: ! 438: if (time < 0 || time > 3*30*24*60*60) { ! 439: (void) sprintf(resbuf, " %s ??:??", updown); ! 440: return (resbuf); ! 441: } ! 442: minutes = (time + 59) / 60; /* round to minutes */ ! 443: hours = minutes / 60; minutes %= 60; ! 444: days = hours / 24; hours %= 24; ! 445: if (days) ! 446: (void) sprintf(resbuf, "%s %2d+%02d:%02d", ! 447: updown, days, hours, minutes); ! 448: else ! 449: (void) sprintf(resbuf, "%s %2d:%02d", ! 450: updown, hours, minutes); ! 451: return (resbuf); ! 452: } ! 453: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.