Syncronise some build files with busybox-cvs-20030819
[oweals/busybox.git] / loginutils / adduser.c
index 3485611cc690f651f5b316f2697eb1e1abf1b895..41dc9f0193202d3ce1e29e61aea5ed31e60007e0 100644 (file)
@@ -21,6 +21,9 @@
  *
  */
 
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
 #include <errno.h>
 #include <fcntl.h>
 #include <stdarg.h>
@@ -29,6 +32,7 @@
 #include <string.h>
 #include <time.h>
 #include <unistd.h>
+#include <getopt.h>
 #include <sys/param.h>
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -66,7 +70,7 @@ static int passwd_study(const char *filename, struct passwd *p)
        const int min = 500;
        const int max = 65000;
 
-       passwd = wfopen(filename, "r");
+       passwd = bb_wfopen(filename, "r");
        if (!passwd)
                return 4;
 
@@ -89,21 +93,23 @@ static int passwd_study(const char *filename, struct passwd *p)
                }
        }
 
-       /* EDR check for an already existing gid */
-       while (getgrgid(p->pw_uid) != NULL)
-               p->pw_uid++;
+       if (p->pw_gid == 0) {
+               /* EDR check for an already existing gid */
+               while (getgrgid(p->pw_uid) != NULL)
+                       p->pw_uid++;
+
+               /* EDR also check for an existing group definition */
+               if (getgrnam(p->pw_name) != NULL)
+                       return 3;
 
-       /* EDR also check for an existing group definition */
-       if (getgrnam(p->pw_name) != NULL)
-               return 3;
+               /* EDR create new gid always = uid */
+               p->pw_gid = p->pw_uid;
+       }
 
        /* EDR bounds check */
        if ((p->pw_uid > max) || (p->pw_uid < min))
                return 2;
 
-       /* EDR create new gid always = uid */
-       p->pw_gid = p->pw_uid;
-
        /* return 1; */
        return 0;
 }
@@ -112,7 +118,7 @@ static void addgroup_wrapper(const char *login, gid_t gid)
 {
        char *cmd;
 
-       bb_asprintf(&cmd, "addgroup -g %d %s", gid, login);
+       bb_xasprintf(&cmd, "addgroup -g %d %s", gid, login);
        system(cmd);
        free(cmd);
 }
@@ -123,11 +129,11 @@ static void passwd_wrapper(const char *login)
 {
        static const char prog[] = "passwd";
        execlp(prog, prog, login, NULL);
-       error_msg_and_die("Failed to execute '%s', you must set the password for '%s' manually", prog, login);
+       bb_error_msg_and_die("Failed to execute '%s', you must set the password for '%s' manually", prog, login);
 }
 
 /* putpwent(3) remix */
