[BACK]Return to ruptime.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ruptime

Annotation of src/usr.bin/ruptime/ruptime.c, Revision 1.14

1.14    ! mickey      1: /*     $OpenBSD: ruptime.c,v 1.13 2004/09/14 22:24:07 deraadt Exp $    */
1.2       deraadt     2:
1.1       deraadt     3: /*
                      4:  * Copyright (c) 1983 The Regents of the University of California.
                      5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
1.9       millert    15:  * 3. Neither the name of the University nor the names of its contributors
1.1       deraadt    16:  *    may be used to endorse or promote products derived from this software
                     17:  *    without specific prior written permission.
                     18:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     20:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     21:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     22:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     23:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     24:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     25:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     26:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     27:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     28:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     29:  * SUCH DAMAGE.
                     30:  */
                     31:
                     32: #ifndef lint
1.14    ! mickey     33: const char copyright[] =
1.1       deraadt    34: "@(#) Copyright (c) 1983 The Regents of the University of California.\n\
                     35:  All rights reserved.\n";
                     36: #endif /* not lint */
                     37:
                     38: #ifndef lint
1.14    ! mickey     39: /*static const char sccsid[] = "from: @(#)ruptime.c    5.8 (Berkeley) 7/21/90";*/
        !            40: static const char rcsid[] = "$OpenBSD: ruptime.c,v 1.13 2004/09/14 22:24:07 deraadt Exp $";
1.1       deraadt    41: #endif /* not lint */
                     42:
                     43: #include <sys/param.h>
                     44: #include <sys/file.h>
                     45: #include <dirent.h>
                     46: #include <protocols/rwhod.h>
                     47: #include <stdio.h>
1.4       deraadt    48: #include <unistd.h>
1.1       deraadt    49: #include <stdlib.h>
                     50: #include <string.h>
                     51: #include <errno.h>
1.14    ! mickey     52: #include <err.h>
1.1       deraadt    53:
                     54: size_t nhosts, hspace = 20;
                     55: struct hs {
                     56:        struct  whod *hs_wd;
                     57:        int     hs_nusers;
                     58: } *hs;
                     59: struct whod awhod;
                     60:
                     61: #define        ISDOWN(h)               (now - (h)->hs_wd->wd_recvtime > 11 * 60)
                     62: #define        WHDRSIZE        (sizeof (awhod) - sizeof (awhod.wd_we))
                     63:
                     64: time_t now;
                     65: int rflg = 1;
1.11      deraadt    66: int    hscmp(const void *, const void *);
                     67: int    ucmp(const void *, const void *);
                     68: int    lcmp(const void *, const void *);
                     69: int    tcmp(const void *, const void *);
1.12      deraadt    70: char   *interval(time_t, char *);
1.1       deraadt    71:
1.7       millert    72: void morehosts(void);
1.4       deraadt    73:
                     74: int
