update
[unix-history] / usr / src / usr.sbin / rwhod / rwhod.c
index ef6d940..4f2a205 100644 (file)
@@ -1,6 +1,18 @@
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)rwhod.c    4.27 (Berkeley) 84/10/23";
-#endif
+char copyright[] =
+"@(#) Copyright (c) 1983 Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif not lint
+
+#ifndef lint
+static char sccsid[] = "@(#)rwhod.c    5.9 (Berkeley) %G%";
+#endif not lint
 
 #include <sys/types.h>
 #include <sys/socket.h>
 
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -19,7 +31,7 @@ static char sccsid[] = "@(#)rwhod.c   4.27 (Berkeley) 84/10/23";
 #include <ctype.h>
 #include <netdb.h>
 #include <syslog.h>
 #include <ctype.h>
 #include <netdb.h>
 #include <syslog.h>
-#include "rwhod.h"
+#include <protocols/rwhod.h>
 
 /*
  * Alarm interval. Don't forget to change the down time check in ruptime
 
 /*
  * Alarm interval. Don't forget to change the down time check in ruptime
@@ -72,9 +84,11 @@ struct       in_addr inet_makeaddr();
 main()
 {
        struct sockaddr_in from;
 main()
 {
        struct sockaddr_in from;
+       struct stat st;
        char path[64];
        char path[64];
-       int addr, on = 1;
-       struct hostent *hp;
+       int on = 1;
+       char *cp;
+       extern char *index();
 
        if (getuid()) {
                fprintf(stderr, "rwhod: not super user\n");
 
        if (getuid()) {
                fprintf(stderr, "rwhod: not super user\n");
@@ -101,9 +115,12 @@ main()
          }
        }
 #endif
          }
        }
 #endif
-       (void) chdir("/dev");
+       if (chdir(RWHODIR) < 0) {
+               perror(RWHODIR);
+               exit(1);
+       }
        (void) signal(SIGHUP, getkmem);
        (void) signal(SIGHUP, getkmem);
-       openlog("rwhod", LOG_PID, 0);
+       openlog("rwhod", LOG_PID, LOG_DAEMON);
        /*
         * Establish host name as returned by system.
         */
        /*
         * Establish host name as returned by system.
         */
@@ -111,6 +128,8 @@ main()
                syslog(LOG_ERR, "gethostname: %m");
                exit(1);
        }
                syslog(LOG_ERR, "gethostname: %m");
                exit(1);
        }
+       if ((cp = index(myname, '.')) != NULL)
+               *cp = '\0';
        strncpy(mywd.wd_hostname, myname, sizeof (myname) - 1);
        utmpf = open("/etc/utmp", O_RDONLY);
        if (utmpf < 0) {
        strncpy(mywd.wd_hostname, myname, sizeof (myname) - 1);
        utmpf = open("/etc/utmp", O_RDONLY);
        if (utmpf < 0) {
@@ -130,12 +149,6 @@ main()
                syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
                exit(1);
        }
                syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
                exit(1);
        }
-       hp = gethostbyname(myname);
-       if (hp == NULL) {
-               syslog(LOG_ERR, "%s: don't know my own name", myname);
-               exit(1);
-       }
-       sin.sin_family = hp->h_addrtype;
        sin.sin_port = sp->s_port;
        if (bind(s, &sin, sizeof (sin)) < 0) {
                syslog(LOG_ERR, "bind: %m");
        sin.sin_port = sp->s_port;
        if (bind(s, &sin, sizeof (sin)) < 0) {
                syslog(LOG_ERR, "bind: %m");
@@ -177,8 +190,12 @@ main()
                                from.sin_addr);
                        continue;
                }
                                from.sin_addr);
                        continue;
                }
-               (void) sprintf(path, "%s/whod.%s", RWHODIR, wd.wd_hostname);
-               whod = creat(path, 0666);
+               (void) sprintf(path, "whod.%s", wd.wd_hostname);
+               /*
+                * Rather than truncating and growing the file each time,
+                * use ftruncate if size is less than previous size.
+                */
+               whod = open(path, O_WRONLY | O_CREAT, 0644);
                if (whod < 0) {
                        syslog(LOG_WARNING, "%s: %m", path);
                        continue;
                if (whod < 0) {
                        syslog(LOG_WARNING, "%s: %m", path);
                        continue;
@@ -204,6 +221,8 @@ main()
 #endif
                (void) time(&wd.wd_recvtime);
                (void) write(whod, (char *)&wd, cc);
 #endif
                (void) time(&wd.wd_recvtime);
                (void) write(whod, (char *)&wd, cc);
+               if (fstat(whod, &st) < 0 || st.st_size > cc)
+                       ftruncate(whod, cc);
                (void) close(whod);
        }
 }
                (void) close(whod);
        }
 }
@@ -228,7 +247,8 @@ verify(name)
 
 int    utmptime;
 int    utmpent;
 
 int    utmptime;
 int    utmpent;
-struct utmp utmp[100];
+int    utmpsize = 0;
+struct utmp *utmp;
 int    alarmcount;
 
 onalrm()
 int    alarmcount;
 
 onalrm()
@@ -245,10 +265,22 @@ onalrm()
                getkmem();
        alarmcount++;
        (void) fstat(utmpf, &stb);
                getkmem();
        alarmcount++;
        (void) fstat(utmpf, &stb);
