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