1.10      deraadt    75: main(int argc, char *argv[])
1.1       deraadt    76: {
1.14    ! mickey     77:        extern char *__progname;
1.6       mpech      78:        struct hs *hsp;
                     79:        struct whod *wd;
                     80:        struct whoent *we;
                     81:        DIR *dirp;
1.1       deraadt    82:        struct dirent *dp;
                     83:        int aflg, cc, ch, f, i, maxloadav;
                     84:        char buf[sizeof(struct whod)];
1.11      deraadt    85:        int (*cmp)(const void *, const void *) = hscmp;
1.1       deraadt    86:
                     87:        aflg = 0;
1.3       millert    88:        while ((ch = getopt(argc, argv, "alrut")) != -1)
1.1       deraadt    89:                switch((char)ch) {
                     90:                case 'a':
                     91:                        aflg = 1;
                     92:                        break;
                     93:                case 'l':
                     94:                        cmp = lcmp;
                     95:                        break;
                     96:                case 'r':
                     97:                        rflg = -1;
                     98:                        break;
                     99:                case 't':
                    100:                        cmp = tcmp;
                    101:                        break;
                    102:                case 'u':
                    103:                        cmp = ucmp;
                    104:                        break;
                    105:                default:
1.14    ! mickey    106:                        fprintf(stderr, "usage: %s [-alrut]\n", __progname);
1.1       deraadt   107:                        exit(1);
                    108:                }
                    109:
1.14    ! mickey    110:        if (chdir(_PATH_RWHODIR) || (dirp = opendir(".")) == NULL)
        !           111:                err(1, "%s", _PATH_RWHODIR);
1.1       deraadt   112:        morehosts();
                    113:        hsp = hs;
                    114:        maxloadav = -1;
1.4       deraadt   115:        while ((dp = readdir(dirp))) {
1.1       deraadt   116:                if (dp->d_ino == 0 || strncmp(dp->d_name, "whod.", 5))
                    117:                        continue;
                    118:                if ((f = open(dp->d_name, O_RDONLY, 0)) < 0) {
1.14    ! mickey    119:                        warn("%s", dp->d_name);
1.1       deraadt   120:                        continue;
                    121:                }
                    122:                cc = read(f, buf, sizeof(struct whod));
                    123:                (void)close(f);
                    124:                if (cc < WHDRSIZE)
                    125:                        continue;
                    126:                if (nhosts == hspace) {
                    127:                        morehosts();
                    128:                        hsp = hs + nhosts;
                    129:                }
                    130:                /* NOSTRICT */
                    131:                hsp->hs_wd = malloc((size_t)WHDRSIZE);
                    132:                wd = (struct whod *)buf;
                    133:                bcopy((char *)wd, (char *)hsp->hs_wd, (size_t)WHDRSIZE);
                    134:                hsp->hs_nusers = 0;
                    135:                for (i = 0; i < 2; i++)
                    136:                        if (wd->wd_loadav[i] > maxloadav)
                    137:                                maxloadav = wd->wd_loadav[i];
                    138:                we = (struct whoent *)(buf+cc);
                    139:                while (--we >= wd->wd_we)
                    140:                        if (aflg || we->we_idle < 3600)
                    141:                                hsp->hs_nusers++;
                    142:                nhosts++;
                    143:                hsp++;
                    144:        }
1.14    ! mickey    145:        if (!nhosts)
        !           146:                errx(1, "no hosts in %s.", _PATH_RWHODIR);
1.1       deraadt   147:        (void)time(&now);
                    148:        qsort((char *)hs, nhosts, sizeof (hs[0]), cmp);
                    149:        for (i = 0; i < nhosts; i++) {
                    150:                hsp = &hs[i];
                    151:                if (ISDOWN(hsp)) {
                    152:                        (void)printf("%-12.12s%s\n", hsp->hs_wd->wd_hostname,
                    153:                            interval(now - hsp->hs_wd->wd_recvtime, "down"));
                    154:                        continue;
                    155:                }
                    156:                (void)printf(
                    157:                    "%-12.12s%s,  %4d user%s  load %*.2f, %*.2f, %*.2f\n",
                    158:                    hsp->hs_wd->wd_hostname,
                    159:                    interval((time_t)hsp->hs_wd->wd_sendtime -
                    160:                        (time_t)hsp->hs_wd->wd_boottime, "  up"),
                    161:                    hsp->hs_nusers,
                    162:                    hsp->hs_nusers == 1 ? ", " : "s,",
                    163:                    maxloadav >= 1000 ? 5 : 4,
                    164:                        hsp->hs_wd->wd_loadav[0] / 100.0,
                    165:                    maxloadav >= 1000 ? 5 : 4,
                    166:                        hsp->hs_wd->wd_loadav[1] / 100.0,
                    167:                    maxloadav >= 1000 ? 5 : 4,
                    168:                        hsp->hs_wd->wd_loadav[2] / 100.0);
                    169:                free((void *)hsp->hs_wd);
                    170:        }
                    171:        exit(0);
                    172: }
                    173:
                    174: char *
