AUSAM/source/libc/addpwent.c

#
/*
 *	This function adds the entry pointed to by "pe" to a
 *	password file. If the pointer at uidtable(pe->pw_uid)==NULL
 *	then this is the new uid. If not then new uid is allocated.
 *	Returns the new uid or -1 for error
 */

#include <local-system>
#include	<passwd.h>

char	pwfd, pwfl;
extern char	*etcpasswd;

addpwent(pe)
register struct pwent	*pe;
{

register struct pwent	*rp;

struct pwent p;
long	t, hte;
int	ht;
int	ri;


ri = -1;

/*	open and lock */

if( !pwfl)
	{
	if((pwfd=open(etcpasswd,2)) < 0) return (-1);
	pwfl++;
	}
writelock(pwfd);

/*	initialise */

do	{
	rp = &p;
	pe->pw_next = PWENTNULL;
	ht=pwhash(pe->pw_strings[LNAME]);
	if( !gethtab(pwfd,ht,&pe->pw_last)) break;
	
	/*	now list from "pe->pw_last" may/maynot be null and
		may/maynot contain the entry.	*/
	
	if( chkentry(pwfd,pe,&pe->pw_last) < 1) break;
	
	/*	now "pe->pw_last" is the seek address for the last list element
		or "PWENTNULL" for a null list	*/
	
	if(( !getutab(pwfd,pe->pw_uid,&hte)) || (hte != PWENTNULL))
		{
		if((pe->pw_uid=freetable(pwfd)) < 0) break;
		}
	
	if(pe->pw_last == PWENTNULL)
		{
		/* no list, so just add it in */
		if(addentry(pwfd,pe,&t) <= 0) break;
		if(!puthtab(pwfd,ht,&t)) break;
		if(!pututab(pwfd,pe->pw_uid,&t)) break;
		}
	  else
		{
		/* here for a list at least one long, so ad on at end */
		if(!getentry(pwfd,rp,&pe->pw_last)) break;
		if(addentry(pwfd,pe,&rp->pw_next) <= 0) break;
		/* now "pe->pw_last" contains the seek address of the last list
		   element stored in "p". "rp->pw_next" contains the seek address
		   for the new element contained in "*pe". "pe->pw_uid" is the
		   new uid, and only remains to write data out */
		if(!pututab(pwfd,pe->pw_uid,&rp->pw_next)) break;
		if(!putentry(pwfd,rp,&pe->pw_last)) break;
		}
	
	/*	return uid and that is all */
	
	ri=pe->pw_uid;
	} while(0);

unlock();

return(ri);
}