aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/rc/start-stop-daemon.c86
1 files changed, 72 insertions, 14 deletions
diff --git a/src/rc/start-stop-daemon.c b/src/rc/start-stop-daemon.c
index fd281a1d..6bb821c5 100644
--- a/src/rc/start-stop-daemon.c
+++ b/src/rc/start-stop-daemon.c
@@ -96,10 +96,10 @@ typedef struct scheduleitem
TAILQ_ENTRY(scheduleitem) entries;
} SCHEDULEITEM;
TAILQ_HEAD(, scheduleitem) schedule;
-static char **nav = NULL;
+static char **nav;
extern const char *applet;
-static char *changeuser = NULL;
+static char *changeuser, *ch_root, *ch_dir;
extern char **environ;
@@ -498,6 +498,45 @@ static void handle_signal(int sig)
errno = serrno;
}
+static char *
+expand_home(const char *home, const char *path)
+{
+ char *pat, *p, *nh;
+ size_t len;
+ struct passwd *pw;
+
+ if (!path || *path != '~')
+ return xstrdup(path);
+
+ pat = xstrdup(path);
+ if (pat[1] != '/' && pat[1] != '\0') {
+ p = strchr(pat + 1, '/');
+ if (p)
+ *p = '\0';
+ pw = getpwnam(pat + 1);
+ if (pw) {
+ home = pw->pw_dir;
+ pat = p;
+ if (pat)
+ *pat = '/';
+ } else
+ home = NULL;
+ } else
+ pat++;
+
+ if (!home) {
+ free(pat);
+ return xstrdup(path);
+ }
+ if (!pat)
+ return xstrdup(home);
+
+ len = strlen(pat) + strlen(home) + 1;
+ nh = xmalloc(len);
+ snprintf(nh, len, "%s%s", home, pat);
+ free(pat);
+ return nh;
+}
#include "_usage.h"
#define getoptstring "KN:R:Sbc:d:e:g:k:mn:op:s:tu:r:x:1:2:" getoptstring_COMMON
@@ -582,8 +621,7 @@ int start_stop_daemon(int argc, char **argv)
bool makepidfile = false;
uid_t uid = 0;
gid_t gid = 0;
- char *ch_root = NULL;
- char *ch_dir = NULL;
+ char *home = NULL;
int tid = 0;
char *redirect_stderr = NULL;
char *redirect_stdout = NULL;
@@ -624,6 +662,14 @@ int start_stop_daemon(int argc, char **argv)
eerror("%s: invalid nice level `%s' (SSD_NICELEVEL)",
applet, tmp);
+ /* Get our initial dir */
+ home = getenv("HOME");
+ if (!home) {
+ pw = getpwuid(getuid());
+ if (pw)
+ home = pw->pw_dir;
+ }
+
while ((opt = getopt_long(argc, argv, getoptstring, longopts,
(int *) 0)) != -1)
switch (opt) {
@@ -633,7 +679,8 @@ int start_stop_daemon(int argc, char **argv)
case 'N': /* --nice */
if (sscanf(optarg, "%d", &nicelevel) != 1)
- eerrorx("%s: invalid nice level `%s'", applet, optarg);
+ eerrorx("%s: invalid nice level `%s'",
+ applet, optarg);
break;
case 'R': /* --retry <schedule>|<timeout> */
@@ -659,10 +706,12 @@ int start_stop_daemon(int argc, char **argv)
else
pw = getpwuid((uid_t) tid);
- if (! pw)
- eerrorx("%s: user `%s' not found", applet, tmp);
+ if (!pw)
+ eerrorx("%s: user `%s' not found",
+ applet, tmp);
uid = pw->pw_uid;
- if (! gid)
+ home = pw->pw_dir;
+ if (!gid)
gid = pw->pw_gid;
if (p) {
@@ -672,8 +721,9 @@ int start_stop_daemon(int argc, char **argv)
else
gr = getgrgid((gid_t) tid);
- if (! gr)
- eerrorx("%s: group `%s' not found",
+ if (!gr)
+ eerrorx("%s: group `%s'"
+ " not found",
applet, tmp);
gid = gr->gr_gid;
}
@@ -686,9 +736,10 @@ int start_stop_daemon(int argc, char **argv)
case 'e': /* --env */
if (putenv(optarg) == 0) {
- if (strncmp("HOME=", optarg, 5) == 0)
+ if (strncmp("HOME=", optarg, 5) == 0) {
sethome = true;
- else if (strncmp("USER=", optarg, 5) == 0)
+ home = strchr(optarg, '=') + 1;
+ } else if (strncmp("USER=", optarg, 5) == 0)
setuser = true;
}
break;
@@ -700,8 +751,9 @@ int start_stop_daemon(int argc, char **argv)
else
gr = getgrgid((gid_t) tid);
- if (! gr)
- eerrorx("%s: group `%s' not found", applet, optarg);
+ if (!gr)
+ eerrorx("%s: group `%s' not found",
+ applet, optarg);
gid = gr->gr_gid;
}
break;
@@ -835,6 +887,12 @@ int start_stop_daemon(int argc, char **argv)
exit(EXIT_SUCCESS);
}
+ /* Expand ~ */
+ if (ch_dir && *ch_dir == '~')
+ ch_dir = expand_home(home, ch_dir);
+ if (ch_root && *ch_root == '~')
+ ch_root = expand_home(home, ch_root);
+
/* Validate that the binary exists if we are starting */
if (*exec == '/' || *exec == '.') {
/* Full or relative path */