diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2018-05-17 21:37:57 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2018-05-17 21:37:57 +0300 |
commit | 41e4cf7b5ad33dcfc7f472b9392831fa197fd8e2 (patch) | |
tree | 6efb7211f656932b6e1848fba21e3c71fb704819 | |
parent | e8e7bbc7de3355af2c14992e09e0881e95b8b580 (diff) | |
download | genrc-41e4cf7b5ad33dcfc7f472b9392831fa197fd8e2.tar.gz genrc-41e4cf7b5ad33dcfc7f472b9392831fa197fd8e2.tar.bz2 |
Implement the --user and --group options.
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/com_start.c | 1 | ||||
-rw-r--r-- | src/genrc.8 | 25 | ||||
-rw-r--r-- | src/genrc.c | 10 | ||||
-rw-r--r-- | src/genrc.h | 2 | ||||
-rw-r--r-- | src/runas.c | 191 | ||||
-rw-r--r-- | src/sentinel.c | 2 |
7 files changed, 232 insertions, 2 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index f78a979..b565303 100644 --- a/src/Makefile.am +++ b/src/Makefile.am | |||
@@ -36,7 +36,8 @@ genrc_SOURCES = \ | |||
36 | match_exact.c\ | 36 | match_exact.c\ |
37 | match_glob.c\ | 37 | match_glob.c\ |
38 | match_regex.c\ | 38 | match_regex.c\ |
39 | sentinel.c | 39 | sentinel.c\ |
40 | runas.c | ||
40 | 41 | ||
41 | AM_CPPFLAGS = @GRECS_INCLUDES@ | 42 | AM_CPPFLAGS = @GRECS_INCLUDES@ |
42 | LDADD = @GRECS_LDADD@ | 43 | LDADD = @GRECS_LDADD@ |
diff --git a/src/com_start.c b/src/com_start.c index 65c1775..5744e39 100644 --- a/src/com_start.c +++ b/src/com_start.c | |||
@@ -112,6 +112,7 @@ com_start(void) | |||
112 | if (pid == 0) { | 112 | if (pid == 0) { |
113 | char *argv[] = { SHELL, "-c", NULL, NULL }; | 113 | char *argv[] = { SHELL, "-c", NULL, NULL }; |
114 | argv[2] = genrc_command; | 114 | argv[2] = genrc_command; |
115 | runas(); | ||
115 | execvp(SHELL, argv); | 116 | execvp(SHELL, argv); |
116 | system_error(errno, "failed to exec %s", genrc_program); | 117 | system_error(errno, "failed to exec %s", genrc_program); |
117 | exit(127); | 118 | exit(127); |
diff --git a/src/genrc.8 b/src/genrc.8 index f900639..00522ee 100644 --- a/src/genrc.8 +++ b/src/genrc.8 | |||
@@ -18,15 +18,19 @@ | |||
18 | genrc \- generic system initialization script helper | 18 | genrc \- generic system initialization script helper |
19 | .SH SYNOPSIS | 19 | .SH SYNOPSIS |
20 | .nh | 20 | .nh |
21 | .na | ||
21 | \fBgenrc\fR\ | 22 | \fBgenrc\fR\ |
22 | [\fB\-hv\fR]\ | 23 | [\fB\-hv\fR]\ |
23 | [\fB\-F\fR \fIPIDFILE\fR]\ | 24 | [\fB\-F\fR \fIPIDFILE\fR]\ |
24 | [\fB\-P\fR \fISOURCE\fR]\ | 25 | [\fB\-P\fR \fISOURCE\fR]\ |
25 | [\fB\-c\fR \fICOMMAND\fR]\ | 26 | [\fB\-c\fR \fICOMMAND\fR]\ |
27 | [\fB\-g\fR \fIGROUP\fR[,\fIGROUP\fR...]]\ | ||
26 | [\fB\-p\fR \fIPROGRAM\fR]\ | 28 | [\fB\-p\fR \fIPROGRAM\fR]\ |
27 | [\fB\-t\fR \fISECONDS\fR]\ | 29 | [\fB\-t\fR \fISECONDS\fR]\ |
30 | [\fB\-u\fR \fIUSER\fR]\ | ||
28 | [\fB\-\-command=\fICOMMAND\fR]\ | 31 | [\fB\-\-command=\fICOMMAND\fR]\ |
29 | [\fB\-\-create\-pidfile=\fIPIDFILE\fR]\ | 32 | [\fB\-\-create\-pidfile=\fIPIDFILE\fR]\ |
33 | [\fB\-\-group=\fIGROUP\fR[,\fIGROUP\fR...]]\ | ||
30 | [\fB\-\-help\fR]\ | 34 | [\fB\-\-help\fR]\ |
31 | [\fB\-\-no\-reload\fR]\ | 35 | [\fB\-\-no\-reload\fR]\ |
32 | [\fB\-\-pid\-from=\fISOURCE\fR]\ | 36 | [\fB\-\-pid\-from=\fISOURCE\fR]\ |
@@ -36,6 +40,7 @@ genrc \- generic system initialization script helper | |||
36 | [\fB\-\-signal\-reload=\fISIG\fR]\ | 40 | [\fB\-\-signal\-reload=\fISIG\fR]\ |
37 | [\fB\-\-signal\-stop=\fISIG\fR]\ | 41 | [\fB\-\-signal\-stop=\fISIG\fR]\ |
38 | [\fB\-\-timeout=\fISECONDS\fR]\ | 42 | [\fB\-\-timeout=\fISECONDS\fR]\ |
43 | [\fB\-\-user=\fIUSER\fR]\ | ||
39 | [\fB\-\-usage\fR]\ | 44 | [\fB\-\-usage\fR]\ |
40 | [\fB\-\-verbose\fR]\ | 45 | [\fB\-\-verbose\fR]\ |
41 | {\ | 46 | {\ |
@@ -165,6 +170,15 @@ Name of the PID file (same as \fB\-\-pid\-from=FILE:\fINAME\fR) | |||
165 | \fB\-h\fR, \fB\-\-help\fR | 170 | \fB\-h\fR, \fB\-\-help\fR |
166 | Display a short help list. | 171 | Display a short help list. |
167 | .TP | 172 | .TP |
173 | \fB\-g\fR, \fB\-\-group=\fIGROUP\fR[,\fIGROUP\fR...] | ||
174 | Run program with this \fIGROUP\fR privileges. If the argument is a | ||
175 | list of groups, the first group becomes the principal, and the | ||
176 | rest of them supplementary groups. Each \fIGROUP\fR is either a group | ||
177 | name or a numeric group number prefixed with a plus sign. Whatever | ||
178 | notation is used, it must exist in the system group database. | ||
179 | |||
180 | See also the \fB\-\-user\fR option. | ||
181 | .TP | ||
168 | \fB\-\-no\-reload\fR | 182 | \fB\-\-no\-reload\fR |
169 | Makes \fBreload\fR equivalent to \fBrestart\fR. | 183 | Makes \fBreload\fR equivalent to \fBrestart\fR. |
170 | .TP | 184 | .TP |
@@ -192,6 +206,15 @@ Time to wait for the program to start up or terminate. | |||
192 | \fB\-\-usage\fR | 206 | \fB\-\-usage\fR |
193 | Display a short usage summary. | 207 | Display a short usage summary. |
194 | .TP | 208 | .TP |
209 | \fB\-u\fR, \fB\-\-user=\fIUSER\fR | ||
210 | Run with this user privileges. The argument is either a login | ||
211 | name or a numeric UID prefixed with the plus sign. Whatever form is | ||
212 | used, it must correspond to a valid user from the system user | ||
213 | database. | ||
214 | |||
215 | Unless \fB\-\-group\fR option is also given, the primary and | ||
216 | supplementary groups of \fIUSER\fR will be used. | ||
217 | .TP | ||
195 | \fB\-\-version\fR | 218 | \fB\-\-version\fR |
196 | Display program version and exit. | 219 | Display program version and exit. |
197 | .TP | 220 | .TP |
@@ -282,6 +305,8 @@ Influential environment variables and corresponding options: | |||
282 | \fBGENRC_TIMEOUT=\fISECONDS\fR \fB\-\-timeout=\fISECONDS\fR | 305 | \fBGENRC_TIMEOUT=\fISECONDS\fR \fB\-\-timeout=\fISECONDS\fR |
283 | \fBGENRC_SENTINEL=1\fR \fB\-\-sentinel\fR | 306 | \fBGENRC_SENTINEL=1\fR \fB\-\-sentinel\fR |
284 | \fBGENRC_CREATE_PIDFILE=\fINAME\fR \fB\-\-create\-pidfile=\fINAME\fR | 307 | \fBGENRC_CREATE_PIDFILE=\fINAME\fR \fB\-\-create\-pidfile=\fINAME\fR |
308 | \fBGENRC_USER=\fINAME\fR \fB\-\-user=\fINAME\fR | ||
309 | \fBGENRC_GROUP=\fIGROUPS\fR \fB\-\-group=\fIGROUPS\fR | ||
285 | .fi | 310 | .fi |
286 | .SH AUTHORS | 311 | .SH AUTHORS |
287 | Sergey Poznyakoff | 312 | Sergey Poznyakoff |
diff --git a/src/genrc.c b/src/genrc.c index 92b0fac..d4904b6 100644 --- a/src/genrc.c +++ b/src/genrc.c | |||
@@ -43,9 +43,11 @@ struct option longopts[] = { | |||
43 | { "create-pidfile", required_argument, 0, OPT_CREATE_PIDFILE }, | 43 | { "create-pidfile", required_argument, 0, OPT_CREATE_PIDFILE }, |
44 | { "version", no_argument, 0, OPT_VERSION }, | 44 | { "version", no_argument, 0, OPT_VERSION }, |
45 | { "verbose", no_argument, 0, 'v' }, | 45 | { "verbose", no_argument, 0, 'v' }, |
46 | { "user", required_argument, 0, 'u' }, | ||
47 | { "group", required_argument, 0, 'g' }, | ||
46 | { NULL } | 48 | { NULL } |
47 | }; | 49 | }; |
48 | char shortopts[] = "c:hF:P:p:St:v"; | 50 | char shortopts[] = "c:hF:g:P:p:St:u:v"; |
49 | 51 | ||
50 | struct sigdefn { | 52 | struct sigdefn { |
51 | char const *sig_name; | 53 | char const *sig_name; |
@@ -386,6 +388,9 @@ main(int argc, char **argv) | |||
386 | setenv("GENRC_PID_FROM", p, 1); | 388 | setenv("GENRC_PID_FROM", p, 1); |
387 | free(p); | 389 | free(p); |
388 | break; | 390 | break; |
391 | case 'g': | ||
392 | setenv("GENRC_GROUP", optarg, 1); | ||
393 | break; | ||
389 | case OPT_CREATE_PIDFILE: | 394 | case OPT_CREATE_PIDFILE: |
390 | setenv("GENRC_CREATE_PIDFILE", optarg, 1); | 395 | setenv("GENRC_CREATE_PIDFILE", optarg, 1); |
391 | break; | 396 | break; |
@@ -404,6 +409,9 @@ main(int argc, char **argv) | |||
404 | case OPT_SIGNAL_STOP: | 409 | case OPT_SIGNAL_STOP: |
405 | setenv("GENRC_SIGNAL_STOP", optarg, 1); | 410 | setenv("GENRC_SIGNAL_STOP", optarg, 1); |
406 | break; | 411 | break; |
412 | case 'u': | ||
413 | setenv("GENRC_USER", optarg, 1); | ||
414 | break; | ||
407 | case 'v': | 415 | case 'v': |
408 | genrc_verbose++; | 416 | genrc_verbose++; |
409 | break; | 417 | break; |
diff --git a/src/genrc.h b/src/genrc.h index a6e81e8..9842016 100644 --- a/src/genrc.h +++ b/src/genrc.h | |||
@@ -31,6 +31,7 @@ void system_error(int ec, char const *fmt, ...); | |||
31 | #define xcalloc grecs_calloc | 31 | #define xcalloc grecs_calloc |
32 | #define xrealloc grecs_realloc | 32 | #define xrealloc grecs_realloc |
33 | #define xstrdup grecs_strdup | 33 | #define xstrdup grecs_strdup |
34 | void *x2nrealloc(void *p, size_t *pn, size_t s); | ||
34 | 35 | ||
35 | #define SHELL "/bin/sh" | 36 | #define SHELL "/bin/sh" |
36 | 37 | ||
@@ -61,6 +62,7 @@ pid_t strtopid(char const *str); | |||
61 | 62 | ||
62 | int pid_is_running(pid_t pid); | 63 | int pid_is_running(pid_t pid); |
63 | 64 | ||
65 | void runas(void); | ||
64 | 66 | ||
65 | enum { | 67 | enum { |
66 | MATCH_REGEX, /* extended POSIX regexp match (default) */ | 68 | MATCH_REGEX, /* extended POSIX regexp match (default) */ |
diff --git a/src/runas.c b/src/runas.c new file mode 100644 index 0000000..9d2a6c1 --- /dev/null +++ b/src/runas.c | |||
@@ -0,0 +1,191 @@ | |||
1 | /* This file is part of genrc | ||
2 | Copyryght (C) 2018 Sergey Poznyakoff | ||
3 | License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> | ||
4 | This is free software: you are free to change and redistribute it. | ||
5 | There is NO WARRANTY, to the extent permitted by law. | ||
6 | */ | ||
7 | #include "genrc.h" | ||
8 | #include <pwd.h> | ||
9 | #include <grp.h> | ||
10 | |||
11 | static void | ||
12 | addgid(gid_t **pgv, size_t *pgc, size_t *pgi, gid_t gid) | ||
13 | { | ||
14 | gid_t *gv = *pgv; | ||
15 | size_t gc = *pgc; | ||
16 | size_t gi = *pgi; | ||
17 | |||
18 | if (gi == gc) | ||
19 | gv = x2nrealloc(gv, &gc, sizeof(gv[0])); | ||
20 | |||
21 | gv[gi++] = gid; | ||
22 | *pgv = gv; | ||
23 | *pgc = gc; | ||
24 | *pgi = gi; | ||
25 | } | ||
26 | |||
27 | static int | ||
28 | member(gid_t *gv, size_t gc, gid_t gid) | ||
29 | { | ||
30 | size_t i; | ||
31 | |||
32 | for (i = 0; i < gc; i++) | ||
33 | if (gv[i] == gid) | ||
34 | return 1; | ||
35 | return 0; | ||
36 | } | ||
37 | |||
38 | static size_t | ||
39 | get_user_groups(const char *user, gid_t **pgv, size_t *pgc) | ||
40 | { | ||
41 | struct group *gr; | ||
42 | size_t gi = 0; | ||
43 | |||
44 | setgrent(); | ||
45 | while ((gr = getgrent())) { | ||
46 | char **p; | ||
47 | for (p = gr->gr_mem; *p; p++) | ||
48 | if (strcmp(*p, user) == 0) | ||
49 | addgid(pgv, pgc, &gi, gr->gr_gid); | ||
50 | } | ||
51 | endgrent(); | ||
52 | return gi; | ||
53 | } | ||
54 | |||
55 | static gid_t | ||
56 | strtogid(char const *str) | ||
57 | { | ||
58 |