Attempt to make s-s-d simpler by not enforcing the need for a full path and maybe working better with interpreted scripts.
This commit is contained in:
parent
46a74f244e
commit
cea206014d
@ -22,7 +22,7 @@
|
|||||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
.\" SUCH DAMAGE.
|
.\" SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.Dd Feb 24, 2008
|
.Dd Jul 08, 2008
|
||||||
.Dt START-STOP-DAEMON 8 SMM
|
.Dt START-STOP-DAEMON 8 SMM
|
||||||
.Os OpenRC
|
.Os OpenRC
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -44,6 +44,11 @@
|
|||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
.Nm
|
.Nm
|
||||||
provides a consistent method of starting, stopping and signalling daemons.
|
provides a consistent method of starting, stopping and signalling daemons.
|
||||||
|
If neither
|
||||||
|
.Fl K , -stop
|
||||||
|
nor
|
||||||
|
.Fl s , -signal
|
||||||
|
are provided, then we assume we are starting the daemon.
|
||||||
If a daemon cannot background by itself, nor create a pidfile,
|
If a daemon cannot background by itself, nor create a pidfile,
|
||||||
.Nm
|
.Nm
|
||||||
can do it for the daemon in a secure fashion.
|
can do it for the daemon in a secure fashion.
|
||||||
@ -67,6 +72,8 @@ Here are the options to specify the daemon and how it should start or stop:
|
|||||||
The
|
The
|
||||||
.Ar daemon
|
.Ar daemon
|
||||||
we start or stop.
|
we start or stop.
|
||||||
|
If this option is not specified, then the first non option argument
|
||||||
|
is used.
|
||||||
If the
|
If the
|
||||||
.Ar daemon
|
.Ar daemon
|
||||||
is a script and you are not using the pidfile or process name options,
|
is a script and you are not using the pidfile or process name options,
|
||||||
@ -76,7 +83,7 @@ with the interpreter and pass
|
|||||||
.Ar daemon
|
.Ar daemon
|
||||||
as an argument. Below is an example:
|
as an argument. Below is an example:
|
||||||
.Pp
|
.Pp
|
||||||
start-stop-daemon -Sx /usr/bin/perl -- /usr/bin/daemon.pl
|
start-stop-daemon perl -- /usr/bin/daemon.pl
|
||||||
.It Fl p , -pidfile Ar pidfile
|
.It Fl p , -pidfile Ar pidfile
|
||||||
When starting, we expect the daemon to create a valid
|
When starting, we expect the daemon to create a valid
|
||||||
.Ar pidfile
|
.Ar pidfile
|
||||||
@ -101,6 +108,10 @@ The return value is set as if the command was taken and worked.
|
|||||||
.Pp
|
.Pp
|
||||||
These options are only used for starting daemons:
|
These options are only used for starting daemons:
|
||||||
.Bl -tag -width indent
|
.Bl -tag -width indent
|
||||||
|
.It Fl a , -startas Ar name
|
||||||
|
Change the process name of the daemon to
|
||||||
|
.Ar name .
|
||||||
|
This just changes the first argument passed to the daemon.
|
||||||
.It Fl b , -background
|
.It Fl b , -background
|
||||||
Force the daemon into the background. Some daemons don't create pidfiles, so a
|
Force the daemon into the background. Some daemons don't create pidfiles, so a
|
||||||
good trick is to get the daemon to run in the foreground, and use the this
|
good trick is to get the daemon to run in the foreground, and use the this
|
||||||
|
@ -40,11 +40,11 @@ static size_t strlcpy(char *dst, const char *src, size_t size)
|
|||||||
|
|
||||||
if (n && --n)
|
if (n && --n)
|
||||||
do {
|
do {
|
||||||
if (! (*dst++ = *src++))
|
if (!(*dst++ = *src++))
|
||||||
break;
|
break;
|
||||||
} while (--n);
|
} while (--n);
|
||||||
|
|
||||||
if (! n) {
|
if (!n) {
|
||||||
if (size)
|
if (size)
|
||||||
*dst = '\0';
|
*dst = '\0';
|
||||||
while (*src++);
|
while (*src++);
|
||||||
@ -57,21 +57,22 @@ static size_t strlcpy(char *dst, const char *src, size_t size)
|
|||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
|
|
||||||
static bool pid_is_cmd(pid_t pid, const char *cmd)
|
static bool pid_is_exec(pid_t pid, const char *exec)
|
||||||
{
|
{
|
||||||
char buffer[32];
|
char buffer[32];
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
int c;
|
int c;
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
|
|
||||||
|
exec = basename_c(exec);
|
||||||
snprintf(buffer, sizeof(buffer), "/proc/%d/stat", pid);
|
snprintf(buffer, sizeof(buffer), "/proc/%d/stat", pid);
|
||||||
if ((fp = fopen(buffer, "r"))) {
|
if ((fp = fopen(buffer, "r"))) {
|
||||||
while ((c = getc(fp)) != EOF && c != '(')
|
while ((c = getc(fp)) != EOF && c != '(')
|
||||||
;
|
;
|
||||||
if (c == '(') {
|
if (c == '(') {
|
||||||
while ((c = getc(fp)) != EOF && c == *cmd)
|
while ((c = getc(fp)) != EOF && c == *exec)
|
||||||
cmd++;
|
exec++;
|
||||||
if (c == ')' && *cmd == '\0')
|
if (c == ')' && *exec == '\0')
|
||||||
retval = true;
|
retval = true;
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
@ -79,7 +80,7 @@ static bool pid_is_cmd(pid_t pid, const char *cmd)
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool pid_is_exec(pid_t pid, const char *const *argv)
|
static bool pid_is_argv(pid_t pid, const char *const *argv)
|
||||||
{
|
{
|
||||||
char cmdline[32];
|
char cmdline[32];
|
||||||
int fd;
|
int fd;
|
||||||
@ -108,7 +109,7 @@ static bool pid_is_exec(pid_t pid, const char *const *argv)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
RC_PIDLIST *rc_find_pids(const char *const *argv, const char *cmd,
|
RC_PIDLIST *rc_find_pids(const char *exec, const char *const *argv,
|
||||||
uid_t uid, pid_t pid)
|
uid_t uid, pid_t pid)
|
||||||
{
|
{
|
||||||
DIR *procdir;
|
DIR *procdir;
|
||||||
@ -143,27 +144,21 @@ RC_PIDLIST *rc_find_pids(const char *const *argv, const char *cmd,
|
|||||||
while ((entry = readdir(procdir)) != NULL) {
|
while ((entry = readdir(procdir)) != NULL) {
|
||||||
if (sscanf(entry->d_name, "%d", &p) != 1)
|
if (sscanf(entry->d_name, "%d", &p) != 1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (runscript_pid != 0 && runscript_pid == p)
|
if (runscript_pid != 0 && runscript_pid == p)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (pid != 0 && pid != p)
|
if (pid != 0 && pid != p)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (uid) {
|
if (uid) {
|
||||||
snprintf(buffer, sizeof(buffer), "/proc/%d", p);
|
snprintf(buffer, sizeof(buffer), "/proc/%d", p);
|
||||||
if (stat(buffer, &sb) != 0 || sb.st_uid != uid)
|
if (stat(buffer, &sb) != 0 || sb.st_uid != uid)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (exec && !pid_is_exec(p, exec))
|
||||||
if (cmd && ! pid_is_cmd(p, cmd))
|
|
||||||
continue;
|
continue;
|
||||||
|
if (argv &&
|
||||||
if (argv && ! cmd && !
|
!pid_is_argv(p, (const char *const *)argv))
|
||||||
pid_is_exec(p, (const char *const *)argv))
|
|
||||||
continue;
|
continue;
|
||||||
|
if (!pids) {
|
||||||
if (! pids) {
|
|
||||||
pids = xmalloc(sizeof(*pids));
|
pids = xmalloc(sizeof(*pids));
|
||||||
LIST_INIT(pids);
|
LIST_INIT(pids);
|
||||||
}
|
}
|
||||||
@ -172,7 +167,6 @@ RC_PIDLIST *rc_find_pids(const char *const *argv, const char *cmd,
|
|||||||
LIST_INSERT_HEAD(pids, pi, entries);
|
LIST_INSERT_HEAD(pids, pi, entries);
|
||||||
}
|
}
|
||||||
closedir(procdir);
|
closedir(procdir);
|
||||||
|
|
||||||
return pids;
|
return pids;
|
||||||
}
|
}
|
||||||
librc_hidden_def(rc_find_pids)
|
librc_hidden_def(rc_find_pids)
|
||||||
@ -201,7 +195,7 @@ librc_hidden_def(rc_find_pids)
|
|||||||
# define _KVM_FLAGS O_RDONLY
|
# define _KVM_FLAGS O_RDONLY
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
RC_PIDLIST *rc_find_pids(const char *const *argv, const char *cmd,
|
RC_PIDLIST *rc_find_pids(const char *exec, const char *const *argv,
|
||||||
uid_t uid, pid_t pid)
|
uid_t uid, pid_t pid)
|
||||||
{
|
{
|
||||||
static kvm_t *kd = NULL;
|
static kvm_t *kd = NULL;
|
||||||
@ -235,39 +229,34 @@ RC_PIDLIST *rc_find_pids(const char *const *argv, const char *cmd,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (exec)
|
||||||
|
exec = basename_c(exec);
|
||||||
for (i = 0; i < processes; i++) {
|
for (i = 0; i < processes; i++) {
|
||||||
p = _GET_KINFO_PID(kp[i]);
|
p = _GET_KINFO_PID(kp[i]);
|
||||||
if (pid != 0 && pid != p)
|
if (pid != 0 && pid != p)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (uid != 0 && uid != _GET_KINFO_UID(kp[i]))
|
if (uid != 0 && uid != _GET_KINFO_UID(kp[i]))
|
||||||
continue;
|
continue;
|
||||||
|
if (exec) {
|
||||||
if (cmd) {
|
if (!_GET_KINFO_COMM(kp[i]) ||
|
||||||
if (! _GET_KINFO_COMM(kp[i]) ||
|
strcmp(exec, _GET_KINFO_COMM(kp[i])) != 0)
|
||||||
strcmp(cmd, _GET_KINFO_COMM(kp[i])) != 0)
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (argv && *argv) {
|
||||||
if (argv && *argv && ! cmd) {
|
|
||||||
pargv = _KVM_GETARGV(kd, &kp[i], pargc);
|
pargv = _KVM_GETARGV(kd, &kp[i], pargc);
|
||||||
if (! pargv || ! *pargv)
|
if (!pargv || !*pargv)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
arg = argv;
|
arg = argv;
|
||||||
match = 1;
|
match = 1;
|
||||||
|
|
||||||
while (*arg && *pargv)
|
while (*arg && *pargv)
|
||||||
if (strcmp(*arg++, *pargv++) != 0) {
|
if (strcmp(*arg++, *pargv++) != 0) {
|
||||||
match = 0;
|
match = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (!match)
|
||||||
if (! match)
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!pids) {
|
||||||
if (! pids) {
|
|
||||||
pids = xmalloc(sizeof(*pids));
|
pids = xmalloc(sizeof(*pids));
|
||||||
LIST_INIT(pids);
|
LIST_INIT(pids);
|
||||||
}
|
}
|
||||||
@ -297,7 +286,7 @@ static bool _match_daemon(const char *path, const char *file,
|
|||||||
snprintf(ffile, sizeof(ffile), "%s/%s", path, file);
|
snprintf(ffile, sizeof(ffile), "%s/%s", path, file);
|
||||||
fp = fopen(ffile, "r");
|
fp = fopen(ffile, "r");
|
||||||
|
|
||||||
if (! fp)
|
if (!fp)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
while ((rc_getline(&line, &len, fp))) {
|
while ((rc_getline(&line, &len, fp))) {
|
||||||
@ -306,7 +295,7 @@ static bool _match_daemon(const char *path, const char *file,
|
|||||||
TAILQ_REMOVE(match, m, entries);
|
TAILQ_REMOVE(match, m, entries);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (! TAILQ_FIRST(match))
|
if (!TAILQ_FIRST(match))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
@ -316,26 +305,26 @@ static bool _match_daemon(const char *path, const char *file,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static RC_STRINGLIST *_match_list(const char* const* argv,
|
static RC_STRINGLIST *_match_list(const char *exec, const char* const* argv,
|
||||||
const char *name, const char *pidfile)
|
const char *pidfile)
|
||||||
{
|
{
|
||||||
RC_STRINGLIST *match = rc_stringlist_new();
|
RC_STRINGLIST *match = rc_stringlist_new();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
size_t l;
|
size_t l;
|
||||||
char *m;
|
char *m;
|
||||||
|
|
||||||
while (argv && argv[i]) {
|
if (exec) {
|
||||||
l = strlen(*argv) + strlen("argv_=") + 16;
|
l = strlen(exec) + 6;
|
||||||
m = xmalloc(sizeof(char) * l);
|
m = xmalloc(sizeof(char) * l);
|
||||||
snprintf(m, l, "argv_0=%s", argv[i++]);
|
snprintf(m, l, "exec=%s", exec);
|
||||||
rc_stringlist_add(match, m);
|
rc_stringlist_add(match, m);
|
||||||
free(m);
|
free(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name) {
|
while (argv && argv[i]) {
|
||||||
l = strlen(name) + 6;
|
l = strlen(*argv) + strlen("argv_=") + 16;
|
||||||
m = xmalloc(sizeof (char) * l);
|
m = xmalloc(sizeof(char) * l);
|
||||||
snprintf(m, l, "name=%s", name);
|
snprintf(m, l, "argv_0=%s", argv[i++]);
|
||||||
rc_stringlist_add(match, m);
|
rc_stringlist_add(match, m);
|
||||||
free(m);
|
free(m);
|
||||||
}
|
}
|
||||||
@ -351,8 +340,9 @@ static RC_STRINGLIST *_match_list(const char* const* argv,
|
|||||||
return match;
|
return match;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rc_service_daemon_set(const char *service, const char *const *argv,
|
bool rc_service_daemon_set(const char *service, const char *exec,
|
||||||
const char *name, const char *pidfile, bool started)
|
const char *const *argv,
|
||||||
|
const char *pidfile, bool started)
|
||||||
{
|
{
|
||||||
char dirpath[PATH_MAX];
|
char dirpath[PATH_MAX];
|
||||||
char file[PATH_MAX];
|
char file[PATH_MAX];
|
||||||
@ -365,7 +355,7 @@ bool rc_service_daemon_set(const char *service, const char *const *argv,
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
if (!(argv && *argv) && ! name && ! pidfile) {
|
if (!exec && !pidfile) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -375,7 +365,7 @@ bool rc_service_daemon_set(const char *service, const char *const *argv,
|
|||||||
|
|
||||||
/* Regardless, erase any existing daemon info */
|
/* Regardless, erase any existing daemon info */
|
||||||
if ((dp = opendir(dirpath))) {
|
if ((dp = opendir(dirpath))) {
|
||||||
match = _match_list(argv, name, pidfile);
|
match = _match_list(exec, argv, pidfile);
|
||||||
while ((d = readdir(dp))) {
|
while ((d = readdir(dp))) {
|
||||||
if (d->d_name[0] == '.')
|
if (d->d_name[0] == '.')
|
||||||
continue;
|
continue;
|
||||||
@ -384,7 +374,7 @@ bool rc_service_daemon_set(const char *service, const char *const *argv,
|
|||||||
dirpath, d->d_name);
|
dirpath, d->d_name);
|
||||||
nfiles++;
|
nfiles++;
|
||||||
|
|
||||||
if (! *oldfile) {
|
if (!*oldfile) {
|
||||||
if (_match_daemon(dirpath, d->d_name, match)) {
|
if (_match_daemon(dirpath, d->d_name, match)) {
|
||||||
unlink(file);
|
unlink(file);
|
||||||
strlcpy(oldfile, file, sizeof(oldfile));
|
strlcpy(oldfile, file, sizeof(oldfile));
|
||||||
@ -405,13 +395,13 @@ bool rc_service_daemon_set(const char *service, const char *const *argv,
|
|||||||
snprintf(file, sizeof(file), "%s/%03d",
|
snprintf(file, sizeof(file), "%s/%03d",
|
||||||
dirpath, nfiles + 1);
|
dirpath, nfiles + 1);
|
||||||
if ((fp = fopen(file, "w"))) {
|
if ((fp = fopen(file, "w"))) {
|
||||||
|
fprintf(fp, "exec=");
|
||||||
|
if (exec)
|
||||||
|
fprintf(fp, "%s", exec);
|
||||||
while (argv && argv[i]) {
|
while (argv && argv[i]) {
|
||||||
fprintf(fp, "argv_%d=%s\n", i, argv[i]);
|
fprintf(fp, "\nargv_%d=%s", i, argv[i]);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
fprintf(fp, "name=");
|
|
||||||
if (name)
|
|
||||||
fprintf(fp, "%s", name);
|
|
||||||
fprintf(fp, "\npidfile=");
|
fprintf(fp, "\npidfile=");
|
||||||
if (pidfile)
|
if (pidfile)
|
||||||
fprintf(fp, "%s", pidfile);
|
fprintf(fp, "%s", pidfile);
|
||||||
@ -427,7 +417,8 @@ bool rc_service_daemon_set(const char *service, const char *const *argv,
|
|||||||
}
|
}
|
||||||
librc_hidden_def(rc_service_daemon_set)
|
librc_hidden_def(rc_service_daemon_set)
|
||||||
|
|
||||||
bool rc_service_started_daemon(const char *service, const char *const *argv,
|
bool rc_service_started_daemon(const char *service,
|
||||||
|
const char *exec, const char *const *argv,
|
||||||
int indx)
|
int indx)
|
||||||
{
|
{
|
||||||
char dirpath[PATH_MAX];
|
char dirpath[PATH_MAX];
|
||||||
@ -442,7 +433,7 @@ bool rc_service_started_daemon(const char *service, const char *const *argv,
|
|||||||
|
|
||||||
snprintf(dirpath, sizeof(dirpath), RC_SVCDIR "/daemons/%s",
|
snprintf(dirpath, sizeof(dirpath), RC_SVCDIR "/daemons/%s",
|
||||||
basename_c(service));
|
basename_c(service));
|
||||||
match = _match_list(argv, NULL, NULL);
|
match = _match_list(exec, argv, NULL);
|
||||||
|
|
||||||
if (indx > 0) {
|
if (indx > 0) {
|
||||||
snprintf(file, sizeof(file), "%03d", indx);
|
snprintf(file, sizeof(file), "%03d", indx);
|
||||||
@ -492,7 +483,7 @@ bool rc_service_daemons_crashed(const char *service)
|
|||||||
path += snprintf(dirpath, sizeof(dirpath), RC_SVCDIR "/daemons/%s",
|
path += snprintf(dirpath, sizeof(dirpath), RC_SVCDIR "/daemons/%s",
|
||||||
basename_c(service));
|
basename_c(service));
|
||||||
|
|
||||||
if (! (dp = opendir(dirpath)))
|
if (!(dp = opendir(dirpath)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
while ((d = readdir(dp))) {
|
while ((d = readdir(dp))) {
|
||||||
@ -502,25 +493,25 @@ bool rc_service_daemons_crashed(const char *service)
|
|||||||
snprintf(path, sizeof(dirpath) - (path - dirpath), "/%s",
|
snprintf(path, sizeof(dirpath) - (path - dirpath), "/%s",
|
||||||
d->d_name);
|
d->d_name);
|
||||||
fp = fopen(dirpath, "r");
|
fp = fopen(dirpath, "r");
|
||||||
if (! fp)
|
if (!fp)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
while ((rc_getline(&line, &len, fp))) {
|
while ((rc_getline(&line, &len, fp))) {
|
||||||
p = line;
|
p = line;
|
||||||
if ((token = strsep(&p, "=")) == NULL || ! p)
|
if ((token = strsep(&p, "=")) == NULL || !p)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (! *p)
|
if (!*p)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (strncmp(token, "argv_", 5) == 0) {
|
if (strcmp(token, "exec") == 0) {
|
||||||
if (! list)
|
|
||||||
list = rc_stringlist_new();
|
|
||||||
rc_stringlist_add(list, p);
|
|
||||||
} else if (strcmp(token, "exec") == 0) {
|
|
||||||
if (exec)
|
if (exec)
|
||||||
free(exec);
|
free(exec);
|
||||||
exec = xstrdup(p);
|
exec = xstrdup(p);
|
||||||
|
} else if (strncmp(token, "argv_", 5) == 0) {
|
||||||
|
if (!list)
|
||||||
|
list = rc_stringlist_new();
|
||||||
|
rc_stringlist_add(list, p);
|
||||||
} else if (strcmp(token, "name") == 0) {
|
} else if (strcmp(token, "name") == 0) {
|
||||||
if (name)
|
if (name)
|
||||||
free(name);
|
free(name);
|
||||||
@ -548,9 +539,9 @@ bool rc_service_daemons_crashed(const char *service)
|
|||||||
name = NULL;
|
name = NULL;
|
||||||
} else {
|
} else {
|
||||||
if (exec) {
|
if (exec) {
|
||||||
if (! list)
|
if (!list)
|
||||||
list = rc_stringlist_new();
|
list = rc_stringlist_new();
|
||||||
if (! TAILQ_FIRST(list))
|
if (!TAILQ_FIRST(list))
|
||||||
rc_stringlist_add(list, exec);
|
rc_stringlist_add(list, exec);
|
||||||
|
|
||||||
free(exec);
|
free(exec);
|
||||||
@ -570,9 +561,10 @@ bool rc_service_daemons_crashed(const char *service)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! retval) {
|
if (!retval) {
|
||||||
if ((pids = rc_find_pids((const char *const *)argv,
|
if ((pids = rc_find_pids(exec,
|
||||||
name, 0, pid)))
|
(const char *const *)argv,
|
||||||
|
0, pid)))
|
||||||
{
|
{
|
||||||
p1 = LIST_FIRST(pids);
|
p1 = LIST_FIRST(pids);
|
||||||
while (p1) {
|
while (p1) {
|
||||||
|
@ -142,7 +142,7 @@ bool rc_service_delete(const char *, const char *);
|
|||||||
* @param name of the process (optional)
|
* @param name of the process (optional)
|
||||||
* @param pidfile of the process (optional)
|
* @param pidfile of the process (optional)
|
||||||
* @param started if true, add the arguments otherwise remove existing matching arguments */
|
* @param started if true, add the arguments otherwise remove existing matching arguments */
|
||||||
bool rc_service_daemon_set(const char *, const char *const *, const char *, const char *,
|
bool rc_service_daemon_set(const char *, const char *, const char *const *, const char *,
|
||||||
bool);
|
bool);
|
||||||
|
|
||||||
/*! Returns a description of what the service and/or option does.
|
/*! Returns a description of what the service and/or option does.
|
||||||
@ -202,9 +202,11 @@ RC_SERVICE rc_service_state(const char *);
|
|||||||
/*! Check if the service started the daemon
|
/*! Check if the service started the daemon
|
||||||
* @param service to check
|
* @param service to check
|
||||||
* @param exec to check
|
* @param exec to check
|
||||||
|
* @param argv to check
|
||||||
* @param indx of the daemon (optional - 1st daemon, 2nd daemon, etc)
|
* @param indx of the daemon (optional - 1st daemon, 2nd daemon, etc)
|
||||||
* @return true if started by this service, otherwise false */
|
* @return true if started by this service, otherwise false */
|
||||||
bool rc_service_started_daemon(const char *, const char *const *, int);
|
bool rc_service_started_daemon(const char *, const char *,
|
||||||
|
const char *const *, int);
|
||||||
|
|
||||||
/*! Return a saved value for a service
|
/*! Return a saved value for a service
|
||||||
* @param service to check
|
* @param service to check
|
||||||
@ -463,11 +465,11 @@ typedef LIST_HEAD(rc_pidlist, rc_pid) RC_PIDLIST;
|
|||||||
* pid overrides anything else.
|
* pid overrides anything else.
|
||||||
* If both exec and cmd are given then we ignore exec.
|
* If both exec and cmd are given then we ignore exec.
|
||||||
* @param exec to check for
|
* @param exec to check for
|
||||||
* @param cmd to check for
|
* @param argv to check for
|
||||||
* @param uid to check for
|
* @param uid to check for
|
||||||
* @param pid to check for
|
* @param pid to check for
|
||||||
* @return NULL terminated list of pids */
|
* @return NULL terminated list of pids */
|
||||||
RC_PIDLIST *rc_find_pids(const char *const *, const char *, uid_t, pid_t);
|
RC_PIDLIST *rc_find_pids(const char *, const char *const *, uid_t, pid_t);
|
||||||
|
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
#endif
|
#endif
|
||||||
|
@ -30,15 +30,14 @@ RC_SBINLINKS= mark_service_starting mark_service_started \
|
|||||||
ALL_LINKS= ${BINLINKS} ${SBINLINKS} ${RC_BINLINKS} ${RC_SBINLINKS}
|
ALL_LINKS= ${BINLINKS} ${SBINLINKS} ${RC_BINLINKS} ${RC_SBINLINKS}
|
||||||
CLEANFILES+= ${ALL_LINKS}
|
CLEANFILES+= ${ALL_LINKS}
|
||||||
|
|
||||||
|
CPPFLAGS+= -I../includes -I../librc -I../libeinfo
|
||||||
LDFLAGS+= -L../librc -L../libeinfo
|
LDFLAGS+= -L../librc -L../libeinfo
|
||||||
LDADD+= -lutil -lrc -leinfo
|
LDADD+= -lutil -lrc -leinfo
|
||||||
|
|
||||||
MK= ../../mk
|
MK= ../../mk
|
||||||
|
include ${MK}/debug.mk
|
||||||
include ${MK}/prog.mk
|
include ${MK}/prog.mk
|
||||||
include ${MK}/cc.mk
|
include ${MK}/cc.mk
|
||||||
include ${MK}/debug.mk
|
|
||||||
|
|
||||||
CPPFLAGS+= -I../includes -I../librc -I../libeinfo
|
|
||||||
|
|
||||||
include ${MK}/${MKTERMCAP}.mk
|
include ${MK}/${MKTERMCAP}.mk
|
||||||
LDADD+= ${LIBDL} ${LIBKVM}
|
LDADD+= ${LIBDL} ${LIBKVM}
|
||||||
|
@ -243,9 +243,9 @@ static int do_e(int argc, char **argv)
|
|||||||
static int do_service(int argc, char **argv)
|
static int do_service(int argc, char **argv)
|
||||||
{
|
{
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
char *service = NULL;
|
char *service;
|
||||||
|
char *exec;
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
char *d[] = { NULL, NULL };
|
|
||||||
|
|
||||||
if (argc > 1)
|
if (argc > 1)
|
||||||
service = argv[1];
|
service = argv[1];
|
||||||
@ -270,21 +270,19 @@ static int do_service(int argc, char **argv)
|
|||||||
else if (strcmp(applet, "service_wasinactive") == 0)
|
else if (strcmp(applet, "service_wasinactive") == 0)
|
||||||
ok = (rc_service_state(service) & RC_SERVICE_WASINACTIVE);
|
ok = (rc_service_state(service) & RC_SERVICE_WASINACTIVE);
|
||||||
else if (strcmp(applet, "service_started_daemon") == 0) {
|
else if (strcmp(applet, "service_started_daemon") == 0) {
|
||||||
d[0] = argv[1];
|
|
||||||
|
|
||||||
service = getenv("RC_SVCNAME");
|
service = getenv("RC_SVCNAME");
|
||||||
|
exec = argv[1];
|
||||||
if (argc > 3) {
|
if (argc > 3) {
|
||||||
service = argv[1];
|
service = argv[1];
|
||||||
d[0] = argv[2];
|
exec = argv[2];
|
||||||
sscanf(argv[3], "%d", &idx);
|
sscanf(argv[3], "%d", &idx);
|
||||||
} else if (argc == 3) {
|
} else if (argc == 3) {
|
||||||
if (sscanf(argv[2], "%d", &idx) != 1) {
|
if (sscanf(argv[2], "%d", &idx) != 1) {
|
||||||
service = argv[1];
|
service = argv[1];
|
||||||
d[0] = argv[2];
|
exec = argv[2];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ok = rc_service_started_daemon(service,
|
ok = rc_service_started_daemon(service, exec, NULL, idx);
|
||||||
(const char * const *)d, idx);
|
|
||||||
|
|
||||||
} else
|
} else
|
||||||
eerrorx("%s: unknown applet", applet);
|
eerrorx("%s: unknown applet", applet);
|
||||||
|
@ -157,7 +157,7 @@ static int parse_signal(const char *sig)
|
|||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
const char *s;
|
const char *s;
|
||||||
|
|
||||||
if (! sig || *sig == '\0')
|
if (!sig || *sig == '\0')
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (sscanf(sig, "%u", &i) == 1) {
|
if (sscanf(sig, "%u", &i) == 1) {
|
||||||
@ -289,13 +289,13 @@ static pid_t get_pid(const char *pidfile, bool quiet)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if ((fp = fopen(pidfile, "r")) == NULL) {
|
if ((fp = fopen(pidfile, "r")) == NULL) {
|
||||||
if (! quiet)
|
if (!quiet)
|
||||||
eerror("%s: fopen `%s': %s", applet, pidfile, strerror(errno));
|
eerror("%s: fopen `%s': %s", applet, pidfile, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fscanf(fp, "%d", &pid) != 1) {
|
if (fscanf(fp, "%d", &pid) != 1) {
|
||||||
if (! quiet)
|
if (!quiet)
|
||||||
eerror("%s: no pid found in `%s'", applet, pidfile);
|
eerror("%s: no pid found in `%s'", applet, pidfile);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return -1;
|
return -1;
|
||||||
@ -307,7 +307,7 @@ static pid_t get_pid(const char *pidfile, bool quiet)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* return number of processed killed, -1 on error */
|
/* return number of processed killed, -1 on error */
|
||||||
static int do_stop(const char *const *argv, const char *cmd,
|
static int do_stop(const char *exec, const char *const *argv,
|
||||||
pid_t pid, uid_t uid,int sig,
|
pid_t pid, uid_t uid,int sig,
|
||||||
bool quiet, bool verbose, bool test)
|
bool quiet, bool verbose, bool test)
|
||||||
{
|
{
|
||||||
@ -320,14 +320,14 @@ static int do_stop(const char *const *argv, const char *cmd,
|
|||||||
if (pid)
|
if (pid)
|
||||||
pids = rc_find_pids(NULL, NULL, 0, pid);
|
pids = rc_find_pids(NULL, NULL, 0, pid);
|
||||||
else
|
else
|
||||||
pids = rc_find_pids(argv, cmd, uid, pid);
|
pids = rc_find_pids(exec, argv, uid, pid);
|
||||||
|
|
||||||
if (! pids)
|
if (!pids)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
LIST_FOREACH_SAFE(pi, pids, entries, np) {
|
LIST_FOREACH_SAFE(pi, pids, entries, np) {
|
||||||
if (test) {
|
if (test) {
|
||||||
if (! quiet)
|
if (!quiet)
|
||||||
einfo("Would send signal %d to PID %d",
|
einfo("Would send signal %d to PID %d",
|
||||||
sig, pi->pid);
|
sig, pi->pid);
|
||||||
nkilled++;
|
nkilled++;
|
||||||
@ -342,7 +342,7 @@ static int do_stop(const char *const *argv, const char *cmd,
|
|||||||
eend(killed ? 0 : 1,
|
eend(killed ? 0 : 1,
|
||||||
"%s: failed to send signal %d to PID %d: %s",
|
"%s: failed to send signal %d to PID %d: %s",
|
||||||
applet, sig, pi->pid, strerror(errno));
|
applet, sig, pi->pid, strerror(errno));
|
||||||
if (! killed) {
|
if (!killed) {
|
||||||
nkilled = -1;
|
nkilled = -1;
|
||||||
} else {
|
} else {
|
||||||
if (nkilled != -1)
|
if (nkilled != -1)
|
||||||
@ -356,7 +356,7 @@ static int do_stop(const char *const *argv, const char *cmd,
|
|||||||
return nkilled;
|
return nkilled;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int run_stop_schedule(const char *const *argv, const char *cmd,
|
static int run_stop_schedule(const char *exec, const char *const *argv,
|
||||||
const char *pidfile, uid_t uid,
|
const char *pidfile, uid_t uid,
|
||||||
bool quiet, bool verbose, bool test)
|
bool quiet, bool verbose, bool test)
|
||||||
{
|
{
|
||||||
@ -369,14 +369,14 @@ static int run_stop_schedule(const char *const *argv, const char *cmd,
|
|||||||
pid_t pid = 0;
|
pid_t pid = 0;
|
||||||
|
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
|
if (exec)
|
||||||
|
einfo ("Will stop %s\n", exec);
|
||||||
if (pidfile)
|
if (pidfile)
|
||||||
einfo("Will stop PID in pidfile `%s'", pidfile);
|
einfo("Will stop PID in pidfile `%s'", pidfile);
|
||||||
if (uid)
|
if (uid)
|
||||||
einfo("Will stop processes owned by UID %d", uid);
|
einfo("Will stop processes owned by UID %d", uid);
|
||||||
if (argv && *argv)
|
if (argv && *argv)
|
||||||
einfo("Will stop processes of `%s'", *argv);
|
einfo("Will stop processes of `%s'", *argv);
|
||||||
if (cmd)
|
|
||||||
einfo("Will stop processes called `%s'", cmd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pidfile) {
|
if (pidfile) {
|
||||||
@ -393,7 +393,7 @@ static int run_stop_schedule(const char *const *argv, const char *cmd,
|
|||||||
|
|
||||||
case SC_SIGNAL:
|
case SC_SIGNAL:
|
||||||
nrunning = 0;
|
nrunning = 0;
|
||||||
nkilled = do_stop(argv, cmd, pid, uid, item->value,
|
nkilled = do_stop(exec, argv, pid, uid, item->value,
|
||||||
quiet, verbose, test);
|
quiet, verbose, test);
|
||||||
if (nkilled == 0) {
|
if (nkilled == 0) {
|
||||||
if (tkilled == 0) {
|
if (tkilled == 0) {
|
||||||
@ -419,7 +419,7 @@ static int run_stop_schedule(const char *const *argv, const char *cmd,
|
|||||||
ts.tv_nsec = POLL_INTERVAL;
|
ts.tv_nsec = POLL_INTERVAL;
|
||||||
|
|
||||||
while (nloops) {
|
while (nloops) {
|
||||||
if ((nrunning = do_stop(argv, cmd, pid,
|
if ((nrunning = do_stop(exec, argv, pid,
|
||||||
uid, 0, true, false, true)) == 0)
|
uid, 0, true, false, true)) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -466,15 +466,15 @@ static void handle_signal(int sig)
|
|||||||
|
|
||||||
switch (sig) {
|
switch (sig) {
|
||||||
case SIGINT:
|
case SIGINT:
|
||||||
if (! signame[0])
|
if (!signame[0])
|
||||||
snprintf(signame, sizeof(signame), "SIGINT");
|
snprintf(signame, sizeof(signame), "SIGINT");
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case SIGTERM:
|
case SIGTERM:
|
||||||
if (! signame[0])
|
if (!signame[0])
|
||||||
snprintf(signame, sizeof(signame), "SIGTERM");
|
snprintf(signame, sizeof(signame), "SIGTERM");
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case SIGQUIT:
|
case SIGQUIT:
|
||||||
if (! signame[0])
|
if (!signame[0])
|
||||||
snprintf(signame, sizeof(signame), "SIGQUIT");
|
snprintf(signame, sizeof(signame), "SIGQUIT");
|
||||||
eerrorx("%s: caught %s, aborting", applet, signame);
|
eerrorx("%s: caught %s, aborting", applet, signame);
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
@ -499,7 +499,7 @@ static void handle_signal(int sig)
|
|||||||
|
|
||||||
|
|
||||||
#include "_usage.h"
|
#include "_usage.h"
|
||||||
#define getoptstring "KN:R:Sbc:d:g:mn:op:s:tu:r:x:1:2:" getoptstring_COMMON
|
#define getoptstring "KN:R:Sbc:d:e:g:mn:op:s:tu:r:x:1:2:" getoptstring_COMMON
|
||||||
static const struct option longopts[] = {
|
static const struct option longopts[] = {
|
||||||
{ "stop", 0, NULL, 'K'},
|
{ "stop", 0, NULL, 'K'},
|
||||||
{ "nicelevel", 1, NULL, 'N'},
|
{ "nicelevel", 1, NULL, 'N'},
|
||||||
@ -529,7 +529,7 @@ static const char * const longopts_help[] = {
|
|||||||
"Set a nicelevel when starting",
|
"Set a nicelevel when starting",
|
||||||
"Retry schedule to use when stopping",
|
"Retry schedule to use when stopping",
|
||||||
"Start daemon",
|
"Start daemon",
|
||||||
"deprecated, use --exec",
|
"deprecated, use --exec or --name",
|
||||||
"Force daemon to background",
|
"Force daemon to background",
|
||||||
"deprecated, use --user",
|
"deprecated, use --user",
|
||||||
"Change the PWD",
|
"Change the PWD",
|
||||||
@ -563,14 +563,14 @@ int start_stop_daemon(int argc, char **argv)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
int opt;
|
int opt;
|
||||||
bool start = false;
|
bool start = true;
|
||||||
bool stop = false;
|
|
||||||
bool oknodo = false;
|
bool oknodo = false;
|
||||||
bool test = false;
|
bool test = false;
|
||||||
bool quiet;
|
bool quiet;
|
||||||
bool verbose = false;
|
bool verbose = false;
|
||||||
char *exec = NULL;
|
char *exec = NULL;
|
||||||
char *cmd = NULL;
|
char *startas = NULL;
|
||||||
|
char *name = NULL;
|
||||||
char *pidfile = NULL;
|
char *pidfile = NULL;
|
||||||
int sig = SIGTERM;
|
int sig = SIGTERM;
|
||||||
int nicelevel = 0;
|
int nicelevel = 0;
|
||||||
@ -585,16 +585,16 @@ int start_stop_daemon(int argc, char **argv)
|
|||||||
char *redirect_stdout = NULL;
|
char *redirect_stdout = NULL;
|
||||||
int stdout_fd;
|
int stdout_fd;
|
||||||
int stderr_fd;
|
int stderr_fd;
|
||||||
pid_t pid;
|
pid_t pid, spid;
|
||||||
int i;
|
int i;
|
||||||
char *svcname = getenv("RC_SVCNAME");
|
char *svcname = getenv("RC_SVCNAME");
|
||||||
RC_STRINGLIST *env_list;
|
RC_STRINGLIST *env_list;
|
||||||
RC_STRING *env;
|
RC_STRING *env;
|
||||||
char *path;
|
char *tmp, *newpath, *np;
|
||||||
bool sethome = false;
|
bool sethome = false;
|
||||||
bool setuser = false;
|
bool setuser = false;
|
||||||
char *p;
|
char *p;
|
||||||
char *tmp;
|
char *token;
|
||||||
char exec_file[PATH_MAX];
|
char exec_file[PATH_MAX];
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
struct group *gr;
|
struct group *gr;
|
||||||
@ -609,16 +609,16 @@ int start_stop_daemon(int argc, char **argv)
|
|||||||
signal_setup(SIGQUIT, handle_signal);
|
signal_setup(SIGQUIT, handle_signal);
|
||||||
signal_setup(SIGTERM, handle_signal);
|
signal_setup(SIGTERM, handle_signal);
|
||||||
|
|
||||||
if ((path = getenv("SSD_NICELEVEL")))
|
if ((tmp = getenv("SSD_NICELEVEL")))
|
||||||
if (sscanf(path, "%d", &nicelevel) != 1)
|
if (sscanf(tmp, "%d", &nicelevel) != 1)
|
||||||
eerror("%s: invalid nice level `%s' (SSD_NICELEVEL)",
|
eerror("%s: invalid nice level `%s' (SSD_NICELEVEL)",
|
||||||
applet, path);
|
applet, tmp);
|
||||||
|
|
||||||
while ((opt = getopt_long(argc, argv, "e:" getoptstring, longopts,
|
while ((opt = getopt_long(argc, argv, getoptstring, longopts,
|
||||||
(int *) 0)) != -1)
|
(int *) 0)) != -1)
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'K': /* --stop */
|
case 'K': /* --stop */
|
||||||
stop = true;
|
start = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'N': /* --nice */
|
case 'N': /* --nice */
|
||||||
@ -701,7 +701,7 @@ int start_stop_daemon(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'n': /* --name <process-name> */
|
case 'n': /* --name <process-name> */
|
||||||
cmd = optarg;
|
name = optarg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'o': /* --oknodo */
|
case 'o': /* --oknodo */
|
||||||
@ -724,7 +724,9 @@ int start_stop_daemon(int argc, char **argv)
|
|||||||
ch_root = optarg;
|
ch_root = optarg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'a':
|
case 'a': /* --startas <name> */
|
||||||
|
startas = optarg;
|
||||||
|
break;
|
||||||
case 'x': /* --exec <executable> */
|
case 'x': /* --exec <executable> */
|
||||||
exec = optarg;
|
exec = optarg;
|
||||||
break;
|
break;
|
||||||
@ -740,65 +742,118 @@ int start_stop_daemon(int argc, char **argv)
|
|||||||
case_RC_COMMON_GETOPT
|
case_RC_COMMON_GETOPT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
argc -= optind;
|
||||||
|
argv += optind;
|
||||||
quiet = rc_yesno(getenv("EINFO_QUIET"));
|
quiet = rc_yesno(getenv("EINFO_QUIET"));
|
||||||
verbose = rc_yesno(getenv("EINFO_VERBOSE"));
|
verbose = rc_yesno(getenv("EINFO_VERBOSE"));
|
||||||
|
|
||||||
/* Allow start-stop-daemon --signal HUP --exec /usr/sbin/dnsmasq
|
/* Allow start-stop-daemon --signal HUP --exec /usr/sbin/dnsmasq
|
||||||
* instead of forcing --stop --oknodo as well */
|
* instead of forcing --stop --oknodo as well */
|
||||||
if (! start && ! stop)
|
if (!start &&
|
||||||
if (sig != SIGINT &&
|
sig != SIGINT &&
|
||||||
sig != SIGTERM &&
|
sig != SIGTERM &&
|
||||||
sig != SIGQUIT &&
|
sig != SIGQUIT &&
|
||||||
sig != SIGKILL)
|
sig != SIGKILL)
|
||||||
{
|
|
||||||
oknodo = true;
|
oknodo = true;
|
||||||
stop = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (start == stop)
|
if (!exec)
|
||||||
eerrorx("%s: need one of --start or --stop", applet);
|
exec = startas;
|
||||||
|
else if (!name)
|
||||||
|
name = startas;
|
||||||
|
|
||||||
if (start && ! exec)
|
if (!exec) {
|
||||||
eerrorx("%s: --start needs --exec", applet);
|
exec = *argv;
|
||||||
|
if (name)
|
||||||
|
*argv = name;
|
||||||
|
} else if (name)
|
||||||
|
*--argv = name;
|
||||||
|
else
|
||||||
|
*--argv = exec;
|
||||||
|
|
||||||
if (stop && ! exec && ! pidfile && ! cmd && ! uid)
|
|
||||||
|
if (start && !exec)
|
||||||
|
eerrorx("%s: nothing to start", applet);
|
||||||
|
|
||||||
|
if (!start && !*argv && !pidfile && !name && !uid)
|
||||||
eerrorx("%s: --stop needs --exec, --pidfile, --name or --user", applet);
|
eerrorx("%s: --stop needs --exec, --pidfile, --name or --user", applet);
|
||||||
|
|
||||||
if (makepidfile && ! pidfile)
|
if (makepidfile && !pidfile)
|
||||||
eerrorx("%s: --make-pidfile is only relevant with --pidfile", applet);
|
eerrorx("%s: --make-pidfile is only relevant with --pidfile", applet);
|
||||||
|
|
||||||
if (background && ! start)
|
if (background && !start)
|
||||||
eerrorx("%s: --background is only relevant with --start", applet);
|
eerrorx("%s: --background is only relevant with --start", applet);
|
||||||
|
|
||||||
if ((redirect_stdout || redirect_stderr) && ! background)
|
if ((redirect_stdout || redirect_stderr) && !background)
|
||||||
eerrorx("%s: --stdout and --stderr are only relevant with --background",
|
eerrorx("%s: --stdout and --stderr are only relevant with --background",
|
||||||
applet);
|
applet);
|
||||||
|
|
||||||
argc -= optind;
|
if (!start) {
|
||||||
argv += optind;
|
if (!TAILQ_FIRST(&schedule)) {
|
||||||
|
if (test || oknodo)
|
||||||
|
parse_schedule("0", sig);
|
||||||
|
else
|
||||||
|
parse_schedule(NULL, sig);
|
||||||
|
}
|
||||||
|
i = run_stop_schedule(exec, (const char *const *)argv,
|
||||||
|
pidfile, uid, quiet, verbose, test);
|
||||||
|
|
||||||
|
if (i < 0)
|
||||||
|
/* We failed to stop something */
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
if (test || oknodo)
|
||||||
|
return i > 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
|
|
||||||
|
/* Even if we have not actually killed anything, we should
|
||||||
|
* remove information about it as it may have unexpectedly
|
||||||
|
* crashed out. We should also return success as the end
|
||||||
|
* result would be the same. */
|
||||||
|
if (pidfile && exists(pidfile))
|
||||||
|
unlink(pidfile);
|
||||||
|
if (svcname)
|
||||||
|
rc_service_daemon_set(svcname, exec,
|
||||||
|
(const char *const *)argv,
|
||||||
|
pidfile, false);
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
/* Validate that the binary exists if we are starting */
|
/* Validate that the binary exists if we are starting */
|
||||||
if (exec) {
|
if (*exec == '/' || *exec == '.') {
|
||||||
if (ch_root) {
|
/* Full or relative path */
|
||||||
|
if (ch_root)
|
||||||
snprintf(exec_file, sizeof(exec_file), "%s/%s", ch_root, exec);
|
snprintf(exec_file, sizeof(exec_file), "%s/%s", ch_root, exec);
|
||||||
tmp = exec_file;
|
else
|
||||||
} else
|
snprintf(exec_file, sizeof(exec_file), "%s", exec);
|
||||||
tmp = exec;
|
} else {
|
||||||
if (start && ! exists(tmp)) {
|
/* Something in $PATH */
|
||||||
eerror("%s: %s does not exist", applet, tmp);
|
p = tmp = xstrdup(getenv("PATH"));
|
||||||
|
*exec_file = '\0';
|
||||||
|
while ((token = strsep(&p, ":"))) {
|
||||||
|
if (ch_root)
|
||||||
|
snprintf(exec_file, sizeof(exec_file), "%s/%s/%s", ch_root, token, exec);
|
||||||
|
else
|
||||||
|
snprintf(exec_file, sizeof(exec_file), "%s/%s", token, exec);
|
||||||
|
if (exists(exec_file))
|
||||||
|
break;
|
||||||
|
*exec_file = '\0';
|
||||||
|
}
|
||||||
|
free(tmp);
|
||||||
|
}
|
||||||
|
if (!exists(exec_file)) {
|
||||||
|
eerror("%s: %s does not exist", applet,
|
||||||
|
*exec_file ? exec_file : exec);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we don't have a pidfile or name, check it's not
|
/* If we don't have a pidfile or name, check it's not
|
||||||
* interpreted, otherwise we should fail */
|
* interpreted, otherwise we should fail */
|
||||||
if (! pidfile && ! cmd) {
|
if (!pidfile && !name) {
|
||||||
fp = fopen (tmp, "r");
|
fp = fopen(tmp, "r");
|
||||||
if (fp) {
|
if (fp) {
|
||||||
fgets(line, sizeof(line), fp);
|
fgets(line, sizeof(line), fp);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
if (line[0] == '#' && line[1] == '!') {
|
if (line[0] == '#' && line[1] == '!') {
|
||||||
len = strlen (line) - 1;
|
len = strlen(line) - 1;
|
||||||
|
|
||||||
/* Remove the trailing newline */
|
/* Remove the trailing newline */
|
||||||
if (line[len] == '\n')
|
if (line[len] == '\n')
|
||||||
@ -816,52 +871,13 @@ int start_stop_daemon(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Add exec to our arguments */
|
if (pidfile)
|
||||||
*--argv = exec;
|
|
||||||
|
|
||||||
if (stop) {
|
|
||||||
int result;
|
|
||||||
|
|
||||||
if (! TAILQ_FIRST(&schedule)) {
|
|
||||||
if (test || oknodo)
|
|
||||||
parse_schedule("0", sig);
|
|
||||||
else
|
|
||||||
parse_schedule(NULL, sig);
|
|
||||||
}
|
|
||||||
|
|
||||||
result = run_stop_schedule((const char *const *)argv, cmd,
|
|
||||||
pidfile, uid, quiet, verbose, test);
|
|
||||||
|
|
||||||
if (result < 0)
|
|
||||||
/* We failed to stop something */
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
|
|
||||||
if (test || oknodo)
|
|
||||||
return result > 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
|
||||||
|
|
||||||
/* Even if we have not actually killed anything, we should
|
|
||||||
* remove information about it as it may have unexpectedly
|
|
||||||
* crashed out. We should also return success as the end
|
|
||||||
* result would be the same. */
|
|
||||||
if (pidfile && exists(pidfile))
|
|
||||||
unlink(pidfile);
|
|
||||||
|
|
||||||
if (svcname)
|
|
||||||
rc_service_daemon_set(svcname,
|
|
||||||
(const char *const *)argv,
|
|
||||||
cmd, pidfile, false);
|
|
||||||
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pidfile) {
|
|
||||||
pid = get_pid(pidfile, true);
|
pid = get_pid(pidfile, true);
|
||||||
} else
|
else
|
||||||
pid = 0;
|
pid = 0;
|
||||||
|
|
||||||
if (do_stop((const char * const *)argv, cmd, pid, uid,
|
if (do_stop(exec, (const char * const *)argv, pid, uid,
|
||||||
0, true, false, true) > 0)
|
0, true, false, true) > 0)
|
||||||
eerrorx("%s: %s is already running", applet, exec);
|
eerrorx("%s: %s is already running", applet, exec);
|
||||||
|
|
||||||
@ -884,6 +900,8 @@ int start_stop_daemon(int argc, char **argv)
|
|||||||
einfo("in dir `%s'", ch_dir);
|
einfo("in dir `%s'", ch_dir);
|
||||||
if (nicelevel != 0)
|
if (nicelevel != 0)
|
||||||
einfo("with a priority of %d", nicelevel);
|
einfo("with a priority of %d", nicelevel);
|
||||||
|
if (name)
|
||||||
|
einfo ("with a process name of %s", name);
|
||||||
eoutdent();
|
eoutdent();
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
@ -918,7 +936,7 @@ int start_stop_daemon(int argc, char **argv)
|
|||||||
if (ch_root && chroot(ch_root) < 0)
|
if (ch_root && chroot(ch_root) < 0)
|
||||||
eerrorx("%s: chroot `%s': %s", applet, ch_root, strerror(errno));
|
eerrorx("%s: chroot `%s': %s", applet, ch_root, strerror(errno));
|
||||||
|
|
||||||
if (ch_dir && chdir (ch_dir) < 0)
|
if (ch_dir && chdir(ch_dir) < 0)
|
||||||
eerrorx("%s: chdir `%s': %s", applet, ch_dir, strerror(errno));
|
eerrorx("%s: chdir `%s': %s", applet, ch_dir, strerror(errno));
|
||||||
|
|
||||||
if (makepidfile && pidfile) {
|
if (makepidfile && pidfile) {
|
||||||
@ -955,12 +973,12 @@ int start_stop_daemon(int argc, char **argv)
|
|||||||
else {
|
else {
|
||||||
pw = getpwuid(uid);
|
pw = getpwuid(uid);
|
||||||
if (pw) {
|
if (pw) {
|
||||||
if (! sethome) {
|
if (!sethome) {
|
||||||
unsetenv("HOME");
|
unsetenv("HOME");
|
||||||
if (pw->pw_dir)
|
if (pw->pw_dir)
|
||||||
setenv("HOME", pw->pw_dir, 1);
|
setenv("HOME", pw->pw_dir, 1);
|
||||||
}
|
}
|
||||||
if (! setuser) {
|
if (!setuser) {
|
||||||
unsetenv("USER");
|
unsetenv("USER");
|
||||||
if (pw->pw_name)
|
if (pw->pw_name)
|
||||||
setenv("USER", pw->pw_name, 1);
|
setenv("USER", pw->pw_name, 1);
|
||||||
@ -996,26 +1014,22 @@ int start_stop_daemon(int argc, char **argv)
|
|||||||
rc_stringlist_free(env_list);
|
rc_stringlist_free(env_list);
|
||||||
|
|
||||||
/* For the path, remove the rcscript bin dir from it */
|
/* For the path, remove the rcscript bin dir from it */
|
||||||
if ((path = getenv("PATH"))) {
|
if ((tmp = xstrdup(getenv("PATH")))) {
|
||||||
size_t mx = strlen(path);
|
len = strlen(tmp);
|
||||||
char *newpath = xmalloc(mx);
|
newpath = np = xmalloc(len);
|
||||||
char *token;
|
p = tmp;
|
||||||
char *np = newpath;
|
while ((token = strsep(&p, ":"))) {
|
||||||
size_t l;
|
if (strcmp(token, RC_LIBDIR "/bin") == 0 ||
|
||||||
|
strcmp(token, RC_LIBDIR "/sbin") == 0)
|
||||||
p = path;
|
|
||||||
while ((token = strsep (&p, ":"))) {
|
|
||||||
if (strcmp (token, RC_LIBDIR "/bin") == 0 ||
|
|
||||||
strcmp (token, RC_LIBDIR "/sbin") == 0)
|
|
||||||
continue;
|
continue;
|
||||||
|
len = strlen(token);
|
||||||
l = strlen (token);
|
|
||||||
if (np != newpath)
|
if (np != newpath)
|
||||||
*np++ = ':';
|
*np++ = ':';
|
||||||
memcpy (np, token, l);
|
memcpy(np, token, len);
|
||||||
np += l;
|
np += len;
|
||||||
*np = '\0';
|
*np = '\0';
|
||||||
}
|
}
|
||||||
|
free(tmp);
|
||||||
unsetenv("PATH");
|
unsetenv("PATH");
|
||||||
setenv("PATH", newpath, 1);
|
setenv("PATH", newpath, 1);
|
||||||
}
|
}
|
||||||
@ -1047,7 +1061,7 @@ int start_stop_daemon(int argc, char **argv)
|
|||||||
close(i);
|
close(i);
|
||||||
|
|
||||||
setsid();
|
setsid();
|
||||||
execv(exec, argv);
|
execvp(exec, argv);
|
||||||
#ifdef HAVE_PAM
|
#ifdef HAVE_PAM
|
||||||
if (pamr == PAM_SUCCESS)
|
if (pamr == PAM_SUCCESS)
|
||||||
pam_close_session(pamh, PAM_SILENT);
|
pam_close_session(pamh, PAM_SILENT);
|
||||||
@ -1056,27 +1070,24 @@ int start_stop_daemon(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Parent process */
|
/* Parent process */
|
||||||
if (! background) {
|
if (!background) {
|
||||||
/* As we're not backgrounding the process, wait for our pid to return */
|
/* As we're not backgrounding the process, wait for our pid to return */
|
||||||
int status = 0;
|
i = 0;
|
||||||
int savepid = pid;
|
spid = pid;
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
do {
|
do {
|
||||||
pid = waitpid(savepid, &status, 0);
|
pid = waitpid(spid, &i, 0);
|
||||||
if (pid < 1) {
|
if (pid < 1) {
|
||||||
eerror("waitpid %d: %s", savepid, strerror(errno));
|
eerror("waitpid %d: %s", spid, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} while (! WIFEXITED(status) && ! WIFSIGNALED(status));
|
} while (!WIFEXITED(i) && !WIFSIGNALED(i));
|
||||||
|
if (!WIFEXITED(i) || WEXITSTATUS(i) != 0) {
|
||||||
if (! WIFEXITED(status) || WEXITSTATUS(status) != 0) {
|
if (!quiet)
|
||||||
if (! quiet)
|
|
||||||
eerrorx("%s: failed to start `%s'", applet, exec);
|
eerrorx("%s: failed to start `%s'", applet, exec);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
pid = spid;
|
||||||
pid = savepid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait a little bit and check that process is still running
|
/* Wait a little bit and check that process is still running
|
||||||
@ -1104,10 +1115,10 @@ int start_stop_daemon(int argc, char **argv)
|
|||||||
* created. Once everything is in place we then wait some more
|
* created. Once everything is in place we then wait some more
|
||||||
* to ensure that the daemon really is running and won't abort due
|
* to ensure that the daemon really is running and won't abort due
|
||||||
* to a config error. */
|
* to a config error. */
|
||||||
if (! background && pidfile && nloopsp)
|
if (!background && pidfile && nloopsp)
|
||||||
nloopsp --;
|
nloopsp--;
|
||||||
else
|
else
|
||||||
nloops --;
|
nloops--;
|
||||||
|
|
||||||
/* This is knarly.
|
/* This is knarly.
|
||||||
If we backgrounded then we know the exact pid.
|
If we backgrounded then we know the exact pid.
|
||||||
@ -1131,19 +1142,19 @@ int start_stop_daemon(int argc, char **argv)
|
|||||||
nloopsp = 0;
|
nloopsp = 0;
|
||||||
} else
|
} else
|
||||||
pid = 0;
|
pid = 0;
|
||||||
if (do_stop((const char *const *)argv, cmd,
|
if (do_stop(exec, (const char *const *)argv,
|
||||||
pid, uid, 0, true, false, true) > 0)
|
pid, uid, 0, true, false, true) > 0)
|
||||||
alive = true;
|
alive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! alive)
|
if (!alive)
|
||||||
eerrorx("%s: %s died", applet, exec);
|
eerrorx("%s: %s died", applet, exec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (svcname)
|
if (svcname)
|
||||||
rc_service_daemon_set(svcname, (const char *const *)argv,
|
rc_service_daemon_set(svcname, exec, (const char *const *)argv,
|
||||||
cmd, pidfile, true);
|
pidfile, true);
|
||||||
|
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
|
Loading…
Reference in New Issue
Block a user