start_stop_daemon: add -chuid support
No binary (build failed)
—
(log yok)
| @@ -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++; | |
| @@ -14,12 +14,11 @@ | |
| 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) { | |
| @@ -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); | |
| @@ -2893,7 +2893,7 @@ | |
| "\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..." | |
| @@ -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() | |