]> git.cameronkatri.com Git - pw-darwin.git/blobdiff - pw/pwupd.c
Do not let pw.conf(5) or -M option affect creation of basehome, e.g., /home.
[pw-darwin.git] / pw / pwupd.c
index 1162d0ce9a1c60cf97ea7939b3ed3f63826912cc..cb8456d9e7c868badb0d5476ae0917f4b1b06910 100644 (file)
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- *
- *     $Id$
  */
 
+#ifndef lint
+static const char rcsid[] =
+  "$FreeBSD$";
+#endif /* not lint */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/param.h>
 #include <sys/wait.h>
 
 #include "pwupd.h"
 
 #define HAVE_PWDB_C    1
+#define        HAVE_PWDB_U     1
 
-static int
+static char pathpwd[] = _PATH_PWD;
+static char * pwpath = pathpwd;
+int
+setpwdir(const char * dir)
+{
+       if (dir == NULL)
+               return -1;
+       else {
+               char * d = malloc(strlen(dir)+1);
+               if (d == NULL)
+                       return -1;
+               pwpath = strcpy(d, dir);
+       }
+       return 0;
+}
+
+char *
+getpwpath(char const * file)
+{
+       static char pathbuf[MAXPATHLEN];
+
+       snprintf(pathbuf, sizeof pathbuf, "%s/%s", pwpath, file);
+       return pathbuf;
+}
+
+int
 pwdb(char *arg,...)
 {
        int             i = 0;
        pid_t           pid;
        va_list         ap;
-       char           *args[8];
+       char           *args[10];
 
        args[i++] = _PATH_PWD_MKDB;
        va_start(ap, arg);
@@ -54,18 +85,22 @@ pwdb(char *arg,...)
                args[i++] = arg;
                arg = va_arg(ap, char *);
        }
-       args[i++] = _PATH_MASTERPASSWD;
+       if (pwpath != pathpwd) {
+               args[i++] = "-d";
+               args[i++] = pwpath;
+       }
+       args[i++] = getpwpath(_MASTERPASSWD);
        args[i] = NULL;
 
        if ((pid = fork()) == -1)       /* Error (errno set) */
-               i = -1;
+               i = errno;
        else if (pid == 0) {    /* Child */
                execv(args[0], args);
                _exit(1);
        } else {                /* Parent */
                waitpid(pid, &i, 0);
-               if ((i = WEXITSTATUS(i)) != 0)
-                       errno = EIO;    /* set SOMETHING */
+               if (WEXITSTATUS(i))
+                       i = EIO;
        }
        return i;
 }
@@ -76,7 +111,8 @@ fmtpwentry(char *buf, struct passwd * pwd, int type)
        int             l;
        char           *pw;
 
-       pw = (pwd->pw_passwd == NULL || !*pwd->pw_passwd) ? "" : (type == PWF_MASTER) ? pwd->pw_passwd : "*";
+       pw = (type == PWF_MASTER) ?
+           ((pwd->pw_passwd == NULL) ? "" : pwd->pw_passwd) : "*";
 
        if (type == PWF_PASSWD)
                l = sprintf(buf, "%s:*:%ld:%ld:%s:%s:%s\n",
@@ -105,20 +141,24 @@ pw_update(struct passwd * pwd, char const * user, int mode)
 {
        int             rc = 0;
 
-       endpwent();
+       ENDPWENT();
 
        /*
         * First, let's check the see if the database is alright
-        * Note: -c is only available in FreeBSD 2.2 and above
+        * Note: -C is only available in FreeBSD 2.2 and above
         */
 #ifdef HAVE_PWDB_C
-       if (pwdb("-c", NULL) == 0) {    /* Check only */
+       rc = pwdb("-C", (char *)NULL);  /* Check only */
+       if (rc == 0) {
 #else
-       {                               /* No -c */
+       {                               /* No -C */
 #endif
-               char            pfx[32];
+               char            pfx[PWBUFSZ];
                char            pwbuf[PWBUFSZ];
-               int             l = sprintf(pfx, "%s:", user);
+               int             l = snprintf(pfx, PWBUFSZ, "%s:", user);
+#ifdef HAVE_PWDB_U
+               int             isrename = pwd!=NULL && strcmp(user, pwd->pw_name);
+#endif
 
                /*
                 * Update the passwd file first
@@ -127,15 +167,28 @@ pw_update(struct passwd * pwd, char const * user, int mode)
                        *pwbuf = '\0';
                else
                        fmtpwentry(pwbuf, pwd, PWF_PASSWD);
-               if ((rc = fileupdate(_PATH_PASSWD, 0644, pwbuf, pfx, l, mode)) != 0) {
+
+               if (l < 0)
+                       l = 0;
+               rc = fileupdate(getpwpath(_PASSWD), 0644, pwbuf, pfx, l, mode);
+               if (rc == 0) {
 
                        /*
                         * Then the master.passwd file
                         */
                        if (pwd != NULL)
                                fmtpwentry(pwbuf, pwd, PWF_MASTER);
-                       if ((rc = fileupdate(_PATH_MASTERPASSWD, 0644, pwbuf, pfx, l, mode)) != 0)
-                               rc = pwdb(NULL) == 0;
+                       rc = fileupdate(getpwpath(_MASTERPASSWD), 0600, pwbuf, pfx, l, mode);
+                       if (rc == 0) {
+#ifdef HAVE_PWDB_U
+                               if (mode == UPD_DELETE || isrename)
+#endif
+                                       rc = pwdb(NULL);
+#ifdef HAVE_PWDB_U
+                               else
+                                       rc = pwdb("-u", user, (char *)NULL);
+#endif
+                       }
                }
        }
        return rc;