#define MIN_POLL_INTERVAL 20000 /*us*/
#if defined(OSHURD)
-# include <hurd.h>
-# include <ps.h>
+#include <hurd.h>
+#include <ps.h>
#endif
-#if defined(OSOpenBSD) || defined(OSFreeBSD) || defined(OSNetBSD)
+#if defined(OSOpenBSD) || defined(OSFreeBSD) || defined(OSNetBSD)
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/stat.h>
#include <err.h>
#include <limits.h>
#endif
-
+
#ifdef HAVE_KVM_H
#include <kvm.h>
#include <sys/sysctl.h>
#endif
#ifdef HAVE_ERROR_H
-# include <error.h>
+#include <error.h>
#endif
#if HAVE_C_ATTRIBUTE
# define CONSTANT __attribute__((constant))
-# define PRINTFFORMAT(si, tc) __attribute__((format(printf,si,tc)))
+# define PRINTFFORMAT(si, tc) __attribute__((format(printf, si, tc)))
# define NONRETURNING __attribute__((noreturn))
# define UNUSED __attribute__((unused))
#else
static struct pid_list *killed = NULL;
struct schedule_item {
- enum { sched_timeout, sched_signal, sched_goto, sched_forever } type;
- int value; /* seconds, signal no., or index into array */
- /* sched_forever is only seen within parse_schedule and callees */
+ enum {
+ sched_timeout,
+ sched_signal,
+ sched_goto,
+ sched_forever /* Only seen within parse_schedule and callees */
+ } type;
+ int value; /* Seconds, signal no., or index into array */
};
static int schedule_length;
static void check(pid_t pid);
static void do_pidfile(const char *name);
static void do_stop(int signal_nr, int quietmode,
- int *n_killed, int *n_notkilled, int retry_nr);
+ int *n_killed, int *n_notkilled, int retry_nr);
#if defined(OSLinux) || defined(OShpux)
static int pid_is_exec(pid_t pid, const struct stat *esb);
#endif
* TVELEM must be linear in TVADJUST.
*/
typedef long tvselector(const struct timeval*);
-static long tvselector_sec(const struct timeval *tv) { return tv->tv_sec; }
-static long tvselector_usec(const struct timeval *tv) { return tv->tv_usec; }
+
+static long
+tvselector_sec(const struct timeval *tv)
+{
+ return tv->tv_sec;
+}
+
+static long
+tvselector_usec(const struct timeval *tv)
+{
+ return tv->tv_usec;
+}
+
#define TVCALC_ELEM(result, expr, sec, adj) \
{ \
const long TVADJUST = adj; \
- long (*const TVELEM)(const struct timeval*) = tvselector_##sec; \
+ long (*const TVELEM)(const struct timeval *) = tvselector_##sec; \
(result).tv_##sec = (expr); \
}
-#define TVCALC(result,expr) \
+#define TVCALC(result, expr) \
do { \
TVCALC_ELEM(result, expr, sec, (-1)); \
TVCALC_ELEM(result, expr, usec, (+1000000)); \
(result).tv_sec += (result).tv_usec / 1000000; \
(result).tv_usec %= 1000000; \
-} while(0)
+} while (0)
static void
exit(2);
}
-
static void *
xmalloc(int size)
{
fatal("malloc(%d) failed", size);
}
-
static void
xgettimeofday(struct timeval *tv)
{
VERSION);
}
-
static void
badusage(const char *msg)
{
{ "TTOU", SIGTTOU }
};
-static int parse_integer(const char *string, int *value_r) {
+static int
+parse_integer(const char *string, int *value_r)
+{
unsigned long ul;
char *ep;
if (!string[0])
return -1;
- ul= strtoul(string,&ep,10);
+ ul = strtoul(string, &ep, 10);
if (ul > INT_MAX || *ep != '\0')
return -1;
- *value_r= ul;
+ *value_r = ul;
return 0;
}
-static int parse_signal(const char *signal_str, int *signal_nr)
+static int
+parse_signal(const char *signal_str, int *signal_nr)
{
unsigned int i;
if (parse_integer(signal_str, signal_nr) == 0)
return 0;
- for (i = 0; i < sizeof (siglist) / sizeof (siglist[0]); i++) {
- if (strcmp (signal_str, siglist[i].name) == 0) {
+ for (i = 0; i < sizeof(siglist) / sizeof(siglist[0]); i++) {
+ if (strcmp(signal_str, siglist[i].name) == 0) {
*signal_nr = siglist[i].signal;
return 0;
}
}
static void
-parse_schedule_item(const char *string, struct schedule_item *item) {
+parse_schedule_item(const char *string, struct schedule_item *item)
+{
const char *after_hyph;
- if (!strcmp(string,"forever")) {
+ if (!strcmp(string, "forever")) {
item->type = sched_forever;
} else if (isdigit(string[0])) {
item->type = sched_timeout;
if (parse_integer(string, &item->value) != 0)
badusage("invalid timeout value in schedule");
} else if ((after_hyph = string + (string[0] == '-')) &&
- parse_signal(after_hyph, &item->value) == 0) {
+ parse_signal(after_hyph, &item->value) == 0) {
item->type = sched_signal;
} else {
badusage("invalid schedule item (must be [-]<signal-name>, "
- "-<signal-number>, <timeout> or `forever'");
+ "-<signal-number>, <timeout> or `forever'");
}
}
static void
-parse_schedule(const char *schedule_str) {
+parse_schedule(const char *schedule_str)
+{
char item_buf[20];
const char *slash;
int count, repeatat;
if (*slash == '/')
count++;
- schedule_length = (count == 0) ? 4 : count+1;
+ schedule_length = (count == 0) ? 4 : count + 1;
schedule = xmalloc(sizeof(*schedule) * schedule_length);
if (count == 0) {
parse_schedule_item(schedule_str, &schedule[1]);
if (schedule[1].type != sched_timeout) {
badusage ("--retry takes timeout, or schedule list"
- " of at least two items");
+ " of at least two items");
}
schedule[2].type = sched_signal;
schedule[2].value = SIGKILL;
- schedule[3]= schedule[1];
+ schedule[3] = schedule[1];
} else {
count = 0;
repeatat = -1;
while (schedule_str != NULL) {
- slash = strchr(schedule_str,'/');
+ slash = strchr(schedule_str, '/');
str_len = slash ? (size_t)(slash - schedule_str) : strlen(schedule_str);
if (str_len >= sizeof(item_buf))
badusage("invalid schedule item: far too long"
- " (you must delimit items with slashes)");
+ " (you must delimit items with slashes)");
memcpy(item_buf, schedule_str, str_len);
item_buf[str_len] = 0;
- schedule_str = slash ? slash+1 : NULL;
+ schedule_str = slash ? slash + 1 : NULL;
parse_schedule_item(item_buf, &schedule[count]);
if (schedule[count].type == sched_forever) {
if (repeatat >= 0)
badusage("invalid schedule: `forever'"
- " appears more than once");
+ " appears more than once");
repeatat = count;
continue;
}
{ "chuid", 1, NULL, 'c'},
{ "nicelevel", 1, NULL, 'N'},
{ "umask", 1, NULL, 'k'},
- { "background", 0, NULL, 'b'},
+ { "background", 0, NULL, 'b'},
{ "make-pidfile", 0, NULL, 'm'},
- { "retry", 1, NULL, 'R'},
- { "chdir", 1, NULL, 'd'},
- { NULL, 0, NULL, 0}
+ { "retry", 1, NULL, 'R'},
+ { "chdir", 1, NULL, 'd'},
+ { NULL, 0, NULL, 0 }
};
const char *umask_str = NULL;
const char *signal_str = NULL;
int c;
for (;;) {
- c = getopt_long(argc, argv, "HKSVa:n:op:qr:s:tu:vx:c:N:k:bmR:g:d:",
- longopts, NULL);
+ c = getopt_long(argc, argv,
+ "HKSVa:n:op:qr:s:tu:vx:c:N:k:bmR:g:d:",
+ longopts, NULL);
if (c == -1)
break;
switch (c) {
}
if (signal_str != NULL) {
- if (parse_signal (signal_str, &signal_nr) != 0)
+ if (parse_signal(signal_str, &signal_nr) != 0)
badusage("signal value must be numeric or name"
" of signal (KILL, INT, ...)");
}
return (sb.st_dev == esb->st_dev && sb.st_ino == esb->st_ino);
}
-
static int
pid_is_user(pid_t pid, uid_t uid)
{
return (sb.st_uid == uid);
}
-
static int
pid_is_cmd(pid_t pid, const char *name)
{
}
#endif /* OSLinux */
-
#if defined(OSHURD)
static void
init_procset(void)
sprintf(buf, "/proc/%d", pid);
if (stat(buf, &sb) != 0) {
- if (errno!=ENOENT)
+ if (errno != ENOENT)
fatal("Error stating %s: %s", buf, strerror(errno));
return 0;
}
#if defined(OSLinux) || defined(OShpux)
if (execname && !pid_is_exec(pid, &exec_stat))
#elif defined(OSHURD) || defined(OSFreeBSD) || defined(OSNetBSD)
- /* I will try this to see if it works */
+ /* Let's try this to see if it works */
if (execname && !pid_is_cmd(pid, execname))
#endif
return;
fclose(f);
} else if (errno != ENOENT)
fatal("open pidfile %s: %s", name, strerror(errno));
-
}
-/* WTA: this needs to be an autoconf check for /proc/pid existance.
- */
-
#if defined(OSLinux) || defined (OSsunos)
static void
do_procinit(void)
}
#endif /* OSLinux */
-
#if defined(OSHURD)
static int
-check_proc_stat (struct proc_stat *ps)
+check_proc_stat(struct proc_stat *ps)
{
check(ps->pid);
return 0;
if (!procset)
init_procset();
- proc_stat_list_for_each (procset, check_proc_stat);
+ proc_stat_list_for_each(procset, check_proc_stat);
}
#endif /* OSHURD */
-
#ifdef HAVE_KVM_H
static int
pid_is_cmd(pid_t pid, const char *name)
{
- kvm_t *kd;
- int nentries, argv_len=0;
- struct kinfo_proc *kp;
- char errbuf[_POSIX2_LINE_MAX], buf[_POSIX2_LINE_MAX];
- char **pid_argv_p;
- char *start_argv_0_p, *end_argv_0_p;
-
-
- kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
- if (kd == NULL)
- errx(1, "%s", errbuf);
- if ((kp = kvm_getprocs(kd, KERN_PROC_PID, pid, &nentries)) == NULL)
- errx(1, "%s", kvm_geterr(kd));
- if ((pid_argv_p = kvm_getargv(kd, kp, argv_len)) == NULL)
- errx(1, "%s", kvm_geterr(kd));
+ kvm_t *kd;
+ int nentries, argv_len = 0;
+ struct kinfo_proc *kp;
+ char errbuf[_POSIX2_LINE_MAX], buf[_POSIX2_LINE_MAX];
+ char **pid_argv_p;
+ char *start_argv_0_p, *end_argv_0_p;
+
+ kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
+ if (kd == NULL)
+ errx(1, "%s", errbuf);
+ kp = kvm_getprocs(kd, KERN_PROC_PID, pid, &nentries);
+ if (kp == NULL)
+ errx(1, "%s", kvm_geterr(kd));
+ pid_argv_p = kvm_getargv(kd, kp, argv_len);
+ if (pid_argv_p == NULL)
+ errx(1, "%s", kvm_geterr(kd));
start_argv_0_p = *pid_argv_p;
- /* find and compare string */
-
- /* find end of argv[0] then copy and cut of str there. */
- if ((end_argv_0_p = strchr(*pid_argv_p, ' ')) == 0 )
- /* There seems to be no space, so we have the command
- * allready in its desired form. */
- start_argv_0_p = *pid_argv_p;
+ /* Find and compare string */
+
+ /* Find end of argv[0] then copy and cut of str there. */
+ end_argv_0_p = strchr(*pid_argv_p, ' ');
+ if (end_argv_0_p == NULL)
+ /* There seems to be no space, so we have the command
+ * allready in its desired form. */
+ start_argv_0_p = *pid_argv_p;
else {
- /* Tests indicate that this never happens, since
- * kvm_getargv itselfe cuts of tailing stuff. This is
- * not what the manpage says, however. */
- strncpy(buf, *pid_argv_p, (end_argv_0_p - start_argv_0_p));
- buf[(end_argv_0_p - start_argv_0_p) + 1] = '\0';
- start_argv_0_p = buf;
+ /* Tests indicate that this never happens, since
+ * kvm_getargv itselfe cuts of tailing stuff. This is
+ * not what the manpage says, however. */
+ strncpy(buf, *pid_argv_p, (end_argv_0_p - start_argv_0_p));
+ buf[(end_argv_0_p - start_argv_0_p) + 1] = '\0';
+ start_argv_0_p = buf;
}
-
+
if (strlen(name) != strlen(start_argv_0_p))
- return 0;
- return (strcmp(name, start_argv_0_p) == 0) ? 1 : 0;
+ return 0;
+ return (strcmp(name, start_argv_0_p) == 0) ? 1 : 0;
}
-
+
static int
pid_is_user(pid_t pid, uid_t uid)
{
kvm_t *kd;
- int nentries; /* Value not used */
+ int nentries; /* Value not used */
uid_t proc_uid;
struct kinfo_proc *kp;
- char errbuf[_POSIX2_LINE_MAX];
-
+ char errbuf[_POSIX2_LINE_MAX];
kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
if (kd == NULL)
errx(1, "%s", errbuf);
- if ((kp = kvm_getprocs(kd, KERN_PROC_PID, pid, &nentries)) == NULL)
+ kp = kvm_getprocs(kd, KERN_PROC_PID, pid, &nentries);
+ if (kp == NULL)
errx(1, "%s", kvm_geterr(kd));
- if (kp->kp_proc.p_cred )
+ if (kp->kp_proc.p_cred)
kvm_read(kd, (u_long)&(kp->kp_proc.p_cred->p_ruid),
- &proc_uid, sizeof(uid_t));
+ &proc_uid, sizeof(uid_t));
else
return 0;
return (proc_uid == (uid_t)uid);
kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
if (kd == NULL)
errx(1, "%s", errbuf);
- if ((kp = kvm_getprocs(kd, KERN_PROC_PID, pid, &nentries)) == NULL)
+ kp = kvm_getprocs(kd, KERN_PROC_PID, pid, &nentries);
+ if (kp == NULL)
errx(1, "%s", kvm_geterr(kd));
pidexec = (&kp->kp_proc)->p_comm;
if (strlen(name) != strlen(pidexec))
return (strcmp(name, pidexec) == 0) ? 1 : 0;
}
-
static void
do_procinit(void)
{
/* Nothing to do */
}
-
#endif /* OSOpenBSD */
-
#if defined(OShpux)
static int
pid_is_user(pid_t pid, uid_t uid)
{
struct pst_status pst;
- if (pstat_getproc(&pst, sizeof(pst), (size_t) 0, (int) pid) < 0)
+ if (pstat_getproc(&pst, sizeof(pst), (size_t)0, (int)pid) < 0)
return 0;
- return ((uid_t) pst.pst_uid == uid);
+ return ((uid_t)pst.pst_uid == uid);
}
static int
{
struct pst_status pst;
- if (pstat_getproc(&pst, sizeof(pst), (size_t) 0, (int) pid) < 0)
+ if (pstat_getproc(&pst, sizeof(pst), (size_t)0, (int)pid) < 0)
return 0;
return (strcmp(pst.pst_ucomm, name) == 0);
}
{
struct pst_status pst;
- if (pstat_getproc(&pst, sizeof(pst), (size_t) 0, (int) pid) < 0)
+ if (pstat_getproc(&pst, sizeof(pst), (size_t)0, (int)pid) < 0)
return 0;
- return ((dev_t) pst.pst_text.psf_fsid.psfs_id == esb->st_dev
- && (ino_t) pst.pst_text.psf_fileid == esb->st_ino);
+ return ((dev_t)pst.pst_text.psf_fsid.psfs_id == esb->st_dev
+ && (ino_t)pst.pst_text.psf_fileid == esb->st_ino);
}
static void
int idx = 0;
while ((count = pstat_getproc(pst, sizeof(pst[0]), 10, idx)) > 0) {
- for (i = 0; i < count; i++)
+ for (i = 0; i < count; i++)
check(pst[i].pst_pid);
- idx = pst[count - 1].pst_idx + 1;
+ idx = pst[count - 1].pst_idx + 1;
}
}
#endif /* OShpux */
-
static void
do_findprocs(void)
{
clear(&found);
-
+
if (pidfile)
do_pidfile(pidfile);
else
{
struct pid_list *p;
- do_findprocs();
-
- *n_killed = 0;
- *n_notkilled = 0;
-
- if (!found)
- return;
-
- clear(&killed);
+ do_findprocs();
+
+ *n_killed = 0;
+ *n_notkilled = 0;
+
+ if (!found)
+ return;
+
+ clear(&killed);
for (p = found; p; p = p->next) {
if (testmode) {
(*n_killed)++;
} else if (kill(p->pid, signal_nr) == 0) {
push(&killed, p->pid);
- (*n_killed)++;
+ (*n_killed)++;
} else {
if (signal_nr)
printf("%s: warning: failed to kill %d: %s\n",
progname, p->pid, strerror(errno));
- (*n_notkilled)++;
+ (*n_notkilled)++;
}
}
if (quietmode < 0 && killed) {
- printf("Stopped %s (pid", what_stop);
+ printf("Stopped %s (pid", what_stop);
for (p = killed; p; p = p->next)
printf(" %d", p->pid);
- putchar(')');
- if (retry_nr > 0)
- printf(", retry #%d", retry_nr);
- printf(".\n");
+ putchar(')');
+ if (retry_nr > 0)
+ printf(", retry #%d", retry_nr);
+ printf(".\n");
}
}
-
static void
set_what_stop(const char *str)
{
strncpy(what_stop, str, sizeof(what_stop));
- what_stop[sizeof(what_stop)-1] = '\0';
+ what_stop[sizeof(what_stop) - 1] = '\0';
}
static int
n_notkilled = 0;
switch (schedule[position].type) {
-
case sched_goto:
position = value;
continue;
-
case sched_signal:
do_stop(value, quietmode, &n_killed, &n_notkilled, retry_nr++);
if (!n_killed)
else
anykilled = 1;
goto next_item;
-
case sched_timeout:
/* We want to keep polling for the processes, to see if they've exited,
* or until the timeout expires.
ratio = 1;
for (;;) {
xgettimeofday(&before);
- if (timercmp(&before,&stopat,>))
+ if (timercmp(&before, &stopat, >))
goto next_item;
do_stop(0, 1, &n_killed, &n_notkilled, 0);
xgettimeofday(&after);
- if (!timercmp(&after,&stopat,<))
+ if (!timercmp(&after, &stopat, <))
goto next_item;
if (ratio < 10)
ratio++;
- TVCALC(interval, ratio * (TVELEM(&after) - TVELEM(&before) + TVADJUST));
- TVCALC(maxinterval, TVELEM(&stopat) - TVELEM(&after) + TVADJUST);
+ TVCALC(interval, TVELEM(&after) * ratio -
+ TVELEM(&before) + TVADJUST);
+ TVCALC(maxinterval, TVELEM(&stopat) -
+ TVELEM(&after) + TVADJUST);
- if (timercmp(&interval,&maxinterval,>))
+ if (timercmp(&interval, &maxinterval, >))
interval = maxinterval;
if (interval.tv_sec == 0 &&
interval.tv_usec <= MIN_POLL_INTERVAL)
- interval.tv_usec = MIN_POLL_INTERVAL;
+ interval.tv_usec = MIN_POLL_INTERVAL;
r = select(0, NULL, NULL, NULL, &interval);
if (r < 0 && errno != EINTR)
fatal("select() failed for pause: %s",
strerror(errno));
}
-
default:
assert(!"schedule[].type value must be valid");
-
}
next_item:
}
}
-
int
main(int argc, char **argv)
{
if (changeroot) {
int fullexecname_len = strlen(changeroot) + 1 +
- strlen(execname) + 1;
+ strlen(execname) + 1;
fullexecname = xmalloc(fullexecname_len);
snprintf(fullexecname, fullexecname_len, "%s/%s",
- changeroot, execname);
+ changeroot, execname);
} else
fullexecname = execname;
if (!pw)
fatal("user `%s' not found\n", changeuser);
runas_uid = pw->pw_uid;
- if (changegroup == NULL) { /* pass the default group of this user */
- changegroup = ""; /* just empty */
+ if (changegroup == NULL) {
+ /* Pass the default group of this user */
+ changegroup = ""; /* Just empty */
runas_gid = pw->pw_gid;
}
if (access(pw->pw_dir, F_OK) == 0)
devnull_fd=open("/dev/null", O_RDWR);
}
if (nicelevel) {
- errno=0;
- if ((nice(nicelevel)==-1) && (errno!=0))
- fatal("Unable to alter nice level by %i: %s", nicelevel,
- strerror(errno));
+ errno = 0;
+ if ((nice(nicelevel) == -1) && (errno != 0))
+ fatal("Unable to alter nice level by %i: %s",
+ nicelevel, strerror(errno));
}
if (umask_value >= 0)
umask(umask_value);
- if (mpidfile && pidfile != NULL) { /* user wants _us_ to make the pidfile :) */
+ if (mpidfile && pidfile != NULL) {
+ /* User wants _us_ to make the pidfile :) */
FILE *pidf = fopen(pidfile, "w");
pid_t pidt = getpid();
if (pidf == NULL)
- fatal("Unable to open pidfile `%s' for writing: %s", pidfile,
- strerror(errno));
+ fatal("Unable to open pidfile `%s' for writing: %s",
+ pidfile, strerror(errno));
fprintf(pidf, "%d\n", pidt);
fclose(pidf);
}
if (chdir(changedir) < 0)
fatal("Unable to chdir() to %s", changedir);
if (changeuser != NULL) {
- if (setgid(runas_gid))
- fatal("Unable to set gid to %d", runas_gid);
+ if (setgid(runas_gid))
+ fatal("Unable to set gid to %d", runas_gid);
if (initgroups(changeuser, runas_gid))
fatal("Unable to set initgroups() with gid %d", runas_gid);
if (setuid(runas_uid))
fatal("Unable to set uid to %s", changeuser);
}
- if (background) { /* continue background setup */
+ if (background) {
+ /* Continue background setup */
int i;
#ifdef HAVE_TIOCNOTTY
- /* change tty */
+ /* Change tty */
ioctl(tty_fd, TIOCNOTTY, 0);
close(tty_fd);
#endif
if (umask_value < 0)
- umask(022); /* set a default for dumb programs */
- dup2(devnull_fd,0); /* stdin */
- dup2(devnull_fd,1); /* stdout */
- dup2(devnull_fd,2); /* stderr */
+ umask(022); /* Set a default for dumb programs */
+ dup2(devnull_fd, 0); /* stdin */
+ dup2(devnull_fd, 1); /* stdout */
+ dup2(devnull_fd, 2); /* stderr */
#if defined(OShpux)
- /* now close all extra fds */
- for (i=sysconf(_SC_OPEN_MAX)-1; i>=3; --i) close(i);
+ /* Now close all extra fds */
+ for (i = sysconf(_SC_OPEN_MAX) - 1; i >= 3; --i)
+ close(i);
#else
- /* now close all extra fds */
- for (i=getdtablesize()-1; i>=3; --i) close(i);
+ /* Now close all extra fds */
+ for (i = getdtablesize() - 1; i >= 3; --i)
+ close(i);
#endif
}
execv(startas, argv);