Improve style for KNF

This commit is contained in:
Roy Marples 2009-04-23 21:31:22 +00:00
parent 6953474655
commit ade85d4bd8
20 changed files with 760 additions and 667 deletions

View File

@ -1,7 +1,7 @@
/* /*
einfo.c einfo.c
Informational functions Informational functions
*/ */
/* /*
* Copyright 2007-2008 Roy Marples <roy@marples.name> * Copyright 2007-2008 Roy Marples <roy@marples.name>
@ -110,10 +110,10 @@ hidden_proto(ewendv)
#define UP "\033[A" #define UP "\033[A"
#define _GET_CAP(_d, _c) strlcpy(_d, tgoto(_c, 0, 0), sizeof(_d)); #define _GET_CAP(_d, _c) strlcpy(_d, tgoto(_c, 0, 0), sizeof(_d));
#define _ASSIGN_CAP(_v) { \ #define _ASSIGN_CAP(_v) do { \
_v = p; \ _v = p; \
p += strlcpy(p, tmp, sizeof(ebuffer) - (p - ebuffer)) + 1; \ p += strlcpy(p, tmp, sizeof(ebuffer) - (p - ebuffer)) + 1; \
} } while (0)
/* A pointer to a string to prefix to einfo/ewarn/eerror messages */ /* A pointer to a string to prefix to einfo/ewarn/eerror messages */
static const char *_eprefix = NULL; static const char *_eprefix = NULL;
@ -497,7 +497,7 @@ colour_terminal(FILE * EINFO_RESTRICT f)
_GET_CAP(tmp, _me); _GET_CAP(tmp, _me);
if (tmp[0]) if (tmp[0])
_ASSIGN_CAP(ecolors_str[i]) _ASSIGN_CAP(ecolors_str[i]);
else else
ecolors_str[i] = &nullstr; ecolors_str[i] = &nullstr;
} }
@ -624,13 +624,13 @@ ecolor(ECOLOR color)
return _ecolor(f, color); return _ecolor(f, color);
} }
#define LASTCMD(_cmd) { \ #define LASTCMD(_cmd) { \
unsetenv("EINFO_LASTCMD"); \ unsetenv("EINFO_LASTCMD"); \
setenv("EINFO_LASTCMD", _cmd, 1); \ setenv("EINFO_LASTCMD", _cmd, 1); \
} }
static int EINFO_PRINTF(3, 0) static int EINFO_PRINTF(3, 0)
_einfo(FILE *f, ECOLOR color, const char *EINFO_RESTRICT fmt, va_list va) _einfo(FILE *f, ECOLOR color, const char *EINFO_RESTRICT fmt, va_list va)
{ {
int retval = 0; int retval = 0;
char *last = getenv("EINFO_LASTCMD"); char *last = getenv("EINFO_LASTCMD");
@ -836,8 +836,8 @@ _eend(FILE * EINFO_RESTRICT fp, int col, ECOLOR color, const char *msg)
* valuable columns when running on 80 column screens. */ * valuable columns when running on 80 column screens. */
if (cols > 0 && colour_terminal(fp)) { if (cols > 0 && colour_terminal(fp)) {
fprintf(fp, "%s%s %s[%s%s%s]%s\n", up, tgoto(goto_column, 0, cols), fprintf(fp, "%s%s %s[%s%s%s]%s\n", up, tgoto(goto_column, 0, cols),
ecolor(ECOLOR_BRACKET), ecolor(color), msg, ecolor(ECOLOR_BRACKET), ecolor(color), msg,
ecolor(ECOLOR_BRACKET), ecolor(ECOLOR_NORMAL)); ecolor(ECOLOR_BRACKET), ecolor(ECOLOR_NORMAL));
} else { } else {
if (col > 0) if (col > 0)
for (i = 0; i < cols - col; i++) for (i = 0; i < cols - col; i++)
@ -847,7 +847,8 @@ _eend(FILE * EINFO_RESTRICT fp, int col, ECOLOR color, const char *msg)
} }
static int EINFO_PRINTF(3, 0) static int EINFO_PRINTF(3, 0)
_do_eend(const char *cmd, int retval, const char *EINFO_RESTRICT fmt, va_list ap) _do_eend(const char *cmd, int retval,
const char *EINFO_RESTRICT fmt, va_list ap)
{ {
int col = 0; int col = 0;
FILE *fp = stdout; FILE *fp = stdout;
@ -864,8 +865,8 @@ _do_eend(const char *cmd, int retval, const char *EINFO_RESTRICT fmt, va_list ap
va_end(apc); va_end(apc);
} }
_eend(fp, col, _eend(fp, col,
retval == 0 ? ECOLOR_GOOD : ECOLOR_BAD, retval == 0 ? ECOLOR_GOOD : ECOLOR_BAD,
retval == 0 ? OK : NOT_OK); retval == 0 ? OK : NOT_OK);
return retval; return retval;
} }

View File

@ -1,7 +1,7 @@
/* /*
librc-daemon librc-daemon
Finds PID for given daemon criteria Finds PID for given daemon criteria
*/ */
/* /*
* Copyright 2007-2009 Roy Marples <roy@marples.name> * Copyright 2007-2009 Roy Marples <roy@marples.name>
@ -32,7 +32,8 @@
#include "librc.h" #include "librc.h"
#if defined(__linux__) #if defined(__linux__)
static bool pid_is_exec(pid_t pid, const char *exec) static bool
pid_is_exec(pid_t pid, const char *exec)
{ {
char buffer[32]; char buffer[32];
FILE *fp; FILE *fp;
@ -55,7 +56,8 @@ static bool pid_is_exec(pid_t pid, const char *exec)
return retval; return retval;
} }
static bool pid_is_argv(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;
@ -84,8 +86,8 @@ static bool pid_is_argv(pid_t pid, const char *const *argv)
return true; return true;
} }
RC_PIDLIST *rc_find_pids(const char *exec, const char *const *argv, RC_PIDLIST *
uid_t uid, pid_t pid) rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
{ {
DIR *procdir; DIR *procdir;
struct dirent *entry; struct dirent *entry;
@ -101,15 +103,15 @@ RC_PIDLIST *rc_find_pids(const char *exec, const char *const *argv,
return NULL; return NULL;
/* /*
We never match RC_RUNSCRIPT_PID if present so we avoid the below We never match RC_RUNSCRIPT_PID if present so we avoid the below
scenario scenario
/etc/init.d/ntpd stop does /etc/init.d/ntpd stop does
start-stop-daemon --stop --name ntpd start-stop-daemon --stop --name ntpd
catching /etc/init.d/ntpd stop catching /etc/init.d/ntpd stop
nasty nasty
*/ */
if ((pp = getenv("RC_RUNSCRIPT_PID"))) { if ((pp = getenv("RC_RUNSCRIPT_PID"))) {
if (sscanf(pp, "%d", &runscript_pid) != 1) if (sscanf(pp, "%d", &runscript_pid) != 1)
@ -170,8 +172,8 @@ 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 *exec, const char *const *argv, RC_PIDLIST *
uid_t uid, pid_t pid) rc_find_pids(const char *exec, const char *const *argv, uid_t uid, pid_t pid)
{ {
static kvm_t *kd = NULL; static kvm_t *kd = NULL;
char errbuf[_POSIX2_LINE_MAX]; char errbuf[_POSIX2_LINE_MAX];
@ -187,7 +189,7 @@ RC_PIDLIST *rc_find_pids(const char *exec, const char *const *argv,
int match; int match;
if ((kd = kvm_openfiles(_KVM_PATH, _KVM_PATH, if ((kd = kvm_openfiles(_KVM_PATH, _KVM_PATH,
NULL, _KVM_FLAGS, errbuf)) == NULL) NULL, _KVM_FLAGS, errbuf)) == NULL)
{ {
fprintf(stderr, "kvm_open: %s\n", errbuf); fprintf(stderr, "kvm_open: %s\n", errbuf);
return NULL; return NULL;
@ -249,8 +251,8 @@ librc_hidden_def(rc_find_pids)
# error "Platform not supported!" # error "Platform not supported!"
#endif #endif
static bool _match_daemon(const char *path, const char *file, static bool
RC_STRINGLIST *match) _match_daemon(const char *path, const char *file, RC_STRINGLIST *match)
{ {
char *line = NULL; char *line = NULL;
size_t len = 0; size_t len = 0;
@ -266,10 +268,10 @@ static bool _match_daemon(const char *path, const char *file,
while ((rc_getline(&line, &len, fp))) { while ((rc_getline(&line, &len, fp))) {
TAILQ_FOREACH(m, match, entries) TAILQ_FOREACH(m, match, entries)
if (strcmp(line, m->value) == 0) { if (strcmp(line, m->value) == 0) {
TAILQ_REMOVE(match, m, entries); TAILQ_REMOVE(match, m, entries);
break; break;
} }
if (!TAILQ_FIRST(match)) if (!TAILQ_FIRST(match))
break; break;
} }
@ -280,8 +282,8 @@ static bool _match_daemon(const char *path, const char *file,
return true; return true;
} }
static RC_STRINGLIST *_match_list(const char *exec, const char* const* argv, static RC_STRINGLIST *
const char *pidfile) _match_list(const char *exec, const char* const* argv, const char *pidfile)
{ {
RC_STRINGLIST *match = rc_stringlist_new(); RC_STRINGLIST *match = rc_stringlist_new();
int i = 0; int i = 0;
@ -315,9 +317,10 @@ static RC_STRINGLIST *_match_list(const char *exec, const char* const* argv,
return match; return match;
} }
bool rc_service_daemon_set(const char *service, const char *exec, bool
const char *const *argv, rc_service_daemon_set(const char *service, const char *exec,
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];
@ -336,7 +339,7 @@ bool rc_service_daemon_set(const char *service, const char *exec,
} }
snprintf(dirpath, sizeof(dirpath), RC_SVCDIR "/daemons/%s", snprintf(dirpath, sizeof(dirpath), RC_SVCDIR "/daemons/%s",
basename_c(service)); basename_c(service));
/* Regardless, erase any existing daemon info */ /* Regardless, erase any existing daemon info */
if ((dp = opendir(dirpath))) { if ((dp = opendir(dirpath))) {
@ -346,7 +349,7 @@ bool rc_service_daemon_set(const char *service, const char *exec,
continue; continue;
snprintf(file, sizeof(file), "%s/%s", snprintf(file, sizeof(file), "%s/%s",
dirpath, d->d_name); dirpath, d->d_name);
nfiles++; nfiles++;
if (!*oldfile) { if (!*oldfile) {
@ -368,7 +371,7 @@ bool rc_service_daemon_set(const char *service, const char *exec,
if (started) { if (started) {
if (mkdir(dirpath, 0755) == 0 || errno == EEXIST) { if (mkdir(dirpath, 0755) == 0 || errno == EEXIST) {
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="); fprintf(fp, "exec=");
if (exec) if (exec)
@ -392,9 +395,9 @@ bool rc_service_daemon_set(const char *service, const char *exec,
} }
librc_hidden_def(rc_service_daemon_set) librc_hidden_def(rc_service_daemon_set)
bool rc_service_started_daemon(const char *service, bool
const char *exec, const char *const *argv, rc_service_started_daemon(const char *service,
int indx) const char *exec, const char *const *argv, int indx)
{ {
char dirpath[PATH_MAX]; char dirpath[PATH_MAX];
char file[16]; char file[16];
@ -407,7 +410,7 @@ bool rc_service_started_daemon(const char *service,
return false; return false;
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(exec, argv, NULL); match = _match_list(exec, argv, NULL);
if (indx > 0) { if (indx > 0) {
@ -431,7 +434,8 @@ bool rc_service_started_daemon(const char *service,
} }
librc_hidden_def(rc_service_started_daemon) librc_hidden_def(rc_service_started_daemon)
bool rc_service_daemons_crashed(const char *service) bool
rc_service_daemons_crashed(const char *service)
{ {
char dirpath[PATH_MAX]; char dirpath[PATH_MAX];
DIR *dp; DIR *dp;
@ -456,7 +460,7 @@ bool rc_service_daemons_crashed(const char *service)
size_t i; size_t i;
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;
@ -466,7 +470,7 @@ bool rc_service_daemons_crashed(const char *service)
continue; continue;
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;
@ -529,19 +533,19 @@ bool rc_service_daemons_crashed(const char *service)
/* We need to flatten our linked list into an array */ /* We need to flatten our linked list into an array */
i = 0; i = 0;
TAILQ_FOREACH(s, list, entries) TAILQ_FOREACH(s, list, entries)
i++; i++;
argv = xmalloc(sizeof(char *) * (i + 1)); argv = xmalloc(sizeof(char *) * (i + 1));
i = 0; i = 0;
TAILQ_FOREACH(s, list, entries) TAILQ_FOREACH(s, list, entries)
argv[i++] = s->value; argv[i++] = s->value;
argv[i] = '\0'; argv[i] = '\0';
} }
} }
if (!retval) { if (!retval) {
if ((pids = rc_find_pids(exec, if ((pids = rc_find_pids(exec,
(const char *const *)argv, (const char *const *)argv,
0, pid))) 0, pid)))
{ {
p1 = LIST_FIRST(pids); p1 = LIST_FIRST(pids);
while (p1) { while (p1) {

View File

@ -1,7 +1,7 @@
/* /*
rc-misc.c rc-misc.c
rc misc functions rc misc functions
*/ */
/* /*
* Copyright 2007-2008 Roy Marples <roy@marples.name> * Copyright 2007-2008 Roy Marples <roy@marples.name>
@ -31,7 +31,8 @@
#include "librc.h" #include "librc.h"
bool rc_yesno(const char *value) bool
rc_yesno(const char *value)
{ {
if (!value) { if (!value) {
errno = ENOENT; errno = ENOENT;
@ -54,7 +55,8 @@ bool rc_yesno(const char *value)
} }
librc_hidden_def(rc_yesno) librc_hidden_def(rc_yesno)
ssize_t rc_getline(char **line, size_t *len, FILE *fp) ssize_t
rc_getline(char **line, size_t *len, FILE *fp)
{ {
char *p; char *p;
size_t last = 0; size_t last = 0;
@ -78,7 +80,8 @@ ssize_t rc_getline(char **line, size_t *len, FILE *fp)
} }
librc_hidden_def(rc_getline) librc_hidden_def(rc_getline)
RC_STRINGLIST *rc_config_list(const char *file) RC_STRINGLIST *
rc_config_list(const char *file)
{ {
FILE *fp; FILE *fp;
char *buffer = NULL; char *buffer = NULL;
@ -116,7 +119,8 @@ RC_STRINGLIST *rc_config_list(const char *file)
} }
librc_hidden_def(rc_config_list) librc_hidden_def(rc_config_list)
RC_STRINGLIST *rc_config_load(const char *file) RC_STRINGLIST *
rc_config_load(const char *file)
{ {
RC_STRINGLIST *list; RC_STRINGLIST *list;
RC_STRINGLIST *config; RC_STRINGLIST *config;
@ -172,7 +176,7 @@ RC_STRINGLIST *rc_config_load(const char *file)
TAILQ_FOREACH(cline, config, entries) { TAILQ_FOREACH(cline, config, entries) {
p = strchr(cline->value, '='); p = strchr(cline->value, '=');
if (p && strncmp(entry, cline->value, if (p && strncmp(entry, cline->value,
(size_t)(p - cline->value)) == 0) (size_t)(p - cline->value)) == 0)
{ {
/* We have a match now - to save time we directly replace it */ /* We have a match now - to save time we directly replace it */
free(cline->value); free(cline->value);
@ -194,7 +198,8 @@ RC_STRINGLIST *rc_config_load(const char *file)
} }
librc_hidden_def(rc_config_load) librc_hidden_def(rc_config_load)
char *rc_config_value(RC_STRINGLIST *list, const char *entry) char *
rc_config_value(RC_STRINGLIST *list, const char *entry)
{ {
RC_STRING *line; RC_STRING *line;
char *p; char *p;

View File

@ -1,7 +1,7 @@
/* /*
librc-strlist.h librc-strlist.h
String list functions to make using queue(3) a little easier. String list functions to make using queue(3) a little easier.
*/ */
/* /*
* Copyright 2007-2008 Roy Marples <roy@marples.name> * Copyright 2007-2008 Roy Marples <roy@marples.name>
@ -31,7 +31,8 @@
#include "librc.h" #include "librc.h"
RC_STRINGLIST *rc_stringlist_new(void) RC_STRINGLIST *
rc_stringlist_new(void)
{ {
RC_STRINGLIST *l = xmalloc(sizeof(*l)); RC_STRINGLIST *l = xmalloc(sizeof(*l));
TAILQ_INIT(l); TAILQ_INIT(l);
@ -39,7 +40,8 @@ RC_STRINGLIST *rc_stringlist_new(void)
} }
librc_hidden_def(rc_stringlist_new) librc_hidden_def(rc_stringlist_new)
RC_STRING *rc_stringlist_add (RC_STRINGLIST *list, const char *value) RC_STRING *
rc_stringlist_add (RC_STRINGLIST *list, const char *value)
{ {
RC_STRING *s = xmalloc(sizeof(*s)); RC_STRING *s = xmalloc(sizeof(*s));
@ -49,51 +51,55 @@ RC_STRING *rc_stringlist_add (RC_STRINGLIST *list, const char *value)
} }
librc_hidden_def(rc_stringlist_add) librc_hidden_def(rc_stringlist_add)
RC_STRING *rc_stringlist_addu (RC_STRINGLIST *list, const char *value) RC_STRING *
rc_stringlist_addu (RC_STRINGLIST *list, const char *value)
{ {
RC_STRING *s; RC_STRING *s;
TAILQ_FOREACH(s, list, entries) TAILQ_FOREACH(s, list, entries)
if (strcmp(s->value, value) == 0) { if (strcmp(s->value, value) == 0) {
errno = EEXIST; errno = EEXIST;
return NULL; return NULL;
} }
return rc_stringlist_add(list, value); return rc_stringlist_add(list, value);
} }
librc_hidden_def(rc_stringlist_addu) librc_hidden_def(rc_stringlist_addu)
bool rc_stringlist_delete(RC_STRINGLIST *list, const char *value) bool
rc_stringlist_delete(RC_STRINGLIST *list, const char *value)
{ {
RC_STRING *s; RC_STRING *s;
TAILQ_FOREACH(s, list, entries) TAILQ_FOREACH(s, list, entries)
if (strcmp(s->value, value) == 0) { if (strcmp(s->value, value) == 0) {
TAILQ_REMOVE(list, s, entries); TAILQ_REMOVE(list, s, entries);
free (s->value); free (s->value);
free (s); free (s);
return true; return true;
} }
errno = EEXIST; errno = EEXIST;
return false; return false;
} }
librc_hidden_def(rc_stringlist_delete) librc_hidden_def(rc_stringlist_delete)
RC_STRING *rc_stringlist_find(RC_STRINGLIST *list, const char *value) RC_STRING *
rc_stringlist_find(RC_STRINGLIST *list, const char *value)
{ {
RC_STRING *s; RC_STRING *s;
if (list) { if (list) {
TAILQ_FOREACH(s, list, entries) TAILQ_FOREACH(s, list, entries)
if (strcmp(s->value, value) == 0) if (strcmp(s->value, value) == 0)
return s; return s;
} }
return NULL; return NULL;
} }
librc_hidden_def(rc_stringlist_find) librc_hidden_def(rc_stringlist_find)
RC_STRINGLIST *rc_stringlist_split(const char *value, const char *sep) RC_STRINGLIST *
rc_stringlist_split(const char *value, const char *sep)
{ {
RC_STRINGLIST *list = rc_stringlist_new(); RC_STRINGLIST *list = rc_stringlist_new();
char *d = xstrdup(value); char *d = xstrdup(value);
@ -107,7 +113,8 @@ RC_STRINGLIST *rc_stringlist_split(const char *value, const char *sep)
} }
librc_hidden_def(rc_stringlist_split) librc_hidden_def(rc_stringlist_split)
void rc_stringlist_sort(RC_STRINGLIST **list) void
rc_stringlist_sort(RC_STRINGLIST **list)
{ {
RC_STRINGLIST *l = *list; RC_STRINGLIST *l = *list;
RC_STRINGLIST *new = rc_stringlist_new(); RC_STRINGLIST *new = rc_stringlist_new();
@ -119,7 +126,7 @@ void rc_stringlist_sort(RC_STRINGLIST **list)
TAILQ_FOREACH_SAFE(s, l, entries, sn) { TAILQ_FOREACH_SAFE(s, l, entries, sn) {
TAILQ_REMOVE(l, s, entries); TAILQ_REMOVE(l, s, entries);
last = NULL; last = NULL;
TAILQ_FOREACH (n, new, entries) { TAILQ_FOREACH(n, new, entries) {
if (strcmp (s->value, n->value) < 0) if (strcmp (s->value, n->value) < 0)
break; break;
last = n; last = n;
@ -136,7 +143,8 @@ void rc_stringlist_sort(RC_STRINGLIST **list)
} }
librc_hidden_def(rc_stringlist_sort) librc_hidden_def(rc_stringlist_sort)
void rc_stringlist_free(RC_STRINGLIST *list) void
rc_stringlist_free(RC_STRINGLIST *list)
{ {
RC_STRING *s1; RC_STRING *s1;
RC_STRING *s2; RC_STRING *s2;

View File

@ -1,7 +1,7 @@
/* /*
librc librc
core RC functions core RC functions
*/ */
/* /*
* Copyright 2007-2008 Roy Marples <roy@marples.name> * Copyright 2007-2008 Roy Marples <roy@marples.name>
@ -33,13 +33,13 @@ const char librc_copyright[] = "Copyright (c) 2007-2008 Roy Marples";
#include "librc.h" #include "librc.h"
#ifdef __FreeBSD__ #ifdef __FreeBSD__
#include <sys/sysctl.h> # include <sys/sysctl.h>
#endif #endif
#define RC_RUNLEVEL RC_SVCDIR "/softlevel" #define RC_RUNLEVEL RC_SVCDIR "/softlevel"
#ifndef S_IXUGO #ifndef S_IXUGO
# define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH) # define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH)
#endif #endif
/* File stream used for plugins to write environ vars to */ /* File stream used for plugins to write environ vars to */
@ -88,7 +88,7 @@ ls_dir(const char *dir, int options)
* This is important as a service maybe in a * This is important as a service maybe in a
* runlevel, but could have been removed. */ * runlevel, but could have been removed. */
snprintf(file, sizeof(file), "%s/%s", snprintf(file, sizeof(file), "%s/%s",
dir, d->d_name); dir, d->d_name);
r = stat(file, &buf); r = stat(file, &buf);
if (r != 0) if (r != 0)
continue; continue;
@ -130,7 +130,7 @@ rm_dir(const char *pathname, bool top)
strcmp(d->d_name, "..") != 0) strcmp(d->d_name, "..") != 0)
{ {
snprintf(file, sizeof(file), snprintf(file, sizeof(file),
"%s/%s", pathname, d->d_name); "%s/%s", pathname, d->d_name);
if (stat(file, &s) != 0) { if (stat(file, &s) != 0) {
retval = false; retval = false;
break; break;
@ -229,12 +229,12 @@ rc_sys(void)
} else if (file_regex("/proc/cpuinfo", "UML")) } else if (file_regex("/proc/cpuinfo", "UML"))
return RC_SYS_UML; return RC_SYS_UML;
else if (file_regex("/proc/self/status", else if (file_regex("/proc/self/status",
"(s_context|VxID):[[:space:]]*[1-9]")) "(s_context|VxID):[[:space:]]*[1-9]"))
return RC_SYS_VSERVER; return RC_SYS_VSERVER;
else if (exists("/proc/vz/veinfo") && !exists("/proc/vz/version")) else if (exists("/proc/vz/veinfo") && !exists("/proc/vz/version"))
return RC_SYS_OPENVZ; return RC_SYS_OPENVZ;
else if (file_regex("/proc/self/status", else if (file_regex("/proc/self/status",
"envID:[[:space:]]*[1-9]")) "envID:[[:space:]]*[1-9]"))
return RC_SYS_OPENVZ; /* old test */ return RC_SYS_OPENVZ; /* old test */
#endif #endif
@ -349,7 +349,7 @@ rc_service_resolve(const char *service)
snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s", "started", service); snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s", "started", service);
if (lstat(file, &buf) || ! S_ISLNK(buf.st_mode)) { if (lstat(file, &buf) || ! S_ISLNK(buf.st_mode)) {
snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s", snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s",
"inactive", service); "inactive", service);
if (lstat(file, &buf) || ! S_ISLNK(buf.st_mode)) if (lstat(file, &buf) || ! S_ISLNK(buf.st_mode))
*file = '\0'; *file = '\0';
} }
@ -497,7 +497,7 @@ rc_service_in_runlevel(const char *service, const char *runlevel)
char file[PATH_MAX]; char file[PATH_MAX];
snprintf(file, sizeof(file), RC_RUNLEVELDIR "/%s/%s", snprintf(file, sizeof(file), RC_RUNLEVELDIR "/%s/%s",
runlevel, basename_c(service)); runlevel, basename_c(service));
return exists(file); return exists(file);
} }
librc_hidden_def(rc_service_in_runlevel) librc_hidden_def(rc_service_in_runlevel)
@ -528,7 +528,7 @@ rc_service_mark(const char *service, const RC_SERVICE state)
} }
snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s", snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s",
rc_parse_service_state(state), base); rc_parse_service_state(state), base);
if (exists(file)) if (exists(file))
unlink(file); unlink(file);
i = symlink(init, file); i = symlink(init, file);
@ -549,22 +549,22 @@ rc_service_mark(const char *service, const RC_SERVICE state)
s = rc_service_state_names[i].state; s = rc_service_state_names[i].state;
if ((s != skip_state && if ((s != skip_state &&
s != RC_SERVICE_STOPPED && s != RC_SERVICE_STOPPED &&
s != RC_SERVICE_HOTPLUGGED && s != RC_SERVICE_HOTPLUGGED &&
s != RC_SERVICE_SCHEDULED) && s != RC_SERVICE_SCHEDULED) &&
(! skip_wasinactive || s != RC_SERVICE_WASINACTIVE)) (! skip_wasinactive || s != RC_SERVICE_WASINACTIVE))
{ {
snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s", snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s",
rc_service_state_names[i].name, base); rc_service_state_names[i].name, base);
if (exists(file)) { if (exists(file)) {
if ((state == RC_SERVICE_STARTING || if ((state == RC_SERVICE_STARTING ||
state == RC_SERVICE_STOPPING) && state == RC_SERVICE_STOPPING) &&
s == RC_SERVICE_INACTIVE) s == RC_SERVICE_INACTIVE)
{ {
snprintf(was, sizeof(was), snprintf(was, sizeof(was),
RC_SVCDIR "/%s/%s", RC_SVCDIR "/%s/%s",
rc_parse_service_state(RC_SERVICE_WASINACTIVE), rc_parse_service_state(RC_SERVICE_WASINACTIVE),
base); base);
if (symlink(init, was) == -1) if (symlink(init, was) == -1)
return false; return false;
skip_wasinactive = true; skip_wasinactive = true;
@ -583,18 +583,18 @@ rc_service_mark(const char *service, const RC_SERVICE state)
state == RC_SERVICE_INACTIVE) state == RC_SERVICE_INACTIVE)
{ {
snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s", snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s",
"exclusive", base); "exclusive", base);
unlink(file); unlink(file);
} }
/* Remove any options and daemons the service may have stored */ /* Remove any options and daemons the service may have stored */
if (state == RC_SERVICE_STOPPED) { if (state == RC_SERVICE_STOPPED) {
snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s", snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s",
"options", base); "options", base);
rm_dir(file, true); rm_dir(file, true);
snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s", snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s",
"daemons", base); "daemons", base);
rm_dir(file, true); rm_dir(file, true);
rc_service_schedule_clear(service); rc_service_schedule_clear(service);
@ -606,7 +606,7 @@ rc_service_mark(const char *service, const RC_SERVICE state)
dirs = ls_dir(file, 0); dirs = ls_dir(file, 0);
TAILQ_FOREACH(dir, dirs, entries) { TAILQ_FOREACH(dir, dirs, entries) {
snprintf(was, sizeof(was), "%s/%s/%s", snprintf(was, sizeof(was), "%s/%s/%s",
file, dir->value, base); file, dir->value, base);
unlink(was); unlink(was);
/* Try and remove the dir; we don't care about errors */ /* Try and remove the dir; we don't care about errors */
@ -634,7 +634,7 @@ rc_service_state(const char *service)
for (i = 0; rc_service_state_names[i].name; i++) { for (i = 0; rc_service_state_names[i].name; i++) {
snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s", snprintf(file, sizeof(file), RC_SVCDIR "/%s/%s",
rc_service_state_names[i].name, base); rc_service_state_names[i].name, base);
if (exists(file)) { if (exists(file)) {
if (rc_service_state_names[i].state <= 0x10) if (rc_service_state_names[i].state <= 0x10)
state = rc_service_state_names[i].state; state = rc_service_state_names[i].state;
@ -647,8 +647,8 @@ rc_service_state(const char *service)
dirs = ls_dir(RC_SVCDIR "/scheduled", 0); dirs = ls_dir(RC_SVCDIR "/scheduled", 0);
TAILQ_FOREACH (dir, dirs, entries) { TAILQ_FOREACH (dir, dirs, entries) {
snprintf(file, sizeof(file), snprintf(file, sizeof(file),
RC_SVCDIR "/scheduled/%s/%s", RC_SVCDIR "/scheduled/%s/%s",
dir->value, service); dir->value, service);
if (exists(file)) { if (exists(file)) {
state |= RC_SERVICE_SCHEDULED; state |= RC_SERVICE_SCHEDULED;
break; break;
@ -670,7 +670,7 @@ rc_service_value_get(const char *service, const char *option)
char file[PATH_MAX]; char file[PATH_MAX];
snprintf(file, sizeof(file), RC_SVCDIR "/options/%s/%s", snprintf(file, sizeof(file), RC_SVCDIR "/options/%s/%s",
service, option); service, option);
if ((fp = fopen(file, "r"))) { if ((fp = fopen(file, "r"))) {
rc_getline(&line, &len, fp); rc_getline(&line, &len, fp);
fclose(fp); fclose(fp);
@ -682,7 +682,7 @@ librc_hidden_def(rc_service_value_get)
bool bool
rc_service_value_set(const char *service, const char *option, rc_service_value_set(const char *service, const char *option,
const char *value) const char *value)
{ {
FILE *fp; FILE *fp;
char file[PATH_MAX]; char file[PATH_MAX];
@ -716,13 +716,13 @@ rc_service_schedule_start(const char *service, const char *service_to_start)
return false; return false;
p += snprintf(file, sizeof(file), RC_SVCDIR "/scheduled/%s", p += snprintf(file, sizeof(file), RC_SVCDIR "/scheduled/%s",
basename_c(service)); basename_c(service));
if (mkdir(file, 0755) != 0 && errno != EEXIST) if (mkdir(file, 0755) != 0 && errno != EEXIST)
return false; return false;
init = rc_service_resolve(service_to_start); init = rc_service_resolve(service_to_start);
snprintf(p, sizeof(file) - (p - file), snprintf(p, sizeof(file) - (p - file),
"/%s", basename_c(service_to_start)); "/%s", basename_c(service_to_start));
retval = (exists(file) || symlink(init, file) == 0); retval = (exists(file) || symlink(init, file) == 0);
free(init); free(init);
return retval; return retval;
@ -735,7 +735,7 @@ rc_service_schedule_clear(const char *service)
char dir[PATH_MAX]; char dir[PATH_MAX];
snprintf(dir, sizeof(dir), RC_SVCDIR "/scheduled/%s", snprintf(dir, sizeof(dir), RC_SVCDIR "/scheduled/%s",
basename_c(service)); basename_c(service));
if (!rm_dir(dir, true) && errno == ENOENT) if (!rm_dir(dir, true) && errno == ENOENT)
return true; return true;
return false; return false;
@ -791,7 +791,7 @@ rc_services_in_state(RC_SERVICE state)
char *p = dir; char *p = dir;
p += snprintf(dir, sizeof(dir), RC_SVCDIR "/%s", p += snprintf(dir, sizeof(dir), RC_SVCDIR "/%s",
rc_parse_service_state(state)); rc_parse_service_state(state));
if (state != RC_SERVICE_SCHEDULED) if (state != RC_SERVICE_SCHEDULED)
return ls_dir(dir, LS_INITD); return ls_dir(dir, LS_INITD);
@ -837,7 +837,7 @@ rc_service_add(const char *runlevel, const char *service)
i = init = rc_service_resolve(service); i = init = rc_service_resolve(service);
snprintf(file, sizeof(file), RC_RUNLEVELDIR "/%s/%s", snprintf(file, sizeof(file), RC_RUNLEVELDIR "/%s/%s",
runlevel, basename_c(service)); runlevel, basename_c(service));
/* We need to ensure that only things in /etc/init.d are added /* We need to ensure that only things in /etc/init.d are added
* to the boot runlevel */ * to the boot runlevel */
@ -868,7 +868,7 @@ rc_service_delete(const char *runlevel, const char *service)
char file[PATH_MAX]; char file[PATH_MAX];
snprintf(file, sizeof(file), RC_RUNLEVELDIR "/%s/%s", snprintf(file, sizeof(file), RC_RUNLEVELDIR "/%s/%s",
runlevel, basename_c(service)); runlevel, basename_c(service));
if (unlink(file) == 0) if (unlink(file) == 0)
return true; return true;
return false; return false;
@ -885,7 +885,7 @@ rc_services_scheduled_by(const char *service)
TAILQ_FOREACH (dir, dirs, entries) { TAILQ_FOREACH (dir, dirs, entries) {
snprintf(file, sizeof(file), RC_SVCDIR "/scheduled/%s/%s", snprintf(file, sizeof(file), RC_SVCDIR "/scheduled/%s/%s",
dir->value, service); dir->value, service);
if (exists(file)) if (exists(file))
rc_stringlist_add(list, file); rc_stringlist_add(list, file);
} }
@ -900,7 +900,7 @@ rc_services_scheduled(const char *service)
char dir[PATH_MAX]; char dir[PATH_MAX];
snprintf(dir, sizeof(dir), RC_SVCDIR "/scheduled/%s", snprintf(dir, sizeof(dir), RC_SVCDIR "/scheduled/%s",
basename_c(service)); basename_c(service));
return ls_dir(dir, LS_INITD); return ls_dir(dir, LS_INITD);
} }
librc_hidden_def(rc_services_scheduled) librc_hidden_def(rc_services_scheduled)

View File

@ -25,15 +25,16 @@
*/ */
#if lint #if lint
# define _noreturn # define _noreturn
#endif #endif
#if __GNUC__ > 2 || defined(__INTEL_COMPILER) #if __GNUC__ > 2 || defined(__INTEL_COMPILER)
# define _noreturn __attribute__ ((__noreturn__)) # define _noreturn __attribute__ ((__noreturn__))
#else #else
# define _noreturn # define _noreturn
#endif #endif
_noreturn static void usage(int exit_status) _noreturn static void
usage(int exit_status)
{ {
const char * const has_arg[] = { "", "<arg>", "[arg]" }; const char * const has_arg[] = { "", "<arg>", "[arg]" };
int i; int i;
@ -53,7 +54,7 @@ _noreturn static void usage(int exit_status)
printf("\n\nOptions: [" getoptstring "]\n"); printf("\n\nOptions: [" getoptstring "]\n");
for (i = 0; longopts[i].name; ++i) { for (i = 0; longopts[i].name; ++i) {
len = printf(" -%c, --%s %s", longopts[i].val, longopts[i].name, len = printf(" -%c, --%s %s", longopts[i].val, longopts[i].name,
has_arg[longopts[i].has_arg]); has_arg[longopts[i].has_arg]);
lo = p = xstrdup(longopts_help[i]); lo = p = xstrdup(longopts_help[i]);
while ((token = strsep(&p, "\n"))) { while ((token = strsep(&p, "\n"))) {

View File

@ -26,17 +26,17 @@
#define getoptstring_COMMON "Chqv" #define getoptstring_COMMON "Chqv"
#define longopts_COMMON \ #define longopts_COMMON \
{ "help", 0, NULL, 'h'}, \ { "help", 0, NULL, 'h'}, \
{ "nocolor", 0, NULL, 'C'}, \ { "nocolor", 0, NULL, 'C'}, \
{ "verbose", 0, NULL, 'v'}, \ { "verbose", 0, NULL, 'v'}, \
{ "quiet", 0, NULL, 'q'}, \ { "quiet", 0, NULL, 'q'}, \
{ NULL, 0, NULL, 0 } { NULL, 0, NULL, 0 }
#define longopts_help_COMMON \ #define longopts_help_COMMON \
"Display this help output", \ "Display this help output", \
"Disable color output", \ "Disable color output", \
"Run verbosely", \ "Run verbosely", \
"Run quietly" "Run quietly"
#define case_RC_COMMON_getopt_case_C setenv ("EINFO_COLOR", "NO", 1); #define case_RC_COMMON_getopt_case_C setenv ("EINFO_COLOR", "NO", 1);
@ -45,9 +45,9 @@
#define case_RC_COMMON_getopt_case_q setenv ("EINFO_QUIET", "YES", 1); #define case_RC_COMMON_getopt_case_q setenv ("EINFO_QUIET", "YES", 1);
#define case_RC_COMMON_getopt_default usage (EXIT_FAILURE); #define case_RC_COMMON_getopt_default usage (EXIT_FAILURE);
#define case_RC_COMMON_GETOPT \ #define case_RC_COMMON_GETOPT \
case 'C': case_RC_COMMON_getopt_case_C; break; \ case 'C': case_RC_COMMON_getopt_case_C; break; \
case 'h': case_RC_COMMON_getopt_case_h; break; \ case 'h': case_RC_COMMON_getopt_case_h; break; \
case 'v': case_RC_COMMON_getopt_case_v; break; \ case 'v': case_RC_COMMON_getopt_case_v; break; \
case 'q': case_RC_COMMON_getopt_case_q; break; \ case 'q': case_RC_COMMON_getopt_case_q; break; \
default: case_RC_COMMON_getopt_default; break; default: case_RC_COMMON_getopt_default; break;

View File

@ -1,8 +1,8 @@
/* /*
checkpath.c checkpath.c
Checks for the existance of a file or directory and creates it Checks for the existance of a file or directory and creates it
if necessary. It can also correct its ownership. if necessary. It can also correct its ownership.
*/ */
/* /*
* Copyright 2007-2008 Roy Marples <roy@marples.name> * Copyright 2007-2008 Roy Marples <roy@marples.name>
@ -49,7 +49,8 @@
extern const char *applet; extern const char *applet;
static int do_check(char *path, uid_t uid, gid_t gid, mode_t mode, int file) static int
do_check(char *path, uid_t uid, gid_t gid, mode_t mode, int file)
{ {
struct stat st; struct stat st;
int fd; int fd;
@ -57,8 +58,9 @@ static int do_check(char *path, uid_t uid, gid_t gid, mode_t mode, int file)
if (stat(path, &st)) { if (stat(path, &st)) {
if (file) { if (file) {
einfo("%s: creating file", path); einfo("%s: creating file", path);
if (! mode) if (!mode)
mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH; mode = S_IRUSR | S_IWUSR | S_IRGRP |
S_IWGRP | S_IROTH;
if ((fd = open(path, O_CREAT, mode)) == -1) { if ((fd = open(path, O_CREAT, mode)) == -1) {
eerror("%s: open: %s", applet, strerror(errno)); eerror("%s: open: %s", applet, strerror(errno));
return -1; return -1;
@ -66,17 +68,18 @@ static int do_check(char *path, uid_t uid, gid_t gid, mode_t mode, int file)
close (fd); close (fd);
} else { } else {
einfo("%s: creating directory", path); einfo("%s: creating directory", path);
if (! mode) if (!mode)
mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH; mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH;
if (mkdir(path, mode)) { if (mkdir(path, mode)) {
eerror("%s: mkdir: %s", applet, strerror (errno)); eerror("%s: mkdir: %s", applet,
strerror (errno));
return -1; return -1;
} }
mode = 0; mode = 0;
} }
} else { } else {
if ((file && S_ISDIR(st.st_mode)) || if ((file && S_ISDIR(st.st_mode)) ||
(! file && ! S_ISDIR(st.st_mode))) (!file && !S_ISDIR(st.st_mode)))
{ {
if (file) if (file)
eerror("%s: is a directory", path); eerror("%s: is a directory", path);
@ -106,8 +109,8 @@ static int do_check(char *path, uid_t uid, gid_t gid, mode_t mode, int file)
return 0; return 0;
} }
static int parse_owner(struct passwd **user, struct group **group, static int
const char *owner) parse_owner(struct passwd **user, struct group **group, const char *owner)
{ {
char *u = xstrdup (owner); char *u = xstrdup (owner);
char *g = strchr (u, ':'); char *g = strchr (u, ':');
@ -122,7 +125,7 @@ static int parse_owner(struct passwd **user, struct group **group,
*user = getpwuid((uid_t) id); *user = getpwuid((uid_t) id);
else else
*user = getpwnam(u); *user = getpwnam(u);
if (! *user) if (*user == NULL)
retval = -1; retval = -1;
} }
@ -131,7 +134,7 @@ static int parse_owner(struct passwd **user, struct group **group,
*group = getgrgid((gid_t) id); *group = getgrgid((gid_t) id);
else else
*group = getgrnam(g); *group = getgrnam(g);
if (! *group) if (*group == NULL)
retval = -1; retval = -1;
} }
@ -158,7 +161,8 @@ static const char * const longopts_help[] = {
}; };
#include "_usage.c" #include "_usage.c"
int checkpath(int argc, char **argv) int
checkpath(int argc, char **argv)
{ {
int opt; int opt;
uid_t uid = geteuid(); uid_t uid = geteuid();
@ -170,7 +174,7 @@ int checkpath(int argc, char **argv)
int retval = EXIT_SUCCESS; int retval = EXIT_SUCCESS;
while ((opt = getopt_long(argc, argv, getoptstring, while ((opt = getopt_long(argc, argv, getoptstring,
longopts, (int *) 0)) != -1) longopts, (int *) 0)) != -1)
{ {
switch (opt) { switch (opt) {
case 'd': case 'd':
@ -181,14 +185,16 @@ int checkpath(int argc, char **argv)
break; break;
case 'm': case 'm':
if (parse_mode(&mode, optarg) != 0) if (parse_mode(&mode, optarg) != 0)
eerrorx("%s: invalid mode `%s'", applet, optarg); eerrorx("%s: invalid mode `%s'",
applet, optarg);
break; break;
case 'o': case 'o':
if (parse_owner(&pw, &gr, optarg) != 0) if (parse_owner(&pw, &gr, optarg) != 0)
eerrorx("%s: owner `%s' not found", applet, optarg); eerrorx("%s: owner `%s' not found",
applet, optarg);
break; break;
case_RC_COMMON_GETOPT case_RC_COMMON_GETOPT;
} }
} }

View File

@ -1,7 +1,7 @@
/* /*
fstabinfo.c fstabinfo.c
Gets information about /etc/fstab. Gets information about /etc/fstab.
*/ */
/* /*
* Copyright 2007-2008 Roy Marples <roy@marples.name> * Copyright 2007-2008 Roy Marples <roy@marples.name>
@ -42,31 +42,31 @@
Okay, we could use getfsent but the man page says use getmntent instead Okay, we could use getfsent but the man page says use getmntent instead
AND we don't have getfsent on uclibc or dietlibc for some odd reason. */ AND we don't have getfsent on uclibc or dietlibc for some odd reason. */
#ifdef __linux__ #ifdef __linux__
#define HAVE_GETMNTENT # define HAVE_GETMNTENT
#include <mntent.h> # include <mntent.h>
#define ENT mntent # define ENT mntent
#define START_ENT fp = setmntent ("/etc/fstab", "r"); # define START_ENT fp = setmntent ("/etc/fstab", "r");
#define GET_ENT getmntent (fp) # define GET_ENT getmntent (fp)
#define GET_ENT_FILE(_name) getmntfile (_name) # define GET_ENT_FILE(_name) getmntfile (_name)
#define END_ENT endmntent (fp) # define END_ENT endmntent (fp)
#define ENT_BLOCKDEVICE(_ent) ent->mnt_fsname # define ENT_BLOCKDEVICE(_ent) ent->mnt_fsname
#define ENT_FILE(_ent) ent->mnt_dir # define ENT_FILE(_ent) ent->mnt_dir
#define ENT_TYPE(_ent) ent->mnt_type # define ENT_TYPE(_ent) ent->mnt_type
#define ENT_OPTS(_ent) ent->mnt_opts # define ENT_OPTS(_ent) ent->mnt_opts
#define ENT_PASS(_ent) ent->mnt_passno # define ENT_PASS(_ent) ent->mnt_passno
#else #else
#define HAVE_GETFSENT # define HAVE_GETFSENT
#include <fstab.h> # include <fstab.h>
#define ENT fstab # define ENT fstab
#define START_ENT # define START_ENT
#define GET_ENT getfsent () # define GET_ENT getfsent ()
#define GET_ENT_FILE(_name) getfsfile (_name) # define GET_ENT_FILE(_name) getfsfile (_name)
#define END_ENT endfsent () # define END_ENT endfsent ()
#define ENT_BLOCKDEVICE(_ent) ent->fs_spec # define ENT_BLOCKDEVICE(_ent) ent->fs_spec
#define ENT_TYPE(_ent) ent->fs_vfstype # define ENT_TYPE(_ent) ent->fs_vfstype
#define ENT_FILE(_ent) ent->fs_file # define ENT_FILE(_ent) ent->fs_file
#define ENT_OPTS(_ent) ent->fs_mntops # define ENT_OPTS(_ent) ent->fs_mntops
#define ENT_PASS(_ent) ent->fs_passno # define ENT_PASS(_ent) ent->fs_passno
#endif #endif
#include "builtins.h" #include "builtins.h"
@ -93,7 +93,8 @@ getmntfile(const char *file)
extern const char *applet; extern const char *applet;
static int do_mount(struct ENT *ent) static int
do_mount(struct ENT *ent)
{ {
char *argv[8]; char *argv[8];
pid_t pid; pid_t pid;
@ -176,7 +177,7 @@ fstabinfo(int argc, char **argv)
unsetenv("EINFO_QUIET"); unsetenv("EINFO_QUIET");
while ((opt = getopt_long(argc, argv, getoptstring, while ((opt = getopt_long(argc, argv, getoptstring,
longopts, (int *) 0)) != -1) longopts, (int *) 0)) != -1)
{ {
switch (opt) { switch (opt) {
case 'M': case 'M':
@ -199,7 +200,7 @@ fstabinfo(int argc, char **argv)
case '>': case '>':
if (sscanf(optarg + 1, "%d", &i) != 1) if (sscanf(optarg + 1, "%d", &i) != 1)
eerrorx("%s: invalid passno %s", eerrorx("%s: invalid passno %s",
argv[0], optarg + 1); argv[0], optarg + 1);
filtered = true; filtered = true;
opt = optarg[0]; opt = optarg[0];
@ -212,7 +213,7 @@ fstabinfo(int argc, char **argv)
(opt == '<' && i > p && p != 0) || (opt == '<' && i > p && p != 0) ||
(opt == '>' && i < p && p != 0)) (opt == '>' && i < p && p != 0))
rc_stringlist_add(files, rc_stringlist_add(files,
ENT_FILE(ent)); ENT_FILE(ent));
} }
END_ENT; END_ENT;
break; break;
@ -222,7 +223,7 @@ fstabinfo(int argc, char **argv)
output = OUTPUT_PASSNO; output = OUTPUT_PASSNO;
break; break;
} }
break; break;
case 't': case 't':
filtered = true; filtered = true;
@ -230,13 +231,14 @@ fstabinfo(int argc, char **argv)
START_ENT; START_ENT;
while ((ent = GET_ENT)) while ((ent = GET_ENT))
if (strcmp(token, ENT_TYPE(ent)) == 0) if (strcmp(token, ENT_TYPE(ent)) == 0)
rc_stringlist_add(files, ENT_FILE(ent)); rc_stringlist_add(files,
ENT_FILE(ent));
END_ENT; END_ENT;
} }
break; break;
case_RC_COMMON_GETOPT case_RC_COMMON_GETOPT
} }
} }
if (optind < argc) { if (optind < argc) {
@ -246,7 +248,8 @@ fstabinfo(int argc, char **argv)
if (strcmp(argv[i], file->value) == 0) if (strcmp(argv[i], file->value) == 0)
break; break;
if (i >= argc) if (i >= argc)
rc_stringlist_delete(files, file->value); rc_stringlist_delete(files,
file->value);
} }
} else { } else {
while (optind < argc) while (optind < argc)
@ -290,10 +293,10 @@ fstabinfo(int argc, char **argv)
case OUTPUT_MOUNTARGS: case OUTPUT_MOUNTARGS:
printf("-o %s -t %s %s %s\n", printf("-o %s -t %s %s %s\n",
ENT_OPTS(ent), ENT_OPTS(ent),
ENT_TYPE(ent), ENT_TYPE(ent),
ENT_BLOCKDEVICE(ent), ENT_BLOCKDEVICE(ent),
file->value); file->value);
break; break;
case OUTPUT_OPTIONS: case OUTPUT_OPTIONS:

View File

@ -1,7 +1,7 @@
/* /*
mountinfo.c mountinfo.c
Obtains information about mounted filesystems. Obtains information about mounted filesystems.
*/ */
/* /*
* Copyright 2007-2008 Roy Marples <roy@marples.name> * Copyright 2007-2008 Roy Marples <roy@marples.name>
@ -33,15 +33,15 @@
#include <sys/param.h> #include <sys/param.h>
#if defined(__DragonFly__) || defined(__FreeBSD__) #if defined(__DragonFly__) || defined(__FreeBSD__)
# include <sys/ucred.h> # include <sys/ucred.h>
# include <sys/mount.h> # include <sys/mount.h>
# define F_FLAGS f_flags # define F_FLAGS f_flags
#elif defined(BSD) #elif defined(BSD)
# include <sys/statvfs.h> # include <sys/statvfs.h>
# define statfs statvfs # define statfs statvfs
# define F_FLAGS f_flag # define F_FLAGS f_flag
#elif defined (__linux__) #elif defined (__linux__)
#include <mntent.h> # include <mntent.h>
#endif #endif
#include <errno.h> #include <errno.h>
@ -84,9 +84,10 @@ struct args {
net_opts netdev; net_opts netdev;
}; };
static int process_mount(RC_STRINGLIST *list, struct args *args, static int
char *from, char *to, char *fstype, char *options, process_mount(RC_STRINGLIST *list, struct args *args,
int netdev) char *from, char *to, char *fstype, char *options,
int netdev)
{ {
char *p; char *p;
RC_STRING *s; RC_STRING *s;
@ -105,7 +106,7 @@ static int process_mount(RC_STRINGLIST *list, struct args *args,
if (netdev != 0) if (netdev != 0)
return 1; return 1;
} else if (args->netdev == net_no && } else if (args->netdev == net_no &&
(netdev != -1 || TAILQ_FIRST(args->mounts))) (netdev != -1 || TAILQ_FIRST(args->mounts)))
{ {
if (netdev != 1) if (netdev != 1)
return 1; return 1;
@ -134,8 +135,8 @@ static int process_mount(RC_STRINGLIST *list, struct args *args,
if (TAILQ_FIRST(args->mounts)) { if (TAILQ_FIRST(args->mounts)) {
TAILQ_FOREACH(s, args->mounts, entries) TAILQ_FOREACH(s, args->mounts, entries)
if (strcmp(s->value, to) == 0) if (strcmp(s->value, to) == 0)
break; break;
if (! s) if (! s)
return -1; return -1;
} }
@ -211,7 +212,8 @@ static struct opt {
{ 0, NULL } { 0, NULL }
}; };
static RC_STRINGLIST *find_mounts(struct args *args) static RC_STRINGLIST *
find_mounts(struct args *args)
{ {
struct statfs *mnts; struct statfs *mnts;
int nmnts; int nmnts;
@ -238,9 +240,11 @@ static RC_STRINGLIST *find_mounts(struct args *args)
if (! options) if (! options)
options = xstrdup(o->o_name); options = xstrdup(o->o_name);
else { else {
l = strlen(options) + strlen(o->o_name) + 2; l = strlen(options) +
strlen(o->o_name) + 2;
tmp = xmalloc(sizeof (char) * l); tmp = xmalloc(sizeof (char) * l);
snprintf(tmp, l, "%s,%s", options, o->o_name); snprintf(tmp, l, "%s,%s", options,
o->o_name);
free(options); free(options);
options = tmp; options = tmp;
} }
@ -249,11 +253,11 @@ static RC_STRINGLIST *find_mounts(struct args *args)
} }
process_mount(list, args, process_mount(list, args,
mnts[i].f_mntfromname, mnts[i].f_mntfromname,
mnts[i].f_mntonname, mnts[i].f_mntonname,
mnts[i].f_fstypename, mnts[i].f_fstypename,
options, options,
netdev); netdev);
free(options); free(options);
options = NULL; options = NULL;
@ -263,7 +267,8 @@ static RC_STRINGLIST *find_mounts(struct args *args)
} }
#elif defined (__linux__) #elif defined (__linux__)
static struct mntent *getmntfile(const char *file) static struct mntent *
getmntfile(const char *file)
{ {
struct mntent *ent = NULL; struct mntent *ent = NULL;
FILE *fp; FILE *fp;
@ -277,7 +282,8 @@ static struct mntent *getmntfile(const char *file)
return ent; return ent;
} }
static RC_STRINGLIST *find_mounts(struct args *args) static RC_STRINGLIST *
find_mounts(struct args *args)
{ {
FILE *fp; FILE *fp;
char *buffer; char *buffer;
@ -321,7 +327,8 @@ static RC_STRINGLIST *find_mounts(struct args *args)
# error "Operating system not supported!" # error "Operating system not supported!"
#endif #endif
static regex_t *get_regex(const char *string) static regex_t *
get_regex(const char *string)
{ {
regex_t *reg = xmalloc(sizeof (*reg)); regex_t *reg = xmalloc(sizeof (*reg));
int result; int result;
@ -373,7 +380,8 @@ static const char * const longopts_help[] = {
}; };
#include "_usage.c" #include "_usage.c"
int mountinfo(int argc, char **argv) int
mountinfo(int argc, char **argv)
{ {
struct args args; struct args args;
regex_t *point_regex = NULL; regex_t *point_regex = NULL;
@ -387,10 +395,10 @@ int mountinfo(int argc, char **argv)
/* Ensure that we are only quiet when explicitly told to be */ /* Ensure that we are only quiet when explicitly told to be */
unsetenv("EINFO_QUIET"); unsetenv("EINFO_QUIET");
#define DO_REG(_var) \ #define DO_REG(_var) \
if (_var) free(_var); \ if (_var) free(_var); \
_var = get_regex(optarg); _var = get_regex(optarg);
#define REG_FREE(_var) \ #define REG_FREE(_var) \
if (_var) { regfree(_var); free(_var); } if (_var) { regfree(_var); free(_var); }
memset (&args, 0, sizeof(args)); memset (&args, 0, sizeof(args));
@ -399,7 +407,7 @@ int mountinfo(int argc, char **argv)
args.mounts = rc_stringlist_new(); args.mounts = rc_stringlist_new();
while ((opt = getopt_long(argc, argv, getoptstring, while ((opt = getopt_long(argc, argv, getoptstring,
longopts, (int *) 0)) != -1) longopts, (int *) 0)) != -1)
{ {
switch (opt) { switch (opt) {
case 'e': case 'e':
@ -442,13 +450,14 @@ int mountinfo(int argc, char **argv)
args.mount_type = mount_from; args.mount_type = mount_from;
break; break;
case_RC_COMMON_GETOPT case_RC_COMMON_GETOPT
} }
} }
while (optind < argc) { while (optind < argc) {
if (argv[optind][0] != '/') if (argv[optind][0] != '/')
eerrorx("%s: `%s' is not a mount point", argv[0], argv[optind]); eerrorx("%s: `%s' is not a mount point",
argv[0], argv[optind]);
rc_stringlist_add(args.mounts, argv[optind++]); rc_stringlist_add(args.mounts, argv[optind++]);
} }
nodes = find_mounts(&args); nodes = find_mounts(&args);

View File

@ -1,10 +1,10 @@
/* /*
rc-applets.c rc-applets.c
Handle multicall applets for use in our init scripts. Handle multicall applets for use in our init scripts.
Basically this makes us a lot faster for the most part, and removes Basically this makes us a lot faster for the most part, and removes
any shell incompatabilities we might otherwise encounter. any shell incompatabilities we might otherwise encounter.
*/ */
/* /*
* Copyright 2007-2009 Roy Marples <roy@marples.name> * Copyright 2007-2009 Roy Marples <roy@marples.name>
@ -60,7 +60,8 @@
/* Applet is first parsed in rc.c - no point in doing it again */ /* Applet is first parsed in rc.c - no point in doing it again */
extern const char *applet; extern const char *applet;
static int syslog_decode(char *name, CODE *codetab) static int
syslog_decode(char *name, CODE *codetab)
{ {
CODE *c; CODE *c;
@ -74,7 +75,8 @@ static int syslog_decode(char *name, CODE *codetab)
return -1; return -1;
} }
static int do_e(int argc, char **argv) static int
do_e(int argc, char **argv)
{ {
int retval = EXIT_SUCCESS; int retval = EXIT_SUCCESS;
int i; int i;
@ -93,12 +95,12 @@ static int do_e(int argc, char **argv)
if (strcmp(applet, "eval_ecolors") == 0) { if (strcmp(applet, "eval_ecolors") == 0) {
printf("GOOD='%s'\nWARN='%s'\nBAD='%s'\nHILITE='%s'\nBRACKET='%s'\nNORMAL='%s'\n", printf("GOOD='%s'\nWARN='%s'\nBAD='%s'\nHILITE='%s'\nBRACKET='%s'\nNORMAL='%s'\n",
ecolor(ECOLOR_GOOD), ecolor(ECOLOR_GOOD),
ecolor(ECOLOR_WARN), ecolor(ECOLOR_WARN),
ecolor(ECOLOR_BAD), ecolor(ECOLOR_BAD),
ecolor(ECOLOR_HILITE), ecolor(ECOLOR_HILITE),
ecolor(ECOLOR_BRACKET), ecolor(ECOLOR_BRACKET),
ecolor(ECOLOR_NORMAL)); ecolor(ECOLOR_NORMAL));
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
@ -120,9 +122,10 @@ static int do_e(int argc, char **argv)
argv++; argv++;
} }
} else if (strcmp(applet, "esyslog") == 0 || } else if (strcmp(applet, "esyslog") == 0 ||
strcmp(applet, "elog") == 0) { strcmp(applet, "elog") == 0) {
p = strchr(argv[0], '.'); p = strchr(argv[0], '.');
if (!p || (level = syslog_decode(p + 1, prioritynames)) == -1) if (!p ||
(level = syslog_decode(p + 1, prioritynames)) == -1)
eerrorx("%s: invalid log level `%s'", applet, argv[0]); eerrorx("%s: invalid log level `%s'", applet, argv[0]);
if (argc < 3) if (argc < 3)
@ -160,7 +163,7 @@ static int do_e(int argc, char **argv)
if (timercmp(&now, &stop, <)) if (timercmp(&now, &stop, <))
continue; continue;
eendv(EXIT_FAILURE, eendv(EXIT_FAILURE,
"timed out waiting for %s", argv[i]); "timed out waiting for %s", argv[i]);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
eendv(EXIT_SUCCESS, NULL); eendv(EXIT_SUCCESS, NULL);
@ -251,7 +254,8 @@ static int do_e(int argc, char **argv)
return retval; return retval;
} }
static int do_service(int argc, char **argv) static int
do_service(int argc, char **argv)
{ {
bool ok = false; bool ok = false;
char *service; char *service;
@ -263,7 +267,7 @@ static int do_service(int argc, char **argv)
else else
service = getenv("RC_SVCNAME"); service = getenv("RC_SVCNAME");
if (! service || *service == '\0') if (service == NULL || *service == '\0')
eerrorx("%s: no service specified", applet); eerrorx("%s: no service specified", applet);
if (strcmp(applet, "service_started") == 0) if (strcmp(applet, "service_started") == 0)
@ -297,15 +301,16 @@ static int do_service(int argc, char **argv)
} else if (strcmp(applet, "service_crashed") == 0) { } else if (strcmp(applet, "service_crashed") == 0) {
ok = (_rc_can_find_pids() && ok = (_rc_can_find_pids() &&
rc_service_daemons_crashed(service) && rc_service_daemons_crashed(service) &&
errno != EACCES); errno != EACCES);
} else } else
eerrorx("%s: unknown applet", applet); eerrorx("%s: unknown applet", applet);
return ok ? EXIT_SUCCESS : EXIT_FAILURE; return ok ? EXIT_SUCCESS : EXIT_FAILURE;
} }
static int do_mark_service(int argc, char **argv) static int
do_mark_service(int argc, char **argv)
{ {
bool ok = false; bool ok = false;
char *svcname = getenv("RC_SVCNAME"); char *svcname = getenv("RC_SVCNAME");
@ -320,7 +325,7 @@ static int do_mark_service(int argc, char **argv)
else else
service = getenv("RC_SVCNAME"); service = getenv("RC_SVCNAME");
if (! service || *service == '\0') if (service == NULL || *service == '\0')
eerrorx("%s: no service specified", applet); eerrorx("%s: no service specified", applet);
if (strcmp(applet, "mark_service_started") == 0) if (strcmp(applet, "mark_service_started") == 0)
@ -340,22 +345,22 @@ static int do_mark_service(int argc, char **argv)
else else
eerrorx("%s: unknown applet", applet); eerrorx("%s: unknown applet", applet);
/* If we're marking ourselves then we need to inform our parent runscript /* If we're marking ourselves then we need to inform our parent
process so they do not mark us based on our exit code */ runscript process so they do not mark us based on our exit code */
if (ok && svcname && strcmp(svcname, service) == 0) { if (ok && svcname && strcmp(svcname, service) == 0) {
runscript_pid = getenv("RC_RUNSCRIPT_PID"); runscript_pid = getenv("RC_RUNSCRIPT_PID");
if (runscript_pid && sscanf(runscript_pid, "%d", &pid) == 1) if (runscript_pid && sscanf(runscript_pid, "%d", &pid) == 1)
if (kill(pid, SIGHUP) != 0) if (kill(pid, SIGHUP) != 0)
eerror("%s: failed to signal parent %d: %s", eerror("%s: failed to signal parent %d: %s",
applet, pid, strerror(errno)); applet, pid, strerror(errno));
/* Remove the exclusive time test. This ensures that it's not /* Remove the exclusive time test. This ensures that it's not
in control as well */ in control as well */
l = strlen(RC_SVCDIR "/exclusive") + strlen(svcname) + l = strlen(RC_SVCDIR "/exclusive") + strlen(svcname) +
strlen(runscript_pid) + 4; strlen(runscript_pid) + 4;
mtime = xmalloc(l); mtime = xmalloc(l);
snprintf(mtime, l, RC_SVCDIR "/exclusive/%s.%s", snprintf(mtime, l, RC_SVCDIR "/exclusive/%s.%s",
svcname, runscript_pid); svcname, runscript_pid);
if (exists(mtime) && unlink(mtime) != 0) if (exists(mtime) && unlink(mtime) != 0)
eerror("%s: unlink: %s", applet, strerror(errno)); eerror("%s: unlink: %s", applet, strerror(errno));
free(mtime); free(mtime);
@ -364,13 +369,14 @@ static int do_mark_service(int argc, char **argv)
return ok ? EXIT_SUCCESS : EXIT_FAILURE; return ok ? EXIT_SUCCESS : EXIT_FAILURE;
} }
static int do_value(int argc, char **argv) static int
do_value(int argc, char **argv)
{ {
bool ok = false; bool ok = false;
char *service = getenv("RC_SVCNAME"); char *service = getenv("RC_SVCNAME");
char *option; char *option;
if (! service) if (service == NULL)
eerrorx("%s: no service specified", applet); eerrorx("%s: no service specified", applet);
if (argc < 2 || ! argv[1] || *argv[1] == '\0') if (argc < 2 || ! argv[1] || *argv[1] == '\0')
@ -386,7 +392,7 @@ static int do_value(int argc, char **argv)
ok = true; ok = true;
} }
} else if (strcmp(applet, "service_set_value") == 0 || } else if (strcmp(applet, "service_set_value") == 0 ||
strcmp(applet, "save_options") == 0) strcmp(applet, "save_options") == 0)
ok = rc_service_value_set(service, argv[1], argv[2]); ok = rc_service_value_set(service, argv[1], argv[2]);
else else
eerrorx("%s: unknown applet", applet); eerrorx("%s: unknown applet", applet);
@ -394,7 +400,8 @@ static int do_value(int argc, char **argv)
return ok ? EXIT_SUCCESS : EXIT_FAILURE; return ok ? EXIT_SUCCESS : EXIT_FAILURE;
} }
static int do_shell_var(int argc, char **argv) static int
do_shell_var(int argc, char **argv)
{ {
int i; int i;
char *p; char *p;
@ -402,10 +409,8 @@ static int do_shell_var(int argc, char **argv)
for (i = 1; i < argc; i++) { for (i = 1; i < argc; i++) {
p = argv[i]; p = argv[i];
if (i != 1) if (i != 1)
putchar(' '); putchar(' ');
while (*p) { while (*p) {
c = (unsigned char)*p++; c = (unsigned char)*p++;
if (! isalnum(c)) if (! isalnum(c))
@ -414,11 +419,11 @@ static int do_shell_var(int argc, char **argv)
} }
} }
putchar('\n'); putchar('\n');
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
void run_applets(int argc, char **argv) void
run_applets(int argc, char **argv)
{ {
int i = 2; int i = 2;
char *p; char *p;
@ -436,7 +441,7 @@ void run_applets(int argc, char **argv)
else if (strcmp(applet, "rc-status") == 0) else if (strcmp(applet, "rc-status") == 0)
exit(rc_status(argc, argv)); exit(rc_status(argc, argv));
else if (strcmp(applet, "rc-update") == 0 || else if (strcmp(applet, "rc-update") == 0 ||
strcmp(applet, "update-rc") == 0) strcmp(applet, "update-rc") == 0)
exit(rc_update(argc, argv)); exit(rc_update(argc, argv));
else if (strcmp(applet, "runscript") == 0) else if (strcmp(applet, "runscript") == 0)
exit(runscript(argc, argv)); exit(runscript(argc, argv));
@ -498,7 +503,7 @@ void run_applets(int argc, char **argv)
if (p && sscanf(p, "%d", &pid) == 1) { if (p && sscanf(p, "%d", &pid) == 1) {
if (kill(pid, SIGUSR1) != 0) if (kill(pid, SIGUSR1) != 0)
eerrorx("rc-abort: failed to signal parent %d: %s", eerrorx("rc-abort: failed to signal parent %d: %s",
pid, strerror(errno)); pid, strerror(errno));
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
exit(EXIT_FAILURE); exit(EXIT_FAILURE);

View File

@ -1,7 +1,7 @@
/* /*
rc-depend rc-depend
rc service dependency and ordering rc service dependency and ordering
*/ */
/* /*
* Copyright 2007-2009 Roy Marples <roy@marples.name> * Copyright 2007-2009 Roy Marples <roy@marples.name>
@ -85,7 +85,7 @@ _rc_deptree_load(int force, int *regen) {
if (st.st_mtime < t) { if (st.st_mtime < t) {
eerror("Clock skew detected with `%s'", file); eerror("Clock skew detected with `%s'", file);
eerrorn("Adjusting mtime of `" RC_DEPTREE_CACHE eerrorn("Adjusting mtime of `" RC_DEPTREE_CACHE
"' to %s", ctime(&t)); "' to %s", ctime(&t));
fp = fopen(RC_DEPTREE_SKEWED, "w"); fp = fopen(RC_DEPTREE_SKEWED, "w");
if (fp != NULL) { if (fp != NULL) {
fprintf(fp, "%s\n", file); fprintf(fp, "%s\n", file);
@ -144,7 +144,7 @@ rc_depend(int argc, char **argv)
types = rc_stringlist_new(); types = rc_stringlist_new();
while ((opt = getopt_long(argc, argv, getoptstring, while ((opt = getopt_long(argc, argv, getoptstring,
longopts, (int *) 0)) != -1) longopts, (int *) 0)) != -1)
{ {
switch (opt) { switch (opt) {
case 'a': case 'a':
@ -167,8 +167,8 @@ rc_depend(int argc, char **argv)
options &= RC_DEP_TRACE; options &= RC_DEP_TRACE;
break; break;
case_RC_COMMON_GETOPT case_RC_COMMON_GETOPT
} }
} }
if (!(deptree = _rc_deptree_load(update, NULL))) if (!(deptree = _rc_deptree_load(update, NULL)))
@ -185,7 +185,7 @@ rc_depend(int argc, char **argv)
depends = rc_deptree_depends(deptree, NULL, list, runlevel, 0); depends = rc_deptree_depends(deptree, NULL, list, runlevel, 0);
if (!depends && errno == ENOENT) if (!depends && errno == ENOENT)
eerror("no dependency info for service `%s'", eerror("no dependency info for service `%s'",
argv[optind]); argv[optind]);
else else
rc_stringlist_add(services, argv[optind]); rc_stringlist_add(services, argv[optind]);
@ -210,7 +210,7 @@ rc_depend(int argc, char **argv)
} }
depends = rc_deptree_depends(deptree, types, services, depends = rc_deptree_depends(deptree, types, services,
runlevel, options); runlevel, options);
if (TAILQ_FIRST(depends)) { if (TAILQ_FIRST(depends)) {
TAILQ_FOREACH(s, depends, entries) { TAILQ_FOREACH(s, depends, entries) {

View File

@ -1,8 +1,8 @@
/* /*
rc-logger.c rc-logger.c
Spawns a logging daemon to capture stdout and stderr so we can log Spawns a logging daemon to capture stdout and stderr so we can log
them to a buffer and/or files. them to a buffer and/or files.
*/ */
/* /*
* Copyright 2007-2008 Roy Marples <roy@marples.name> * Copyright 2007-2008 Roy Marples <roy@marples.name>
@ -46,11 +46,11 @@
#include <unistd.h> #include <unistd.h>
#ifdef __linux__ #ifdef __linux__
# include <pty.h> # include <pty.h>
#elif defined(__NetBSD__) || defined(__OpenBSD__) #elif defined(__NetBSD__) || defined(__OpenBSD__)
# include <util.h> # include <util.h>
#else #else
# include <libutil.h> # include <libutil.h>
#endif #endif
#include "einfo.h" #include "einfo.h"
@ -60,7 +60,7 @@
#define LOGFILE RC_SVCDIR "/rc.log" #define LOGFILE RC_SVCDIR "/rc.log"
#define PERMLOG "/var/log/rc.log" #define PERMLOG "/var/log/rc.log"
#define MOVELOG "cat " LOGFILE " 2>/dev/null >>" PERMLOG " && " \ #define MOVELOG "cat " LOGFILE " 2>/dev/null >>" PERMLOG " && " \
"rm -f " LOGFILE "rm -f " LOGFILE
static int signal_pipe[2] = { -1, -1 }; static int signal_pipe[2] = { -1, -1 };
@ -78,11 +78,12 @@ pid_t rc_logger_pid = -1;
int rc_logger_tty = -1; int rc_logger_tty = -1;
bool rc_in_logger = false; bool rc_in_logger = false;
static void write_log(int logfd, const char *buffer, size_t bytes) static void
write_log(int logfd, const char *buffer, size_t bytes)
{ {
const char *p = buffer; const char *p = buffer;
while ((size_t) (p - buffer) < bytes) { while ((size_t)(p - buffer) < bytes) {
switch (*p) { switch (*p) {
case '\r': case '\r':
goto cont; goto cont;
@ -110,7 +111,9 @@ cont:
p++; p++;
} }
} }
static void write_time(FILE *f, const char *s)
static void
write_time(FILE *f, const char *s)
{ {
time_t now = time(NULL); time_t now = time(NULL);
struct tm *tm = localtime(&now); struct tm *tm = localtime(&now);
@ -119,7 +122,8 @@ static void write_time(FILE *f, const char *s)
fflush(f); fflush(f);
} }
void rc_logger_close(void) void
rc_logger_close(void)
{ {
int sig = SIGTERM; int sig = SIGTERM;
@ -138,7 +142,8 @@ void rc_logger_close(void)
dup2(fd_stderr, STDERR_FILENO); dup2(fd_stderr, STDERR_FILENO);
} }
void rc_logger_open(const char *level) void
rc_logger_open(const char *level)
{ {
int slave_tty; int slave_tty;
struct termios tt; struct termios tt;
@ -157,7 +162,7 @@ void rc_logger_open(const char *level)
eerrorx("pipe: %s", strerror(errno)); eerrorx("pipe: %s", strerror(errno));
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
if ((s = fcntl (signal_pipe[i], F_GETFD, 0) == -1 || if ((s = fcntl (signal_pipe[i], F_GETFD, 0) == -1 ||
fcntl (signal_pipe[i], F_SETFD, s | FD_CLOEXEC) == -1)) fcntl (signal_pipe[i], F_SETFD, s | FD_CLOEXEC) == -1))
eerrorx("fcntl: %s", strerror (errno)); eerrorx("fcntl: %s", strerror (errno));
if (isatty(STDOUT_FILENO)) { if (isatty(STDOUT_FILENO)) {
@ -202,36 +207,38 @@ void rc_logger_open(const char *level)
if (rc_logger_tty >= 0) if (rc_logger_tty >= 0)
fd[1].fd = rc_logger_tty; fd[1].fd = rc_logger_tty;
for (;;) { for (;;) {
if ((s = poll(fd, rc_logger_tty >= 0 ? 2 : 1, -1)) == -1) { if ((s = poll(fd,
rc_logger_tty >= 0 ? 2 : 1, -1)) == -1)
{
eerror("poll: %s", strerror(errno)); eerror("poll: %s", strerror(errno));
break; break;
} } else if (s == 0)
continue;
if (s > 0) { if (fd[1].revents & (POLLIN | POLLHUP)) {
if (fd[1].revents & (POLLIN | POLLHUP)) { memset(buffer, 0, BUFSIZ);
memset(buffer, 0, BUFSIZ); bytes = read(rc_logger_tty, buffer, BUFSIZ);
bytes = read(rc_logger_tty, buffer, BUFSIZ); write(STDOUT_FILENO, buffer, bytes);
write(STDOUT_FILENO, buffer, bytes);
if (log) if (log)
write_log(fileno (log), buffer, bytes); write_log(fileno (log), buffer, bytes);
else { else {
if (logbuf_size - logbuf_len < bytes) { if (logbuf_size - logbuf_len < bytes) {
logbuf_size += BUFSIZ * 10; logbuf_size += BUFSIZ * 10;
logbuf = xrealloc(logbuf, logbuf = xrealloc(logbuf,
sizeof(char ) * sizeof(char ) *
logbuf_size); logbuf_size);
}
memcpy(logbuf + logbuf_len, buffer, bytes);
logbuf_len += bytes;
} }
}
/* Only SIGTERMS signals come down this pipe */ memcpy(logbuf + logbuf_len,
if (fd[0].revents & (POLLIN | POLLHUP)) buffer, bytes);
break; logbuf_len += bytes;
}
} }
/* Only SIGTERMS signals come down this pipe */
if (fd[0].revents & (POLLIN | POLLHUP))
break;
} }
free(buffer); free(buffer);
if (logbuf) { if (logbuf) {
@ -246,10 +253,9 @@ void rc_logger_open(const char *level)
fclose(log); fclose(log);
} }
/* Try and cat our new logfile to a more permament location and then /* Try and cat our new logfile to a more permament location
* punt it */ and then punt it */
system(MOVELOG); system(MOVELOG);
exit(0); exit(0);
/* NOTREACHED */ /* NOTREACHED */

View File

@ -1,7 +1,7 @@
/* /*
librc-misc.c librc-misc.c
rc misc functions rc misc functions
*/ */
/* /*
* Copyright 2007-2008 Roy Marples <roy@marples.name> * Copyright 2007-2008 Roy Marples <roy@marples.name>
@ -34,8 +34,8 @@
#include <sys/utsname.h> #include <sys/utsname.h>
#ifdef __linux__ #ifdef __linux__
#include <sys/sysinfo.h> # include <sys/sysinfo.h>
#include <regex.h> # include <regex.h>
#endif #endif
#include <ctype.h> #include <ctype.h>
@ -244,7 +244,8 @@ env_config(void)
if (sys) if (sys)
setenv("RC_SYS", sys, 1); setenv("RC_SYS", sys, 1);
/* Some scripts may need to take a different code path if Linux/FreeBSD, etc /* Some scripts may need to take a different code path if
Linux/FreeBSD, etc
To save on calling uname, we store it in an environment variable */ To save on calling uname, we store it in an environment variable */
if (uname(&uts) == 0) if (uname(&uts) == 0)
setenv("RC_UNAME", uts.sysname, 1); setenv("RC_UNAME", uts.sysname, 1);
@ -346,7 +347,7 @@ exec_service(const char *service, const char *arg)
/* Safe to run now */ /* Safe to run now */
execl(file, file, "--lockfd", sfd, arg, (char *) NULL); execl(file, file, "--lockfd", sfd, arg, (char *) NULL);
fprintf(stderr, "unable to exec `%s': %s\n", fprintf(stderr, "unable to exec `%s': %s\n",
file, strerror(errno)); file, strerror(errno));
svc_unlock(basename_c(service), fd); svc_unlock(basename_c(service), fd);
_exit(EXIT_FAILURE); _exit(EXIT_FAILURE);
} }

View File

@ -1,7 +1,7 @@
/* /*
librc-plugin.c librc-plugin.c
Simple plugin handler Simple plugin handler
*/ */
/* /*
* Copyright 2007-2008 Roy Marples <roy@marples.name> * Copyright 2007-2008 Roy Marples <roy@marples.name>
@ -62,7 +62,8 @@ typedef struct plugin
TAILQ_HEAD(, plugin) plugins; TAILQ_HEAD(, plugin) plugins;
#ifndef __FreeBSD__ #ifndef __FreeBSD__
dlfunc_t dlfunc(void * __restrict handle, const char * __restrict symbol) dlfunc_t
dlfunc(void * __restrict handle, const char * __restrict symbol)
{ {
union { union {
void *d; void *d;
@ -74,7 +75,8 @@ dlfunc_t dlfunc(void * __restrict handle, const char * __restrict symbol)
} }
#endif #endif
void rc_plugin_load(void) void
rc_plugin_load(void)
{ {
DIR *dp; DIR *dp;
struct dirent *d; struct dirent *d;
@ -89,7 +91,7 @@ void rc_plugin_load(void)
TAILQ_INIT(&plugins); TAILQ_INIT(&plugins);
if (! (dp = opendir(RC_PLUGINDIR))) if (!(dp = opendir(RC_PLUGINDIR)))
return; return;
while ((d = readdir(dp))) { while ((d = readdir(dp))) {
@ -98,14 +100,16 @@ void rc_plugin_load(void)
snprintf(file, sizeof(file), RC_PLUGINDIR "/%s", d->d_name); snprintf(file, sizeof(file), RC_PLUGINDIR "/%s", d->d_name);
h = dlopen(file, RTLD_LAZY); h = dlopen(file, RTLD_LAZY);
if (! h) { if (h == NULL) {
eerror("dlopen: %s", dlerror()); eerror("dlopen: %s", dlerror());
continue; continue;
} }
fptr = (int (*)(RC_HOOK, const char*))dlfunc(h, RC_PLUGIN_HOOK); fptr = (int (*)(RC_HOOK, const char*))
if (! fptr) { dlfunc(h, RC_PLUGIN_HOOK);
eerror("%s: cannot find symbol `%s'", d->d_name, RC_PLUGIN_HOOK); if (fptr == NULL) {
eerror("%s: cannot find symbol `%s'",
d->d_name, RC_PLUGIN_HOOK);
dlclose(h); dlclose(h);
} else { } else {
plugin = xmalloc(sizeof(*plugin)); plugin = xmalloc(sizeof(*plugin));
@ -118,7 +122,8 @@ void rc_plugin_load(void)
closedir(dp); closedir(dp);
} }
int rc_waitpid(pid_t pid) int
rc_waitpid(pid_t pid)
{ {
int status; int status;
@ -131,7 +136,8 @@ int rc_waitpid(pid_t pid)
return status; return status;
} }
void rc_plugin_run(RC_HOOK hook, const char *value) void
rc_plugin_run(RC_HOOK hook, const char *value)
{ {
PLUGIN *plugin; PLUGIN *plugin;
struct sigaction sa; struct sigaction sa;
@ -234,7 +240,8 @@ void rc_plugin_run(RC_HOOK hook, const char *value)
} }
} }
void rc_plugin_unload(void) void
rc_plugin_unload(void)
{ {
PLUGIN *plugin = TAILQ_FIRST(&plugins); PLUGIN *plugin = TAILQ_FIRST(&plugins);
PLUGIN *next; PLUGIN *next;

View File

@ -1,7 +1,7 @@
/* /*
rc-service.c rc-service.c
Finds all OpenRC services Finds all OpenRC services
*/ */
/* /*
* Copyright 2008 Roy Marples <roy@marples.name> * Copyright 2008 Roy Marples <roy@marples.name>
@ -70,7 +70,7 @@ rc_service(int argc, char **argv)
unsetenv("EINFO_QUIET"); unsetenv("EINFO_QUIET");
while ((opt = getopt_long(argc, argv, getoptstring, while ((opt = getopt_long(argc, argv, getoptstring,
longopts, (int *) 0)) != -1) longopts, (int *) 0)) != -1)
{ {
switch (opt) { switch (opt) {
case 'e': case 'e':
@ -87,7 +87,7 @@ rc_service(int argc, char **argv)
return EXIT_FAILURE; return EXIT_FAILURE;
rc_stringlist_sort(&list); rc_stringlist_sort(&list);
TAILQ_FOREACH(s, list, entries) TAILQ_FOREACH(s, list, entries)
printf("%s\n", s->value); printf("%s\n", s->value);
#ifdef DEBUG_MEMORY #ifdef DEBUG_MEMORY
rc_stringlist_free(list); rc_stringlist_free(list);
#endif #endif
@ -104,8 +104,8 @@ rc_service(int argc, char **argv)
return EXIT_SUCCESS; return EXIT_SUCCESS;
/* NOTREACHED */ /* NOTREACHED */
case_RC_COMMON_GETOPT case_RC_COMMON_GETOPT
} }
} }
argc -= optind; argc -= optind;

View File

@ -1,7 +1,7 @@
/* /*
rc-update rc-update
Manage init scripts and runlevels Manage init scripts and runlevels
*/ */
/* /*
* Copyright 2007-2009 Roy Marples <roy@marples.name> * Copyright 2007-2009 Roy Marples <roy@marples.name>
@ -57,19 +57,21 @@ add(const char *runlevel, const char *service)
if (!rc_service_exists(service)) { if (!rc_service_exists(service)) {
if (errno == ENOEXEC) if (errno == ENOEXEC)
eerror("%s: service `%s' is not executeable", applet, service); eerror("%s: service `%s' is not executeable",
applet, service);
else else
eerror("%s: service `%s' does not exist", applet, service); eerror("%s: service `%s' does not exist",
applet, service);
} else if (rc_service_in_runlevel(service, runlevel)) { } else if (rc_service_in_runlevel(service, runlevel)) {
ewarn ("%s: %s already installed in runlevel `%s'; skipping", ewarn ("%s: %s already installed in runlevel `%s'; skipping",
applet, service, runlevel); applet, service, runlevel);
retval = 0; retval = 0;
} else if (rc_service_add(runlevel, service)) { } else if (rc_service_add(runlevel, service)) {
einfo ("%s added to runlevel %s", service, runlevel); einfo ("%s added to runlevel %s", service, runlevel);
retval = 1; retval = 1;
} else } else
eerror("%s: failed to add service `%s' to runlevel `%s': %s", eerror("%s: failed to add service `%s' to runlevel `%s': %s",
applet, service, runlevel, strerror (errno)); applet, service, runlevel, strerror (errno));
return retval; return retval;
} }
@ -87,10 +89,10 @@ delete(const char *runlevel, const char *service)
if (errno == ENOENT) if (errno == ENOENT)
eerror ("%s: service `%s' is not in the runlevel `%s'", eerror ("%s: service `%s' is not in the runlevel `%s'",
applet, service, runlevel); applet, service, runlevel);
else else
eerror ("%s: failed to remove service `%s' from runlevel `%s': %s", eerror ("%s: failed to remove service `%s' from runlevel `%s': %s",
applet, service, runlevel, strerror (errno)); applet, service, runlevel, strerror (errno));
return retval; return retval;
} }
@ -112,7 +114,7 @@ show(RC_STRINGLIST *runlevels, bool verbose)
TAILQ_FOREACH(runlevel, runlevels, entries) { TAILQ_FOREACH(runlevel, runlevels, entries) {
if (rc_service_in_runlevel(service->value, if (rc_service_in_runlevel(service->value,
runlevel->value)) runlevel->value))
{ {
rc_stringlist_add(in, runlevel->value); rc_stringlist_add(in, runlevel->value);
inone = true; inone = true;
@ -127,7 +129,7 @@ show(RC_STRINGLIST *runlevels, bool verbose)
if (inone || verbose) { if (inone || verbose) {
printf(" %20s |", service->value); printf(" %20s |", service->value);
TAILQ_FOREACH(runlevel, in, entries) TAILQ_FOREACH(runlevel, in, entries)
printf (" %s", runlevel->value); printf (" %s", runlevel->value);
printf ("\n"); printf ("\n");
} }
rc_stringlist_free(in); rc_stringlist_free(in);
@ -137,9 +139,9 @@ show(RC_STRINGLIST *runlevels, bool verbose)
} }
#include "_usage.h" #include "_usage.h"
#define usagestring "" \ #define usagestring "" \
"Usage: rc-update [options] add service <runlevel>\n" \ "Usage: rc-update [options] add service <runlevel>\n" \
" rc-update [options] del service <runlevel>\n" \ " rc-update [options] del service <runlevel>\n" \
" rc-update [options] show" " rc-update [options] show"
#define getoptstring "u" getoptstring_COMMON #define getoptstring "u" getoptstring_COMMON
static const struct option longopts[] = { static const struct option longopts[] = {
@ -172,13 +174,13 @@ rc_update(int argc, char **argv)
int ret; int ret;
while ((opt = getopt_long(argc, argv, getoptstring, while ((opt = getopt_long(argc, argv, getoptstring,
longopts, (int *)0)) != -1) longopts, (int *)0)) != -1)
switch (opt) { switch (opt) {
case 'u': case 'u':
_rc_deptree_load(-1, &ret); _rc_deptree_load(-1, &ret);
return ret; return ret;
case_RC_COMMON_GETOPT case_RC_COMMON_GETOPT
} }
verbose = rc_yesno(getenv ("EINFO_VERBOSE")); verbose = rc_yesno(getenv ("EINFO_VERBOSE"));
@ -192,14 +194,15 @@ rc_update(int argc, char **argv)
if (strcmp(argv[optind], "add") == 0) if (strcmp(argv[optind], "add") == 0)
action = DOADD; action = DOADD;
else if (strcmp(argv[optind], "delete") == 0 || else if (strcmp(argv[optind], "delete") == 0 ||
strcmp(argv[optind], "del") == 0) strcmp(argv[optind], "del") == 0)
action = DODELETE; action = DODELETE;
else if (strcmp(argv[optind], "show") == 0) else if (strcmp(argv[optind], "show") == 0)
action = DOSHOW; action = DOSHOW;
if (action) if (action)
optind++; optind++;
else else
eerrorx("%s: invalid command `%s'", applet, argv[optind]); eerrorx("%s: invalid command `%s'",
applet, argv[optind]);
} }
if (!action) if (!action)
action = DOSHOW; action = DOSHOW;
@ -219,7 +222,7 @@ rc_update(int argc, char **argv)
else { else {
rc_stringlist_free(runlevels); rc_stringlist_free(runlevels);
eerrorx ("%s: `%s' is not a valid runlevel", eerrorx ("%s: `%s' is not a valid runlevel",
applet, argv[optind]); applet, argv[optind]);
} }
} }
@ -254,13 +257,13 @@ rc_update(int argc, char **argv)
if (!TAILQ_FIRST(runlevels)) { if (!TAILQ_FIRST(runlevels)) {
free(runlevels); free(runlevels);
eerrorx ("%s: no runlevels found", applet); eerrorx("%s: no runlevels found", applet);
} }
TAILQ_FOREACH(runlevel, runlevels, entries) { TAILQ_FOREACH(runlevel, runlevels, entries) {
if (!rc_runlevel_exists(runlevel->value)) { if (!rc_runlevel_exists(runlevel->value)) {
eerror ("%s: runlevel `%s' does not exist", eerror ("%s: runlevel `%s' does not exist",
applet, runlevel->value); applet, runlevel->value);
continue; continue;
} }
@ -273,8 +276,8 @@ rc_update(int argc, char **argv)
if (retval == EXIT_SUCCESS && if (retval == EXIT_SUCCESS &&
num_updated == 0 && action & DODELETE) num_updated == 0 && action & DODELETE)
ewarnx("%s: service `%s' not found in any" ewarnx("%s: service `%s' not found in any"
" of the specified runlevels", " of the specified runlevels",
applet, service); applet, service);
} }
} }

View File

@ -44,7 +44,7 @@ const char rc_copyright[] = "Copyright (c) 2007-2008 Roy Marples";
#include <sys/wait.h> #include <sys/wait.h>
#ifdef __linux__ #ifdef __linux__
# include <asm/setup.h> /* for COMMAND_LINE_SIZE */ # include <asm/setup.h> /* for COMMAND_LINE_SIZE */
#endif #endif
#include <errno.h> #include <errno.h>
@ -108,17 +108,17 @@ clean_failed(void)
while ((d = readdir(dp))) { while ((d = readdir(dp))) {
if (d->d_name[0] == '.' && if (d->d_name[0] == '.' &&
(d->d_name[1] == '\0' || (d->d_name[1] == '\0' ||
(d->d_name[1] == '.' && d->d_name[2] == '\0'))) (d->d_name[1] == '.' && d->d_name[2] == '\0')))
continue; continue;
l = strlen(RC_SVCDIR "/failed/") + l = strlen(RC_SVCDIR "/failed/") +
strlen(d->d_name) + 1; strlen(d->d_name) + 1;
path = xmalloc(sizeof(char) * l); path = xmalloc(sizeof(char) * l);
snprintf(path, l, RC_SVCDIR "/failed/%s", d->d_name); snprintf(path, l, RC_SVCDIR "/failed/%s", d->d_name);
if (path) { if (path) {
if (unlink(path)) if (unlink(path))
eerror("%s: unlink `%s': %s", eerror("%s: unlink `%s': %s",
applet, path, strerror(errno)); applet, path, strerror(errno));
free(path); free(path);
} }
} }
@ -217,8 +217,8 @@ read_key(bool block)
if (!isatty(fd)) if (!isatty(fd))
return false; return false;
/* Now save our terminal settings. We need to restore them at exit as we /* Now save our terminal settings. We need to restore them at exit as
* will be changing it for non-blocking reads for Interactive */ we will be changing it for non-blocking reads for Interactive */
if (!termios_orig) { if (!termios_orig) {
termios_orig = xmalloc(sizeof(*termios_orig)); termios_orig = xmalloc(sizeof(*termios_orig));
tcgetattr(fd, termios_orig); tcgetattr(fd, termios_orig);
@ -301,7 +301,7 @@ run_program(const char *prog)
execl(prog, prog, (char *) NULL); execl(prog, prog, (char *) NULL);
eerror("%s: unable to exec `%s': %s", applet, prog, eerror("%s: unable to exec `%s': %s", applet, prog,
strerror(errno)); strerror(errno));
_exit(EXIT_FAILURE); _exit(EXIT_FAILURE);
} }
@ -323,7 +323,7 @@ sulogin(bool cont)
{ {
execl("/sbin/halt", "/sbin/halt", "-f", (char *) NULL); execl("/sbin/halt", "/sbin/halt", "-f", (char *) NULL);
eerrorx("%s: unable to exec `/sbin/halt': %s", eerrorx("%s: unable to exec `/sbin/halt': %s",
applet, strerror(errno)); applet, strerror(errno));
} }
#endif #endif
if (!cont) { if (!cont) {
@ -343,7 +343,7 @@ single_user(void)
rc_logger_close(); rc_logger_close();
execl(SHUTDOWN, SHUTDOWN, "now", (char *) NULL); execl(SHUTDOWN, SHUTDOWN, "now", (char *) NULL);
eerrorx("%s: unable to exec `" SHUTDOWN "': %s", eerrorx("%s: unable to exec `" SHUTDOWN "': %s",
applet, strerror(errno)); applet, strerror(errno));
} }
static bool static bool
@ -359,7 +359,7 @@ set_krunlevel(const char *level)
if (exists(RC_KRUNLEVEL) && if (exists(RC_KRUNLEVEL) &&
unlink(RC_KRUNLEVEL) != 0) unlink(RC_KRUNLEVEL) != 0)
eerror("unlink `%s': %s", RC_KRUNLEVEL, eerror("unlink `%s': %s", RC_KRUNLEVEL,
strerror(errno)); strerror(errno));
return false; return false;
} }
@ -409,11 +409,11 @@ remove_pid(pid_t pid)
RC_PID *p; RC_PID *p;
LIST_FOREACH(p, &service_pids, entries) LIST_FOREACH(p, &service_pids, entries)
if (p->pid == pid) { if (p->pid == pid) {
LIST_REMOVE(p, entries); LIST_REMOVE(p, entries);
free(p); free(p);
return; return;
} }
} }
static void static void
@ -484,7 +484,7 @@ handle_signal(int sig)
/* Kill any running services we have started */ /* Kill any running services we have started */
LIST_FOREACH(pi, &service_pids, entries) LIST_FOREACH(pi, &service_pids, entries)
kill(pi->pid, SIGTERM); kill(pi->pid, SIGTERM);
/* Notify plugins we are aborting */ /* Notify plugins we are aborting */
rc_plugin_run(RC_HOOK_ABORT, NULL); rc_plugin_run(RC_HOOK_ABORT, NULL);
@ -514,15 +514,15 @@ do_sysinit()
uname(&uts); uname(&uts);
printf("\n %sOpenRC %s" VERSION "%s is starting up %s", printf("\n %sOpenRC %s" VERSION "%s is starting up %s",
ecolor(ECOLOR_GOOD), ecolor(ECOLOR_HILITE), ecolor(ECOLOR_GOOD), ecolor(ECOLOR_HILITE),
ecolor(ECOLOR_NORMAL), ecolor(ECOLOR_BRACKET)); ecolor(ECOLOR_NORMAL), ecolor(ECOLOR_BRACKET));
#ifdef BRANDING #ifdef BRANDING
printf(BRANDING " (%s)", uts.machine); printf(BRANDING " (%s)", uts.machine);
#else #else
printf("%s %s (%s)", printf("%s %s (%s)",
uts.sysname, uts.sysname,
uts.release, uts.release,
uts.machine); uts.machine);
#endif #endif
if ((sys = rc_sys())) if ((sys = rc_sys()))
@ -533,7 +533,7 @@ do_sysinit()
if (!rc_yesno(getenv ("EINFO_QUIET")) && if (!rc_yesno(getenv ("EINFO_QUIET")) &&
rc_conf_yesno("rc_interactive")) rc_conf_yesno("rc_interactive"))
printf("Press %sI%s to enter interactive boot mode\n\n", printf("Press %sI%s to enter interactive boot mode\n\n",
ecolor(ECOLOR_GOOD), ecolor(ECOLOR_NORMAL)); ecolor(ECOLOR_GOOD), ecolor(ECOLOR_NORMAL));
setenv("RC_RUNLEVEL", RC_LEVEL_SYSINIT, 1); setenv("RC_RUNLEVEL", RC_LEVEL_SYSINIT, 1);
run_program(INITSH); run_program(INITSH);
@ -611,13 +611,14 @@ do_stop_services(const char *newlevel, bool parallel)
if (!svc1) { if (!svc1) {
tmplist = rc_stringlist_new(); tmplist = rc_stringlist_new();
rc_stringlist_add(tmplist, service->value); rc_stringlist_add(tmplist, service->value);
deporder = rc_deptree_depends(deptree, types_n, tmplist, deporder = rc_deptree_depends(deptree, types_n,
newlevel ? newlevel : runlevel, tmplist, newlevel ? newlevel : runlevel,
RC_DEP_STRICT | RC_DEP_TRACE); RC_DEP_STRICT | RC_DEP_TRACE);
rc_stringlist_free(tmplist); rc_stringlist_free(tmplist);
svc2 = NULL; svc2 = NULL;
TAILQ_FOREACH(svc1, deporder, entries) { TAILQ_FOREACH(svc1, deporder, entries) {
svc2 = rc_stringlist_find(start_services, svc1->value); svc2 = rc_stringlist_find(start_services,
svc1->value);
if (svc2) if (svc2)
break; break;
} }
@ -661,21 +662,21 @@ do_start_services(bool parallel)
interactive = want_interactive(); interactive = want_interactive();
if (interactive) { if (interactive) {
interactive_retry: interactive_retry:
printf("\n"); printf("\n");
einfo("About to start the service %s", einfo("About to start the service %s",
service->value); service->value);
eindent(); eindent();
einfo("1) Start the service\t\t2) Skip the service"); einfo("1) Start the service\t\t2) Skip the service");
einfo("3) Continue boot process\t\t4) Exit to shell"); einfo("3) Continue boot process\t\t4) Exit to shell");
eoutdent(); eoutdent();
interactive_option: interactive_option:
switch (read_key(true)) { switch (read_key(true)) {
case '1': break; case '1': break;
case '2': continue; case '2': continue;
case '3': interactive = false; break; case '3': interactive = false; break;
case '4': sulogin(true); goto interactive_retry; case '4': sulogin(true); goto interactive_retry;
default: goto interactive_option; default: goto interactive_option;
} }
} }
@ -693,7 +694,7 @@ interactive_option:
/* Store our interactive status for boot */ /* Store our interactive status for boot */
if (interactive && if (interactive &&
(strcmp(runlevel, RC_LEVEL_SYSINIT) == 0 || (strcmp(runlevel, RC_LEVEL_SYSINIT) == 0 ||
strcmp(runlevel, getenv("RC_BOOTLEVEL")) == 0)) strcmp(runlevel, getenv("RC_BOOTLEVEL")) == 0))
mark_interactive(); mark_interactive();
else { else {
if (exists(INTERACTIVE)) if (exists(INTERACTIVE))
@ -711,17 +712,17 @@ handle_bad_signal(int sig)
pid_t crashed_pid = getpid(); pid_t crashed_pid = getpid();
switch (fork()) { switch (fork()) {
case -1: case -1:
_exit(sig); _exit(sig);
/* NOTREACHED */ /* NOTREACHED */
case 0: case 0:
sprintf(pid, "%i", crashed_pid); sprintf(pid, "%i", crashed_pid);
printf("\nAuto launching gdb!\n\n"); printf("\nAuto launching gdb!\n\n");
_exit(execlp("gdb", "gdb", "--quiet", "--pid", pid, _exit(execlp("gdb", "gdb", "--quiet", "--pid", pid,
"-ex", "bt full", NULL)); "-ex", "bt full", NULL));
/* NOTREACHED */ /* NOTREACHED */
default: default:
wait(&status); wait(&status);
} }
_exit(1); _exit(1);
/* NOTREACHED */ /* NOTREACHED */
@ -737,7 +738,8 @@ static const struct option longopts[] = {
longopts_COMMON longopts_COMMON
}; };
static const char * const longopts_help[] = { static const char * const longopts_help[] = {
"override the next runlevel to change into\nwhen leaving single user or boot runlevels", "override the next runlevel to change into\n"
"when leaving single user or boot runlevels",
"runs the service specified with the rest\nof the arguments", "runs the service specified with the rest\nof the arguments",
"output the RC system type, if any", "output the RC system type, if any",
longopts_help_COMMON longopts_help_COMMON
@ -783,9 +785,9 @@ main(int argc, char **argv)
printf(" [%s]", bootlevel); printf(" [%s]", bootlevel);
printf(") " VERSION printf(") " VERSION
#ifdef BRANDING #ifdef BRANDING
" (" BRANDING ")" " (" BRANDING ")"
#endif #endif
"\n"); "\n");
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
@ -806,7 +808,7 @@ main(int argc, char **argv)
argc++; argc++;
argv--; argv--;
while ((opt = getopt_long(argc, argv, getoptstring, while ((opt = getopt_long(argc, argv, getoptstring,
longopts, (int *) 0)) != -1) longopts, (int *) 0)) != -1)
{ {
switch (opt) { switch (opt) {
case 'o': case 'o':
@ -825,7 +827,7 @@ main(int argc, char **argv)
newlevel = rc_service_resolve(optarg); newlevel = rc_service_resolve(optarg);
if (!newlevel) if (!newlevel)
eerrorx("%s: service `%s' does not exist", eerrorx("%s: service `%s' does not exist",
applet, optarg); applet, optarg);
argv += optind - 1; argv += optind - 1;
*argv = newlevel; *argv = newlevel;
execv(*argv, argv); execv(*argv, argv);
@ -837,8 +839,8 @@ main(int argc, char **argv)
printf("%s\n", bootlevel); printf("%s\n", bootlevel);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
/* NOTREACHED */ /* NOTREACHED */
case_RC_COMMON_GETOPT case_RC_COMMON_GETOPT
} }
} }
newlevel = argv[optind++]; newlevel = argv[optind++];
@ -886,7 +888,7 @@ main(int argc, char **argv)
if (newlevel && if (newlevel &&
(strcmp(newlevel, RC_LEVEL_SHUTDOWN) == 0 || (strcmp(newlevel, RC_LEVEL_SHUTDOWN) == 0 ||
strcmp(newlevel, RC_LEVEL_SINGLE) == 0)) strcmp(newlevel, RC_LEVEL_SINGLE) == 0))
{ {
going_down = true; going_down = true;
if (!exists(RC_KRUNLEVEL)) if (!exists(RC_KRUNLEVEL))
@ -895,10 +897,10 @@ main(int argc, char **argv)
setenv("RC_RUNLEVEL", newlevel, 1); setenv("RC_RUNLEVEL", newlevel, 1);
setenv("RC_GOINGDOWN", "YES", 1); setenv("RC_GOINGDOWN", "YES", 1);
} else { } else {
/* We should not use krunevel in sysinit or the boot runlevel */ /* We should not use krunevel in sysinit or boot runlevels */
if (!newlevel || if (!newlevel ||
(strcmp(newlevel, RC_LEVEL_SYSINIT) != 0 && (strcmp(newlevel, RC_LEVEL_SYSINIT) != 0 &&
strcmp(newlevel, getenv("RC_BOOTLEVEL")) != 0)) strcmp(newlevel, getenv("RC_BOOTLEVEL")) != 0))
{ {
if (get_krunlevel(krunlevel, sizeof(krunlevel))) { if (get_krunlevel(krunlevel, sizeof(krunlevel))) {
newlevel = krunlevel; newlevel = krunlevel;
@ -960,7 +962,7 @@ main(int argc, char **argv)
if (errno == EACCES) if (errno == EACCES)
eerrorx("%s: superuser access required", applet); eerrorx("%s: superuser access required", applet);
eerrorx("%s: failed to create stopping dir `%s': %s", eerrorx("%s: failed to create stopping dir `%s': %s",
applet, RC_STOPPING, strerror(errno)); applet, RC_STOPPING, strerror(errno));
} }
/* Build a list of all services to stop and then work out the /* Build a list of all services to stop and then work out the
@ -982,7 +984,7 @@ main(int argc, char **argv)
if (stop_services) { if (stop_services) {
tmplist = rc_deptree_depends(deptree, types_nua, stop_services, tmplist = rc_deptree_depends(deptree, types_nua, stop_services,
runlevel, depoptions | RC_DEP_STOP); runlevel, depoptions | RC_DEP_STOP);
rc_stringlist_free(stop_services); rc_stringlist_free(stop_services);
stop_services = tmplist; stop_services = tmplist;
} }
@ -990,7 +992,7 @@ main(int argc, char **argv)
/* Load our list of start services */ /* Load our list of start services */
hotplugged_services = rc_services_in_state(RC_SERVICE_HOTPLUGGED); hotplugged_services = rc_services_in_state(RC_SERVICE_HOTPLUGGED);
start_services = rc_services_in_runlevel(newlevel ? start_services = rc_services_in_runlevel(newlevel ?
newlevel : runlevel); newlevel : runlevel);
if (strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 && if (strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 &&
strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SYSINIT) != 0) strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SYSINIT) != 0)
{ {
@ -998,10 +1000,10 @@ main(int argc, char **argv)
TAILQ_CONCAT(start_services, tmplist, entries); TAILQ_CONCAT(start_services, tmplist, entries);
free(tmplist); free(tmplist);
if (strcmp(newlevel ? newlevel : runlevel, if (strcmp(newlevel ? newlevel : runlevel,
RC_LEVEL_SINGLE) != 0) RC_LEVEL_SINGLE) != 0)
{ {
if (strcmp(newlevel ? newlevel : runlevel, if (strcmp(newlevel ? newlevel : runlevel,
bootlevel) != 0) bootlevel) != 0)
{ {
tmplist = rc_services_in_runlevel(bootlevel); tmplist = rc_services_in_runlevel(bootlevel);
TAILQ_CONCAT(start_services, tmplist, entries); TAILQ_CONCAT(start_services, tmplist, entries);
@ -1009,9 +1011,9 @@ main(int argc, char **argv)
} }
if (hotplugged_services) { if (hotplugged_services) {
TAILQ_FOREACH(service, hotplugged_services, TAILQ_FOREACH(service, hotplugged_services,
entries) entries)
rc_stringlist_addu(start_services, rc_stringlist_addu(start_services,
service->value); service->value);
} }
} }
} }
@ -1027,7 +1029,7 @@ main(int argc, char **argv)
/* Notify the plugins we have finished */ /* Notify the plugins we have finished */
rc_plugin_run(RC_HOOK_RUNLEVEL_STOP_OUT, rc_plugin_run(RC_HOOK_RUNLEVEL_STOP_OUT,
going_down ? newlevel : runlevel); going_down ? newlevel : runlevel);
hook_out = 0; hook_out = 0;
rmdir(RC_STOPPING); rmdir(RC_STOPPING);
@ -1054,14 +1056,14 @@ main(int argc, char **argv)
/* Re-add our hotplugged services if they stopped */ /* Re-add our hotplugged services if they stopped */
if (hotplugged_services) if (hotplugged_services)
TAILQ_FOREACH(service, hotplugged_services, entries) TAILQ_FOREACH(service, hotplugged_services, entries)
rc_service_mark(service->value, RC_SERVICE_HOTPLUGGED); rc_service_mark(service->value, RC_SERVICE_HOTPLUGGED);
/* Order the services to start */ /* Order the services to start */
if (start_services) { if (start_services) {
rc_stringlist_sort(&start_services); rc_stringlist_sort(&start_services);
deporder = rc_deptree_depends(deptree, types_nua, deporder = rc_deptree_depends(deptree, types_nua,
start_services, runlevel, start_services, runlevel,
depoptions | RC_DEP_START); depoptions | RC_DEP_START);
rc_stringlist_free(start_services); rc_stringlist_free(start_services);
start_services = deporder; start_services = deporder;
} }

View File

@ -54,11 +54,11 @@
#include <unistd.h> #include <unistd.h>
#ifdef __linux__ #ifdef __linux__
# include <pty.h> # include <pty.h>
#elif defined(__NetBSD__) || defined(__OpenBSD__) #elif defined(__NetBSD__) || defined(__OpenBSD__)
# include <util.h> # include <util.h>
#else #else
# include <libutil.h> # include <libutil.h>
#endif #endif
#include "builtins.h" #include "builtins.h"
@ -121,9 +121,9 @@ setup_selinux(int argc, char **argv)
} }
selinux_run_init_old = (void (*)(void)) selinux_run_init_old = (void (*)(void))
dlfunc(lib_handle, "selinux_runscript"); dlfunc(lib_handle, "selinux_runscript");
selinux_run_init_new = (void (*)(int, char **)) selinux_run_init_new = (void (*)(int, char **))
dlfunc(lib_handle, "selinux_runscript2"); dlfunc(lib_handle, "selinux_runscript2");
/* Use new run_init if it exists, else fall back to old */ /* Use new run_init if it exists, else fall back to old */
if (selinux_run_init_new) if (selinux_run_init_new)
@ -154,7 +154,7 @@ handle_signal(int sig)
if (signal_pipe[1] > -1) { if (signal_pipe[1] > -1) {
if (write(signal_pipe[1], &sig, sizeof(sig)) == -1) if (write(signal_pipe[1], &sig, sizeof(sig)) == -1)
eerror("%s: send: %s", eerror("%s: send: %s",
service, strerror(errno)); service, strerror(errno));
} else } else
rc_waitpid(-1); rc_waitpid(-1);
break; break;
@ -217,16 +217,16 @@ start_services(RC_STRINGLIST *list)
{ {
TAILQ_FOREACH(svc, list, entries) { TAILQ_FOREACH(svc, list, entries) {
if (!(rc_service_state(svc->value) & if (!(rc_service_state(svc->value) &
RC_SERVICE_STOPPED)) RC_SERVICE_STOPPED))
continue; continue;
if (state & RC_SERVICE_INACTIVE || if (state & RC_SERVICE_INACTIVE ||
state & RC_SERVICE_WASINACTIVE) state & RC_SERVICE_WASINACTIVE)
{ {
rc_service_schedule_start(service, rc_service_schedule_start(service,
svc->value); svc->value);
ewarn("WARNING: %s is scheduled to started" ewarn("WARNING: %s is scheduled to started"
" when %s has started", " when %s has started",
svc->value, applet); svc->value, applet);
} else } else
service_start(svc->value); service_start(svc->value);
} }
@ -269,10 +269,10 @@ cleanup(void)
rc_plugin_run(hook_out, applet); rc_plugin_run(hook_out, applet);
if (hook_out == RC_HOOK_SERVICE_START_DONE) if (hook_out == RC_HOOK_SERVICE_START_DONE)
rc_plugin_run(RC_HOOK_SERVICE_START_OUT, rc_plugin_run(RC_HOOK_SERVICE_START_OUT,
applet); applet);
else if (hook_out == RC_HOOK_SERVICE_STOP_DONE) else if (hook_out == RC_HOOK_SERVICE_STOP_DONE)
rc_plugin_run(RC_HOOK_SERVICE_STOP_OUT, rc_plugin_run(RC_HOOK_SERVICE_STOP_OUT,
applet); applet);
} }
if (restart_services) if (restart_services)
@ -369,7 +369,7 @@ svc_exec(const char *arg1, const char *arg2)
eerrorx("%s: pipe: %s", service, applet); eerrorx("%s: pipe: %s", service, applet);
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
if ((flags = fcntl(signal_pipe[i], F_GETFD, 0) == -1 || if ((flags = fcntl(signal_pipe[i], F_GETFD, 0) == -1 ||
fcntl(signal_pipe[i], F_SETFD, flags | FD_CLOEXEC) == -1)) fcntl(signal_pipe[i], F_SETFD, flags | FD_CLOEXEC) == -1))
eerrorx("%s: fcntl: %s", service, strerror(errno)); eerrorx("%s: fcntl: %s", service, strerror(errno));
/* Open a pty for our prefixed output /* Open a pty for our prefixed output
@ -387,11 +387,11 @@ svc_exec(const char *arg1, const char *arg2)
openpty(&master_tty, &slave_tty, NULL, &tt, &ws); openpty(&master_tty, &slave_tty, NULL, &tt, &ws);
if (master_tty >= 0 && if (master_tty >= 0 &&
(flags = fcntl(master_tty, F_GETFD, 0)) == 0) (flags = fcntl(master_tty, F_GETFD, 0)) == 0)
fcntl(master_tty, F_SETFD, flags | FD_CLOEXEC); fcntl(master_tty, F_SETFD, flags | FD_CLOEXEC);
if (slave_tty >=0 && if (slave_tty >=0 &&
(flags = fcntl(slave_tty, F_GETFD, 0)) == 0) (flags = fcntl(slave_tty, F_GETFD, 0)) == 0)
fcntl(slave_tty, F_SETFD, flags | FD_CLOEXEC); fcntl(slave_tty, F_SETFD, flags | FD_CLOEXEC);
} }
service_pid = fork(); service_pid = fork();
@ -405,17 +405,17 @@ svc_exec(const char *arg1, const char *arg2)
if (exists(RC_SVCDIR "/runscript.sh")) { if (exists(RC_SVCDIR "/runscript.sh")) {
execl(RC_SVCDIR "/runscript.sh", execl(RC_SVCDIR "/runscript.sh",
RC_SVCDIR "/runscript.sh", RC_SVCDIR "/runscript.sh",
service, arg1, arg2, (char *) NULL); service, arg1, arg2, (char *) NULL);
eerror("%s: exec `" RC_SVCDIR "/runscript.sh': %s", eerror("%s: exec `" RC_SVCDIR "/runscript.sh': %s",
service, strerror(errno)); service, strerror(errno));
_exit(EXIT_FAILURE); _exit(EXIT_FAILURE);
} else { } else {
execl(RC_LIBDIR "/sh/runscript.sh", execl(RC_LIBDIR "/sh/runscript.sh",
RC_LIBDIR "/sh/runscript.sh", RC_LIBDIR "/sh/runscript.sh",
service, arg1, arg2, (char *) NULL); service, arg1, arg2, (char *) NULL);
eerror("%s: exec `" RC_LIBDIR "/sh/runscript.sh': %s", eerror("%s: exec `" RC_LIBDIR "/sh/runscript.sh': %s",
service, strerror(errno)); service, strerror(errno));
_exit(EXIT_FAILURE); _exit(EXIT_FAILURE);
} }
} }
@ -434,7 +434,7 @@ svc_exec(const char *arg1, const char *arg2)
if ((s = poll(fd, master_tty >= 0 ? 2 : 1, -1)) == -1) { if ((s = poll(fd, master_tty >= 0 ? 2 : 1, -1)) == -1) {
if (errno != EINTR) { if (errno != EINTR) {
eerror("%s: poll: %s", eerror("%s: poll: %s",
service, strerror(errno)); service, strerror(errno));
break; break;
} }
} }
@ -488,7 +488,7 @@ svc_wait(const char *svc)
rc_stringlist_free(keywords); rc_stringlist_free(keywords);
snprintf(file, sizeof(file), RC_SVCDIR "/exclusive/%s", snprintf(file, sizeof(file), RC_SVCDIR "/exclusive/%s",
basename_c(svc)); basename_c(svc));
interval.tv_sec = 0; interval.tv_sec = 0;
interval.tv_nsec = WAIT_INTERVAL; interval.tv_nsec = WAIT_INTERVAL;
@ -521,7 +521,7 @@ svc_wait(const char *svc)
timespecsub(&warn, &interval, &warn); timespecsub(&warn, &interval, &warn);
if (warn.tv_sec <= 0) { if (warn.tv_sec <= 0) {
ewarn("%s: waiting for %s (%zu)", applet, svc, ewarn("%s: waiting for %s (%zu)", applet, svc,
timeout.tv_sec); timeout.tv_sec);
warn.tv_sec = WARN_TIMEOUT; warn.tv_sec = WARN_TIMEOUT;
warn.tv_nsec = 0; warn.tv_nsec = 0;
} }
@ -593,7 +593,7 @@ svc_start(bool deps)
rc_service_mark(service, RC_SERVICE_HOTPLUGGED); rc_service_mark(service, RC_SERVICE_HOTPLUGGED);
if (strcmp(runlevel, RC_LEVEL_SYSINIT) == 0) if (strcmp(runlevel, RC_LEVEL_SYSINIT) == 0)
ewarnx("WARNING: %s will be started in the" ewarnx("WARNING: %s will be started in the"
" next runlevel", applet); " next runlevel", applet);
} }
if (exclusive_fd == -1) if (exclusive_fd == -1)
@ -607,14 +607,14 @@ svc_start(bool deps)
ewarnx("WARNING: %s is already starting", applet); ewarnx("WARNING: %s is already starting", applet);
} }
fcntl(exclusive_fd, F_SETFD, fcntl(exclusive_fd, F_SETFD,
fcntl(exclusive_fd, F_GETFD, 0) | FD_CLOEXEC); fcntl(exclusive_fd, F_GETFD, 0) | FD_CLOEXEC);
if (state & RC_SERVICE_STARTED) { if (state & RC_SERVICE_STARTED) {
ewarn("WARNING: %s has already been started", applet); ewarn("WARNING: %s has already been started", applet);
return; return;
} else if (state & RC_SERVICE_INACTIVE && ! background) } else if (state & RC_SERVICE_INACTIVE && ! background)
ewarnx("WARNING: %s has already started, but is inactive", ewarnx("WARNING: %s has already started, but is inactive",
applet); applet);
rc_service_mark(service, RC_SERVICE_STARTING); rc_service_mark(service, RC_SERVICE_STARTING);
hook_out = RC_HOOK_SERVICE_START_OUT; hook_out = RC_HOOK_SERVICE_START_OUT;
@ -631,7 +631,7 @@ svc_start(bool deps)
setup_types(); setup_types();
services = rc_deptree_depends(deptree, types_b, applet_list, services = rc_deptree_depends(deptree, types_b, applet_list,
runlevel, 0); runlevel, 0);
if (TAILQ_FIRST(services)) { if (TAILQ_FIRST(services)) {
eerrorn("ERROR: `%s' needs ", applet); eerrorn("ERROR: `%s' needs ", applet);
first = true; first = true;
@ -648,11 +648,11 @@ svc_start(bool deps)
services = NULL; services = NULL;
need_services = rc_deptree_depends(deptree, types_n, need_services = rc_deptree_depends(deptree, types_n,
applet_list, runlevel, applet_list, runlevel,
depoptions); depoptions);
use_services = rc_deptree_depends(deptree, types_nu, use_services = rc_deptree_depends(deptree, types_nu,
applet_list, runlevel, applet_list, runlevel,
depoptions); depoptions);
if (!rc_runlevel_starting()) { if (!rc_runlevel_starting()) {
TAILQ_FOREACH(svc, use_services, entries) { TAILQ_FOREACH(svc, use_services, entries) {
@ -673,7 +673,7 @@ svc_start(bool deps)
/* Now wait for them to start */ /* Now wait for them to start */
services = rc_deptree_depends(deptree, types_nua, applet_list, services = rc_deptree_depends(deptree, types_nua, applet_list,
runlevel, depoptions); runlevel, depoptions);
/* We use tmplist to hold our scheduled by list */ /* We use tmplist to hold our scheduled by list */
tmplist = rc_stringlist_new(); tmplist = rc_stringlist_new();
TAILQ_FOREACH(svc, services, entries) { TAILQ_FOREACH(svc, services, entries) {
@ -687,15 +687,15 @@ svc_start(bool deps)
state & RC_SERVICE_WASINACTIVE) state & RC_SERVICE_WASINACTIVE)
{ {
if (!rc_stringlist_find(need_services, if (!rc_stringlist_find(need_services,
svc->value) && svc->value) &&
!rc_stringlist_find(use_services, !rc_stringlist_find(use_services,
svc->value)) svc->value))
continue; continue;
} }
if (!svc_wait(svc->value)) if (!svc_wait(svc->value))
eerror("%s: timed out waiting for %s", eerror("%s: timed out waiting for %s",
applet, svc->value); applet, svc->value);
state = rc_service_state(svc->value); state = rc_service_state(svc->value);
if (state & RC_SERVICE_STARTED) if (state & RC_SERVICE_STARTED)
continue; continue;
@ -706,8 +706,8 @@ svc_start(bool deps)
rc_stringlist_add(tmplist, svc->value); rc_stringlist_add(tmplist, svc->value);
} else if (!TAILQ_FIRST(tmplist)) } else if (!TAILQ_FIRST(tmplist))
eerrorx("ERROR: cannot start %s as" eerrorx("ERROR: cannot start %s as"
" %s would not start", " %s would not start",
applet, svc->value); applet, svc->value);
} }
} }
@ -723,11 +723,11 @@ svc_start(bool deps)
TAILQ_FOREACH(svc, tmplist, entries) { TAILQ_FOREACH(svc, tmplist, entries) {
rc_service_schedule_start(svc->value, service); rc_service_schedule_start(svc->value, service);
use_services = rc_deptree_depend(deptree, use_services = rc_deptree_depend(deptree,
"iprovide", "iprovide",
svc->value); svc->value);
TAILQ_FOREACH(svc2, use_services, entries) TAILQ_FOREACH(svc2, use_services, entries)
rc_service_schedule_start(svc2->value, rc_service_schedule_start(svc2->value,
service); service);
rc_stringlist_free(use_services); rc_stringlist_free(use_services);
use_services = NULL; use_services = NULL;
len += strlen(svc->value) + 2; len += strlen(svc->value) + 2;
@ -740,12 +740,12 @@ svc_start(bool deps)
if (p != tmp) if (p != tmp)
p += snprintf(p, len, ", "); p += snprintf(p, len, ", ");
p += snprintf(p, len - (p - tmp), p += snprintf(p, len - (p - tmp),
"%s", svc->value); "%s", svc->value);
} }
rc_stringlist_free(tmplist); rc_stringlist_free(tmplist);
tmplist = NULL; tmplist = NULL;
ewarnx("WARNING: %s is scheduled to start when " ewarnx("WARNING: %s is scheduled to start when "
"%s has started", applet, tmp); "%s has started", applet, tmp);
free(tmp); free(tmp);
} }
@ -766,7 +766,7 @@ svc_start(bool deps)
else { else {
if (rc_service_state(service) & RC_SERVICE_INACTIVE) if (rc_service_state(service) & RC_SERVICE_INACTIVE)
ewarnx("WARNING: %s has started, but is inactive", ewarnx("WARNING: %s has started, but is inactive",
applet); applet);
} }
rc_service_mark(service, RC_SERVICE_STARTED); rc_service_mark(service, RC_SERVICE_STARTED);
@ -777,8 +777,8 @@ svc_start(bool deps)
/* Now start any scheduled services */ /* Now start any scheduled services */
services = rc_services_scheduled(service); services = rc_services_scheduled(service);
TAILQ_FOREACH(svc, services, entries) TAILQ_FOREACH(svc, services, entries)
if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) if (rc_service_state(svc->value) & RC_SERVICE_STOPPED)
service_start(svc->value); service_start(svc->value);
rc_stringlist_free(services); rc_stringlist_free(services);
services = NULL; services = NULL;
@ -788,9 +788,9 @@ svc_start(bool deps)
TAILQ_FOREACH(svc, tmplist, entries) { TAILQ_FOREACH(svc, tmplist, entries) {
services = rc_services_scheduled(svc->value); services = rc_services_scheduled(svc->value);
TAILQ_FOREACH(svc2, services, entries) TAILQ_FOREACH(svc2, services, entries)
if (rc_service_state(svc2->value) & if (rc_service_state(svc2->value) &
RC_SERVICE_STOPPED) RC_SERVICE_STOPPED)
service_start(svc2->value); service_start(svc2->value);
rc_stringlist_free(services); rc_stringlist_free(services);
services = NULL; services = NULL;
} }
@ -829,7 +829,7 @@ svc_stop(bool deps)
eerrorx("ERROR: %s has been stopped by something else", applet); eerrorx("ERROR: %s has been stopped by something else", applet);
} }
fcntl(exclusive_fd, F_SETFD, fcntl(exclusive_fd, F_SETFD,
fcntl(exclusive_fd, F_GETFD, 0) | FD_CLOEXEC); fcntl(exclusive_fd, F_GETFD, 0) | FD_CLOEXEC);
if (state & RC_SERVICE_STOPPED) { if (state & RC_SERVICE_STOPPED) {
ewarn("WARNING: %s is already stopped", applet); ewarn("WARNING: %s is already stopped", applet);
@ -859,7 +859,7 @@ svc_stop(bool deps)
setup_types(); setup_types();
services = rc_deptree_depends(deptree, types_m, applet_list, services = rc_deptree_depends(deptree, types_m, applet_list,
runlevel, depoptions); runlevel, depoptions);
tmplist = rc_stringlist_new(); tmplist = rc_stringlist_new();
TAILQ_FOREACH_REVERSE(svc, services, rc_stringlist, entries) { TAILQ_FOREACH_REVERSE(svc, services, rc_stringlist, entries) {
state = rc_service_state(svc->value); state = rc_service_state(svc->value);
@ -898,14 +898,14 @@ svc_stop(bool deps)
* if a dependant failed */ * if a dependant failed */
if (runlevel && if (runlevel &&
(strcmp(runlevel, (strcmp(runlevel,
RC_LEVEL_SHUTDOWN) == 0 || RC_LEVEL_SHUTDOWN) == 0 ||
strcmp(runlevel, strcmp(runlevel,
RC_LEVEL_SINGLE) == 0)) RC_LEVEL_SINGLE) == 0))
continue; continue;
rc_service_mark(service, RC_SERVICE_FAILED); rc_service_mark(service, RC_SERVICE_FAILED);
} }
eerrorx("ERROR: cannot stop %s as %s " eerrorx("ERROR: cannot stop %s as %s "
"is still up", applet, svc->value); "is still up", applet, svc->value);
} }
rc_stringlist_free(tmplist); rc_stringlist_free(tmplist);
tmplist = NULL; tmplist = NULL;
@ -914,7 +914,7 @@ svc_stop(bool deps)
/* We now wait for other services that may use us and are /* We now wait for other services that may use us and are
* stopping. This is important when a runlevel stops */ * stopping. This is important when a runlevel stops */
services = rc_deptree_depends(deptree, types_mua, applet_list, services = rc_deptree_depends(deptree, types_mua, applet_list,
runlevel, depoptions); runlevel, depoptions);
TAILQ_FOREACH(svc, services, entries) { TAILQ_FOREACH(svc, services, entries) {
if (rc_service_state(svc->value) & RC_SERVICE_STOPPED) if (rc_service_state(svc->value) & RC_SERVICE_STOPPED)
continue; continue;
@ -1062,7 +1062,7 @@ runscript(int argc, char **argv)
if (stat(argv[1], &stbuf) != 0) { if (stat(argv[1], &stbuf) != 0) {
fprintf(stderr, "runscript `%s': %s\n", fprintf(stderr, "runscript `%s': %s\n",
argv[1], strerror(errno)); argv[1], strerror(errno));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -1158,7 +1158,7 @@ runscript(int argc, char **argv)
/* Right then, parse any options there may be */ /* Right then, parse any options there may be */
while ((opt = getopt_long(argc, argv, getoptstring, while ((opt = getopt_long(argc, argv, getoptstring,
longopts, (int *)0)) != -1) longopts, (int *)0)) != -1)
switch (opt) { switch (opt) {
case 'd': case 'd':
setenv("RC_DEBUG", "YES", 1); setenv("RC_DEBUG", "YES", 1);
@ -1175,8 +1175,8 @@ runscript(int argc, char **argv)
case 'D': case 'D':
deps = false; deps = false;
break; break;
case_RC_COMMON_GETOPT case_RC_COMMON_GETOPT
} }
/* If we're changing runlevels and not called by rc then we cannot /* If we're changing runlevels and not called by rc then we cannot
work with any dependencies */ work with any dependencies */
@ -1238,12 +1238,12 @@ runscript(int argc, char **argv)
eprefix(save); eprefix(save);
prefix = save; prefix = save;
} else if (strcmp(optarg, "ineed") == 0 || } else if (strcmp(optarg, "ineed") == 0 ||
strcmp(optarg, "iuse") == 0 || strcmp(optarg, "iuse") == 0 ||
strcmp(optarg, "needsme") == 0 || strcmp(optarg, "needsme") == 0 ||
strcmp(optarg, "usesme") == 0 || strcmp(optarg, "usesme") == 0 ||
strcmp(optarg, "iafter") == 0 || strcmp(optarg, "iafter") == 0 ||
strcmp(optarg, "ibefore") == 0 || strcmp(optarg, "ibefore") == 0 ||
strcmp(optarg, "iprovide") == 0) strcmp(optarg, "iprovide") == 0)
{ {
errno = 0; errno = 0;
if (rc_conf_yesno("rc_depend_strict") || if (rc_conf_yesno("rc_depend_strict") ||
@ -1257,11 +1257,11 @@ runscript(int argc, char **argv)
tmplist = rc_stringlist_new(); tmplist = rc_stringlist_new();
rc_stringlist_add(tmplist, optarg); rc_stringlist_add(tmplist, optarg);
services = rc_deptree_depends(deptree, tmplist, services = rc_deptree_depends(deptree, tmplist,
applet_list, applet_list,
runlevel, depoptions); runlevel, depoptions);
rc_stringlist_free(tmplist); rc_stringlist_free(tmplist);
TAILQ_FOREACH(svc, services, entries) TAILQ_FOREACH(svc, services, entries)
printf("%s ", svc->value); printf("%s ", svc->value);
printf ("\n"); printf ("\n");
rc_stringlist_free(services); rc_stringlist_free(services);
services = NULL; services = NULL;
@ -1297,20 +1297,20 @@ runscript(int argc, char **argv)
RC_SERVICE_INACTIVE) RC_SERVICE_INACTIVE)
{ {
TAILQ_FOREACH(svc, TAILQ_FOREACH(svc,
restart_services, restart_services,
entries) entries)
if (rc_service_state(svc->value) & if (rc_service_state(svc->value) &
RC_SERVICE_STOPPED) RC_SERVICE_STOPPED)
rc_service_schedule_start(service, svc->value); rc_service_schedule_start(service, svc->value);
} }
} }
} else if (strcmp(optarg, "zap") == 0) { } else if (strcmp(optarg, "zap") == 0) {
einfo("Manually resetting %s to stopped state", einfo("Manually resetting %s to stopped state",
applet); applet);
if (!rc_service_mark(applet, if (!rc_service_mark(applet,
RC_SERVICE_STOPPED)) RC_SERVICE_STOPPED))
eerrorx("rc_service_mark: %s", eerrorx("rc_service_mark: %s",
strerror(errno)); strerror(errno));
unhotplug(); unhotplug();
} else } else
svc_exec(optarg, NULL); svc_exec(optarg, NULL);

View File

@ -1,11 +1,11 @@
/* /*
start-stop-daemon start-stop-daemon
Starts, stops, tests and signals daemons Starts, stops, tests and signals daemons
This is essentially a ground up re-write of Debians This is essentially a ground up re-write of Debians
start-stop-daemon for cleaner code and to integrate into our RC start-stop-daemon for cleaner code and to integrate into our RC
system so we can monitor daemons a little. system so we can monitor daemons a little.
*/ */
/* /*
* Copyright 2007-2009 Roy Marples <roy@marples.name> * Copyright 2007-2009 Roy Marples <roy@marples.name>
@ -75,9 +75,9 @@ static struct pam_conv conv = { NULL, NULL};
/* Some libc implementations don't define this */ /* Some libc implementations don't define this */
#ifndef LIST_FOREACH_SAFE #ifndef LIST_FOREACH_SAFE
#define LIST_FOREACH_SAFE(var, head, field, tvar) \ #define LIST_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = LIST_FIRST((head)); \ for ((var) = LIST_FIRST((head)); \
(var) && ((tvar) = LIST_NEXT((var), field), 1); \ (var) && ((tvar) = LIST_NEXT((var), field), 1); \
(var) = (tvar)) (var) = (tvar))
#endif #endif
@ -85,12 +85,12 @@ static struct pam_conv conv = { NULL, NULL};
typedef struct scheduleitem typedef struct scheduleitem
{ {
enum enum
{ {
SC_TIMEOUT, SC_TIMEOUT,
SC_SIGNAL, SC_SIGNAL,
SC_GOTO, SC_GOTO,
SC_FOREVER SC_FOREVER
} type; } type;
int value; int value;
struct scheduleitem *gotoitem; struct scheduleitem *gotoitem;
TAILQ_ENTRY(scheduleitem) entries; TAILQ_ENTRY(scheduleitem) entries;
@ -103,7 +103,8 @@ static char *changeuser, *ch_root, *ch_dir;
extern char **environ; extern char **environ;
static void free_schedulelist(void) static void
free_schedulelist(void)
{ {
SCHEDULEITEM *s1 = TAILQ_FIRST(&schedule); SCHEDULEITEM *s1 = TAILQ_FIRST(&schedule);
SCHEDULEITEM *s2; SCHEDULEITEM *s2;
@ -117,7 +118,8 @@ static void free_schedulelist(void)
} }
#ifdef DEBUG_MEMORY #ifdef DEBUG_MEMORY
static void cleanup(void) static void
cleanup(void)
{ {
free(changeuser); free(changeuser);
free(nav); free(nav);
@ -125,7 +127,8 @@ static void cleanup(void)
} }
#endif #endif
static int parse_signal(const char *sig) static int
parse_signal(const char *sig)
{ {
typedef struct signalpair typedef struct signalpair
{ {
@ -181,7 +184,8 @@ static int parse_signal(const char *sig)
/* NOTREACHED */ /* NOTREACHED */
} }
static SCHEDULEITEM *parse_schedule_item(const char *string) static SCHEDULEITEM *
parse_schedule_item(const char *string)
{ {
const char *after_hyph; const char *after_hyph;
int sig; int sig;
@ -195,21 +199,21 @@ static SCHEDULEITEM *parse_schedule_item(const char *string)
item->type = SC_TIMEOUT; item->type = SC_TIMEOUT;
errno = 0; errno = 0;
if (sscanf(string, "%d", &item->value) != 1) if (sscanf(string, "%d", &item->value) != 1)
eerrorx("%s: invalid timeout value in schedule `%s'", applet, eerrorx("%s: invalid timeout value in schedule `%s'",
string); applet, string);
} else if ((after_hyph = string + (string[0] == '-')) && } else if ((after_hyph = string + (string[0] == '-')) &&
((sig = parse_signal(after_hyph)) != -1)) ((sig = parse_signal(after_hyph)) != -1))
{ {
item->type = SC_SIGNAL; item->type = SC_SIGNAL;
item->value = (int)sig; item->value = (int)sig;
} } else
else
eerrorx("%s: invalid schedule item `%s'", applet, string); eerrorx("%s: invalid schedule item `%s'", applet, string);
return item; return item;
} }
static void parse_schedule(const char *string, int timeout) static void
parse_schedule(const char *string, int timeout)
{ {
char buffer[20]; char buffer[20];
const char *slash; const char *slash;
@ -238,7 +242,8 @@ static void parse_schedule(const char *string, int timeout)
TAILQ_INSERT_TAIL(&schedule, item, entries); TAILQ_INSERT_TAIL(&schedule, item, entries);
if (string) { if (string) {
if (sscanf(string, "%d", &item->value) != 1) if (sscanf(string, "%d", &item->value) != 1)
eerrorx("%s: invalid timeout value in schedule", applet); eerrorx("%s: invalid timeout in schedule",
applet);
} else } else
item->value = 5; item->value = 5;
@ -251,8 +256,9 @@ static void parse_schedule(const char *string, int timeout)
else else
len = strlen(string); len = strlen(string);
if (len >= (ptrdiff_t) sizeof(buffer)) if (len >= (ptrdiff_t)sizeof(buffer))
eerrorx("%s: invalid schedule item, far too long", applet); eerrorx("%s: invalid schedule item, far too long",
applet);
memcpy(buffer, string, len); memcpy(buffer, string, len);
buffer[len] = 0; buffer[len] = 0;
@ -263,7 +269,7 @@ static void parse_schedule(const char *string, int timeout)
if (item->type == SC_FOREVER) { if (item->type == SC_FOREVER) {
if (repeatat) if (repeatat)
eerrorx("%s: invalid schedule, `forever' " eerrorx("%s: invalid schedule, `forever' "
"appears more than once", applet); "appears more than once", applet);
repeatat = item; repeatat = item;
continue; continue;
@ -281,7 +287,8 @@ static void parse_schedule(const char *string, int timeout)
return; return;
} }
static pid_t get_pid(const char *pidfile, bool quiet) static pid_t
get_pid(const char *pidfile, bool quiet)
{ {
FILE *fp; FILE *fp;
pid_t pid; pid_t pid;
@ -291,7 +298,8 @@ static pid_t get_pid(const char *pidfile, bool quiet)
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;
} }
@ -308,9 +316,10 @@ 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 *exec, const char *const *argv, static int
pid_t pid, uid_t uid,int sig, do_stop(const char *exec, const char *const *argv,
bool quiet, bool verbose, bool test) pid_t pid, uid_t uid,int sig,
bool quiet, bool verbose, bool test)
{ {
RC_PIDLIST *pids; RC_PIDLIST *pids;
RC_PID *pi; RC_PID *pi;
@ -330,19 +339,19 @@ static int do_stop(const char *exec, const char *const *argv,
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++;
} else { } else {
if (verbose) if (verbose)
ebegin("Sending signal %d to PID %d", ebegin("Sending signal %d to PID %d",
sig, pi->pid); sig, pi->pid);
errno = 0; errno = 0;
killed = (kill(pi->pid, sig) == 0 || killed = (kill(pi->pid, sig) == 0 ||
errno == ESRCH ? true : false); errno == ESRCH ? true : false);
if (verbose) if (verbose)
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 {
@ -357,9 +366,10 @@ static int do_stop(const char *exec, const char *const *argv,
return nkilled; return nkilled;
} }
static int run_stop_schedule(const char *exec, const char *const *argv, static int
const char *pidfile, uid_t uid, run_stop_schedule(const char *exec, const char *const *argv,
bool quiet, bool verbose, bool test) const char *pidfile, uid_t uid,
bool quiet, bool verbose, bool test)
{ {
SCHEDULEITEM *item = TAILQ_FIRST(&schedule); SCHEDULEITEM *item = TAILQ_FIRST(&schedule);
int nkilled = 0; int nkilled = 0;
@ -403,12 +413,12 @@ static int run_stop_schedule(const char *exec, const char *const *argv,
case SC_SIGNAL: case SC_SIGNAL:
nrunning = 0; nrunning = 0;
nkilled = do_stop(exec, argv, 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) {
if (! quiet) if (! quiet)
eerror("%s: no matching " eerror("%s: no matching "
"processes found", applet); "processes found", applet);
} }
return tkilled; return tkilled;
} }
@ -429,24 +439,26 @@ static int run_stop_schedule(const char *exec, const char *const *argv,
while (nloops) { while (nloops) {
if ((nrunning = do_stop(exec, argv, pid, if ((nrunning = do_stop(exec, argv, pid,
uid, 0, true, false, true)) == 0) uid, 0, true, false, true)) == 0)
return 0; return 0;
if (nanosleep(&ts, NULL) == -1) { if (nanosleep(&ts, NULL) == -1) {
if (errno == EINTR) if (errno == EINTR)
eerror("%s: caught an interrupt", applet); eerror("%s: caught an"
" interrupt", applet);
else { else {
eerror("%s: nanosleep: %s", eerror("%s: nanosleep: %s",
applet, strerror(errno)); applet, strerror(errno));
return 0; return 0;
} }
} }
nloops --; nloops --;
} }
break; break;
default: default:
eerror("%s: invalid schedule item `%d'", applet, item->type); eerror("%s: invalid schedule item `%d'",
applet, item->type);
return 0; return 0;
} }
@ -459,15 +471,18 @@ static int run_stop_schedule(const char *exec, const char *const *argv,
if (! quiet) { if (! quiet) {
if (nrunning == 1) if (nrunning == 1)
eerror("%s: %d process refused to stop", applet, nrunning); eerror("%s: %d process refused to stop",
applet, nrunning);
else else
eerror("%s: %d process(es) refused to stop", applet, nrunning); eerror("%s: %d process(es) refused to stop",
applet, nrunning);
} }
return -nrunning; return -nrunning;
} }
static void handle_signal(int sig) static void
handle_signal(int sig)
{ {
int status; int status;
int serrno = errno; int serrno = errno;
@ -492,7 +507,8 @@ static void handle_signal(int sig)
for (;;) { for (;;) {
if (waitpid(-1, &status, WNOHANG) < 0) { if (waitpid(-1, &status, WNOHANG) < 0) {
if (errno != ECHILD) if (errno != ECHILD)
eerror("%s: waitpid: %s", applet, strerror(errno)); eerror("%s: waitpid: %s",
applet, strerror(errno));
break; break;
} }
} }
@ -606,7 +622,8 @@ static const char * const longopts_help[] = {
}; };
#include "_usage.c" #include "_usage.c"
int start_stop_daemon(int argc, char **argv) int
start_stop_daemon(int argc, char **argv)
{ {
int devnull_fd = -1; int devnull_fd = -1;
#ifdef TIOCNOTTY #ifdef TIOCNOTTY
@ -674,7 +691,7 @@ int start_stop_daemon(int argc, char **argv)
if ((tmp = getenv("SSD_NICELEVEL"))) if ((tmp = getenv("SSD_NICELEVEL")))
if (sscanf(tmp, "%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, tmp); applet, tmp);
/* Get our user name and initial dir */ /* Get our user name and initial dir */
p = getenv("USER"); p = getenv("USER");
@ -692,7 +709,7 @@ int start_stop_daemon(int argc, char **argv)
} }
while ((opt = getopt_long(argc, argv, 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; stop = true;
@ -700,7 +717,7 @@ int start_stop_daemon(int argc, char **argv)
case 'N': /* --nice */ case 'N': /* --nice */
if (sscanf(optarg, "%d", &nicelevel) != 1) if (sscanf(optarg, "%d", &nicelevel) != 1)
eerrorx("%s: invalid nice level `%s'", eerrorx("%s: invalid nice level `%s'",
applet, optarg); applet, optarg);
break; break;
case 'R': /* --retry <schedule>|<timeout> */ case 'R': /* --retry <schedule>|<timeout> */
@ -717,44 +734,44 @@ int start_stop_daemon(int argc, char **argv)
case 'u': /* --user <username>|<uid> */ case 'u': /* --user <username>|<uid> */
case 'c': /* --chuid <username>|<uid> */ case 'c': /* --chuid <username>|<uid> */
{ {
p = optarg; p = optarg;
tmp = strsep(&p, ":"); tmp = strsep(&p, ":");
changeuser = xstrdup(tmp); changeuser = xstrdup(tmp);
if (sscanf(tmp, "%d", &tid) != 1)
pw = getpwnam(tmp);
else
pw = getpwuid((uid_t)tid);
if (pw == NULL)
eerrorx("%s: user `%s' not found",
applet, tmp);
uid = pw->pw_uid;
home = pw->pw_dir;
unsetenv("HOME");
if (pw->pw_dir)
setenv("HOME", pw->pw_dir, 1);
unsetenv("USER");
if (pw->pw_name)
setenv("USER", pw->pw_name, 1);
if (gid == 0)
gid = pw->pw_gid;
if (p) {
tmp = strsep (&p, ":");
if (sscanf(tmp, "%d", &tid) != 1) if (sscanf(tmp, "%d", &tid) != 1)
pw = getpwnam(tmp); gr = getgrnam(tmp);
else else
pw = getpwuid((uid_t)tid); gr = getgrgid((gid_t) tid);
if (pw == NULL) if (gr == NULL)
eerrorx("%s: user `%s' not found", eerrorx("%s: group `%s'"
applet, tmp); " not found",
uid = pw->pw_uid; applet, tmp);
home = pw->pw_dir; gid = gr->gr_gid;
unsetenv("HOME");
if (pw->pw_dir)
setenv("HOME", pw->pw_dir, 1);
unsetenv("USER");
if (pw->pw_name)
setenv("USER", pw->pw_name, 1);
if (gid == 0)
gid = pw->pw_gid;
if (p) {
tmp = strsep (&p, ":");
if (sscanf(tmp, "%d", &tid) != 1)
gr = getgrnam(tmp);
else
gr = getgrgid((gid_t) tid);
if (gr == NULL)
eerrorx("%s: group `%s'"
" not found",
applet, tmp);
gid = gr->gr_gid;
}
} }
break; }
break;
case 'd': /* --chdir /new/dir */ case 'd': /* --chdir /new/dir */
ch_dir = optarg; ch_dir = optarg;
@ -771,7 +788,7 @@ int start_stop_daemon(int argc, char **argv)
gr = getgrgid((gid_t)tid); gr = getgrgid((gid_t)tid);
if (gr == NULL) if (gr == NULL)
eerrorx("%s: group `%s' not found", eerrorx("%s: group `%s' not found",
applet, optarg); applet, optarg);
gid = gr->gr_gid; gid = gr->gr_gid;
break; break;
@ -782,7 +799,7 @@ int start_stop_daemon(int argc, char **argv)
case 'k': case 'k':
if (parse_mode(&numask, optarg)) if (parse_mode(&numask, optarg))
eerrorx("%s: invalid mode `%s'", eerrorx("%s: invalid mode `%s'",
applet, optarg); applet, optarg);
break; break;
case 'm': /* --make-pidfile */ case 'm': /* --make-pidfile */
@ -819,7 +836,7 @@ int start_stop_daemon(int argc, char **argv)
case 'w': case 'w':
if (sscanf(optarg, "%d", &start_wait) != 1) if (sscanf(optarg, "%d", &start_wait) != 1)
eerrorx("%s: `%s' not a number", eerrorx("%s: `%s' not a number",
applet, optarg); applet, optarg);
break; break;
case 'x': /* --exec <executable> */ case 'x': /* --exec <executable> */
exec = optarg; exec = optarg;
@ -834,7 +851,7 @@ int start_stop_daemon(int argc, char **argv)
break; break;
case_RC_COMMON_GETOPT case_RC_COMMON_GETOPT
} }
endpwent(); endpwent();
argc -= optind; argc -= optind;
@ -873,25 +890,25 @@ int start_stop_daemon(int argc, char **argv)
sig = SIGTERM; sig = SIGTERM;
if (!*argv && !pidfile && !name && !uid) if (!*argv && !pidfile && !name && !uid)
eerrorx("%s: --stop needs --exec, --pidfile," eerrorx("%s: --stop needs --exec, --pidfile,"
" --name or --user", applet); " --name or --user", applet);
if (background) if (background)
eerrorx("%s: --background is only relevant with" eerrorx("%s: --background is only relevant with"
" --start", applet); " --start", applet);
if (makepidfile) if (makepidfile)
eerrorx("%s: --make-pidfile is only relevant with" eerrorx("%s: --make-pidfile is only relevant with"
" --start", applet); " --start", applet);
if (redirect_stdout || redirect_stderr) if (redirect_stdout || redirect_stderr)
eerrorx("%s: --stdout and --stderr are only relevant" eerrorx("%s: --stdout and --stderr are only relevant"
" with --start", applet); " with --start", applet);
} else { } else {
if (!exec) if (!exec)
eerrorx("%s: nothing to start", applet); eerrorx("%s: nothing to start", applet);
if (makepidfile && !pidfile) if (makepidfile && !pidfile)
eerrorx("%s: --make-pidfile is only relevant with" eerrorx("%s: --make-pidfile is only relevant with"
" --pidfile", applet); " --pidfile", applet);
if ((redirect_stdout || redirect_stderr) && !background) if ((redirect_stdout || redirect_stderr) && !background)
eerrorx("%s: --stdout and --stderr are only relevant" eerrorx("%s: --stdout and --stderr are only relevant"
" with --background", applet); " with --background", applet);
} }
/* Expand ~ */ /* Expand ~ */
@ -908,10 +925,10 @@ int start_stop_daemon(int argc, char **argv)
/* Full or relative path */ /* Full or relative path */
if (ch_root) if (ch_root)
snprintf(exec_file, sizeof(exec_file), snprintf(exec_file, sizeof(exec_file),
"%s/%s", ch_root, exec); "%s/%s", ch_root, exec);
else else
snprintf(exec_file, sizeof(exec_file), snprintf(exec_file, sizeof(exec_file),
"%s", exec); "%s", exec);
} else { } else {
/* Something in $PATH */ /* Something in $PATH */
p = tmp = xstrdup(getenv("PATH")); p = tmp = xstrdup(getenv("PATH"));
@ -919,11 +936,11 @@ int start_stop_daemon(int argc, char **argv)
while ((token = strsep(&p, ":"))) { while ((token = strsep(&p, ":"))) {
if (ch_root) if (ch_root)
snprintf(exec_file, sizeof(exec_file), snprintf(exec_file, sizeof(exec_file),
"%s/%s/%s", "%s/%s/%s",
ch_root, token, exec); ch_root, token, exec);
else else
snprintf(exec_file, sizeof(exec_file), snprintf(exec_file, sizeof(exec_file),
"%s/%s", token, exec); "%s/%s", token, exec);
if (exists(exec_file)) if (exists(exec_file))
break; break;
*exec_file = '\0'; *exec_file = '\0';
@ -933,7 +950,7 @@ int start_stop_daemon(int argc, char **argv)
} }
if (start && !exists(exec_file)) { if (start && !exists(exec_file)) {
eerror("%s: %s does not exist", applet, eerror("%s: %s does not exist", applet,
*exec_file ? exec_file : exec); *exec_file ? exec_file : exec);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -984,7 +1001,7 @@ int start_stop_daemon(int argc, char **argv)
else else
parse_schedule(NULL, sig); parse_schedule(NULL, sig);
i = run_stop_schedule(exec, (const char *const *)margv, i = run_stop_schedule(exec, (const char *const *)margv,
pidfile, uid, quiet, verbose, test); pidfile, uid, quiet, verbose, test);
if (i < 0) if (i < 0)
/* We failed to stop something */ /* We failed to stop something */
@ -1000,8 +1017,8 @@ int start_stop_daemon(int argc, char **argv)
unlink(pidfile); unlink(pidfile);
if (svcname) if (svcname)
rc_service_daemon_set(svcname, exec, rc_service_daemon_set(svcname, exec,
(const char *const *)argv, (const char *const *)argv,
pidfile, false); pidfile, false);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
@ -1011,7 +1028,7 @@ int start_stop_daemon(int argc, char **argv)
pid = 0; pid = 0;
if (do_stop(exec, (const char * const *)margv, pid, uid, if (do_stop(exec, (const char * const *)margv, 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);
if (test) { if (test) {
@ -1067,30 +1084,35 @@ int start_stop_daemon(int argc, char **argv)
if (nicelevel) { if (nicelevel) {
if (setpriority(PRIO_PROCESS, mypid, nicelevel) == -1) if (setpriority(PRIO_PROCESS, mypid, nicelevel) == -1)
eerrorx("%s: setpritory %d: %s", applet, nicelevel, eerrorx("%s: setpritory %d: %s",
strerror(errno)); applet, nicelevel,
strerror(errno));
} }
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) {
fp = fopen(pidfile, "w"); fp = fopen(pidfile, "w");
if (! fp) if (! fp)
eerrorx("%s: fopen `%s': %s", applet, pidfile, eerrorx("%s: fopen `%s': %s", applet, pidfile,
strerror(errno)); strerror(errno));
fprintf(fp, "%d\n", mypid); fprintf(fp, "%d\n", mypid);
fclose(fp); fclose(fp);
} }
#ifdef HAVE_PAM #ifdef HAVE_PAM
if (changeuser != NULL) if (changeuser != NULL)
pamr = pam_start("start-stop-daemon", changeuser, &conv, &pamh); pamr = pam_start("start-stop-daemon",
changeuser, &conv, &pamh);
else else
pamr = pam_start("start-stop-daemon", "nobody", &conv, &pamh); pamr = pam_start("start-stop-daemon",
"nobody", &conv, &pamh);
if (pamr == PAM_SUCCESS) if (pamr == PAM_SUCCESS)
pamr = pam_authenticate(pamh, PAM_SILENT); pamr = pam_authenticate(pamh, PAM_SILENT);
@ -1099,15 +1121,19 @@ int start_stop_daemon(int argc, char **argv)
if (pamr == PAM_SUCCESS) if (pamr == PAM_SUCCESS)
pamr = pam_open_session(pamh, PAM_SILENT); pamr = pam_open_session(pamh, PAM_SILENT);
if (pamr != PAM_SUCCESS) if (pamr != PAM_SUCCESS)
eerrorx("%s: pam error: %s", applet, pam_strerror(pamh, pamr)); eerrorx("%s: pam error: %s",
applet, pam_strerror(pamh, pamr));
#endif #endif
if (gid && setgid(gid)) if (gid && setgid(gid))
eerrorx("%s: unable to set groupid to %d", applet, gid); eerrorx("%s: unable to set groupid to %d",
applet, gid);
if (changeuser && initgroups(changeuser, gid)) if (changeuser && initgroups(changeuser, gid))
eerrorx("%s: initgroups (%s, %d)", applet, changeuser, gid); eerrorx("%s: initgroups (%s, %d)",
applet, changeuser, gid);
if (uid && setuid(uid)) if (uid && setuid(uid))
eerrorx ("%s: unable to set userid to %d", applet, uid); eerrorx ("%s: unable to set userid to %d",
applet, uid);
/* Close any fd's to the passwd database */ /* Close any fd's to the passwd database */
endpwent(); endpwent();
@ -1137,8 +1163,8 @@ int start_stop_daemon(int argc, char **argv)
TAILQ_FOREACH(env, env_list, entries) { TAILQ_FOREACH(env, env_list, entries) {
if ((strncmp(env->value, "RC_", 3) == 0 && if ((strncmp(env->value, "RC_", 3) == 0 &&
strncmp(env->value, "RC_SERVICE=", 10) != 0 && strncmp(env->value, "RC_SERVICE=", 10) != 0 &&
strncmp(env->value, "RC_SVCNAME=", 10) != 0) || strncmp(env->value, "RC_SVCNAME=", 10) != 0) ||
strncmp(env->value, "SSD_NICELEVEL=", 14) == 0) strncmp(env->value, "SSD_NICELEVEL=", 14) == 0)
{ {
p = strchr(env->value, '='); p = strchr(env->value, '=');
@ -1179,16 +1205,20 @@ int start_stop_daemon(int argc, char **argv)
stdout_fd = devnull_fd; stdout_fd = devnull_fd;
stderr_fd = devnull_fd; stderr_fd = devnull_fd;
if (redirect_stdout) { if (redirect_stdout) {
if ((stdout_fd = open(redirect_stdout, O_WRONLY | O_CREAT | O_APPEND, if ((stdout_fd = open(redirect_stdout,
S_IRUSR | S_IWUSR)) == -1) O_WRONLY | O_CREAT | O_APPEND,
eerrorx("%s: unable to open the logfile for stdout `%s': %s", S_IRUSR | S_IWUSR)) == -1)
applet, redirect_stdout, strerror(errno)); eerrorx("%s: unable to open the logfile"
" for stdout `%s': %s",
applet, redirect_stdout, strerror(errno));
} }
if (redirect_stderr) { if (redirect_stderr) {
if ((stderr_fd = open(redirect_stderr, O_WRONLY | O_CREAT | O_APPEND, if ((stderr_fd = open(redirect_stderr,
S_IRUSR | S_IWUSR)) == -1) O_WRONLY | O_CREAT | O_APPEND,
eerrorx("%s: unable to open the logfile for stderr `%s': %s", S_IRUSR | S_IWUSR)) == -1)
applet, redirect_stderr, strerror(errno)); eerrorx("%s: unable to open the logfile"
" for stderr `%s': %s",
applet, redirect_stderr, strerror(errno));
} }
/* We don't redirect stdin as some daemons may need it */ /* We don't redirect stdin as some daemons may need it */
@ -1207,7 +1237,7 @@ int start_stop_daemon(int argc, char **argv)
pam_close_session(pamh, PAM_SILENT); pam_close_session(pamh, PAM_SILENT);
#endif #endif
eerrorx("%s: failed to exec `%s': %s", eerrorx("%s: failed to exec `%s': %s",
applet, exec,strerror(errno)); applet, exec,strerror(errno));
} }
/* Parent process */ /* Parent process */
@ -1220,13 +1250,15 @@ int start_stop_daemon(int argc, char **argv)
do { do {
pid = waitpid(spid, &i, 0); pid = waitpid(spid, &i, 0);
if (pid < 1) { if (pid < 1) {
eerror("waitpid %d: %s", spid, strerror(errno)); eerror("waitpid %d: %s",
spid, strerror(errno));
return -1; return -1;
} }
} while (!WIFEXITED(i) && !WIFSIGNALED(i)); } while (!WIFEXITED(i) && !WIFSIGNALED(i));
if (!WIFEXITED(i) || WEXITSTATUS(i) != 0) { if (!WIFEXITED(i) || WEXITSTATUS(i) != 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 = spid;
@ -1236,7 +1268,7 @@ int start_stop_daemon(int argc, char **argv)
We do this as some badly written daemons fork and then barf */ We do this as some badly written daemons fork and then barf */
if (start_wait == 0 && if (start_wait == 0 &&
((p = getenv("SSD_STARTWAIT")) || ((p = getenv("SSD_STARTWAIT")) ||
(p = rc_conf_value("rc_start_wait")))) (p = rc_conf_value("rc_start_wait"))))
{ {
if (sscanf(p, "%u", &start_wait) != 1) if (sscanf(p, "%u", &start_wait) != 1)
start_wait = 0; start_wait = 0;
@ -1253,7 +1285,7 @@ int start_stop_daemon(int argc, char **argv)
eerror("%s: caught an interrupt", applet); eerror("%s: caught an interrupt", applet);
else { else {
eerror("%s: nanosleep: %s", eerror("%s: nanosleep: %s",
applet, strerror(errno)); applet, strerror(errno));
return 0; return 0;
} }
} }
@ -1265,14 +1297,14 @@ int start_stop_daemon(int argc, char **argv)
pid = get_pid(pidfile, true); pid = get_pid(pidfile, true);
if (pid == -1) { if (pid == -1) {
eerrorx("%s: did not " eerrorx("%s: did not "
"create a valid" "create a valid"
" pid in `%s'", " pid in `%s'",
applet, pidfile); applet, pidfile);
} }
} else } else
pid = 0; pid = 0;
if (do_stop(exec, (const char *const *)margv, if (do_stop(exec, (const char *const *)margv,
pid, uid, 0, true, false, true) > 0) pid, uid, 0, true, false, true) > 0)
alive = true; alive = true;
} }
@ -1281,8 +1313,8 @@ int start_stop_daemon(int argc, char **argv)
} }
if (svcname) if (svcname)
rc_service_daemon_set(svcname, exec, (const char *const *)margv, rc_service_daemon_set(svcname, exec,
pidfile, true); (const char *const *)margv, pidfile, true);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
/* NOTREACHED */ /* NOTREACHED */