start_stop_daemon: add -chuid support
authorDenis Vlasenko <vda.linux@googlemail.com>
Mon, 26 Feb 2007 22:47:42 +0000 (22:47 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Mon, 26 Feb 2007 22:47:42 +0000 (22:47 -0000)
coreutils/chown.c
debianutils/start_stop_daemon.c
include/libbb.h
include/usage.h
libpwdgrp/uidgid_get.c

index dad5ce0..3380677 100644 (file)
@@ -56,7 +56,6 @@ static int fileAction(const char *fileName, struct stat *statbuf,
 int chown_main(int argc, char **argv);
 int chown_main(int argc, char **argv)
 {
-       char *groupName;
        int retval = EXIT_SUCCESS;
 
        opt_complementary = "-2";
@@ -65,24 +64,7 @@ int chown_main(int argc, char **argv)
 
        if (OPT_NODEREF) chown_func = lchown;
 
-       /* First, check if there is a group name here */
-       groupName = strchr(*argv, '.'); /* deprecated? */
-       if (!groupName)
-               groupName = strchr(*argv, ':');
-       else
-               *groupName = ':'; /* replace '.' with ':' */
-
-       /* First, try parsing "user[:[group]]" */
-       if (!groupName) { /* "user" */
-               ugid.uid = get_ug_id(*argv, xuname2uid);
-       } else if (groupName == *argv) { /* ":group" */
-               ugid.gid = get_ug_id(groupName + 1, xgroup2gid);
-       } else {
-               if (!groupName[1]) /* "user:" */
-                       *groupName = '\0';
-               if (!get_uidgid(&ugid, *argv, 1))
-                       bb_error_msg_and_die("unknown user/group %s", *argv);
-       }
+       parse_chown_usergroup_or_die(&ugid, argv[0]);
 
        /* Ok, ready to do the deed now */
        argv++;
index eb2427a..1862f11 100644 (file)
 
 static int signal_nr = 15;
 static int user_id = -1;
-static int quiet;
 static char *userspec;
-static char *chuid;
 static char *cmdname;
 static char *execname;
 static char *pidfile;
+static smallint quiet;
 
 struct pid_list {
        struct pid_list *next;
@@ -222,20 +221,28 @@ static const struct option long_options[] = {
 enum {
        CTX_STOP       = 0x1,
        CTX_START      = 0x2,
-       OPT_BACKGROUND = 0x4,
-       OPT_QUIET      = 0x8,
-       OPT_MAKEPID    = 0x10,
-       OPT_OKNODO     = 0x20 * ENABLE_FEATURE_START_STOP_DAEMON_FANCY,
-       OPT_VERBOSE    = 0x40 * ENABLE_FEATURE_START_STOP_DAEMON_FANCY,
-       OPT_NICELEVEL  = 0x80 * ENABLE_FEATURE_START_STOP_DAEMON_FANCY,
+       OPT_BACKGROUND = 0x4, // -b
+       OPT_QUIET      = 0x8, // -q
+       OPT_MAKEPID    = 0x10, // -m
+       OPT_a          = 0x20, // -a
+       OPT_n          = 0x40, // -n
+       OPT_s          = 0x80, // -s
+       OPT_u          = 0x100, // -u
+       OPT_c          = 0x200, // -c
+       OPT_x          = 0x400, // -x
+       OPT_p          = 0x800, // -p
+       OPT_OKNODO     = 0x1000 * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -o
+       OPT_VERBOSE    = 0x2000 * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -v
+       OPT_NICELEVEL  = 0x4000 * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -N
 };
 
 int start_stop_daemon_main(int argc, char **argv);
 int start_stop_daemon_main(int argc, char **argv)
 {
        unsigned opt;
-       char *signame = NULL;
-       char *startas = NULL;
+       char *signame;
+       char *startas;
+       char *chuid;
 #if ENABLE_FEATURE_START_STOP_DAEMON_FANCY
 //     char *retry_arg = NULL;
 //     int retries = -1;
@@ -247,22 +254,22 @@ int start_stop_daemon_main(int argc, char **argv)
 
        /* Check required one context option was given */
        opt_complementary = "K:S:?:K--S:S--K:m?p:K?xpun:S?xa";
-       opt = getopt32(argc, argv, "KSbqm"
-//             USE_FEATURE_START_STOP_DAEMON_FANCY("ovN:R:")
-               USE_FEATURE_START_STOP_DAEMON_FANCY("ovN:")
-               "a:n:s:u:c:x:p:"
+       opt = getopt32(argc, argv, "KSbqma:n:s:u:c:x:p:"
+               USE_FEATURE_START_STOP_DAEMON_FANCY("ovN:"),
+//             USE_FEATURE_START_STOP_DAEMON_FANCY("ovN:R:"),
+               &startas, &cmdname, &signame, &userspec, &chuid, &execname, &pidfile
                USE_FEATURE_START_STOP_DAEMON_FANCY(,&opt_N)
 //             USE_FEATURE_START_STOP_DAEMON_FANCY(,&retry_arg)
-               ,&startas, &cmdname, &signame, &userspec, &chuid, &execname, &pidfile);
+       );
 
        quiet = (opt & OPT_QUIET) && !(opt & OPT_VERBOSE);
 
-       if (signame) {
+       if (opt & OPT_s) {
                signal_nr = get_signum(signame);
                if (signal_nr < 0) bb_show_usage();
        }
 
-       if (!startas)
+       if (!(opt & OPT_a))
                startas = execname;
 
 //     USE_FEATURE_START_STOP_DAEMON_FANCY(
@@ -303,11 +310,11 @@ int start_stop_daemon_main(int argc, char **argv)
                fprintf(pidf, "%d\n", pidt);
                fclose(pidf);
        }
-       if (chuid) {
-               user_id = bb_strtou(chuid, NULL, 10);
-               if (errno)
-                       user_id = xuname2uid(chuid);
-               xsetuid(user_id);
+       if (opt & OPT_c) {
+               struct bb_uidgid_t ugid;
+               parse_chown_usergroup_or_die(&ugid, chuid);
+               if (ugid.gid != (gid_t) -1) xsetgid(ugid.gid);
+               if (ugid.uid != (uid_t) -1) xsetuid(ugid.uid);
        }
 #if ENABLE_FEATURE_START_STOP_DAEMON_FANCY
        if (opt & OPT_NICELEVEL) {
index a32e615..4293ae2 100644 (file)
@@ -443,7 +443,10 @@ struct bb_uidgid_t {
        uid_t uid;
        gid_t gid;
 };
+/* always sets uid and gid */
 int get_uidgid(struct bb_uidgid_t*, const char*, int numeric_ok);
+/* chown-like handling of "user[:[group]" */
+void parse_chown_usergroup_or_die(struct bb_uidgid_t *u, char *user_group);
 /* what is this? */
 /*extern char *bb_getug(char *buffer, char *idname, long id, int bufsize, char prefix);*/
 char *bb_getpwuid(char *name, long uid, int bufsize);
index 52f9720..04dddd7 100644 (file)
        "\n     -N|--nicelevel <N>              Add N to process's nice level" \
        ) \
        "\n     -s|--signal <signal>            Signal to send (default TERM)" \
-       "\n     -U|--chuid <username>|<uid>     Start process with this name"
+       "\n     -c|--chuid <user>[:[<group>]]   Change to specified user/group"
 
 #define stat_trivial_usage \
        "[OPTION] FILE..."
index 69c228e..f10b406 100644 (file)
@@ -27,6 +27,7 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include "busybox.h"
 
+/* Always sets uid and gid */
 int get_uidgid(struct bb_uidgid_t *u, const char *ug, int numeric_ok)
 {
        struct passwd *pwd;
@@ -53,6 +54,7 @@ int get_uidgid(struct bb_uidgid_t *u, const char *ug, int numeric_ok)
                        goto skip;
                }
        }
+       /* Either it is not numeric, or caller disallows numeric username */
        pwd = getpwnam(user);
        if (!pwd)
                return 0;
@@ -75,6 +77,40 @@ int get_uidgid(struct bb_uidgid_t *u, const char *ug, int numeric_ok)
        return 1;
 }
 
+/* chown-like:
+ * "user" sets uid only,
+ * ":group" sets gid only
+ * "user:" sets uid and gid (to user's primary group id)
+ * "user:group" sets uid and gid
+ * ('unset' uid or gid is actually set to -1)
+ */
+void parse_chown_usergroup_or_die(struct bb_uidgid_t *u, char *user_group)
+{
+       char *group;
+
+       u->uid = -1;
+       u->gid = -1;
+
+       /* Check if there is a group name */
+       group = strchr(user_group, '.'); /* deprecated? */
+       if (!group)
+               group = strchr(user_group, ':');
+       else
+               *group = ':'; /* replace '.' with ':' */
+
+       /* Parse "user[:[group]]" */
+       if (!group) { /* "user" */
+               u->uid = get_ug_id(user_group, xuname2uid);
+       } else if (group == user_group) { /* ":group" */
+               u->gid = get_ug_id(group + 1, xgroup2gid);
+       } else {
+               if (!group[1]) /* "user:" */
+                       *group = '\0';
+               if (!get_uidgid(u, user_group, 1))
+                       bb_error_msg_and_die("unknown user/group %s", user_group);
+       }
+}
+
 #if 0
 #include <stdio.h>
 int main()