pwupd.c revision 20302
1139804Simp/*-
2185435Sbz * Copyright (C) 1996
3185435Sbz *	David L. Nugent.  All rights reserved.
4191673Sjamie *
5185435Sbz * Redistribution and use in source and binary forms, with or without
6190466Sjamie * modification, are permitted provided that the following conditions
7185404Sbz * are met:
8185404Sbz * 1. Redistributions of source code must retain the above copyright
9185404Sbz *    notice, this list of conditions and the following disclaimer.
10185404Sbz * 2. Redistributions in binary form must reproduce the above copyright
11185404Sbz *    notice, this list of conditions and the following disclaimer in the
12185404Sbz *    documentation and/or other materials provided with the distribution.
13185404Sbz *
14185404Sbz * THIS SOFTWARE IS PROVIDED BY DAVID L. NUGENT AND CONTRIBUTORS ``AS IS'' AND
15185404Sbz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16185404Sbz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17185404Sbz * ARE DISCLAIMED.  IN NO EVENT SHALL DAVID L. NUGENT OR CONTRIBUTORS BE LIABLE
18185404Sbz * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19185404Sbz * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20185404Sbz * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21185404Sbz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22185404Sbz * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23185404Sbz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24185404Sbz * SUCH DAMAGE.
25185404Sbz *
26185404Sbz *	$Id: pwupd.c,v 1.1.1.2 1996/12/09 23:55:27 joerg Exp $
2746197Sphk */
2846155Sphk
29116182Sobrien#include <stdio.h>
30116182Sobrien#include <stdlib.h>
31116182Sobrien#include <string.h>
32193066Sjamie#include <unistd.h>
33185435Sbz#include <stdarg.h>
34185435Sbz#include <errno.h>
35185435Sbz#include <sys/types.h>
36131177Spjd#include <sys/stat.h>
3746155Sphk#include <sys/wait.h>
3846155Sphk#include <stdarg.h>
3946155Sphk
4046155Sphk#include "pwupd.h"
4146155Sphk
4246155Sphk#define HAVE_PWDB_C	1
4346155Sphk
44192895Sjamiestatic int
45164032Srwatsonpwdb(char *arg,...)
4646155Sphk{
47124882Srwatson	int             i = 0;
48177785Skib	pid_t           pid;
4946155Sphk	va_list         ap;
5087275Srwatson	char           *args[8];
5187275Srwatson
52220137Strasz	args[i++] = _PATH_PWD_MKDB;
53221362Strasz	va_start(ap, arg);
54168401Spjd	while (i < 6 && arg != NULL) {
55193066Sjamie		args[i++] = arg;
56113275Smike		arg = va_arg(ap, char *);
57147185Spjd	}
58113275Smike	args[i++] = _PATH_MASTERPASSWD;
5946155Sphk	args[i] = NULL;
60113275Smike
6157163Srwatson	if ((pid = fork()) == -1)	/* Error (errno set) */
62113275Smike		i = -1;
63196019Srwatson	else if (pid == 0) {	/* Child */
6446155Sphk		execv(args[0], args);
65196019Srwatson		_exit(1);
66196019Srwatson	} else {		/* Parent */
6746155Sphk		waitpid(pid, &i, 0);
68196019Srwatson		if ((i = WEXITSTATUS(i)) != 0)
69185435Sbz			errno = EIO;	/* set SOMETHING */
70185435Sbz	}
71185435Sbz	return i;
72185435Sbz}
73185435Sbz
74185435Sbzint
7546155Sphkfmtpwentry(char *buf, struct passwd * pwd, int type)
76163606Srwatson{
77163606Srwatson	int             l;
78195944Sjamie	char           *pw;
79195944Sjamie
8046155Sphk	pw = (pwd->pw_passwd == NULL || !*pwd->pw_passwd) ? "" : (type == PWF_MASTER) ? pwd->pw_passwd : "*";
81227293Sed
8246155Sphk	if (type == PWF_PASSWD)
83202468Sbz		l = sprintf(buf, "%s:*:%ld:%ld:%s:%s:%s\n",
84202468Sbz		       pwd->pw_name, (long) pwd->pw_uid, (long) pwd->pw_gid,
85202468Sbz			    pwd->pw_gecos ? pwd->pw_gecos : "User &",
86202468Sbz			    pwd->pw_dir, pwd->pw_shell);
87202468Sbz	else
88202468Sbz		l = sprintf(buf, "%s:%s:%ld:%ld:%s:%lu:%lu:%s:%s:%s\n",
89202468Sbz		   pwd->pw_name, pw, (long) pwd->pw_uid, (long) pwd->pw_gid,
90202468Sbz			    pwd->pw_class ? pwd->pw_class : "",
91202468Sbz			    (unsigned long) pwd->pw_change,
92202468Sbz			    (unsigned long) pwd->pw_expire,
93202468Sbz			    pwd->pw_gecos, pwd->pw_dir, pwd->pw_shell);
94202468Sbz	return l;
95202468Sbz}
96202468Sbz
97202468Sbz
98192895Sjamieint
99192895Sjamiefmtpwent(char *buf, struct passwd * pwd)
100192895Sjamie{
101192895Sjamie	return fmtpwentry(buf, pwd, PWF_STANDARD);
102192895Sjamie}
103192895Sjamie
104192895Sjamiestatic int
105192895Sjamiepw_update(struct passwd * pwd, char const * user, int mode)
106231267Smm{
107194762Sjamie	int             rc = 0;
108195944Sjamie
109201145Santoine	endpwent();
110196176Sbz
111202468Sbz	/*
112196176Sbz	 * First, let's check the see if the database is alright
113202468Sbz	 * Note: -c is only available in FreeBSD 2.2 and above
114196176Sbz	 */
115192895Sjamie#ifdef HAVE_PWDB_C
116192895Sjamie	if (pwdb("-c", NULL) == 0) {	/* Check only */
117192895Sjamie#else
11857163Srwatson	{				/* No -c */
119221362Strasz#endif
120168401Spjd		char            pfx[32];
121191673Sjamie		char            pwbuf[MAXPWLINE];
122191673Sjamie		int             l = sprintf(pfx, "%s:", user);
123221362Strasz
124179881Sdelphij		/*
125113275Smike		 * Update the passwd file first
126191673Sjamie		 */
127190466Sjamie		if (pwd == NULL)
128191673Sjamie			*pwbuf = '\0';
129192895Sjamie		else
130192895Sjamie			fmtpwentry(pwbuf, pwd, PWF_PASSWD);
131221362Strasz		if ((rc = fileupdate(_PATH_PASSWD, 0644, pwbuf, pfx, l, mode)) != 0) {
132221362Strasz
133232598Strasz			/*
134221362Strasz			 * Then the master.passwd file
135221362Strasz			 */
136185435Sbz			if (pwd != NULL)
137190466Sjamie				fmtpwentry(pwbuf, pwd, PWF_MASTER);
138192895Sjamie			if ((rc = fileupdate(_PATH_MASTERPASSWD, 0644, pwbuf, pfx, l, mode)) != 0)
139185435Sbz				rc = pwdb(NULL) == 0;
140185435Sbz		}
141190466Sjamie	}
142192895Sjamie	return rc;
143185435Sbz}
144113275Smike
145191673Sjamieint
146191673Sjamieaddpwent(struct passwd * pwd)
147191673Sjamie{
148191673Sjamie	return pw_update(pwd, pwd->pw_name, UPD_CREATE);
149191673Sjamie}
150191673Sjamie
151113275Smikeint
152192895Sjamiechgpwent(char const * login, struct passwd * pwd)
153216861Sbz{
154216861Sbz	return pw_update(pwd, login, UPD_REPLACE);
155216861Sbz}
156192895Sjamie
157192895Sjamieint
158192895Sjamiedelpwent(struct passwd * pwd)
159202468Sbz{
160202468Sbz	return pw_update(NULL, pwd->pw_name, UPD_DELETE);
161202468Sbz}
162202468Sbz