pwupd.c revision 52511
166864Sadrian/*-
266864Sadrian * Copyright (C) 1996
366864Sadrian *	David L. Nugent.  All rights reserved.
466864Sadrian *
566864Sadrian * Redistribution and use in source and binary forms, with or without
666864Sadrian * modification, are permitted provided that the following conditions
766864Sadrian * are met:
866864Sadrian * 1. Redistributions of source code must retain the above copyright
966864Sadrian *    notice, this list of conditions and the following disclaimer.
1066864Sadrian * 2. Redistributions in binary form must reproduce the above copyright
1166864Sadrian *    notice, this list of conditions and the following disclaimer in the
1266864Sadrian *    documentation and/or other materials provided with the distribution.
1366864Sadrian *
1466864Sadrian * THIS SOFTWARE IS PROVIDED BY DAVID L. NUGENT AND CONTRIBUTORS ``AS IS'' AND
1566864Sadrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1666864Sadrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1766864Sadrian * ARE DISCLAIMED.  IN NO EVENT SHALL DAVID L. NUGENT OR CONTRIBUTORS BE LIABLE
1866864Sadrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1966864Sadrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2066864Sadrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2166864Sadrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2266864Sadrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2366864Sadrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2466864Sadrian * SUCH DAMAGE.
2566864Sadrian */
2666864Sadrian
2766864Sadrian#ifndef lint
2866864Sadrianstatic const char rcsid[] =
2966864Sadrian  "$FreeBSD: head/usr.sbin/pw/pwupd.c 52511 1999-10-26 08:30:20Z davidn $";
30114589Sobrien#endif /* not lint */
3166864Sadrian
3266864Sadrian#include <stdio.h>
33114589Sobrien#include <stdlib.h>
3466864Sadrian#include <string.h>
35114589Sobrien#include <unistd.h>
36114589Sobrien#include <stdarg.h>
3766864Sadrian#include <errno.h>
3866864Sadrian#include <sys/types.h>
39107671Siedowse#include <sys/stat.h>
4066864Sadrian#include <sys/param.h>
4186514Siedowse#include <sys/wait.h>
42221233Sdes
4398542Smckusick#include "pwupd.h"
44221233Sdes
4566864Sadrian#define HAVE_PWDB_C	1
4666864Sadrian
4766864Sadrianstatic char pathpwd[] = _PATH_PWD;
4866864Sadrianstatic char * pwpath = pathpwd;
4966864Sadrian
5066864Sadrianint
5166864Sadriansetpwdir(const char * dir)
5266864Sadrian{
5366864Sadrian	if (dir == NULL)
5466864Sadrian		return -1;
5566864Sadrian	else {
56101037Smux		char * d = malloc(strlen(dir)+1);
5766864Sadrian		if (d == NULL)
5866864Sadrian			return -1;
59249788Smckusick		pwpath = strcpy(d, dir);
6066864Sadrian	}
6166864Sadrian	return 0;
6266864Sadrian}
6366864Sadrian
64107671Siedowsechar *
65107671Siedowsegetpwpath(char const * file)
66249788Smckusick{
67107671Siedowse	static char pathbuf[MAXPATHLEN];
68249788Smckusick
69249788Smckusick	snprintf(pathbuf, sizeof pathbuf, "%s/%s", pwpath, file);
70107671Siedowse	return pathbuf;
71107671Siedowse}
72107671Siedowse
73249788Smckusickint
74248628Smckusickpwdb(char *arg,...)
75248628Smckusick{
76249788Smckusick	int             i = 0;
7766864Sadrian	pid_t           pid;
7866864Sadrian	va_list         ap;
7998542Smckusick	char           *args[10];
8066864Sadrian
8198542Smckusick	args[i++] = _PATH_PWD_MKDB;
8266864Sadrian	va_start(ap, arg);
8366864Sadrian	while (i < 6 && arg != NULL) {
8466864Sadrian		args[i++] = arg;
8566864Sadrian		arg = va_arg(ap, char *);
8666864Sadrian	}
8766864Sadrian	if (pwpath != pathpwd) {
8866864Sadrian		args[i++] = "-d";
8966864Sadrian		args[i++] = pwpath;
9066864Sadrian	}
9166864Sadrian	args[i++] = getpwpath(_MASTERPASSWD);
9266864Sadrian	args[i] = NULL;
9366864Sadrian
9498542Smckusick	if ((pid = fork()) == -1)	/* Error (errno set) */
9566864Sadrian		i = errno;
9666864Sadrian	else if (pid == 0) {	/* Child */
9766864Sadrian		execv(args[0], args);
9866864Sadrian		_exit(1);
9966864Sadrian	} else {		/* Parent */
100100935Sphk		waitpid(pid, &i, 0);
10166864Sadrian		if (WEXITSTATUS(i))
10266864Sadrian			i = EIO;
10366864Sadrian	}
10466864Sadrian	return i;
10566864Sadrian}
10666864Sadrian
10766864Sadrianint
10866864Sadrianfmtpwentry(char *buf, struct passwd * pwd, int type)
10974556Smckusick{
11066864Sadrian	int             l;
11166864Sadrian	char           *pw;
11266864Sadrian
11366864Sadrian	pw = (pwd->pw_passwd == NULL || !*pwd->pw_passwd) ? "" : (type == PWF_MASTER) ? pwd->pw_passwd : "*";
11466864Sadrian
11566864Sadrian	if (type == PWF_PASSWD)
11666864Sadrian		l = sprintf(buf, "%s:*:%ld:%ld:%s:%s:%s\n",
11766864Sadrian		       pwd->pw_name, (long) pwd->pw_uid, (long) pwd->pw_gid,
11866864Sadrian			    pwd->pw_gecos ? pwd->pw_gecos : "User &",
11966864Sadrian			    pwd->pw_dir, pwd->pw_shell);
12066864Sadrian	else
12166864Sadrian		l = sprintf(buf, "%s:%s:%ld:%ld:%s:%lu:%lu:%s:%s:%s\n",
12266864Sadrian		   pwd->pw_name, pw, (long) pwd->pw_uid, (long) pwd->pw_gid,
12366864Sadrian			    pwd->pw_class ? pwd->pw_class : "",
12466864Sadrian			    (unsigned long) pwd->pw_change,
12566864Sadrian			    (unsigned long) pwd->pw_expire,
12666864Sadrian			    pwd->pw_gecos, pwd->pw_dir, pwd->pw_shell);
12766864Sadrian	return l;
12866864Sadrian}
12966864Sadrian
13066864Sadrian
13166864Sadrianint
13266864Sadrianfmtpwent(char *buf, struct passwd * pwd)
13366864Sadrian{
13466864Sadrian	return fmtpwentry(buf, pwd, PWF_STANDARD);
13566864Sadrian}
13666864Sadrian
13766864Sadrianstatic int
13866864Sadrianpw_update(struct passwd * pwd, char const * user, int mode)
13966864Sadrian{
14092839Simp	int             rc = 0;
14166864Sadrian
14266864Sadrian	ENDPWENT();
14366864Sadrian
14466864Sadrian	/*
14566864Sadrian	 * First, let's check the see if the database is alright
14666864Sadrian	 * Note: -C is only available in FreeBSD 2.2 and above
14766864Sadrian	 */
14866864Sadrian#ifdef HAVE_PWDB_C
14966864Sadrian	if (pwdb("-C", NULL) == 0) {	/* Check only */
15066864Sadrian#else
15166864Sadrian	{				/* No -C */
15266864Sadrian#endif
15366864Sadrian		char            pfx[32];
15466864Sadrian		char            pwbuf[PWBUFSZ];
15566864Sadrian		int             l = sprintf(pfx, "%s:", user);
15666864Sadrian
15766864Sadrian		/*
15866864Sadrian		 * Update the passwd file first
15992839Simp		 */
16066864Sadrian		if (pwd == NULL)
16192806Sobrien			*pwbuf = '\0';
16266864Sadrian		else
16366864Sadrian			fmtpwentry(pwbuf, pwd, PWF_PASSWD);
16466864Sadrian
16566864Sadrian		rc = fileupdate(getpwpath(_PASSWD), 0644, pwbuf, pfx, l, mode);
166249788Smckusick		if (rc == 0) {
16766864Sadrian
16866864Sadrian			/*
16966864Sadrian			 * Then the master.passwd file
170249788Smckusick			 */
171248628Smckusick			if (pwd != NULL)
172248628Smckusick				fmtpwentry(pwbuf, pwd, PWF_MASTER);
17366864Sadrian			rc = fileupdate(getpwpath(_MASTERPASSWD), 0644, pwbuf, pfx, l, mode);
17466864Sadrian			if (rc == 0) {
17566864Sadrian				if (mode == UPD_DELETE)
176249788Smckusick					rc = pwdb(NULL);
177249788Smckusick				else
17866864Sadrian					rc = pwdb("-u", user, NULL);
17966864Sadrian			}
18066864Sadrian		}
18166864Sadrian	}
18266864Sadrian	return rc;
18366864Sadrian}
184248628Smckusick
185249788Smckusickint
18666864Sadrianaddpwent(struct passwd * pwd)
187248628Smckusick{
188249788Smckusick	return pw_update(pwd, pwd->pw_name, UPD_CREATE);
189249788Smckusick}
190249788Smckusick
191249788Smckusickint
192249788Smckusickchgpwent(char const * login, struct passwd * pwd)
19366864Sadrian{
19466864Sadrian	return pw_update(pwd, login, UPD_REPLACE);
19566864Sadrian}
196249788Smckusick
197249788Smckusickint
198249788Smckusickdelpwent(struct passwd * pwd)
199249788Smckusick{
200249788Smckusick	return pw_update(NULL, pwd->pw_name, UPD_DELETE);
201249788Smckusick}
202249788Smckusick