1.10      deraadt   175: interval(time_t tval, char *updown)
1.1       deraadt   176: {
                    177:        static char resbuf[32];
                    178:        int days, hours, minutes;
                    179:
1.5       millert   180:        if (tval < 0 || tval > 999*24*60*60) {
1.8       deraadt   181:                (void)snprintf(resbuf, sizeof resbuf, "%s     ??:??", updown);
1.1       deraadt   182:                return(resbuf);
                    183:        }
                    184:        minutes = (tval + 59) / 60;             /* round to minutes */
                    185:        hours = minutes / 60; minutes %= 60;
                    186:        days = hours / 24; hours %= 24;
                    187:        if (days)
1.8       deraadt   188:                (void)snprintf(resbuf, sizeof resbuf, "%s %3d+%02d:%02d",
1.1       deraadt   189:                    updown, days, hours, minutes);
                    190:        else
1.8       deraadt   191:                (void)snprintf(resbuf, sizeof resbuf, "%s     %2d:%02d",
1.1       deraadt   192:                    updown, hours, minutes);
                    193:        return(resbuf);
                    194: }
                    195:
                    196: /* alphabetical comparison */
1.4       deraadt   197: int
1.11      deraadt   198: hscmp(const void *a1, const void *a2)
1.1       deraadt   199: {
1.11      deraadt   200:        const struct hs *h1 = a1, *h2 = a2;
1.1       deraadt   201:
                    202:        return(rflg * strcmp(h1->hs_wd->wd_hostname, h2->hs_wd->wd_hostname));
                    203: }
                    204:
                    205: /* load average comparison */
1.4       deraadt   206: int
1.11      deraadt   207: lcmp(const void *a1, const void *a2)
1.1       deraadt   208: {
1.11      deraadt   209:        const struct hs *h1 = a1, *h2 = a2;
1.1       deraadt   210:
                    211:        if (ISDOWN(h1))
                    212:                if (ISDOWN(h2))
                    213:                        return(tcmp(a1, a2));
                    214:                else
                    215:                        return(rflg);
                    216:        else if (ISDOWN(h2))
                    217:                return(-rflg);
                    218:        else
                    219:                return(rflg *
                    220:                        (h2->hs_wd->wd_loadav[0] - h1->hs_wd->wd_loadav[0]));
                    221: }
                    222:
                    223: /* number of users comparison */
1.4       deraadt   224: int
1.11      deraadt   225: ucmp(const void *a1, const void *a2)
1.1       deraadt   226: {
1.11      deraadt   227:        const struct hs *h1 = a1, *h2 = a2;
1.1       deraadt   228:
                    229:        if (ISDOWN(h1))
                    230:                if (ISDOWN(h2))
                    231:                        return(tcmp(a1, a2));
                    232:                else
                    233:                        return(rflg);
                    234:        else if (ISDOWN(h2))
                    235:                return(-rflg);
                    236:        else
                    237:                return(rflg * (h2->hs_nusers - h1->hs_nusers));
                    238: }
                    239:
                    240: /* uptime comparison */
1.4       deraadt   241: int
1.11      deraadt   242: tcmp(const void *a1, const void *a2)
1.1       deraadt   243: {
1.11      deraadt   244:        const struct hs *h1 = a1, *h2 = a2;
1.1       deraadt   245:
                    246:        return(rflg * (
                    247:                (ISDOWN(h2) ? h2->hs_wd->wd_recvtime - now
                    248:                          : h2->hs_wd->wd_sendtime - h2->hs_wd->wd_boottime)
                    249:                -
                    250:                (ISDOWN(h1) ? h1->hs_wd->wd_recvtime - now
                    251:                          : h1->hs_wd->wd_sendtime - h1->hs_wd->wd_boottime)
                    252:        ));
                    253: }
                    254:
1.4       deraadt   255: void
1.10      deraadt   256: morehosts(void)
1.1       deraadt   257: {
                    258:        hs = realloc((char *)hs, (hspace *= 2) * sizeof(*hs));
1.14    ! mickey    259:        if (hs == NULL)
        !           260:                err(1, "realloc");
1.1       deraadt   261: }