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