home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Beijing Paradise BBS Backup
/
PARADISE.ISO
/
software
/
BBSDOORW
/
UUPC11XS.ZIP
/
LIB
/
USERTABL.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-11-27
|
12KB
|
328 lines
/*--------------------------------------------------------------------*/
/* 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 */
/*--------------------------------------------------------------------*/
/*
* $Id: USERTABL.C 1.2 1992/11/22 20:58:55 ahd Exp $
*
* $Log: USERTABL.C $
* Revision 1.2 1992/11/22 20:58:55 ahd
* Use strpool to allocate const strings
* Normalize directories as read
*
*/
#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 "expath.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 = newstr(name);
checkref(users[hit].uid);
users[hit].realname = "????";
users[hit].beep = NULL;
users[hit].homedir = E_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( E_mailbox );
userp->realname = E_name;
userp->homedir = E_homedir;
/*--------------------------------------------------------------------*/
/* Password file format: */
/* user id:password:::user/system name:homedir:shell */
/*--------------------------------------------------------------------*/
mkfilename(s_systems, E_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 = newstr(token); /* Yes --> Set password */
token = NextField(NULL); /* Use UNIX user number as tone */
/* to beep at */
if (token != NULL)
userp->beep = newstr( 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 = newstr(token); /* Yes --> Copy */
token = NextField(NULL); /* Get home directory (optional) */
if ( token != NULL)
userp->homedir = newstr(normalize( token ));
token = NextField(NULL); /* Get user shell (optional) */
if ( token != NULL ) /* Did we get it? */
userp->sh = newstr(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 */