-static int adduser(const char *filename, struct passwd *p)
+static int adduser(const char *filename, struct passwd *p, int makehome, int setpass)
 {
        FILE *passwd;
        int r;
@@ -135,9 +141,14 @@ static int adduser(const char *filename, struct passwd *p)
        FILE *shadow;
        struct spwd *sp;
 #endif
+       int new_group = 1;
+
+       /* if using a pre-existing group, don't create one */
+       if (p->pw_gid != 0)
+               new_group = 0;
 
        /* make sure everything is kosher and setup uid && gid */
-       passwd = wfopen(filename, "a");
+       passwd = bb_wfopen(filename, "a");
        if (passwd == NULL) {
                return 1;
        }
@@ -147,13 +158,13 @@ static int adduser(const char *filename, struct passwd *p)
        r = passwd_study(filename, p);
        if (r) {
                if (r == 1)
-                       error_msg("%s: login already in use", p->pw_name);
+                       bb_error_msg("%s: login already in use", p->pw_name);
                else if (r == 2)
-                       error_msg("illegal uid or no uids left");
+                       bb_error_msg("illegal uid or no uids left");
                else if (r == 3)
-                       error_msg("group name %s already in use", p->pw_name);
+                       bb_error_msg("group name %s already in use", p->pw_name);
                else
-                       error_msg("generic error.");
+                       bb_error_msg("generic error.");
                return 1;
        }
 
@@ -166,7 +177,7 @@ static int adduser(const char *filename, struct passwd *p)
 #ifdef CONFIG_FEATURE_SHADOWPASSWDS
        /* add to shadow if necessary */
        if (shadow_enabled) {
-               shadow = wfopen(shadow_file, "a");
+               shadow = bb_wfopen(bb_path_shadow_file, "a");
                if (shadow == NULL) {
                        return 1;
                }
@@ -181,38 +192,56 @@ static int adduser(const char *filename, struct passwd *p)
        }
 #endif
 
-       /* add to group */
-       /* addgroup should be responsible for dealing w/ gshadow */
-       addgroup_wrapper(p->pw_name, p->pw_gid);
+       if (new_group) {
+               /* add to group */
+               /* addgroup should be responsible for dealing w/ gshadow */
+               addgroup_wrapper(p->pw_name, p->pw_gid);
+       }
 
        /* Clear the umask for this process so it doesn't
         * * screw up the permissions on the mkdir and chown. */
        umask(0);
 
-       /* mkdir */
-       if (mkdir(p->pw_dir, 0755)) {
-               perror_msg("%s", p->pw_dir);
-       }
-       /* Set the owner and group so it is owned by the new user. */
-       if (chown(p->pw_dir, p->pw_uid, p->pw_gid)) {
-               perror_msg("%s", p->pw_dir);
+       if (makehome) {
+               /* mkdir */
+               if (mkdir(p->pw_dir, 0755)) {
+                       bb_perror_msg("%s", p->pw_dir);
+               }
+               /* Set the owner and group so it is owned by the new user. */
+               if (chown(p->pw_dir, p->pw_uid, p->pw_gid)) {
+                       bb_perror_msg("%s", p->pw_dir);
+               }
+               /* Now fix up the permissions to 2755. Can't do it before now
+                * since chown will clear the setgid bit */
+               if (chmod(p->pw_dir, 02755)) {
+                       bb_perror_msg("%s", p->pw_dir);
+               }
        }
-       /* Now fix up the permissions to 2755. Can't do it before now
-        * since chown will clear the setgid bit */
-       if (chmod(p->pw_dir, 02755)) {
-               perror_msg("%s", p->pw_dir);
+
+       if (setpass) {
+               /* interactively set passwd */
+               passwd_wrapper(p->pw_name);
        }
-       /* interactively set passwd */
-       passwd_wrapper(p->pw_name);
+
+       return 0;
 }
 
 
 /* return current uid (root is always uid == 0, right?) */
-static inline uid_t i_am_not_root(void)
+#ifndef CONFIG_ADDGROUP
+static inline void if_i_am_not_root(void)
+#else
+void if_i_am_not_root(void)
+#endif
 {
-       return geteuid();
+       if (geteuid()) {
+               bb_error_msg_and_die( "Only root may add a user or group to the system.");
+       }
 }
 
+#define SETPASS                                1
+#define MAKEHOME                       4
+
 /*
  * adduser will take a login_name as its first parameter.
  *
@@ -224,46 +253,36 @@ static inline uid_t i_am_not_root(void)
  * ________________________________________________________________________ */
 int adduser_main(int argc, char **argv)
 {
-       int opt;
+       struct passwd pw;
        const char *login;
-       const char *gecos;
+       const char *gecos = default_gecos;
        const char *home = NULL;
-       const char *shell;
-
-       struct passwd pw;
+       const char *shell = default_shell;
+       const char *usegroup = NULL;
+       int flags;
+       int setpass = 1;
+       int makehome = 1;
 
        /* init */
        if (argc < 2) {
-               show_usage();
+               bb_show_usage();
        }
-       gecos = default_gecos;
-       shell = default_shell;
-
        /* get args */
-       while ((opt = getopt (argc, argv, "h:g:s:")) != -1)
-               switch (opt) {
-                       case 'h':
-                               home = optarg;
-                               break;
-                       case 'g':
-                               gecos = optarg;
-                               break;
-                       case 's':
-                               shell = optarg;
-                               break;
-                       default:
-                               show_usage ();
-                               break;
-               }
+       flags = bb_getopt_ulflags(argc, argv, "h:g:s:G:DSH", &home, &gecos, &shell, &usegroup);
 
-       /* got root? */
-       if (i_am_not_root()) {
-               error_msg_and_die( "Only root may add a user or group to the system.");
+       if (flags & SETPASS) {
+               setpass = 0;
+       }
+       if (flags & MAKEHOME) {
+               makehome = 0;
        }
 
+       /* got root? */
+       if_i_am_not_root();
+
        /* get login */
        if (optind >= argc) {
-               error_msg_and_die( "no user specified");
+               bb_error_msg_and_die( "no user specified");
        }
        login = argv[optind];
 
@@ -273,7 +292,7 @@ int adduser_main(int argc, char **argv)
        }
 #ifdef CONFIG_FEATURE_SHADOWPASSWDS
        /* is /etc/shadow in use? */
-       shadow_enabled = (0 == access(shadow_file, F_OK));
+       shadow_enabled = (0 == access(bb_path_shadow_file, F_OK));
 #endif
 
        /* create a passwd struct */
@@ -285,8 +304,17 @@ int adduser_main(int argc, char **argv)
        pw.pw_dir = (char *)home;
        pw.pw_shell = (char *)shell;
 
+       if (usegroup) {
+               /* Add user to a group that already exists */
+               struct group *g;
+
+               g = getgrnam(usegroup);
+               if (g == NULL)
+                       bb_error_msg_and_die("group %s does not exist", usegroup);
+
+               pw.pw_gid = g->gr_gid;
+       }
+
        /* grand finale */
-       return adduser(passwd_file, &pw);
+       return adduser(bb_path_passwd_file, &pw, makehome, setpass);
 }
-
-/* $Id: adduser.c,v 1.4 2002/09/16 06:22:24 andersen Exp $ */