Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1489053
  • 博文数量: 408
  • 博客积分: 10036
  • 博客等级: 上将
  • 技术积分: 4440
  • 用 户 组: 普通用户
  • 注册时间: 2006-04-06 13:57
文章分类

全部博文(408)

文章存档

2011年(1)

2010年(2)

2009年(1)

2008年(3)

2007年(7)

2006年(394)

我的朋友

分类: C/C++

2006-07-31 13:20:42

who.c
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*    Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T    */
     22 /*      All Rights Reserved      */
     23
     24
     25 /*
     26  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
     27  * Use is subject to license terms.
     28  */
     29
     30 #pragma ident    "@(#)who.c    1.33    06/04/03 SMI"
     31
     32 /*
     33  *    This program analyzes information found in /var/adm/utmpx
     34  *
     35  *    Additionally information is gathered from /etc/inittab
     36  *    if requested.
     37  *
     38  *
     39  *    Syntax:
     40  *
     41  *        who am i    Displays info on yourself
     42  *
     43  *        who -a        Displays information about All
     44  *                entries in /var/adm/utmpx
     45  *
     46  *        who -b        Displays info on last boot
     47  *
     48  *        who -d        Displays info on DEAD PROCESSES
     49  *
     50  *        who -H        Displays HEADERS for output
     51  *
     52  *        who -l         Displays info on LOGIN entries
     53  *
     54  *        who -m         Same as who am i
     55  *
     56  *        who -p         Displays info on PROCESSES spawned by init
     57  *
     58  *        who -q        Displays short information on
     59  *                current users who LOGGED ON
     60  *
     61  *        who -r        Displays info of current run-level
     62  *
     63  *        who -s        Displays requested info in SHORT form
     64  *
     65  *        who -t        Displays info on TIME changes
     66  *
     67  *        who -T        Displays writeability of each user
     68  *                (+ writeable, - non-writeable, ? hung)
     69  *
     70  *        who -u        Displays LONG info on users
     71  *                who have LOGGED ON
     72  */
     73
     74 #define        DATE_FMT    "%b %e %H:%M"
     75
     76 /*
     77  *  %b    Abbreviated month name
     78  *  %e    Day of month
     79  *  %H    hour (24-hour clock)
     80  *  %M  minute
     81  */
     82 #include   
     83 #include   
     84 #include   
     85 #include   
     86 #include   
     87 #include   
     88 #include   
     89 #include   
     90 #include   
     91 #include   
     92 #include   
     93 #include   
     94 #include   
     95
     96 static void process(void);
     97 static void ck_file(char *);
     98 static void dump(void);
     99
    100 static struct    utmpx *utmpp;    /* pointer for getutxent()    */
    101
    102 /*
    103  * utmpx defines wider fields for user and line.  For compatibility of output,
    104  * we are limiting these to the old maximums in utmp. Define UTMPX_NAMELEN
    105  * to use the full lengths.
    106  */
    107 #ifndef UTMPX_NAMELEN
    108 /* XXX - utmp - fix name length */
    109 #define    NMAX    (_POSIX_LOGIN_NAME_MAX - 1)
    110 #define    LMAX    12
    111 #else /* UTMPX_NAMELEN */
    112 #define    NMAX    (sizeof (utmpp->ut_user))
    113 #define    LMAX    (sizeof (utmpp->ut_line))
    114 #endif
    115
    116 static char    comment[BUFSIZ]; /* holds inittab comment    */
    117 static char    errmsg[BUFSIZ];    /* used in snprintf for errors    */
    118 static int    fildes;        /* file descriptor for inittab    */
    119 static int    Hopt = 0;    /* 1 = who -H            */
    120 static char    *inittab;    /* ptr to inittab contents    */
    121 static char    *iinit;        /* index into inittab        */
    122 static int    justme = 0;    /* 1 = who am i            */
    123 static struct    tm *lptr;    /* holds user login time    */
    124 static char    *myname;    /* pointer to invoker's name     */
    125 static char    *mytty;        /* holds device user is on    */
    126 static char    nameval[sizeof (utmpp->ut_user) + 1]; /*  invoker's name */
    127 static int    number = 8;    /* number of users per -q line    */
    128 static int    optcnt = 0;    /* keeps count of options    */
    129 static char    outbuf[BUFSIZ];    /* buffer for output        */
    130 static char    *program;    /* holds name of this program    */
    131 #ifdef    XPG4
    132 static int    aopt = 0;    /* 1 = who -a            */
    133 static int    dopt = 0;    /* 1 = who -d            */
    134 #endif    /* XPG4 */
    135 static int    qopt = 0;    /* 1 = who -q            */
    136 static int    sopt = 0;    /* 1 = who -s            */
    137 static struct    stat stbuf;    /* area for stat buffer        */
    138 static struct    stat *stbufp;    /* ptr to structure        */
    139 static int    terse = 1;    /* 1 = print terse msgs        */
    140 static int    Topt = 0;    /* 1 = who -T            */
    141 static time_t    timnow;        /* holds current time        */
    142 static int    totlusrs = 0;    /* cntr for users on system    */
    143 static int    uopt = 0;    /* 1 = who -u            */
    144 static char    user[sizeof (utmpp->ut_user) + 1]; /* holds user name */
    145 static int    validtype[UTMAXTYPE+1];    /* holds valid types    */
    146 static int    wrap;        /* flag to indicate wrap    */
    147 static char    time_buf[128];    /* holds date and time string    */
    148 static char    *end;        /* used in strtol for end pointer */
    149
    150 int
    151 main(int argc, char **argv)
    152 {
    153     int    goerr = 0;    /* non-zero indicates cmd error    */
    154     int    i;
    155     int    optsw;        /* switch for while of getopt()    */
    156
    157     (void) setlocale(LC_ALL, "");
    158
    159 #if    !defined(TEXT_DOMAIN)    /* Should be defined by cc -D */
    160 #define    TEXT_DOMAIN "SYS_TEST"    /* Use this only if it weren't */
    161 #endif
    162     (void) textdomain(TEXT_DOMAIN);
    163
    164     validtype[USER_PROCESS] = 1;
    165     validtype[EMPTY] = 0;
    166     stbufp = &stbuf;
    167
    168     /*
    169      *    Strip off path name of this command
    170      */
    171     for (i = strlen(argv[0]); i >= 0 && argv[0][i] != '/'; --i);
    172     if (i >= 0)
    173         argv[0] += i+1;
    174     program = argv[0];
    175
    176     /*
    177      *    Buffer stdout for speed
    178      */
    179     setbuf(stdout, outbuf);
    180
    181     /*
    182      *    Retrieve options specified on command line
    183      *    XCU4 - add -m option
    184      */
    185     while ((optsw = getopt(argc, argv, "abdHlmn:pqrstTu")) != EOF) {
    186         optcnt++;
    187         switch (optsw) {
    188
    189         case 'a':
    190             optcnt += 7;
    191             validtype[BOOT_TIME] = 1;
    192             validtype[DEAD_PROCESS] = 1;
    193             validtype[LOGIN_PROCESS] = 1;
    194             validtype[INIT_PROCESS] = 1;
    195             validtype[RUN_LVL] = 1;
    196             validtype[OLD_TIME] = 1;
    197             validtype[NEW_TIME] = 1;
    198             validtype[USER_PROCESS] = 1;
    199 #ifdef    XPG4
    200             aopt = 1;
    201 #endif    /* XPG4 */
    202             uopt = 1;
    203             Topt = 1;
    204             if (!sopt) terse = 0;
    205             break;
    206
    207         case 'b':
    208             validtype[BOOT_TIME] = 1;
    209             if (!uopt) validtype[USER_PROCESS] = 0;
    210             break;
    211
    212         case 'd':
    213             validtype[DEAD_PROCESS] = 1;
    214             if (!uopt) validtype[USER_PROCESS] = 0;
    215 #ifdef    XPG4
    216             dopt = 1;
    217 #endif    /* XPG4 */
    218             break;
    219
    220         case 'H':
    221             optcnt--; /* Don't count Header */
    222             Hopt = 1;
    223             break;
    224
    225         case 'l':
    226             validtype[LOGIN_PROCESS] = 1;
    227             if (!uopt) validtype[USER_PROCESS] = 0;
    228             terse = 0;
    229             break;
    230         case 'm':        /* New XCU4 option */
    231             justme = 1;
    232             break;
    233
    234         case 'n':
    235             errno = 0;
    236             number = strtol(optarg, &end, 10);
    237             if (errno != 0 || *end != '\0') {
    238                 (void) fprintf(stderr, gettext(
    239                     "%s: Invalid numeric argument\n"),
    240                     program);
    241                 exit(1);
    242             }
    243             if (number < 1) {
    244                 (void) fprintf(stderr, gettext(
    245                     "%s: Number of users per line must "
    246                     "be at least 1\n"), program);
    247                 exit(1);
    248             }
    249             break;
    250
    251         case 'p':
    252             validtype[INIT_PROCESS] = 1;
    253             if (!uopt) validtype[USER_PROCESS] = 0;
    254             break;
    255
    256         case 'q':
    257             qopt = 1;
    258             break;
    259
    260         case 'r':
    261             validtype[RUN_LVL] = 1;
    262             terse = 0;
    263             if (!uopt) validtype[USER_PROCESS] = 0;
    264             break;
    265
    266         case 's':
    267             sopt = 1;
    268             terse = 1;
    269             break;
    270
    271         case 't':
    272             validtype[OLD_TIME] = 1;
    273             validtype[NEW_TIME] = 1;
    274             if (!uopt) validtype[USER_PROCESS] = 0;
    275             break;
    276
    277         case 'T':
    278             Topt = 1;
    279 #ifdef    XPG4
    280             terse = 1;    /* XPG4 requires -T */
    281 #else    /* XPG4 */
    282             terse = 0;
    283 #endif    /* XPG4 */
    284             break;
    285
    286         case 'u':
    287             uopt = 1;
    288             validtype[USER_PROCESS] = 1;
    289             if (!sopt) terse = 0;
    290             break;
    291
    292         case '?':
    293             goerr++;
    294             break;
    295         default:
    296             break;
    297         }
    298     }
    299 #ifdef    XPG4
    300     /*
    301      * XCU4 changes - check for illegal sopt, Topt & aopt combination
    302      */
    303     if (sopt == 1) {
    304         terse = 1;
    305         if (Topt == 1 || aopt == 1)
    306         goerr++;
    307     }
    308 #endif    /* XPG4 */
    309
    310     if (goerr > 0) {
    311 #ifdef    XPG4
    312         /*
    313          * XCU4 - slightly different usage with -s -a & -T
    314          */
    315         (void) fprintf(stderr, gettext("\nUsage:\t%s"), program);
    316         (void) fprintf(stderr,
    317             gettext(" -s [-bdHlmpqrtu] [utmpx_like_file]\n"));
    318
    319         (void) fprintf(stderr, gettext(
    320             "\t%s [-abdHlmpqrtTu] [utmpx_like_file]\n"), program);
    321 #else    /* XPG4 */
    322         (void) fprintf(stderr, gettext(
    323             "\nUsage:\t%s [-abdHlmpqrstTu] [utmpx_like_file]\n"),
    324             program);
    325 #endif    /* XPG4 */
    326         (void) fprintf(stderr,
    327             gettext("\t%s -q [-n x] [utmpx_like_file]\n"), program);
    328         (void) fprintf(stderr, gettext("\t%s [am i]\n"), program);
    329         /*
    330          * XCU4 changes - be explicit with "am i" options
    331          */
    332         (void) fprintf(stderr, gettext("\t%s [am I]\n"), program);
    333         (void) fprintf(stderr, gettext(
    334             "a\tall (bdlprtu options)\n"));
    335         (void) fprintf(stderr, gettext("b\tboot time\n"));
    336         (void) fprintf(stderr, gettext("d\tdead processes\n"));
    337         (void) fprintf(stderr, gettext("H\tprint header\n"));
    338         (void) fprintf(stderr, gettext("l\tlogin processes\n"));
    339         (void) fprintf(stderr, gettext(
    340             "n #\tspecify number of users per line for -q\n"));
    341         (void) fprintf(stderr,
    342             gettext("p\tprocesses other than getty or users\n"));
    343         (void) fprintf(stderr, gettext("q\tquick %s\n"), program);
    344         (void) fprintf(stderr, gettext("r\trun level\n"));
    345         (void) fprintf(stderr, gettext(
    346         "s\tshort form of %s (no time since last output or pid)\n"),
    347             program);
    348         (void) fprintf(stderr, gettext("t\ttime changes\n"));
    349         (void) fprintf(stderr, gettext(
    350             "T\tstatus of tty (+ writable, - not writable, "
    351             "? hung)\n"));
    352         (void) fprintf(stderr, gettext("u\tuseful information\n"));
    353         (void) fprintf(stderr,
    354             gettext("m\tinformation only about current terminal\n"));
    355         (void) fprintf(stderr, gettext(
    356             "am i\tinformation about current terminal "
    357             "(same as -m)\n"));
    358         (void) fprintf(stderr, gettext(
    359             "am I\tinformation about current terminal "
    360             "(same as -m)\n"));
    361         exit(1);
    362     }
    363
    364     /*
    365      * XCU4: If -q option ignore all other options
    366      */
    367     if (qopt == 1) {
    368         Hopt = 0;
    369         sopt = 0;
    370         Topt = 0;
    371         uopt = 0;
    372         justme = 0;
    373         validtype[ACCOUNTING] = 0;
    374         validtype[BOOT_TIME] = 0;
    375         validtype[DEAD_PROCESS] = 0;
    376         validtype[LOGIN_PROCESS] = 0;
    377         validtype[INIT_PROCESS] = 0;
    378         validtype[RUN_LVL] = 0;
    379         validtype[OLD_TIME] = 0;
    380         validtype[NEW_TIME] = 0;
    381         validtype[USER_PROCESS] = 1;
    382     }
    383
    384     if (argc == optind + 1) {
    385         optcnt++;
    386         ck_file(argv[optind]);
    387         (void) utmpxname(argv[optind]);
    388     }
    389
    390     /*
    391      *    Test for 'who am i' or 'who am I'
    392      *    XCU4 - check if justme was already set by -m option
    393      */
    394     if (justme == 1 || (argc == 3 && strcmp(argv[1], "am") == 0 &&
    395         ((argv[2][0] == 'i' || argv[2][0] == 'I') &&
    396         argv[2][1] == '\0'))) {
    397         justme = 1;
    398         myname = nameval;
    399         (void) cuserid(myname);
    400         if ((mytty = ttyname(fileno(stdin))) == NULL &&
    401             (mytty = ttyname(fileno(stdout))) == NULL &&
    402             (mytty = ttyname(fileno(stderr))) == NULL) {
    403             (void) fprintf(stderr, gettext(
    404             "Must be attached to terminal for 'am I' option\n"));
    405             (void) fflush(stderr);
    406             exit(1);
    407         } else
    408             mytty += 5; /* bump past "/dev/" */
    409     }
    410
    411     if (!terse) {
    412         if (Hopt)
    413             (void) printf(gettext(
    414     "NAME       LINE         TIME          IDLE    PID  COMMENTS\n"));
    415
    416         timnow = time(0);
    417
    418         if ((fildes = open("/etc/inittab",
    419             O_NONBLOCK|O_RDONLY)) == -1) {
    420             (void) snprintf(errmsg, sizeof (errmsg),
    421                 gettext("%s: Cannot open /etc/inittab"), program);
    422             perror(errmsg);
    423             exit(errno);
    424         }
    425
    426         if (fstat(fildes, stbufp) == -1) {
    427             (void) snprintf(errmsg, sizeof (errmsg),
    428                 gettext("%s: Cannot stat /etc/inittab"), program);
    429             perror(errmsg);
    430             exit(errno);
    431         }
    432
    433         if ((inittab = malloc(stbufp->st_size + 1)) == NULL) {
    434             (void) snprintf(errmsg, sizeof (errmsg),
    435                 gettext("%s: Cannot allocate %ld bytes"),
    436                 program, stbufp->st_size);
    437             perror(errmsg);
    438             exit(errno);
    439         }
    440
    441         if (read(fildes, inittab, stbufp->st_size)
    442             != stbufp->st_size) {
    443             (void) snprintf(errmsg, sizeof (errmsg),
    444                 gettext("%s: Error reading /etc/inittab"),
    445                 program);
    446             perror(errmsg);
    447             exit(errno);
    448         }
    449
    450         inittab[stbufp->st_size] = '\0';
    451         iinit = inittab;
    452     } else {
    453         if (Hopt) {
    454 #ifdef    XPG4
    455             if (dopt) {
    456                 (void) printf(gettext(
    457             "NAME       LINE         TIME        COMMENTS\n"));
    458             } else {
    459                 (void) printf(
    460                     gettext("NAME       LINE         TIME\n"));
    461             }
    462 #else    /* XPG4 */
    463             (void) printf(
    464                 gettext("NAME       LINE         TIME\n"));
    465 #endif    /* XPG4 */
    466         }
    467     }
    468     process();
    469
    470     /*
    471      *    'who -q' requires EOL upon exit,
    472      *    followed by total line
    473      */
    474     if (qopt)
    475         (void) printf(gettext("\n# users=%d\n"), totlusrs);
    476     return (0);
    477 }
    478
    479 static void
    480 dump()
    481 {
    482     char    device[sizeof (utmpp->ut_line) + 1];
    483     time_t hr;
    484     time_t    idle;
    485     time_t min;
    486     char    path[sizeof (utmpp->ut_line) + 6];
    487     int    pexit;
    488     int    pterm;
    489     int    rc;
    490     char    w;    /* writeability indicator */
    491
    492     /*
    493      * Get and check user name
    494      */
    495     if (utmpp->ut_user[0] == '\0')
    496         (void) strcpy(user, "   .");
    497     else {
    498         (void) strncpy(user, utmpp->ut_user, sizeof (user));
    499         user[sizeof (user) - 1] = '\0';
    500     }
    501     totlusrs++;
    502
    503     /*
    504      * Do print in 'who -q' format
    505      */
    506     if (qopt) {
    507         /*
    508          * XCU4 - Use non user macro for correct user count
    509          */
    510         if (((totlusrs - 1) % number) == 0 && totlusrs > 1)
    511             (void) printf("\n");
    512         (void) printf("%-*s ", NMAX, user);
    513         return;
    514     }
    515
    516
    517     pexit = (int)' ';
    518     pterm = (int)' ';
    519
    520     /*
    521      *    Get exit info if applicable
    522      */
    523     if (utmpp->ut_type == RUN_LVL || utmpp->ut_type == DEAD_PROCESS) {
    524         pterm = utmpp->ut_exit.e_termination;
    525         pexit = utmpp->ut_exit.e_exit;
    526     }
    527
    528     /*
    529      *    Massage ut_xtime field
    530      */
    531     lptr = localtime(&utmpp->ut_xtime);
    532     (void) strftime(time_buf, sizeof (time_buf),
    533         dcgettext(NULL, DATE_FMT, LC_TIME), lptr);
    534
    535     /*
    536      *    Get and massage device
    537      */
    538     if (utmpp->ut_line[0] == '\0')
    539         (void) strcpy(device, "     .");
    540     else {
    541         (void) strncpy(device, utmpp->ut_line,
    542             sizeof (utmpp->ut_line));
    543         device[sizeof (utmpp->ut_line)] = '\0';
    544     }
    545
    546     /*
    547      *    Get writeability if requested
    548      *    XCU4 - only print + or - for user processes
    549      */
    550     if (Topt && (utmpp->ut_type == USER_PROCESS)) {
    551         w = '-';
    552         (void) strcpy(path, "/dev/");
    553         (void) strncpy(path + 5, utmpp->ut_line,
    554             sizeof (utmpp->ut_line));
    555         path[5 + sizeof (utmpp->ut_line)] = '\0';
    556
    557         if ((rc = stat(path, stbufp)) == -1) w = '?';
    558         else if ((stbufp->st_mode & S_IWOTH) ||
    559             (stbufp->st_mode & S_IWGRP))  /* Check group & other */
    560             w = '+';
    561
    562     } else
    563         w = ' ';
    564
    565     /*
    566      *    Print the TERSE portion of the output
    567      */
    568     (void) printf("%-*s %c %-12s %s", NMAX, user, w, device, time_buf);
    569
    570     if (!terse) {
    571         /*
    572          *    Stat device for idle time
    573          *    (Don't complain if you can't)
    574          */
    575         rc = -1;
    576         if (utmpp->ut_type == USER_PROCESS) {
    577             (void) strcpy(path, "/dev/");
    578             (void) strncpy(path + 5, utmpp->ut_line,
    579                 sizeof (utmpp->ut_line));
    580             path[5 + sizeof (utmpp->ut_line)] = '\0';
    581             rc = stat(path, stbufp);
    582         }
    583         if (rc != -1) {
    584             idle = timnow - stbufp->st_mtime;
    585             hr = idle/3600;
    586             min = (unsigned)(idle/60)%60;
    587             if (hr == 0 && min == 0)
    588                 (void) printf(gettext("   .  "));
    589             else {
    590                 if (hr < 24)
    591                     (void) printf(" %2d:%2.2d", (int)hr,
    592                         (int)min);
    593                 else
    594                     (void) printf(gettext("  old "));
    595             }
    596         }
    597
    598         /*
    599          *    Add PID for verbose output
    600          */
    601         if (utmpp->ut_type != BOOT_TIME &&
    602             utmpp->ut_type != RUN_LVL &&
    603             utmpp->ut_type != ACCOUNTING)
    604             (void) printf("  %5ld", utmpp->ut_pid);
    605
    606         /*
    607          *    Handle /etc/inittab comment
    608          */
    609         if (utmpp->ut_type == DEAD_PROCESS) {
    610             (void) printf(gettext("  id=%4.4s "),
    611                 utmpp->ut_id);
    612             (void) printf(gettext("term=%-3d "), pterm);
    613             (void) printf(gettext("exit=%d  "), pexit);
    614         } else if (utmpp->ut_type != INIT_PROCESS) {
    615             /*
    616              *    Search for each entry in inittab
    617              *    string. Keep our place from
    618              *    search to search to try and
    619              *    minimize the work. Wrap once if needed
    620              *    for each entry.
    621              */
    622             wrap = 0;
    623             /*
    624              *    Look for a line beginning with
    625              *    utmpp->ut_id
    626              */
    627             while ((rc = strncmp(utmpp->ut_id, iinit,
    628                 strcspn(iinit, ":"))) != 0) {
    629                 for (; *iinit != '\n'; iinit++);
    630                 iinit++;
    631
    632                 /*
    633                  *    Wrap once if necessary to
    634                  *    find entry in inittab
    635                  */
    636                 if (*iinit == '\0') {
    637                     if (!wrap) {
    638                         iinit = inittab;
    639                         wrap = 1;
    640                     }
    641                 }
    642             }
    643
    644             if (*iinit != '\0') {
    645                 /*
    646                  *    We found our entry
    647                  */
    648                 for (iinit++; *iinit != '#' &&
    649                      *iinit != '\n'; iinit++);
    650                 if (*iinit == '#') {
    651                     for (iinit++; *iinit == ' ' ||
    652                          *iinit == '\t'; iinit++);
    653                     for (rc = 0; *iinit != '\n'; iinit++)
    654                         comment[rc++] = *iinit;
    655                     comment[rc] = '\0';
    656                 } else
    657                     (void) strcpy(comment, " ");
    658
    659                 (void) printf("  %s", comment);
    660             } else
    661                 iinit = inittab;    /* Reset pointer */
    662         }
    663         if (utmpp->ut_type == INIT_PROCESS)
    664             (void) printf(gettext("  id=%4.4s"), utmpp->ut_id);
    665     }
    666 #ifdef    XPG4
    667     else
    668         if (dopt && utmpp->ut_type == DEAD_PROCESS) {
    669             (void) printf(gettext("\tterm=%-3d "), pterm);
    670             (void) printf(gettext("exit=%d  "), pexit);
    671         }
    672 #endif    /* XPG4 */
    673
    674
    675     /*
    676      *    Handle RUN_LVL process - If no alt. file - Only one!
    677      */
    678     if (utmpp->ut_type == RUN_LVL) {
    679         (void) printf("     %c  %5ld  %c", pterm, utmpp->ut_pid,
    680             pexit);
    681         if (optcnt == 1 && !validtype[USER_PROCESS]) {
    682             (void) printf("\n");
    683             exit(0);
    684         }
    685     }
    686
    687     /*
    688      *    Handle BOOT_TIME process -  If no alt. file - Only one!
    689      */
    690     if (utmpp->ut_type == BOOT_TIME) {
    691         if (optcnt == 1 && !validtype[USER_PROCESS]) {
    692             (void) printf("\n");
    693             exit(0);
    694         }
    695     }
    696
    697     /*
    698      *    Get remote host from utmpx structure
    699      */
    700     if (utmpp && utmpp->ut_host[0])
    701         (void) printf("\t(%.*s)", sizeof (utmpp->ut_host),
    702             utmpp->ut_host);
    703
    704     /*
    705      *    Now, put on the trailing EOL
    706      */
    707     (void) printf("\n");
    708 }
    709
    710 static void
    711 process()
    712 {
    713     struct passwd *pwp;
    714     int i = 0;
    715     char *ttname;
    716
    717     /*
    718      *    Loop over each entry in /var/adm/utmpx
    719      */
    720
    721     setutxent();
    722     while ((utmpp = getutxent()) != NULL) {
    723 #ifdef DEBUG
    724     (void) printf(
    725         "ut_user '%s'\nut_id '%s'\nut_line '%s'\nut_type '%d'\n\n",
    726         utmpp->ut_user, utmpp->ut_id, utmpp->ut_line, utmpp->ut_type);
    727 #endif
    728         if (utmpp->ut_type <= UTMAXTYPE) {
    729             /*
    730              *    Handle "am i"
    731              */
    732             if (justme) {
    733                 if (strncmp(myname, utmpp->ut_user,
    734                     sizeof (utmpp->ut_user)) == 0 &&
    735                     strncmp(mytty, utmpp->ut_line,
    736                     sizeof (utmpp->ut_line)) == 0 &&
    737                     utmpp->ut_type == USER_PROCESS) {
    738                     /*
    739                      * we have have found ourselves
    740                      * in the utmp file and the entry
    741                      * is a user process, this is not
    742                      * meaningful otherwise
    743                      *
    744                      */
    745
    746                     dump();
    747                     exit(0);
    748                 }
    749                 continue;
    750             }
    751
    752             /*
    753              *    Print the line if we want it
    754              */
    755             if (validtype[utmpp->ut_type]) {
    756 #ifdef    XPG4
    757                 if (utmpp->ut_type == LOGIN_PROCESS) {
    758                     if ((utmpp->ut_line[0] == '\0') ||
    759                     (strcmp(utmpp->ut_user, "LOGIN") != 0))
    760                         continue;
    761                 }
    762 #endif    /* XPG4 */
    763                 dump();
    764             }
    765         } else {
    766             (void) fprintf(stderr,
    767                 gettext("%s: Error --- entry has ut_type "
    768                 "of %d\n"), program, utmpp->ut_type);
    769             (void) fprintf(stderr,
    770                 gettext(" when maximum is %d\n"), UTMAXTYPE);
    771         }
    772     }
    773
    774     /*
    775      * If justme is set at this point than the utmp entry
    776      * was not found.
    777      */
    778     if (justme) {
    779         static struct utmpx utmpt;
    780
    781         pwp = getpwuid(geteuid());
    782         if (pwp != NULL)
    783             while (i < (int)sizeof (utmpt.ut_user) &&
    784                 *pwp->pw_name != 0)
    785                 utmpt.ut_user[i++] = *pwp->pw_name++;
    786
    787         ttname = ttyname(1);
    788
    789         i = 0;
    790         if (ttname != NULL)
    791             while (i < (int)sizeof (utmpt.ut_line) &&
    792                 *ttname != 0)
    793                 utmpt.ut_line[i++] = *ttname++;
    794
    795         utmpt.ut_id[0] = 0;
    796         utmpt.ut_pid = getpid();
    797         utmpt.ut_type = USER_PROCESS;
    798         (void) time(&utmpt.ut_xtime);
    799         utmpp = &utmpt;
    800         dump();
    801         exit(0);
    802     }
    803 }
    804
    805 /*
    806  *    This routine checks the following:
    807  *
    808  *    1.    File exists
    809  *
    810  *    2.    We have read permissions
    811  *
    812  *    3.    It is a multiple of utmp entries in size
    813  *
    814  *    Failing any of these conditions causes who(1) to
    815  *    abort processing.
    816  *
    817  *    4.    If file is empty we exit right away as there
    818  *        is no info to report on.
    819  *
    820  *    This routine does not check utmpx files.
    821  */
    822 static void
    823 ck_file(char *name)
    824 {
    825     struct    stat sbuf;
    826     int    rc;
    827
    828     /*
    829      *    Does file exist? Do stat to check, and save structure
    830      *    so that we can check on the file's size later on.
    831      */
    832     if ((rc = stat(name, &sbuf)) == -1) {
    833         (void) snprintf(errmsg, sizeof (errmsg),
    834             gettext("%s: Cannot stat file '%s'"), program, name);
    835         perror(errmsg);
    836         exit(1);
    837     }
    838
    839     /*
    840      *    The only real way we can be sure we can access the
    841      *    file is to try. If we succeed then we close it.
    842      */
    843     if (access(name, R_OK) < 0) {
    844         (void) snprintf(errmsg, sizeof (errmsg),
    845             gettext("%s: Cannot open file '%s'"), program, name);
    846         perror(errmsg);
    847         exit(1);
    848     }
    849
    850     /*
    851      *    If the file is empty, we are all done.
    852      */
    853     if (!sbuf.st_size)
    854         exit(0);
    855
    856     /*
    857      *    Make sure the file is a utmp file.
    858      *    We can only check for size being a multiple of
    859      *    utmp structures in length.
    860      */
    861     rc = sbuf.st_size % (int)sizeof (struct utmpx);
    862     if (rc) {
    863         (void) fprintf(stderr, gettext("%s: File '%s' is not "
    864             "a utmpx file\n"), program, name);
    865         exit(1);
    866     }
    867 }
    868
    (载自)
阅读(1606) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~