-       if (stb.st_mtime != utmptime) {
+       if ((stb.st_mtime != utmptime) || (stb.st_size > utmpsize)) {
                utmptime = stb.st_mtime;
                utmptime = stb.st_mtime;
+               if (stb.st_size > utmpsize) {
+                       utmpsize = stb.st_size + 10 * sizeof(struct utmp);
+                       if (utmp)
+                               utmp = (struct utmp *)realloc(utmp, utmpsize);
+                       else
+                               utmp = (struct utmp *)malloc(utmpsize);
+                       if (! utmp) {
+                               fprintf(stderr, "rwhod: malloc failed\n");
+                               utmpsize = 0;
+                               goto done;
+                       }
+               }
                (void) lseek(utmpf, (long)0, L_SET);
                (void) lseek(utmpf, (long)0, L_SET);
-               cc = read(utmpf, (char *)utmp, sizeof (utmp));
+               cc = read(utmpf, (char *)utmp, stb.st_size);
                if (cc < 0) {
                        perror("/etc/utmp");
                        goto done;
                if (cc < 0) {
                        perror("/etc/utmp");
                        goto done;
@@ -268,6 +300,16 @@ onalrm()
                        }
                utmpent = we - mywd.wd_we;
        }
                        }
                utmpent = we - mywd.wd_we;
        }
+
+       /*
+        * The test on utmpent looks silly---after all, if no one is
+        * logged on, why worry about efficiency?---but is useful on
+        * (e.g.) compute servers.
+        */
+       if (utmpent && chdir("/dev")) {
+               syslog(LOG_ERR, "chdir(/dev): %m");
+               exit(1);
+       }
        we = mywd.wd_we;
        for (i = 0; i < utmpent; i++) {
                if (stat(we->we_utmp.out_line, &stb) >= 0)
        we = mywd.wd_we;
        for (i = 0; i < utmpent; i++) {
                if (stat(we->we_utmp.out_line, &stb) >= 0)
@@ -285,13 +327,16 @@ onalrm()
        for (np = neighbors; np != NULL; np = np->n_next)
                (void) sendto(s, (char *)&mywd, cc, 0,
                        np->n_addr, np->n_addrlen);
        for (np = neighbors; np != NULL; np = np->n_next)
                (void) sendto(s, (char *)&mywd, cc, 0,
                        np->n_addr, np->n_addrlen);
+       if (utmpent && chdir(RWHODIR)) {
+               syslog(LOG_ERR, "chdir(%s): %m", RWHODIR);
+               exit(1);
+       }
 done:
        (void) alarm(AL_INTERVAL);
 }
 
 getkmem()
 {
 done:
        (void) alarm(AL_INTERVAL);
 }
 
 getkmem()
 {
-       struct nlist *nlp;
        static ino_t vmunixino;
        static time_t vmunixctime;
        struct stat sb;
        static ino_t vmunixino;
        static time_t vmunixctime;
        struct stat sb;
@@ -375,7 +420,8 @@ configure(s)
                        free((char *)np);
                        continue;
                }
                        free((char *)np);
                        continue;
                }
-               if ((ifreq.ifr_flags & (IFF_BROADCAST|IFF_POINTOPOINT)) == 0) {
+               if ((ifreq.ifr_flags & IFF_UP) == 0 ||
+                   (ifreq.ifr_flags & (IFF_BROADCAST|IFF_POINTOPOINT)) == 0) {
                        free((char *)np);
                        continue;
                }
                        free((char *)np);
                        continue;
                }
@@ -391,12 +437,14 @@ configure(s)
                          np->n_addr, np->n_addrlen);
                }
                if (np->n_flags & IFF_BROADCAST) {
                          np->n_addr, np->n_addrlen);
                }
                if (np->n_flags & IFF_BROADCAST) {
+                       if (ioctl(s, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
+                               syslog(LOG_ERR, "ioctl (get broadaddr)");
+                               free((char *)np);
+                               continue;
+                       }
                        /* we assume addresses are all the same size */
                        /* we assume addresses are all the same size */
-                       sin = (struct sockaddr_in *)np->n_addr;
-                       sin->sin_addr = inet_makeaddr((np->n_flags & IFF_LOCAL)?
-                               inet_subnetof(sin->sin_addr) :
-                               inet_netof(sin->sin_addr),
-                               INADDR_ANY);
+                       bcopy((char *)&ifreq.ifr_broadaddr,
+                         np->n_addr, np->n_addrlen);
                }
                /* gag, wish we could get rid of Internet dependencies */
                sin = (struct sockaddr_in *)np->n_addr;
                }
                /* gag, wish we could get rid of Internet dependencies */
                sin = (struct sockaddr_in *)np->n_addr;
@@ -407,32 +455,6 @@ configure(s)
        return (1);
 }
 
        return (1);
 }
 
-/*
- * Return the possible subnetwork number from an internet address.
- * If the address is of the form of a subnet address (most significant
- * bit of the host part is set), believe the subnet exists.
- * Otherwise, return the network number.  Any subnet number is only valid
- * if this is a ``local'' net.
- */
-inet_subnetof(in)
-       struct in_addr in;
-{
-       register u_long i = ntohl(in.s_addr);
-
-       if (IN_CLASSA(i)) {
-               if (IN_SUBNETA(i))
-                       return ((i & IN_CLASSA_SUBNET) >> IN_CLASSA_SUBNSHIFT);
-               else
-                       return ((i & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT);
-       } else if (IN_CLASSB(i)) {
-               if (IN_SUBNETB(i))
-                       return ((i & IN_CLASSB_SUBNET) >> IN_CLASSB_SUBNSHIFT);
-               else
-                       return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
-       } else
-               return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
-}
-
 #ifdef DEBUG
 sendto(s, buf, cc, flags, to, tolen)
        int s;
 #ifdef DEBUG
 sendto(s, buf, cc, flags, to, tolen)
        int s;