Print this page
2989 Eliminate use of LOGNAME_MAX in ON
1166 useradd have warning with name more 8 chars


   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 http://www.opensolaris.org/os/licensing.
  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   "%Z%%M% %I%     %E% 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  *


  83 #include        <fcntl.h>
  84 #include        <stdio.h>
  85 #include        <string.h>
  86 #include        <sys/types.h>
  87 #include        <unistd.h>
  88 #include        <stdlib.h>
  89 #include        <sys/stat.h>
  90 #include        <time.h>
  91 #include        <utmpx.h>
  92 #include        <locale.h>
  93 #include        <pwd.h>
  94 #include        <limits.h>
  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                   */


 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;


 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),


 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("   .  "));


 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 */


 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;




   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 http://www.opensolaris.org/os/licensing.
  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 (c) 2013 Gary Mills
  27  *
  28  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  29  * Use is subject to license terms.
  30  */
  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  *


  83 #include        <fcntl.h>
  84 #include        <stdio.h>
  85 #include        <string.h>
  86 #include        <sys/types.h>
  87 #include        <unistd.h>
  88 #include        <stdlib.h>
  89 #include        <sys/stat.h>
  90 #include        <time.h>
  91 #include        <utmpx.h>
  92 #include        <locale.h>
  93 #include        <pwd.h>
  94 #include        <limits.h>
  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  * Use the full lengths from utmpx for user and line.


 104  */





 105 #define NMAX    (sizeof (utmpp->ut_user))
 106 #define LMAX    (sizeof (utmpp->ut_line))

 107 
 108 /* Print minimum field widths. */
 109 #define LOGIN_WIDTH     8
 110 #define LINE_WIDTH      12
 111 
 112 static char     comment[BUFSIZ]; /* holds inittab comment       */
 113 static char     errmsg[BUFSIZ]; /* used in snprintf for errors  */
 114 static int      fildes;         /* file descriptor for inittab  */
 115 static int      Hopt = 0;       /* 1 = who -H                   */
 116 static char     *inittab;       /* ptr to inittab contents      */
 117 static char     *iinit;         /* index into inittab           */
 118 static int      justme = 0;     /* 1 = who am i                 */
 119 static struct   tm *lptr;       /* holds user login time        */
 120 static char     *myname;        /* pointer to invoker's name    */
 121 static char     *mytty;         /* holds device user is on      */
 122 static char     nameval[sizeof (utmpp->ut_user) + 1]; /*  invoker's name */
 123 static int      number = 8;     /* number of users per -q line  */
 124 static int      optcnt = 0;     /* keeps count of options       */
 125 static char     outbuf[BUFSIZ]; /* buffer for output            */
 126 static char     *program;       /* holds name of this program   */
 127 #ifdef  XPG4
 128 static int      aopt = 0;       /* 1 = who -a                   */
 129 static int      dopt = 0;       /* 1 = who -d                   */
 130 #endif  /* XPG4 */
 131 static int      qopt = 0;       /* 1 = who -q                   */


 147 main(int argc, char **argv)
 148 {
 149         int     goerr = 0;      /* non-zero indicates cmd error */
 150         int     i;
 151         int     optsw;          /* switch for while of getopt() */
 152 
 153         (void) setlocale(LC_ALL, "");
 154 
 155 #if     !defined(TEXT_DOMAIN)   /* Should be defined by cc -D */
 156 #define TEXT_DOMAIN "SYS_TEST"  /* Use this only if it weren't */
 157 #endif
 158         (void) textdomain(TEXT_DOMAIN);
 159 
 160         validtype[USER_PROCESS] = 1;
 161         validtype[EMPTY] = 0;
 162         stbufp = &stbuf;
 163 
 164         /*
 165          *      Strip off path name of this command
 166          */
 167         for (i = strlen(argv[0]); i >= 0 && argv[0][i] != '/'; --i)
 168                 ;
 169         if (i >= 0)
 170                 argv[0] += i+1;
 171         program = argv[0];
 172 
 173         /*
 174          *      Buffer stdout for speed
 175          */
 176         setbuf(stdout, outbuf);
 177 
 178         /*
 179          *      Retrieve options specified on command line
 180          *      XCU4 - add -m option
 181          */
 182         while ((optsw = getopt(argc, argv, "abdHlmn:pqrstTu")) != EOF) {
 183                 optcnt++;
 184                 switch (optsw) {
 185 
 186                 case 'a':
 187                         optcnt += 7;
 188                         validtype[BOOT_TIME] = 1;


 489         /*
 490          * Get and check user name
 491          */
 492         if (utmpp->ut_user[0] == '\0')
 493                 (void) strcpy(user, "   .");
 494         else {
 495                 (void) strncpy(user, utmpp->ut_user, sizeof (user));
 496                 user[sizeof (user) - 1] = '\0';
 497         }
 498         totlusrs++;
 499 
 500         /*
 501          * Do print in 'who -q' format
 502          */
 503         if (qopt) {
 504                 /*
 505                  * XCU4 - Use non user macro for correct user count
 506                  */
 507                 if (((totlusrs - 1) % number) == 0 && totlusrs > 1)
 508                         (void) printf("\n");
 509                 (void) printf("%-*.*s ", LOGIN_WIDTH, NMAX, user);
 510                 return;
 511         }
 512 
 513 
 514         pexit = (int)' ';
 515         pterm = (int)' ';
 516 
 517         /*
 518          *      Get exit info if applicable
 519          */
 520         if (utmpp->ut_type == RUN_LVL || utmpp->ut_type == DEAD_PROCESS) {
 521                 pterm = utmpp->ut_exit.e_termination;
 522                 pexit = utmpp->ut_exit.e_exit;
 523         }
 524 
 525         /*
 526          *      Massage ut_xtime field
 527          */
 528         lptr = localtime(&utmpp->ut_xtime);
 529         (void) strftime(time_buf, sizeof (time_buf),


 545          *      XCU4 - only print + or - for user processes
 546          */
 547         if (Topt && (utmpp->ut_type == USER_PROCESS)) {
 548                 w = '-';
 549                 (void) strcpy(path, "/dev/");
 550                 (void) strncpy(path + 5, utmpp->ut_line,
 551                     sizeof (utmpp->ut_line));
 552                 path[5 + sizeof (utmpp->ut_line)] = '\0';
 553 
 554                 if ((rc = stat(path, stbufp)) == -1) w = '?';
 555                 else if ((stbufp->st_mode & S_IWOTH) ||
 556                     (stbufp->st_mode & S_IWGRP))  /* Check group & other */
 557                         w = '+';
 558 
 559         } else
 560                 w = ' ';
 561 
 562         /*
 563          *      Print the TERSE portion of the output
 564          */
 565         (void) printf("%-*.*s %c %-12s %s", LOGIN_WIDTH, NMAX, user,
 566             w, device, time_buf);
 567 
 568         if (!terse) {
 569                 /*
 570                  *      Stat device for idle time
 571                  *      (Don't complain if you can't)
 572                  */
 573                 rc = -1;
 574                 if (utmpp->ut_type == USER_PROCESS) {
 575                         (void) strcpy(path, "/dev/");
 576                         (void) strncpy(path + 5, utmpp->ut_line,
 577                             sizeof (utmpp->ut_line));
 578                         path[5 + sizeof (utmpp->ut_line)] = '\0';
 579                         rc = stat(path, stbufp);
 580                 }
 581                 if (rc != -1) {
 582                         idle = timnow - stbufp->st_mtime;
 583                         hr = idle/3600;
 584                         min = (unsigned)(idle/60)%60;
 585                         if (hr == 0 && min == 0)
 586                                 (void) printf(gettext("   .  "));


 607                 if (utmpp->ut_type == DEAD_PROCESS) {
 608                         (void) printf(gettext("  id=%4.4s "),
 609                             utmpp->ut_id);
 610                         (void) printf(gettext("term=%-3d "), pterm);
 611                         (void) printf(gettext("exit=%d  "), pexit);
 612                 } else if (utmpp->ut_type != INIT_PROCESS) {
 613                         /*
 614                          *      Search for each entry in inittab
 615                          *      string. Keep our place from
 616                          *      search to search to try and
 617                          *      minimize the work. Wrap once if needed
 618                          *      for each entry.
 619                          */
 620                         wrap = 0;
 621                         /*
 622                          *      Look for a line beginning with
 623                          *      utmpp->ut_id
 624                          */
 625                         while ((rc = strncmp(utmpp->ut_id, iinit,
 626                             strcspn(iinit, ":"))) != 0) {
 627                                 for (; *iinit != '\n'; iinit++)
 628                                         ;
 629                                 iinit++;
 630 
 631                                 /*
 632                                  *      Wrap once if necessary to
 633                                  *      find entry in inittab
 634                                  */
 635                                 if (*iinit == '\0') {
 636                                         if (!wrap) {
 637                                                 iinit = inittab;
 638                                                 wrap = 1;
 639                                         }
 640                                 }
 641                         }
 642 
 643                         if (*iinit != '\0') {
 644                                 /*
 645                                  *      We found our entry
 646                                  */
 647                                 for (iinit++; *iinit != '#' &&
 648                                     *iinit != '\n'; iinit++)
 649                                         ;
 650                                 if (*iinit == '#') {
 651                                         for (iinit++; *iinit == ' ' ||
 652                                             *iinit == '\t'; iinit++)
 653                                                 ;
 654                                         for (rc = 0; *iinit != '\n'; iinit++)
 655                                                 comment[rc++] = *iinit;
 656                                         comment[rc] = '\0';
 657                                 } else
 658                                         (void) strcpy(comment, " ");
 659 
 660                                 (void) printf("  %s", comment);
 661                         } else
 662                                 iinit = inittab;        /* Reset pointer */
 663                 }
 664                 if (utmpp->ut_type == INIT_PROCESS)
 665                         (void) printf(gettext("  id=%4.4s"), utmpp->ut_id);
 666         }
 667 #ifdef  XPG4
 668         else
 669                 if (dopt && utmpp->ut_type == DEAD_PROCESS) {
 670                         (void) printf(gettext("\tterm=%-3d "), pterm);
 671                         (void) printf(gettext("exit=%d  "), pexit);
 672                 }
 673 #endif  /* XPG4 */


 740                                          * we have have found ourselves
 741                                          * in the utmp file and the entry
 742                                          * is a user process, this is not
 743                                          * meaningful otherwise
 744                                          *
 745                                          */
 746 
 747                                         dump();
 748                                         exit(0);
 749                                 }
 750                                 continue;
 751                         }
 752 
 753                         /*
 754                          *      Print the line if we want it
 755                          */
 756                         if (validtype[utmpp->ut_type]) {
 757 #ifdef  XPG4
 758                                 if (utmpp->ut_type == LOGIN_PROCESS) {
 759                                         if ((utmpp->ut_line[0] == '\0') ||
 760                                             (strcmp(utmpp->ut_user,
 761                                             "LOGIN") != 0))
 762                                                 continue;
 763                                 }
 764 #endif  /* XPG4 */
 765                                 dump();
 766                         }
 767                 } else {
 768                         (void) fprintf(stderr,
 769                             gettext("%s: Error --- entry has ut_type "
 770                             "of %d\n"), program, utmpp->ut_type);
 771                         (void) fprintf(stderr,
 772                             gettext(" when maximum is %d\n"), UTMAXTYPE);
 773                 }
 774         }
 775 
 776         /*
 777          * If justme is set at this point than the utmp entry
 778          * was not found.
 779          */
 780         if (justme) {
 781                 static struct utmpx utmpt;