aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2018-05-17 21:37:57 +0300
committerSergey Poznyakoff <gray@gnu.org>2018-05-17 21:37:57 +0300
commit41e4cf7b5ad33dcfc7f472b9392831fa197fd8e2 (patch)
tree6efb7211f656932b6e1848fba21e3c71fb704819
parente8e7bbc7de3355af2c14992e09e0881e95b8b580 (diff)
downloadgenrc-41e4cf7b5ad33dcfc7f472b9392831fa197fd8e2.tar.gz
genrc-41e4cf7b5ad33dcfc7f472b9392831fa197fd8e2.tar.bz2
Implement the --user and --group options.
-rw-r--r--src/Makefile.am3
-rw-r--r--src/com_start.c1
-rw-r--r--src/genrc.825
-rw-r--r--src/genrc.c10
-rw-r--r--src/genrc.h2
-rw-r--r--src/runas.c191
-rw-r--r--src/sentinel.c2
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
41AM_CPPFLAGS = @GRECS_INCLUDES@ 42AM_CPPFLAGS = @GRECS_INCLUDES@
42LDADD = @GRECS_LDADD@ 43LDADD = @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 @@
18genrc \- generic system initialization script helper 18genrc \- 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
166Display a short help list. 171Display a short help list.
167.TP 172.TP
173\fB\-g\fR, \fB\-\-group=\fIGROUP\fR[,\fIGROUP\fR...]
174Run program with this \fIGROUP\fR privileges. If the argument is a
175list of groups, the first group becomes the principal, and the
176rest of them supplementary groups. Each \fIGROUP\fR is either a group
177name or a numeric group number prefixed with a plus sign. Whatever
178notation is used, it must exist in the system group database.
179
180See also the \fB\-\-user\fR option.
181.TP
168\fB\-\-no\-reload\fR 182\fB\-\-no\-reload\fR
169Makes \fBreload\fR equivalent to \fBrestart\fR. 183Makes \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
193Display a short usage summary. 207Display a short usage summary.
194.TP 208.TP
209\fB\-u\fR, \fB\-\-user=\fIUSER\fR
210Run with this user privileges. The argument is either a login
211name or a numeric UID prefixed with the plus sign. Whatever form is
212used, it must correspond to a valid user from the system user
213database.
214
215Unless \fB\-\-group\fR option is also given, the primary and
216supplementary groups of \fIUSER\fR will be used.
217.TP
195\fB\-\-version\fR 218\fB\-\-version\fR
196Display program version and exit. 219Display 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
287Sergey Poznyakoff 312Sergey 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};
48char shortopts[] = "c:hF:P:p:St:v"; 50char shortopts[] = "c:hF:g:P:p:St:u:v";
49 51
50struct sigdefn { 52struct 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
34void *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
62int pid_is_running(pid_t pid); 63int pid_is_running(pid_t pid);
63 64
65void runas(void);
64 66
65enum { 67enum {
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
2Copyryght (C) 2018 Sergey Poznyakoff
3License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
4This is free software: you are free to change and redistribute it.
5There is NO WARRANTY, to the extent permitted by law.
6*/
7#include "genrc.h"
8#include <pwd.h>
9#include <grp.h>
10
11static void
12addgid(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
27static int
28member(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
38static size_t
39get_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
55static gid_t
56strtogid(char const *str)
57{
58</