home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume38 / shadow / part09 / utmp.c < prev   
C/C++ Source or Header  |  1993-08-14  |  9KB  |  409 lines

  1. /*
  2.  * Copyright 1989, 1990, 1991, 1992, 1993, John F. Haugh II
  3.  * All rights reserved.
  4.  *
  5.  * Permission is granted to copy and create derivative works for any
  6.  * non-commercial purpose, provided this copyright notice is preserved
  7.  * in all copies of source code, or included in human readable form
  8.  * and conspicuously displayed on all copies of object code or
  9.  * distribution media.
  10.  *
  11.  * This software is provided on an AS-IS basis and the author makes
  12.  * no warrantee of any kind.
  13.  */
  14.  
  15. #ifdef    SVR4
  16. #include <stdlib.h>
  17. #include <utmp.h>
  18. #include <utmpx.h>
  19. #include <sys/time.h>
  20. #else
  21. #include <sys/types.h>
  22. #include <utmp.h>
  23. #endif    /* SVR4 */
  24.  
  25. #include <fcntl.h>
  26. #ifndef    BSD
  27. #include <string.h>
  28. #include <memory.h>
  29. #define    bzero(a,n)    memset(a, 0, n)
  30. #else
  31. #include <strings.h>
  32. #define    strchr    index
  33. #define    strrchr    rindex
  34. #endif
  35. #include <stdio.h>
  36. #ifdef    STDLIB_H
  37. #include <stdlib.h>
  38. #endif
  39. #ifdef    UNISTD_H
  40. #include <unistd.h>
  41. #endif
  42. #include "config.h"
  43.  
  44. #ifndef    UTMP_FILE
  45. #define    UTMP_FILE    "/etc/utmp"
  46. #endif
  47.  
  48. #if defined(SUN) || defined(BSD) || defined(SUN4)
  49. #ifndef    WTMP_FILE
  50. #define WTMP_FILE "/usr/adm/wtmp"
  51. #endif
  52. #endif    /* SUN || BSD */
  53.  
  54. #ifndef    lint
  55. static    char    sccsid[] = "@(#)utmp.c    3.17    08:15:06    07 May 1993";
  56. #endif
  57.  
  58. #ifdef    SVR4
  59. extern    struct    utmpx    utxent;
  60. extern    char    host;
  61. #endif
  62. extern    struct    utmp    utent;
  63.  
  64. extern    struct    utmp    *getutent();
  65. extern    struct    utmp    *getutline();
  66. extern    void    setutent();
  67. extern    void    endutent();
  68. extern    time_t    time();
  69. extern    char    *ttyname();
  70. extern    long    lseek();
  71.  
  72. #define    NO_UTENT \
  73.     "No utmp entry.  You must exec \"login\" from the lowest level \"sh\""
  74. #define    NO_TTY \
  75.     "Unable to determine your tty name."
  76.  
  77. /*
  78.  * checkutmp - see if utmp file is correct for this process
  79.  *
  80.  *    System V is very picky about the contents of the utmp file
  81.  *    and requires that a slot for the current process exist.
  82.  *    The utmp file is scanned for an entry with the same process
  83.  *    ID.  If no entry exists the process exits with a message.
  84.  *
  85.  *    The "picky" flag is for network and other logins that may
  86.  *    use special flags.  It allows the pid checks to be overridden.
  87.  *    This means that getty should never invoke login with any
  88.  *    command line flags.
  89.  */
  90.  
  91. void
  92. checkutmp (picky)
  93. int    picky;
  94. {
  95.     char    *line;
  96. #ifdef    USG
  97. #ifdef    SVR4
  98.     struct    utmpx    *utx, utmpx, *getutxline();
  99. #endif    /* SVR4 */
  100.     struct    utmp    *ut, utmp, *getutline();
  101. #ifndef    NDEBUG
  102.     int    pid = getppid ();
  103. #else
  104.     int    pid = getpid ();
  105. #endif    /* !NDEBUG */
  106. #endif    /* USG */
  107.  
  108. #if !defined(SUN) && !defined(SUN4)
  109. #ifdef    SVR4
  110.     setutxent ();
  111. #endif
  112.     setutent ();
  113. #endif    /* !SUN */
  114.  
  115. #ifdef    USG
  116.     if (picky) {
  117. #ifdef    SVR4
  118.         while (utx = getutxent ())
  119.             if (utx->ut_pid == pid)
  120.                 break;
  121.  
  122.         if (utx)
  123.             utxent = *utx;
  124. #endif
  125.         while (ut = getutent ())
  126.             if (ut->ut_pid == pid)
  127.                 break;
  128.  
  129.         if (ut)
  130.             utent = *ut;
  131.  
  132. #ifdef    SVR4
  133.         endutxent ();
  134. #endif
  135.         endutent ();
  136.  
  137.         if (! ut) {
  138.              (void) puts (NO_UTENT);
  139.             exit (1);
  140.         }
  141. #ifndef    UNIXPC
  142.  
  143.         /*
  144.          * If there is no ut_line value in this record, fill
  145.          * it in by getting the TTY name and stuffing it in
  146.          * the structure.  The UNIX/PC is broken in this regard
  147.          * and needs help ...
  148.          */
  149.  
  150.         if (utent.ut_line[0] == '\0')
  151. #endif    /* !UNIXPC */
  152.         {
  153.             if (! (line = ttyname (0))) {
  154.                 (void) puts (NO_TTY);
  155.                 exit (1);
  156.             }
  157.             if (strncmp (line, "/dev/", 5) == 0)
  158.                 line += 5;
  159.             (void) strncpy (utent.ut_line, line,
  160.                     (int) sizeof utent.ut_line);
  161. #ifdef    SVR4
  162.             (void) strncpy (utxent.ut_line, line,
  163.                     (int) sizeof utxent.ut_line);
  164. #endif
  165.         }
  166.     } else {
  167.         if (! (line = ttyname (0))) {
  168.             puts (NO_TTY);
  169.             exit (1);
  170.         }
  171.         if (strncmp (line, "/dev/", 5) == 0)
  172.             line += 5;
  173.  
  174.          (void) strncpy (utent.ut_line, line,
  175.                           (int) sizeof utent.ut_line);
  176.         if (ut = getutline (&utent))
  177.              (void) strncpy (utent.ut_id, ut->ut_id,
  178.                      (int) sizeof ut->ut_id);
  179.  
  180.         (void) strcpy (utent.ut_user, "LOGIN");
  181.         utent.ut_pid = getpid ();
  182.         utent.ut_type = LOGIN_PROCESS;
  183.         (void) time (&utent.ut_time);
  184. #ifdef    SVR4
  185.         if (utx = getutxline (&utent))
  186.             (void) strncpy (utxent.ut_id, utent.ut_id,
  187.                     (int) sizeof utxent.ut_id);
  188.  
  189.         (void) strncpy (utxent.ut_user, utent.ut_user,
  190.             sizeof utent.ut_user);
  191.         utxent.ut_pid = utent.ut_pid;
  192.         utxent.ut_type = utent.ut_type;
  193.         (void) gettimeofday ((struct timeval *) &utxent.ut_tv, 0);
  194.         utent.ut_time = utxent.ut_tv.tv_sec;
  195. #endif
  196.     }
  197. #else    /* !USG */
  198.  
  199.     /*
  200.      * Hand-craft a new utmp entry.
  201.      */
  202.  
  203.     bzero (&utent, sizeof utent);
  204.     if (! (line = ttyname (0))) {
  205.         puts (NO_TTY);
  206.         exit (1);
  207.     }
  208.     if (strncmp (line, "/dev/", 5) == 0)
  209.         line += 5;
  210.  
  211.     (void) strncpy (utent.ut_line, line, sizeof utent.ut_line);
  212.     (void) time (&utent.ut_time);
  213. #endif    /* !USG */
  214. }
  215.  
  216. /*
  217.  * setutmp - put a USER_PROCESS entry in the utmp file
  218.  *
  219.  *    setutmp changes the type of the current utmp entry to
  220.  *    USER_PROCESS.  the wtmp file will be updated as well.
  221.  */
  222.  
  223. void
  224. setutmp (name, line)
  225. char    *name;
  226. char    *line;
  227. {
  228. #ifdef SVR4
  229.     struct    utmp    *utmp, utline;
  230.     struct    utmpx    *utmpx, utxline;
  231.     pid_t    pid = getpid ();
  232.     FILE    *utmpx_fp;
  233.     int    found_utmpx = 0, found_utmp;
  234.     int    fd;
  235.  
  236.     /*
  237.      * The canonical device name doesn't include "/dev/"; skip it
  238.      * if it is already there.
  239.      */
  240.  
  241.     if (strncmp (line, "/dev/", 5) == 0)
  242.         line += 5;
  243.  
  244.     /*
  245.      * Update utmpx.  We create an empty entry in case there is
  246.      * no matching entry in the utmpx file.
  247.      */
  248.  
  249.     setutxent ();
  250.     setutent ();
  251.  
  252.     while (utmpx = getutxent ()) {
  253.         if (utmpx->ut_pid == pid) {
  254.             found_utmpx = 1;
  255.             break;
  256.         }
  257.     }
  258.     while (utmp = getutent ()) {
  259.         if (utmp->ut_pid == pid) {
  260.             found_utmp = 1;
  261.             break;
  262.         }
  263.     }
  264.  
  265.     /*
  266.      * If the entry matching `pid' cannot be found, create a new
  267.      * entry with the device name in it.
  268.      */
  269.  
  270.     if (! found_utmpx) {
  271.         memset ((void *) &utxline, 0, sizeof utxline);
  272.         strncpy (utxline.ut_line, line, sizeof utxline.ut_line);
  273.         utxline.ut_pid = getpid ();
  274.     } else {
  275.         utxline = *utmpx;
  276.         if (strncmp (utxline.ut_line, "/dev/", 5) == 0) {
  277.             memmove (utxline.ut_line, utxline.ut_line + 5,
  278.                 sizeof utxline.ut_line - 5);
  279.             utxline.ut_line[sizeof utxline.ut_line - 5] = '\0';
  280.         }
  281.     }
  282.     if (! found_utmp) {
  283.         memset ((void *) &utline, 0, sizeof utline);
  284.         strncpy (utline.ut_line, utxline.ut_line,
  285.             sizeof utline.ut_line);
  286.         utline.ut_pid = utxline.ut_pid;
  287.     } else {
  288.         utline = *utmp;
  289.         if (strncmp (utline.ut_line, "/dev/", 5) == 0) {
  290.             memmove (utline.ut_line, utline.ut_line + 5,
  291.                 sizeof utline.ut_line - 5);
  292.             utline.ut_line[sizeof utline.ut_line - 5] = '\0';
  293.         }
  294.     }
  295.  
  296.     /*
  297.      * Fill in the fields in the utmpx entry and write it out.  Do
  298.      * the utmp entry at the same time to make sure things don't
  299.      * get messed up.
  300.      */
  301.  
  302.     strncpy (utxline.ut_user, name, sizeof utxline.ut_user);
  303.     strncpy (utline.ut_user, name, sizeof utline.ut_user);
  304.  
  305.     utline.ut_type = utxline.ut_type = USER_PROCESS;
  306.  
  307.     gettimeofday (&utxline.ut_tv);
  308.     utline.ut_time = utxline.ut_tv.tv_sec;
  309.  
  310.     strncpy (utxline.ut_host, host, sizeof utxline.ut_host);
  311.  
  312.     pututxline (&utxline);
  313.     pututline (&utline);
  314.  
  315.     if ((fd = open (WTMP_FILE "x", O_WRONLY|O_APPEND)) != -1) {
  316.         write (fd, (void *) &utxline, sizeof utxline);
  317.         close (fd);
  318.     }
  319.     if ((fd = open (WTMP_FILE, O_WRONLY|O_APPEND)) != -1) {
  320.         write (fd, (void *) &utline, sizeof utline);
  321.         close (fd);
  322.     }
  323.  
  324.     utxent = utxline;
  325.     utent = utline;
  326.     
  327. #else /* !SVR4 */
  328.     struct    utmp    utmp;
  329.     int    fd;
  330.     int    found = 0;
  331.  
  332.     if (! (fd = open (UTMP_FILE, O_RDWR)))
  333.         return;
  334.  
  335. #if !defined(SUN) && !defined(BSD) && !defined(SUN4)
  336.      while (! found && read (fd, &utmp, sizeof utmp) == sizeof utmp) {
  337.          if (! strncmp (line, utmp.ut_line, (int) sizeof utmp.ut_line))
  338.             found++;
  339.     }
  340. #endif
  341.     if (! found) {
  342.  
  343.         /*
  344.          * This is a brand-new entry.  Clear it out and fill it in
  345.          * later.
  346.          */
  347.  
  348.           (void) bzero (&utmp, sizeof utmp);
  349.          (void) strncpy (utmp.ut_line, line, (int) sizeof utmp.ut_line);
  350.     }
  351.  
  352.     /*
  353.      * Fill in the parts of the UTMP entry.  BSD has just the name,
  354.      * while System V has the name, PID and a type.
  355.      */
  356.  
  357. #if defined(SUN) || defined(BSD) || defined(SUN4)
  358.     (void) strncpy (utmp.ut_name, name, (int) sizeof utent.ut_name);
  359. #else    /* SUN */
  360.      (void) strncpy (utmp.ut_user, name, (int) sizeof utent.ut_user);
  361.     utmp.ut_type = USER_PROCESS;
  362.     utmp.ut_pid = getpid ();
  363. #endif    /* SUN || BSD */
  364.  
  365.     /*
  366.      * Put in the current time (common to everyone)
  367.      */
  368.  
  369.     (void) time (&utmp.ut_time);
  370.  
  371. #ifdef UT_HOST
  372.     /*
  373.      * Update the host name field for systems with networking support
  374.      */
  375.  
  376.     (void) strncpy (utmp.ut_host, utent.ut_host, (int) sizeof utmp.ut_host);
  377. #endif
  378.  
  379.     /*
  380.      * Locate the correct position in the UTMP file for this
  381.      * entry.
  382.      */
  383.  
  384. #if defined(SUN) || defined(BSD) || defined(SUN4)
  385.     (void) lseek (fd, (long) (sizeof utmp) * ttyslot (), 0);
  386. #else
  387.     if (found)    /* Back up a splot */
  388.         lseek (fd, (long) - sizeof utmp, 1);
  389.     else        /* Otherwise, go to the end of the file */
  390.         lseek (fd, (long) 0, 2);
  391. #endif
  392.  
  393.     /*
  394.      * Scribble out the new entry and close the file.  We're done
  395.      * with UTMP, next we do WTMP (which is real easy, put it on
  396.      * the end of the file.
  397.      */
  398.  
  399.     (void) write (fd, &utmp, sizeof utmp);
  400.     (void) close (fd);
  401.  
  402.     if ((fd = open (WTMP_FILE, O_WRONLY|O_APPEND)) >= 0) {
  403.         (void) write (fd, &utmp, sizeof utmp);
  404.         (void) close (fd);
  405.     }
  406.      utent = utmp;
  407. #endif /* SVR4 */
  408. }
  409.