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