home *** CD-ROM | disk | FTP | other *** search
- /*--------------------------------------------------------------------*/
- /* u s e r t a b l . c */
- /* */
- /* User table routines for UUPC/extended */
- /* */
- /* Copyright (C) 1989, 1990 by Andrew H. Derbyshire */
- /* */
- /* See file README.SCR for restrictions on re-distribution. */
- /* */
- /* History: */
- /* Create from hostable.c */
- /*--------------------------------------------------------------------*/
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <assert.h>
- #include <ctype.h>
- #include <sys/types.h>
-
- #include "lib.h"
- #include "hlib.h"
- #include "usertabl.h"
- #include "hostable.h"
- #include "security.h"
-
- #define MAXUSERS 100 /* max number of unique users in PASSWD */
-
- struct UserTable *users = NULL; /* Public to allow router.c to use it */
-
- size_t UserElements = 0; /* Public to allow router.c to use it */
-
- static size_t loaduser( void );
-
- static int usercmp( const void *a , const void *b );
-
- char *NextField( char *input );
-
- static char uucpsh[] = UUCPSHELL;
-
- currentfile();
-
- /*--------------------------------------------------------------------*/
- /* c h e c k u s e r */
- /* */
- /* Look up a user name in the PASSWD file */
- /*--------------------------------------------------------------------*/
-
- struct UserTable *checkuser(const char *name)
- {
- int lower;
- int upper;
-
- if ( (name == NULL) || (strlen(name) == 0) )
- {
- printmsg(0,"checkuser: Invalid argument!");
- panic();
- }
-
- printmsg(14,"checkuser: Searching for user id %s",name);
-
- /*------------------------------------------------------------------*/
- /* Initialize the host name table if needed */
- /*------------------------------------------------------------------*/
-
- if (UserElements == 0) /* host table initialized yet? */
- UserElements = loaduser(); /* No --> load it */
-
- lower = 0;
- upper = UserElements - 1;
-
- /*--------------------------------------------------------------------*/
- /* Peform a binary search on the user table */
- /*--------------------------------------------------------------------*/
-
- while ( lower <= upper )
- {
- int midpoint;
- int hit;
- midpoint = (lower + upper) / 2;
-
- hit = stricmp(name,users[midpoint].uid);
-
- if (hit > 0)
- lower = midpoint + 1;
- else if (hit < 0)
- upper = midpoint - 1;
- else
- return &users[midpoint];
- }
-
- /*--------------------------------------------------------------------*/
- /* We didn't find the user. Return failure to caller */
- /*--------------------------------------------------------------------*/
-
- return BADUSER;
-
- } /* checkuser */
-
-
- /*--------------------------------------------------------------------*/
- /* i n i t u s e r */
- /* */
- /* Intializes a user table entry for for loaduser */
- /*--------------------------------------------------------------------*/
-
- struct UserTable *inituser(char *name)
- {
-
- size_t hit = UserElements;
- size_t element = 0;
-
- if (users == NULL)
- {
- users = calloc(MAXUSERS, sizeof(*users));
- checkref(users);
- }
-
- /*--------------------------------------------------------------------*/
- /* Add the user to the table. Note that we must add the user */
- /* to the table ourselves (rather than use lsearch) because we */
- /* must make a copy of the string; the *token we use for the */
- /* search is in the middle of our I/O buffer! */
- /*--------------------------------------------------------------------*/
-
- while ( element < hit )
- {
- if (equali( users[element].uid , name ))
- hit = element;
- else
- element++;
- }
-
- if (hit == UserElements)
- {
- users[hit].uid = strdup(name);
- checkref(users[hit].uid);
- users[hit].realname = "????";
- users[hit].beep = NULL;
- users[hit].homedir = pubdir;
- users[hit].hsecure = NULL;
- users[hit].password = NULL;
- users[hit].sh = uucpsh;
- assert(UserElements++ < MAXUSERS);
- } /* if */
-
- return &users[hit];
-
- } /* inituser */
-
- /*--------------------------------------------------------------------*/
- /* l o a d u s e r */
- /* */
- /* Load the user password file */
- /*--------------------------------------------------------------------*/
-
- static size_t loaduser( void )
- {
- char s_systems[FILENAME_MAX];
- FILE *stream;
- struct UserTable *userp;
- size_t hit;
- char buf[BUFSIZ];
- char *token;
-
- /*--------------------------------------------------------------------*/
- /* First, load in the active user as first user in the table */
- /*--------------------------------------------------------------------*/
-
- userp = inituser( mailbox );
- userp->realname = name;
- userp->homedir = homedir;
-
- /*--------------------------------------------------------------------*/
- /* Password file format: */
- /* user id:password:::user/system name:homedir:shell */
- /*--------------------------------------------------------------------*/
-
- mkfilename(s_systems, confdir, PASSWD);
-
- if ((stream = FOPEN(s_systems, "r", TEXT)) == NULL)
- {
- printmsg(2,"loaduser: Cannot open password file %s",s_systems);
- users = realloc(users, UserElements * sizeof(*users));
- checkref(users);
- return UserElements;
- } /* if */
-
- /*--------------------------------------------------------------------*/
- /* The password file is open; read it */
- /*--------------------------------------------------------------------*/
-
- while (! feof(stream)) {
- if (fgets(buf,BUFSIZ,stream) == NULL) /* Try to read a line */
- break; /* Exit if end of file */
- if ((*buf == '#') || (*buf == '\0'))
- continue; /* Line is a comment; loop again */
- if ( buf[ strlen(buf) - 1 ] == '\n')
- buf[ strlen(buf) - 1 ] = '\0';
- token = NextField(buf);
- if (token == NULL) /* Any data? */
- continue; /* No --> read another line */
- userp = inituser(token);/* Initialize record for user */
-
- if (userp->password != NULL) /* Does the user already exist? */
- { /* Yes --> Report and ignore */
- printmsg(0,"loaduser: Duplicate entry for '%s' in '%s' ignored",
- token,s_systems);
- continue; /* System already in /etc/passwd,
- ignore it. */
- }
-
- token = NextField(NULL); /* Get the user password */
- if (!equal(token,"*")) /* User can login? */
- userp->password = strdup(token); /* Yes --> Set password */
-
- token = NextField(NULL); /* Use UNIX user number as tone */
- /* to beep at */
- if (token != NULL)
- userp->beep = strdup( token );
-
- token = NextField(NULL); /* Skip UNIX group number */
-
- token = NextField(NULL); /* Get the formal user name */
- if (token != NULL) /* Did they provide user name? */
- userp->realname = strdup(token); /* Yes --> Copy */
-
- token = NextField(NULL); /* Get home directory (optional) */
- if ( token != NULL)
- userp->homedir = strdup(token);
-
- token = NextField(NULL); /* Get user shell (optional) */
- if ( token != NULL ) /* Did we get it? */
- userp->sh = strdup(token); /* Yes --> Copy it in */
-
- } /* while */
-
- fclose(stream);
- users = realloc(users, UserElements * sizeof(*users));
- checkref(users);
-
- qsort(users, UserElements ,sizeof(users[0]) , usercmp);
-
- for (hit = 0 ; hit < UserElements; hit ++)
- {
- printmsg(8,"loaduser: user[%d] user id(%s) no(%s) name(%s) \
- home directory(%s) shell(%s)",
- hit,
- users[hit].uid,
- users[hit].beep == NULL ? "NONE" : users[hit].beep,
- users[hit].realname,
- users[hit].homedir,
- users[hit].sh);
- } /* for */
-
- return UserElements;
- } /* loaduser */
-
- /*--------------------------------------------------------------------*/
- /* u s e r c m p */
- /* */
- /* Accepts indirect pointers to two strings and compares */
- /* them using stricmp (case insensitive string compare) */
- /*--------------------------------------------------------------------*/
-
- int usercmp( const void *a , const void *b )
- {
- return stricmp(((struct UserTable*) a)->uid,
- ((struct UserTable*) b)->uid);
- } /*usercmp*/
-
- /*--------------------------------------------------------------------*/
- /* n e x t f i e l d */
- /* */
- /* Find the next field in the user password file */
- /*--------------------------------------------------------------------*/
-
- char *NextField( char *input )
- {
- static char *start = NULL;
- char *next = NULL;
-
- if (input == NULL) /* Starting a new field? */
- {
- if ( start == NULL ) /* Anything left to parse? */
- return NULL; /* No --> Return empty string */
- else
- input = start; /* Yes --> Continue parse of old one */
- } /* if */
-
- /*--------------------------------------------------------------------*/
- /* Look for the next field; because MS-DOS directories may have */
- /* a sequence of x:/ or x:\ where 'x' is a drive letter, we take */
- /* special care to allow DOS directories to appear unmolested */
- /* in the password file */
- /*--------------------------------------------------------------------*/
-
- if ((strlen(input) > 2) && isalpha(input[0]) && (input[1] == ':') &&
- ((input[2] == '/') || (input[2] == '\\')))
- next = strchr( &input[2], ':'); /* Find start of next field */
- else
- next = strchr( input, ':'); /* Find start of next field */
-
- if (next == NULL ) /* Last field? */
- start = NULL; /* Yes --> Make next call return NULL */
- else { /* No */
- *next = '\0'; /* Terminate the string */
- start = ++next; /* Have next call look at next field */
- } /* else */
-
- if (strlen(input)) /* Did we get anything in the field? */
- return input; /* Yes --> Return the string */
- else
- return NULL; /* Field is empty, return NULL */
-
- } /* NextField */
-