storepwent.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 257 行

C
257
字号
#ifndef lintstatic	char	*sccsid = "@(#)storepwent.c	4.1	(ULTRIX)	7/2/90";#endif lint/************************************************************************ *									* *			Copyright (c) 1989 by				* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************//* * Modification history * * 6-Sep-89 D. A. Long *	Replace getpwent_local() with straight read of /etc/passwd (or file *	set if setpwfile() call). Using getpwent causes YP entries to be lost. * * 25-Jul-89 D. A. Long *	Fixed to make a copy of incoming passwd struct which would otherwise *	probably get clobbered by the first call to getpw*().  Notice when *	this function returns the incoming pwd will probably point to *	something else.  Also fixed error returns.  Also, use local versions *	of getpwent routines. * * 18-Jul-89 D. A. Long *	Ignore the data base if it is not present.  Update just the ASCII file. */#include <sys/errno.h>#include <sys/param.h>#include <sys/file.h>#include <stdio.h>#include <pwd.h>#include <ndbm.h>extern char _pw_file[];extern DBM *_pw_db;extern struct passwd *getpwent_local();extern char *malloc();/* * Define to allocate and copy a string. */#define	scopy(in,out)	{ if(in) { out=malloc(strlen(in)+1); strcpy(out, in);} \	else out=(char *)0; }/* * Internal function to make a copy of a passwd structure. */static pcopy(in, out)struct passwd *in, *out;{	scopy(in->pw_name, out->pw_name);	scopy(in->pw_passwd, out->pw_passwd);	out->pw_uid = in->pw_uid;	out->pw_gid = in->pw_gid;#ifndef	SYSTEM_FIVE	out->pw_quota = in->pw_quota;#else	scopy(in->pw_age, out->pw_age);#endif	SYSTEM_FIVE	scopy(in->pw_comment, out->pw_comment);	scopy(in->pw_gecos, out->pw_gecos);	scopy(in->pw_dir, out->pw_dir);	scopy(in->pw_shell, out->pw_shell);}/* * Internal function to safely get a line from the named stream.  If * the line is too long to fit into the buffer it is thrown away and a * new line is fetched until successful or end-of-file. */static char *getline(string, len, file)char *string;int len;FILE *file;{	register char *s;	int c;	while(s=fgets(string, len, file))		if(strchr(string, '\n'))			break;		else			while((c=getc(file)) != EOF && c != '\n') ;	return s;}/* * Returns -1 for fail and 0 for success. */int storepwent(pwd)struct passwd *pwd;{	datum key, content;	struct passwd *pass, pwd_save;	char *cp, *tp, line[BUFSIZ+1], *tmpfile = "/etc/ptmp";	char string[BUFSIZ+1];	FILE *tfp, *pfp;	int i, tfd, acctlen;	pcopy(pwd, &pwd_save);	pwd = &pwd_save;	if(!(pfp=fopen(_pw_file, "r")))		return -1;	for(i=1; i <= 5; i++)		if((tfd=open(tmpfile, O_RDWR|O_EXCL|O_CREAT, 0644)) < 0){			if(errno == EEXIST) {				sleep(i);				continue;			} else				break;		} else			break;	if(tfd < 0) {		fclose(pfp);		return -1;	}	if(!(tfp=fdopen(tfd, "w"))) {		close(tfd);		unlink(tmpfile);		fclose(pfp);		return -1;	}	if(_pw_db) {		dbm_close(_pw_db);		_pw_db = (DBM *) NULL;	}	if((_pw_db=dbm_open(_pw_file, O_RDWR, 0))) {		if (flock(dbm_dirfno(_pw_db), LOCK_EX) < 0) {			fclose(tfp);			unlink(tmpfile);			dbm_close(_pw_db);			_pw_db = (DBM *)0;			fclose(pfp);			return -1;		}	}	acctlen = strlen(pwd->pw_name);	while(getline(string, sizeof string, pfp)) {		i = strcspn(string, ":\n");		if(i == acctlen && !strncmp(pwd->pw_name, string, i)) {			fprintf(tfp, "%s:%s:%d:%d:%s:%s:%s\n",				pwd->pw_name, pwd->pw_passwd, pwd->pw_uid,				pwd->pw_gid, pwd->pw_gecos, pwd->pw_dir,				pwd->pw_shell);/*	There's a bug in putpwent.  It treats negative UIDs as unsigned.			putpwent(pwd, tfp);*/			if(_pw_db && *string != '+' && *string != '-') {			cp = line;#define	COMPACT(e)	tp = pwd->pw_/**/e; while (*cp++ = *tp++);			COMPACT(name);			COMPACT(passwd);			i = pwd->pw_uid;			bcopy(&i, cp, sizeof i);			cp += sizeof i;			i = pwd->pw_gid;			bcopy(&i, cp, sizeof i);			cp += sizeof i;			i = pwd->pw_quota;			bcopy(&i, cp, sizeof i);			cp += sizeof i;			COMPACT(comment);			COMPACT(gecos);			COMPACT(dir);			COMPACT(shell);			content.dptr = line;			content.dsize = cp - line;			key.dptr = pwd->pw_name;			key.dsize = strlen(pwd->pw_name);			if (dbm_store(_pw_db, key, content, DBM_REPLACE) < 0) {				fclose(tfp);				unlink(tmpfile);				(void) flock(dbm_dirfno(_pw_db), LOCK_UN);				dbm_close(_pw_db);				_pw_db = (DBM *) 0;				fclose(pfp);				return -1;			}			i = pwd->pw_uid;			key.dptr = (char *)&i;			key.dsize = sizeof i;			if (dbm_store(_pw_db, key, content, DBM_REPLACE) < 0) {				fclose(tfp);				unlink(tmpfile);				(void) flock(dbm_dirfno(_pw_db), LOCK_UN);				dbm_close(_pw_db);				_pw_db = (DBM *) 0;				fclose(pfp);				return -1;			}			}		} else			fputs(string, tfp);	}	if(ferror(tfp)) {		fclose(tfp);		unlink(tmpfile);		if(_pw_db) {			(void) flock(dbm_dirfno(_pw_db), LOCK_UN);			dbm_close(_pw_db);			_pw_db = (DBM *) 0;		}		fclose(pfp);		return -1;	}	if(fclose(tfp)) {		unlink(tmpfile);		if(_pw_db) {			(void) flock(dbm_dirfno(_pw_db), LOCK_UN);			dbm_close(_pw_db);			_pw_db = (DBM *) 0;		}		fclose(pfp);		return -1;	}	if(rename(tmpfile, _pw_file) < 0) {		unlink(tmpfile);		if(_pw_db) {			(void) flock(dbm_dirfno(_pw_db), LOCK_UN);			dbm_close(_pw_db);			_pw_db = (DBM *) 0;		}		fclose(pfp);		return -1;	}	if(_pw_db) {		(void) flock(dbm_dirfno(_pw_db), LOCK_UN);		dbm_close(_pw_db);		_pw_db = (DBM *) 0;	}	fclose(pfp);	return 0;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?