home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume15 / ru / ru.c < prev   
Encoding:
C/C++ Source or Header  |  1988-06-06  |  7.6 KB  |  374 lines

  1. /*
  2.  * ru - remote users(1)        (version 2)
  3.  *    list users on all "visible" hosts.
  4.  *    usage: ru [-acdms] [-D domain] [-h host ...]
  5.  *
  6.  * P. Kern (pkern@utcsri)
  7.  */
  8.  
  9. #include <stdio.h>
  10. #include <sys/types.h>
  11. #include <sys/stat.h>
  12. #include <sys/dir.h>
  13. #include <sys/file.h>
  14. #include <netdb.h>
  15.  
  16. #define MINSTR    8        /* minimum string length */
  17. #define HNSZ    32        /* hostname length */
  18. #define RWFSZ    HNSZ+5        /* spool-file name length */
  19. #define MRGN    12        /* 12 space "tab" */
  20. #define HOUR    3600        /* seconds in an hour */
  21. #define RWPERIOD    300    /* 5 minute rwho refresh period */
  22. #define MAXPORTS    160    /* max tty ports per host */
  23.  
  24. struct rw_utmp {
  25.     char tty[MINSTR];    /* user's tty */
  26.     char name[MINSTR];    /* user's login */
  27.     long time;        /* login time */
  28.     long idle;        /* idle time */
  29. } rut;
  30.  
  31. struct rw_hdr {
  32.     char pad[4];        /* ignore first 4 bytes */
  33.     int sent, rcvd;        /* time sent,  time rec'vd */
  34.     char host[HNSZ];    /* host's name */
  35.     int loadav[3];        /* load averages */
  36.     int boot;        /* boot date */
  37. } hdr;
  38.  
  39. int rutsize, hdrsize;
  40. #define RWHODIR "/usr/spool/rwho"
  41.  
  42. long now;        /* it won't be ... (long now :-) */
  43. int n, fd;
  44. struct stat st;
  45. char *hnbuf, *hp;    /* hostname buffer & extra pointer */
  46. char *rubuf, *ep;    /* utmp data buffer & end pointer */
  47. char *program, *domain;
  48. int aflag=1;    /* only show users with <1 HR idle time */
  49. int sflag=1;    /* show output by domains (not by hosts) */
  50. int mflag=1;    /* ignore multiple logins */
  51. int cflag=0;    /* (if mflag) don't show login counts */
  52. int dflag=1;    /* sort hostnames within domains */
  53. int Dflag=0;    /* show users in a given domain */
  54. int hflag=0;    /* show users on a given host */
  55. int errflag=0;
  56.  
  57. extern char *rindex(), *malloc();
  58.  
  59. main(argc, argv)
  60. int argc;
  61. char *argv[];
  62. {
  63.     DIR *dirp;
  64.     struct direct *dp;
  65.     int rwfcmp(), rutcmp(), drwcmp();    /* qsort() routines */
  66.     extern int optind;    /* see getopt(3C) */
  67.     extern char *optarg;    /* see getopt(3C) */
  68.  
  69.     program = argv[0];
  70.     now = time(0);
  71.     rutsize = sizeof(rut);
  72.     hdrsize = sizeof(hdr);
  73.  
  74.     while ((n = getopt(argc, argv, "acdhmsD:")) != EOF)
  75.         switch(n) {
  76.         case 'a': aflag=0; break;    /* same as rwho(1) */
  77.         case 'c': cflag=1; break;    /* show login count */
  78.         case 'd': dflag=0; break;    /* domain-wise sort */
  79.         case 'm': mflag=0; break;    /* drop multi-logins */
  80.         case 's': sflag=0; break;    /* domain-only lists */
  81.         case 'D': Dflag++; domain = optarg; break;
  82.         case 'h': hflag++; break;
  83.         default: errflag++;
  84.         }
  85.     if (errflag) {
  86.         fprintf(stderr,"Usage: %s [-acdms] [-D domain] [-h host ...]\n", program);
  87.         exit(1);
  88.     }
  89.  
  90.     if (!dflag) sflag=0;
  91.     if (!mflag) cflag=0;    /* not really needed (see burp()) */
  92.  
  93.     if (chdir(RWHODIR) < 0) {    /* cd RWHODIR */
  94.         perror(RWHODIR);
  95.         exit(1);
  96.     }
  97.  
  98.     if (hflag) {
  99.         sflag=0;
  100.         for ( ;optind < argc; optind++)
  101.             dohost(argv[optind]);
  102.         exit(0);
  103.     }
  104.  
  105.     /*
  106.      * read "." directory (assuming chdir() worked), 
  107.      * and get all files with the "whod." prefix.
  108.      * if Dflag, only get files ending with "domain".
  109.      */
  110.     if ((dirp = opendir(".")) == NULL
  111.         || stat(".", &st) < 0) { 
  112.         perror(RWHODIR);
  113.         exit(1);
  114.     }
  115.     dp = readdir(dirp);    /* get "." */
  116.     n = (st.st_size/(DIRSIZ(dp)+8))*RWFSZ;
  117.     hnbuf = malloc((unsigned)n);
  118.     n = 0; ep = hnbuf;
  119.     while (dp = readdir(dirp)) {
  120.         strncpy(ep, dp->d_name, dp->d_namlen);
  121.         *(ep+dp->d_namlen) = '\0';
  122.         if (strncmp(ep, "whod.", 5) == 0 &&
  123.            (!Dflag || strcmp(rindex(ep,'.')+1,domain) == 0)) {
  124.             ep += RWFSZ;
  125.             n++;
  126.         }
  127.     }
  128.     /* ep should now point to the end of the host name buffer */
  129.     closedir(dirp);
  130.  
  131.     if (dflag)    /* sort host names within domains */
  132.         qsort(hnbuf, n, RWFSZ, drwcmp);
  133.     else        /* sort full host name */
  134.         qsort(hnbuf, n, RWFSZ, rwfcmp);
  135.  
  136.     if (sflag) {    /* process by domains only */
  137.         dodomains();
  138.         exit(0);
  139.     }
  140.  
  141.     /*
  142.      * process each "whod." file in hnbuf list.
  143.      * - get <filesize> bytes of mem
  144.      * - gobble rutmp data from file
  145.      * - sort names alphabetically
  146.      * - print names (burp)
  147.      * - free up mem
  148.      */
  149.     hp = hnbuf;
  150.     while (hp < ep) {
  151.         if ((fd = open(hp, O_RDONLY)) < 0
  152.             || fstat(fd, &st) < 0) {
  153.             perror(hp);
  154.             exit(1);
  155.         }
  156.         if (n = st.st_size-hdrsize) {
  157.             if ((rubuf = malloc((unsigned)n)) == 0) {
  158.                 perror(program);
  159.                 exit(1);
  160.             }
  161.             n = read(fd, (char *)&hdr, hdrsize);
  162.             if (now-hdr.rcvd <= RWPERIOD &&
  163.                (n = ldrut(fd,rubuf,st.st_size-hdrsize))>0 ){
  164.                 qsort(rubuf, n/rutsize, rutsize, rutcmp);
  165.                 burp(hp, rubuf, n);
  166.             }
  167.         }
  168.         free(rubuf);
  169.         close(fd);
  170.         hp += RWFSZ;
  171.     }
  172. }
  173.  
  174. /*
  175.  * compare rwho spool-file names
  176.  */
  177. rwfcmp(p, q)
  178. register char *p, *q;
  179. {
  180.     return(strncmp(p, q, RWFSZ));
  181. }
  182.  
  183. /*
  184.  * compare utmp name entries
  185.  */
  186. rutcmp(p, q)
  187. register struct rw_utmp *p, *q;
  188. {
  189.     return(strncmp(p->name, q->name, MINSTR));
  190.  
  191. /*
  192.  * compare sub-domain names
  193.  */
  194. drwcmp(p, q)
  195. register char *p, *q;
  196. {
  197.     int x;
  198.     char *s, *t;
  199.  
  200.     s = rindex(p, '.');
  201.     t = rindex(q, '.');
  202.     if (s) s++; else s = p;
  203.     if (t) t++; else t = q;
  204.     if(x = strncmp(s, t, RWFSZ))
  205.         return(x);
  206.     return(strncmp(p, q, RWFSZ));
  207. }
  208.  
  209. /*
  210.  * print "host:       user1 user2 ... "
  211.  */
  212. burp(s, r, n)
  213. register char *s, *r;
  214. int n;
  215. {    
  216.     register int l;
  217.     register char *xp;
  218.  
  219.     if (!sflag)
  220.         s += 5;        /* skip "whod." prefix */
  221.     if ((l = strlen(s)) > MRGN) {
  222.         s[MRGN]= '\0';
  223.         l = MRGN;
  224.     }
  225.     if (sflag) l += 5;
  226.     printf("%.*s:%*s", MRGN, s, MRGN+1-l, " ");
  227.  
  228.     if (mflag) {
  229.         for(l=0, xp="", s=r+MINSTR; s < (r+n); s += rutsize)
  230.             if (strncmp(s, xp, MINSTR)) {
  231.                 printf( (l)?" %.*s/%d":" %.*s",
  232.                     MINSTR, s, l+1);
  233.                 xp = s; l = 0;
  234.             }
  235.             else
  236.                 l += cflag;
  237.         printf("\n");
  238.         return;
  239.     }
  240.  
  241.     for (s = r+MINSTR; s < (r+n); s += rutsize)
  242.         printf(" %.*s", MINSTR, s);
  243.     printf("\n");
  244. }
  245.  
  246. /*
  247.  * show users on a specific host
  248.  */
  249. dohost(host)
  250. char *host;
  251. {
  252.     struct hostent *h, *gethostbyname();
  253.  
  254.     /*
  255.      * try to get host's proper name
  256.      * and try to find the proper spool file
  257.      */
  258.     if((h = gethostbyname(host)) == NULL) {
  259.         perror(host);
  260.         return(1);
  261.     }
  262.     hp = malloc(strlen(h->h_name)+6);
  263.     sprintf(hp, "whod.%s", h->h_name);
  264.     if ((fd = open(hp, O_RDONLY)) < 0) {
  265.         char **s;
  266.         /*
  267.          * can't find file related to h_name
  268.          * try the aliases instead.
  269.          */
  270.         s = h->h_aliases;
  271.         while(*s) {
  272.             free(hp);
  273.             hp = malloc(strlen(*s)+6);
  274.             sprintf(hp, "whod.%s", *s);
  275.             if ((fd = open(hp, O_RDONLY)) > 0)
  276.                 break;
  277.             s++;
  278.         }
  279.         if (*s == NULL) {
  280.             fprintf(stderr,  "%s: no data\n",  host);
  281.             return(1);
  282.         }
  283.     }
  284.     if (fstat(fd, &st) < 0) {
  285.         perror(hp);
  286.         return(1);
  287.     }
  288.     n = st.st_size - hdrsize;
  289.     if ((rubuf = malloc((unsigned)n)) == 0) {
  290.         perror(program);
  291.         exit(1);
  292.     }
  293.     n = read(fd, (char *)&hdr, hdrsize);
  294.     n = ldrut(fd,rubuf,st.st_size-hdrsize);
  295.     qsort(rubuf, n/rutsize, rutsize, rutcmp);
  296.     if (now-hdr.rcvd > RWPERIOD)
  297.         strcat(hp, "*");
  298.     burp(hp, rubuf, n);
  299. }
  300.  
  301. /*
  302.  * show users by domain
  303.  */
  304. dodomains()
  305. {
  306.     int z;
  307.     register int i;
  308.     char *p0, *p1, *fnp, *rbp;
  309.  
  310.     fnp = hp = hnbuf;
  311.  
  312.     if ((rubuf = malloc(n * MAXPORTS * rutsize)) == NULL) {
  313.         perror(program);
  314.         exit(1);
  315.     }
  316.  
  317.     p0 = rindex(fnp, '.') + 1;
  318.     if ((int)p0 == 1) p0 = fnp;
  319.  
  320.     while (fnp < ep) {
  321.         rbp = rubuf;
  322.         for (p1=p0, n=i=0; fnp < ep && !strcmp(p1, p0); i++) {
  323.             if ((fd = open(fnp, O_RDONLY)) < 0
  324.                 || fstat(fd, &st) < 0) {
  325.                 perror(fnp);
  326.                 exit(1);
  327.             }
  328.             read(fd, (char *)&hdr, hdrsize);
  329.             if (now-hdr.rcvd <= RWPERIOD &&
  330.                (z = ldrut(fd,rbp,st.st_size-hdrsize))>0 ) {
  331.                 n += z;
  332.                 rbp += z;
  333.             }
  334.             close(fd);
  335.             fnp += RWFSZ;
  336.             p1 = p0;
  337.             p0 = rindex(fnp, '.') + 1;
  338.             if ((int)p0 == 1) p0 = fnp;
  339.         }
  340.         if (!n) continue;
  341.         *rbp = '\0';
  342.         qsort(rubuf, n/rutsize, rutsize, rutcmp);
  343.         burp(p1, rubuf, n);
  344.     }
  345.     free(rubuf);
  346. }
  347.  
  348. /*
  349.  * load rutmp data into buffer.
  350.  */
  351. ldrut(fd, p, n)
  352. int fd, n;
  353. char *p;
  354. {
  355.     register int m1, m2, nr;
  356.     register char *s;
  357.  
  358.     if (!aflag) return(read(fd, p, n));
  359.  
  360.     s = p;
  361.     m1 = m2 = 0;
  362.  
  363.     while (m2 < n && (nr = read(fd, s, rutsize)) > 0) {
  364.         m2 += nr;
  365.         if (((struct rw_utmp *)s)->idle > HOUR)
  366.             /* ignore entries with >1 hr idle time */
  367.             continue;
  368.         m1 += nr;
  369.         s += nr;
  370.     }
  371.     return(m1);
  372. }
  373.