pwupd.c revision 20253
120253Sjoerg/*-
220253Sjoerg * Copyright (c) 1996 by David L. Nugent <davidn@blaze.net.au>.
320253Sjoerg * All rights reserved.
420253Sjoerg *
520253Sjoerg * Redistribution and use in source and binary forms, with or without
620253Sjoerg * modification, are permitted provided that the following conditions
720253Sjoerg * are met:
820253Sjoerg * 1. Redistributions of source code must retain the above copyright
920253Sjoerg *    notice, this list of conditions and the following disclaimer as
1020253Sjoerg *    the first lines of this file unmodified.
1120253Sjoerg * 2. Redistributions in binary form must reproduce the above copyright
1220253Sjoerg *    notice, this list of conditions and the following disclaimer in the
1320253Sjoerg *    documentation and/or other materials provided with the distribution.
1420253Sjoerg * 3. All advertising materials mentioning features or use of this software
1520253Sjoerg *    must display the following acknowledgement:
1620253Sjoerg *	This product includes software developed by David L. Nugent.
1720253Sjoerg * 4. The name of the author may not be used to endorse or promote products
1820253Sjoerg *    derived from this software without specific prior written permission.
1920253Sjoerg *
2020253Sjoerg * THIS SOFTWARE IS PROVIDED BY THE DAVID L. NUGENT ``AS IS'' AND
2120253Sjoerg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2220253Sjoerg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2320253Sjoerg * ARE DISCLAIMED.  IN NO EVENT SHALL DAVID L. NUGENT BE LIABLE
2420253Sjoerg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2520253Sjoerg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2620253Sjoerg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2720253Sjoerg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2820253Sjoerg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2920253Sjoerg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3020253Sjoerg * SUCH DAMAGE.
3120253Sjoerg *
3220253Sjoerg *	$Id$
3320253Sjoerg */
3420253Sjoerg
3520253Sjoerg#include <stdio.h>
3620253Sjoerg#include <stdlib.h>
3720253Sjoerg#include <string.h>
3820253Sjoerg#include <unistd.h>
3920253Sjoerg#include <stdarg.h>
4020253Sjoerg#include <errno.h>
4120253Sjoerg#include <sys/types.h>
4220253Sjoerg#include <sys/stat.h>
4320253Sjoerg#include <sys/wait.h>
4420253Sjoerg#include <stdarg.h>
4520253Sjoerg
4620253Sjoerg#include "pwupd.h"
4720253Sjoerg
4820253Sjoergstatic int
4920253Sjoergpwdb(char *arg,...)
5020253Sjoerg{
5120253Sjoerg	int             i = 0;
5220253Sjoerg	pid_t           pid;
5320253Sjoerg	va_list         ap;
5420253Sjoerg	char           *args[8];
5520253Sjoerg
5620253Sjoerg	args[i++] = _PATH_PWD_MKDB;
5720253Sjoerg	va_start(ap, arg);
5820253Sjoerg	while (i < 6 && arg != NULL) {
5920253Sjoerg		args[i++] = arg;
6020253Sjoerg		arg = va_arg(ap, char *);
6120253Sjoerg	}
6220253Sjoerg	args[i++] = _PATH_MASTERPASSWD;
6320253Sjoerg	args[i] = NULL;
6420253Sjoerg
6520253Sjoerg	if ((pid = fork()) == -1)	/* Error (errno set) */
6620253Sjoerg		i = -1;
6720253Sjoerg	else if (pid == 0) {	/* Child */
6820253Sjoerg		execv(args[0], args);
6920253Sjoerg		_exit(1);
7020253Sjoerg	} else {		/* Parent */
7120253Sjoerg		waitpid(pid, &i, 0);
7220253Sjoerg		if ((i = WEXITSTATUS(i)) != 0)
7320253Sjoerg			errno = EIO;	/* set SOMETHING */
7420253Sjoerg	}
7520253Sjoerg	return i;
7620253Sjoerg}
7720253Sjoerg
7820253Sjoergint
7920253Sjoergfmtpwentry(char *buf, struct passwd * pwd, int type)
8020253Sjoerg{
8120253Sjoerg	int             l;
8220253Sjoerg	char           *pw;
8320253Sjoerg
8420253Sjoerg	pw = (pwd->pw_passwd == NULL || !*pwd->pw_passwd) ? "" : (type == PWF_MASTER) ? pwd->pw_passwd : "*";
8520253Sjoerg
8620253Sjoerg	if (type == PWF_PASSWD)
8720253Sjoerg		l = sprintf(buf, "%s:*:%ld:%ld:%s:%s:%s\n",
8820253Sjoerg		       pwd->pw_name, (long) pwd->pw_uid, (long) pwd->pw_gid,
8920253Sjoerg			    pwd->pw_gecos ? pwd->pw_gecos : "User &",
9020253Sjoerg			    pwd->pw_dir, pwd->pw_shell);
9120253Sjoerg	else
9220253Sjoerg		l = sprintf(buf, "%s:%s:%ld:%ld:%s:%lu:%lu:%s:%s:%s\n",
9320253Sjoerg		   pwd->pw_name, pw, (long) pwd->pw_uid, (long) pwd->pw_gid,
9420253Sjoerg			    pwd->pw_class ? pwd->pw_class : "",
9520253Sjoerg			    (unsigned long) pwd->pw_change,
9620253Sjoerg			    (unsigned long) pwd->pw_expire,
9720253Sjoerg			    pwd->pw_gecos, pwd->pw_dir, pwd->pw_shell);
9820253Sjoerg	return l;
9920253Sjoerg}
10020253Sjoerg
10120253Sjoerg
10220253Sjoergint
10320253Sjoergfmtpwent(char *buf, struct passwd * pwd)
10420253Sjoerg{
10520253Sjoerg	return fmtpwentry(buf, pwd, PWF_STANDARD);
10620253Sjoerg}
10720253Sjoerg
10820253Sjoergstatic int
10920253Sjoergpw_update(struct passwd * pwd, char const * user, int mode)
11020253Sjoerg{
11120253Sjoerg	int             rc = 0;
11220253Sjoerg
11320253Sjoerg	endpwent();
11420253Sjoerg
11520253Sjoerg	/*
11620253Sjoerg	 * First, let's check the see if the database is alright
11720253Sjoerg	 */
11820253Sjoerg	if (pwdb("-c", NULL) == 0) {	/* Check only */
11920253Sjoerg		char            pfx[32];
12020253Sjoerg		char            pwbuf[MAXPWLINE];
12120253Sjoerg		int             l = sprintf(pfx, "%s:", user);
12220253Sjoerg
12320253Sjoerg		/*
12420253Sjoerg		 * Update the passwd file first
12520253Sjoerg		 */
12620253Sjoerg		if (pwd == NULL)
12720253Sjoerg			*pwbuf = '\0';
12820253Sjoerg		else
12920253Sjoerg			fmtpwentry(pwbuf, pwd, PWF_PASSWD);
13020253Sjoerg		if ((rc = fileupdate(_PATH_PASSWD, 0644, pwbuf, pfx, l, mode)) != 0) {
13120253Sjoerg
13220253Sjoerg			/*
13320253Sjoerg			 * Then the master.passwd file
13420253Sjoerg			 */
13520253Sjoerg			if (pwd != NULL)
13620253Sjoerg				fmtpwentry(pwbuf, pwd, PWF_MASTER);
13720253Sjoerg			if ((rc = fileupdate(_PATH_MASTERPASSWD, 0644, pwbuf, pfx, l, mode)) != 0)
13820253Sjoerg				rc = pwdb(NULL) == 0;
13920253Sjoerg		}
14020253Sjoerg	}
14120253Sjoerg	return rc;
14220253Sjoerg}
14320253Sjoerg
14420253Sjoergint
14520253Sjoergaddpwent(struct passwd * pwd)
14620253Sjoerg{
14720253Sjoerg	return pw_update(pwd, pwd->pw_name, UPD_CREATE);
14820253Sjoerg}
14920253Sjoerg
15020253Sjoergint
15120253Sjoergchgpwent(char const * login, struct passwd * pwd)
15220253Sjoerg{
15320253Sjoerg	return pw_update(pwd, login, UPD_REPLACE);
15420253Sjoerg}
15520253Sjoerg
15620253Sjoergint
15720253Sjoergdelpwent(struct passwd * pwd)
15820253Sjoerg{
15920253Sjoerg	return pw_update(NULL, pwd->pw_name, UPD_DELETE);
16020253Sjoerg}
161