home *** CD-ROM | disk | FTP | other *** search
/ ftp.wwiv.com / ftp.wwiv.com.zip / ftp.wwiv.com / pub / INTERNET / UPC2S1.ZIP / USERTABL.C < prev    next >
C/C++ Source or Header  |  1993-10-02  |  13KB  |  345 lines

  1. /*--------------------------------------------------------------------*/
  2. /*       u s e r t a b l . c                                          */
  3. /*                                                                    */
  4. /*       User table routines for UUPC/extended                        */
  5. /*                                                                    */
  6. /*       Copyright (C) 1989, 1990 by Andrew H. Derbyshire             */
  7. /*                                                                    */
  8. /*       See file README.SCR for restrictions on re-distribution.     */
  9. /*                                                                    */
  10. /*       History:                                                     */
  11. /*          Create from hostable.c                                    */
  12. /*--------------------------------------------------------------------*/
  13.  
  14. /*
  15.  *    $Id: usertabl.c 1.7 1993/10/02 19:07:49 ahd Exp $
  16.  *
  17.  *    $Log: usertabl.c $
  18.  *     Revision 1.7  1993/10/02  19:07:49  ahd
  19.  *     Drop unneeded checkref()
  20.  *
  21.  *     Revision 1.6  1993/05/29  15:19:59  ahd
  22.  *     Allow configured systems, passwd files
  23.  *
  24.  *     Revision 1.5  1993/05/06  03:41:48  ahd
  25.  *     Use expand_path to get reasonable correct drive for aliases file
  26.  *
  27.  *     Revision 1.4  1993/04/15  03:17:21  ahd
  28.  *     Use standard define for undefined user names
  29.  *
  30.  *     Revision 1.3  1993/04/11  00:31:04  ahd
  31.  *     Global edits for year, TEXT, etc.
  32.  *
  33.  * Revision 1.2  1992/11/22  20:58:55  ahd
  34.  * Use strpool to allocate const strings
  35.  * Normalize directories as read
  36.  *
  37.  */
  38.  
  39. #include <stdio.h>
  40. #include <stdlib.h>
  41. #include <string.h>
  42. #include <assert.h>
  43. #include <ctype.h>
  44. #include <sys/types.h>
  45.  
  46. #include "lib.h"
  47. #include "hlib.h"
  48. #include "expath.h"
  49. #include "usertabl.h"
  50. #include "hostable.h"
  51. #include "security.h"
  52. #include "pushpop.h"
  53.  
  54. #define MAXUSERS  100         /* max number of unique users in PASSWD */
  55.  
  56. struct UserTable *users = NULL;  /* Public to allow router.c to use it  */
  57.  
  58. size_t  UserElements = 0;        /* Public to allow router.c to use it  */
  59.  
  60. static size_t loaduser( void );
  61.  
  62. static int usercmp( const void *a , const void *b );
  63.  
  64. char *NextField( char *input );
  65.  
  66. static char uucpsh[] = UUCPSHELL;
  67.  
  68. currentfile();
  69.  
  70. /*--------------------------------------------------------------------*/
  71. /*    c h e c k u s e r                                               */
  72. /*                                                                    */
  73. /*    Look up a user name in the PASSWD file                          */
  74. /*--------------------------------------------------------------------*/
  75.  
  76. struct UserTable *checkuser(const char *name)
  77. {
  78.    int   lower;
  79.    int   upper;
  80.  
  81.    if ( (name == NULL) || (strlen(name) == 0) )
  82.    {
  83.       printmsg(0,"checkuser: Invalid argument!");
  84.       panic();
  85.    }
  86.  
  87.    printmsg(14,"checkuser: Searching for user id %s",name);
  88.  
  89.  /*------------------------------------------------------------------*/
  90.  /*             Initialize the host name table if needed             */
  91.  /*------------------------------------------------------------------*/
  92.  
  93.    if (UserElements == 0)           /* host table initialized yet?   */
  94.       UserElements = loaduser();        /* No --> load it            */
  95.  
  96.    lower = 0;
  97.    upper = UserElements - 1;
  98.  
  99. /*--------------------------------------------------------------------*/
  100. /*              Peform a binary search on the user table              */
  101. /*--------------------------------------------------------------------*/
  102.  
  103.    while ( lower <= upper )
  104.    {
  105.       int midpoint;
  106.       int hit;
  107.       midpoint = (lower + upper) / 2;
  108.  
  109.       hit = stricmp(name,users[midpoint].uid);
  110.  
  111.       if (hit > 0)
  112.          lower = midpoint + 1;
  113.       else if (hit < 0)
  114.          upper = midpoint - 1;
  115.       else
  116.          return &users[midpoint];
  117.    }
  118.  
  119. /*--------------------------------------------------------------------*/
  120. /*         We didn't find the user.  Return failure to caller         */
  121. /*--------------------------------------------------------------------*/
  122.  
  123.    return BADUSER;
  124.  
  125. }  /* checkuser */
  126.  
  127.  
  128. /*--------------------------------------------------------------------*/
  129. /*    i n i t u s e r                                                 */
  130. /*                                                                    */
  131. /*    Intializes a user table entry for for loaduser                  */
  132. /*--------------------------------------------------------------------*/
  133.  
  134. struct UserTable *inituser(char *name)
  135. {
  136.  
  137.    size_t hit = UserElements;
  138.    size_t element = 0;
  139.  
  140.    if (users == NULL)
  141.    {
  142.       users = calloc(MAXUSERS, sizeof(*users));
  143.       checkref(users);
  144.    }
  145.  
  146. /*--------------------------------------------------------------------*/
  147. /*    Add the user to the table.  Note that we must add the user      */
  148. /*    to the table ourselves (rather than use lsearch) because we     */
  149. /*    must make a copy of the string; the *token we use for the       */
  150. /*    search is in the middle of our I/O buffer!                      */
  151. /*--------------------------------------------------------------------*/
  152.  
  153.    while ( element < hit )
  154.    {
  155.       if (equali( users[element].uid , name ))
  156.          hit = element;
  157.       else
  158.          element++;
  159.    }
  160.  
  161.    if (hit == UserElements)
  162.    {
  163.       users[hit].uid      = newstr(name);
  164.       users[hit].realname = EMPTY_GCOS;
  165.       users[hit].beep     = NULL;
  166.       users[hit].homedir  = E_pubdir;
  167.       users[hit].hsecure  = NULL;
  168.       users[hit].password = NULL;
  169.       users[hit].sh       = uucpsh;
  170.       assert(UserElements++ < MAXUSERS);
  171.    } /* if */
  172.  
  173.    return &users[hit];
  174.  
  175. } /* inituser */
  176.  
  177. /*--------------------------------------------------------------------*/
  178. /*    l o a d u s e r                                                 */
  179. /*                                                                    */
  180. /*    Load the user password file                                     */
  181. /*--------------------------------------------------------------------*/
  182.  
  183. static size_t loaduser( void )
  184. {
  185.    FILE *stream;
  186.    struct UserTable *userp;
  187.    size_t hit;
  188.    char buf[BUFSIZ];
  189.    char *token;
  190.  
  191. /*--------------------------------------------------------------------*/
  192. /*     First, load in the active user as first user in the table      */
  193. /*--------------------------------------------------------------------*/
  194.  
  195.    userp = inituser( E_mailbox );
  196.    userp->realname = E_name;
  197.    userp->homedir  = E_homedir;
  198.  
  199. /*--------------------------------------------------------------------*/
  200. /*       Password file format:                                        */
  201. /*          user id:password:::user/system name:homedir:shell         */
  202. /*--------------------------------------------------------------------*/
  203.  
  204.    if ((stream = FOPEN(E_passwd, "r",TEXT_MODE)) == NULL)
  205.    {
  206.       printmsg(2,"loaduser: Cannot open password file %s",E_passwd);
  207.       users = realloc(users, UserElements *  sizeof(*users));
  208.       checkref(users);
  209.       return UserElements;
  210.    } /* if */
  211.  
  212.    PushDir( E_confdir );      // Use standard reference point for
  213.                               // for directories
  214.  
  215. /*--------------------------------------------------------------------*/
  216. /*                 The password file is open; read it                 */
  217. /*--------------------------------------------------------------------*/
  218.  
  219.    while (! feof(stream)) {
  220.       if (fgets(buf,BUFSIZ,stream) == NULL)   /* Try to read a line      */
  221.          break;               /* Exit if end of file                 */
  222.       if ((*buf == '#') || (*buf == '\0'))
  223.          continue;            /* Line is a comment; loop again       */
  224.       if ( buf[ strlen(buf) - 1 ] == '\n')
  225.          buf[ strlen(buf) - 1 ] = '\0';
  226.       token = NextField(buf);
  227.       if (token    == NULL)   /* Any data?                           */
  228.          continue;            /* No --> read another line            */
  229.       userp = inituser(token);/* Initialize record for user          */
  230.  
  231.       if (userp->password != NULL)  /* Does the user already exist?  */
  232.       {                       /* Yes --> Report and ignore           */
  233.          printmsg(0,"loaduser: Duplicate entry for '%s' in '%s' ignored",
  234.                token,E_passwd);
  235.          continue;            /* System already in /etc/passwd,
  236.                                  ignore it.                          */
  237.       }
  238.  
  239.       token = NextField(NULL);   /* Get the user password            */
  240.       if (!equal(token,"*"))     /* User can login?                  */
  241.          userp->password = newstr(token); /* Yes --> Set password    */
  242.  
  243.       token = NextField(NULL);   /* Use  UNIX user number as tone    */
  244.                                  /* to beep at                       */
  245.       if (token != NULL)
  246.          userp->beep = newstr( token );
  247.  
  248.       token = NextField(NULL);   /* Skip UNIX group number           */
  249.  
  250.       token = NextField(NULL);   /* Get the formal user name         */
  251.       if (token != NULL)         /* Did they provide user name?      */
  252.          userp->realname = newstr(token); /* Yes --> Copy            */
  253.  
  254.       token = NextField(NULL);   /* Get home directory (optional)    */
  255.       if ( token != NULL)
  256.          userp->homedir = newstr(normalize( token ));
  257.  
  258.       token = NextField(NULL);   /* Get user shell (optional)        */
  259.       if ( token != NULL )       /* Did we get it?                   */
  260.          userp->sh = newstr(token); /* Yes --> Copy it in            */
  261.  
  262.    }  /* while */
  263.  
  264.    PopDir();
  265.  
  266.    fclose(stream);
  267.    users = realloc(users, UserElements *  sizeof(*users));
  268.    checkref(users);
  269.  
  270.    qsort(users, UserElements ,sizeof(users[0]) , usercmp);
  271.  
  272.    for (hit = 0 ; hit < UserElements; hit ++)
  273.    {
  274.       printmsg(8,"loaduser: user[%d] user id(%s) no(%s) name(%s) "
  275.                  "home directory(%s) shell(%s)",
  276.          hit,
  277.          users[hit].uid,
  278.          users[hit].beep == NULL ? "NONE" : users[hit].beep,
  279.          users[hit].realname,
  280.          users[hit].homedir,
  281.          users[hit].sh);
  282.    } /* for */
  283.  
  284.    return UserElements;
  285. } /* loaduser */
  286.  
  287. /*--------------------------------------------------------------------*/
  288. /*    u s e r c m p                                                   */
  289. /*                                                                    */
  290. /*    Accepts indirect pointers to two strings and compares           */
  291. /*    them using stricmp (case insensitive string compare)            */
  292. /*--------------------------------------------------------------------*/
  293.  
  294. int usercmp( const void *a , const void *b )
  295. {
  296.    return stricmp(((struct UserTable*) a)->uid,
  297.         ((struct UserTable*) b)->uid);
  298. }  /*usercmp*/
  299.  
  300. /*--------------------------------------------------------------------*/
  301. /*    n e x t f i e l d                                               */
  302. /*                                                                    */
  303. /*    Find the next field in the user password file                   */
  304. /*--------------------------------------------------------------------*/
  305.  
  306. char *NextField( char *input )
  307. {
  308.    static char *start = NULL;
  309.    char *next = NULL;
  310.  
  311.    if (input == NULL)         /* Starting a new field?               */
  312.    {
  313.       if ( start  == NULL )   /* Anything left to parse?             */
  314.          return NULL;         /* No --> Return empty string          */
  315.       else
  316.          input = start;       /* Yes --> Continue parse of old one   */
  317.    } /* if */
  318.  
  319. /*--------------------------------------------------------------------*/
  320. /*    Look for the next field; because MS-DOS directories may have    */
  321. /*    a sequence of x:/ or x:\ where 'x' is a drive letter, we take   */
  322. /*    special care to allow DOS directories to appear unmolested      */
  323. /*    in the password file                                            */
  324. /*--------------------------------------------------------------------*/
  325.  
  326.    if ((strlen(input) > 2) && isalpha(input[0]) && (input[1] == ':') &&
  327.        ((input[2] == '/') || (input[2] == '\\')))
  328.       next = strchr( &input[2], ':');   /* Find start of next field  */
  329.    else
  330.       next = strchr( input, ':');   /* Find start of next field      */
  331.  
  332.    if (next == NULL )         /* Last field?                         */
  333.       start = NULL;           /* Yes --> Make next call return NULL  */
  334.    else {                     /* No                                  */
  335.       *next = '\0';           /* Terminate the string                */
  336.       start = ++next;         /* Have next call look at next field   */
  337.    } /* else */
  338.  
  339.    if (strlen(input))         /* Did we get anything in the field?   */
  340.       return input;           /* Yes --> Return the string           */
  341.    else
  342.       return NULL;            /* Field is empty, return NULL         */
  343.  
  344. } /* NextField */
  345.