rc_find_pids now returns RC_PIDLIST instead of a NULL terminated array.

This commit is contained in:
Roy Marples 2008-03-17 09:59:52 +00:00
parent 40930d7d0a
commit 50a7697bf2
5 changed files with 93 additions and 72 deletions

View File

@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE. .\" SUCH DAMAGE.
.\" .\"
.Dd Feb 22, 2008 .Dd Mar 17, 2008
.Dt RC_FIND_PIDS 3 SMM .Dt RC_FIND_PIDS 3 SMM
.Os OpenRC .Os OpenRC
.Sh NAME .Sh NAME
@ -32,20 +32,22 @@
Run Command library (librc, -lrc) Run Command library (librc, -lrc)
.Sh SYNOPSIS .Sh SYNOPSIS
.In rc.h .In rc.h
.Ft "pid_t *" Fo rc_find_pids .Ft "RC_PIDLIST *" Fo rc_find_pids
.Fa "const char *exec" .Fa "const char *const *argv"
.Fa "const char *cmd" .Fa "const char *cmd"
.Fa "uid_t uid" .Fa "uid_t uid"
.Fa "pid_t pid" .Fa "pid_t pid"
.Fc .Fc
.Sh DESCRIPTION .Sh DESCRIPTION
.Fn rc_find_pids .Fn rc_find_pids
returns a NULL terminated list of pids for processes matching the given returns RC_PIDLIST, a structure based on the LIST macro from
criteria. If .Xr queue 3
which contains all the pids found matching the given criteria.
If
.Fa pid .Fa pid
is given then only that pid is returned if it is running. Otherise we check is given then only that pid is returned if it is running. Otherise we check
all instances of all instances of
.Fa exec .Fa argv
with a process name of with a process name of
.Fa cmd .Fa cmd
owned by owned by
@ -59,8 +61,10 @@ On BSD systems we use
and on Linux systems we use the and on Linux systems we use the
.Pa /proc .Pa /proc
filesystem to find our processes. filesystem to find our processes.
.Pp
Each RC_PID should be freed in the list as well as the list itself when done.
.Sh SEE ALSO .Sh SEE ALSO
.Xr free 3 , .Xr free 3 ,
.Xr malloc 3 .Xr queue 3
.Sh AUTHORS .Sh AUTHORS
.An "Roy Marples" Aq roy@marples.name .An "Roy Marples" Aq roy@marples.name

View File

@ -107,19 +107,18 @@ static bool pid_is_exec(pid_t pid, const char *const *argv)
return true; return true;
} }
pid_t *rc_find_pids(const char *const *argv, const char *cmd, RC_PIDLIST *rc_find_pids(const char *const *argv, const char *cmd,
uid_t uid, pid_t pid) uid_t uid, pid_t pid)
{ {
DIR *procdir; DIR *procdir;
struct dirent *entry; struct dirent *entry;
int npids = 0;
pid_t p; pid_t p;
pid_t *pids = NULL;
pid_t *tmp = NULL;
char buffer[PATH_MAX]; char buffer[PATH_MAX];
struct stat sb; struct stat sb;
pid_t runscript_pid = 0; pid_t runscript_pid = 0;
char *pp; char *pp;
RC_PIDLIST *pids = NULL;
RC_PID *pi;
if ((procdir = opendir("/proc")) == NULL) if ((procdir = opendir("/proc")) == NULL)
return NULL; return NULL;
@ -159,21 +158,17 @@ pid_t *rc_find_pids(const char *const *argv, const char *cmd,
if (cmd && ! pid_is_cmd(p, cmd)) if (cmd && ! pid_is_cmd(p, cmd))
continue; continue;
if (argv && ! cmd && ! pid_is_exec(p, (const char *const *)argv)) if (argv && ! cmd && !
pid_is_exec(p, (const char *const *)argv))
continue; continue;
tmp = realloc(pids, sizeof (pid_t) * (npids + 2)); if (! pids) {
if (! tmp) { pids = xmalloc(sizeof(*pids));
free(pids); LIST_INIT(pids);
closedir(procdir);
errno = ENOMEM;
return NULL;
} }
pids = tmp; pi = xmalloc(sizeof(*pi));
pi->pid = p;
pids[npids] = p; LIST_INSERT_HEAD(pids, pi, entries);
pids[npids + 1] = 0;
npids++;
} }
closedir(procdir); closedir(procdir);
@ -205,7 +200,7 @@ librc_hidden_def(rc_find_pids)
# define _KVM_FLAGS O_RDONLY # define _KVM_FLAGS O_RDONLY
# endif # endif
pid_t *rc_find_pids(const char *const *argv, const char *cmd, RC_PIDLIST *rc_find_pids(const char *const *argv, const char *cmd,
uid_t uid, pid_t pid) uid_t uid, pid_t pid)
{ {
static kvm_t *kd = NULL; static kvm_t *kd = NULL;
@ -215,8 +210,8 @@ pid_t *rc_find_pids(const char *const *argv, const char *cmd,
int processes = 0; int processes = 0;
int pargc = 0; int pargc = 0;
char **pargv; char **pargv;
pid_t *pids = NULL; RC_PIDLIST *pids = NULL;
pid_t *tmp; RC_PID *pi;
pid_t p; pid_t p;
const char *const *arg; const char *const *arg;
int npids = 0; int npids = 0;
@ -272,18 +267,13 @@ pid_t *rc_find_pids(const char *const *argv, const char *cmd,
continue; continue;
} }
tmp = realloc(pids, sizeof(pid_t) * (npids + 2)); if (! pids) {
if (! tmp) { pids = xmalloc(sizeof(*pids));
free(pids); LIST_INIT(pids);
kvm_close(kd);
errno = ENOMEM;
return NULL;
} }
pids = tmp; pi = xmalloc(sizeof(*pi));
pi->pid = p;
pids[npids] = p; LIST_INSERT_HEAD(pids, pi, entries);
pids[npids + 1] = 0;
npids++;
} }
kvm_close(kd); kvm_close(kd);
@ -498,7 +488,9 @@ bool rc_service_daemons_crashed(const char *service)
char *name = NULL; char *name = NULL;
char *pidfile = NULL; char *pidfile = NULL;
pid_t pid = 0; pid_t pid = 0;
pid_t *pids = NULL; RC_PIDLIST *pids;
RC_PID *p1;
RC_PID *p2;
char *p; char *p;
char *token; char *token;
bool retval = false; bool retval = false;
@ -604,9 +596,18 @@ bool rc_service_daemons_crashed(const char *service)
argv[i] = '\0'; argv[i] = '\0';
} }
if ((pids = rc_find_pids((const char *const *)argv, name, 0, pid)) == NULL) if ((pids = rc_find_pids((const char *const *)argv,
retval = true; name, 0, pid)) == NULL)
{
p1 = LIST_FIRST(pids);
while (p1) {
p2 = LIST_NEXT(p1, entries);
free(p1);
p1 = p2;
}
free(pids); free(pids);
retval = true;
}
free(argv); free(argv);
argv = NULL; argv = NULL;
rc_stringlist_free(list); rc_stringlist_free(list);

View File

@ -451,6 +451,13 @@ void rc_stringlist_free(RC_STRINGLIST *);
* @return pointer to the new path */ * @return pointer to the new path */
char *rc_strcatpaths(const char *, const char *, ...) SENTINEL; char *rc_strcatpaths(const char *, const char *, ...) SENTINEL;
typedef struct rc_pid
{
pid_t pid;
LIST_ENTRY(rc_pid) entries;
} RC_PID;
typedef LIST_HEAD(rc_pidlist, rc_pid) RC_PIDLIST;
/*! Find processes based on criteria. /*! Find processes based on criteria.
* All of these are optional. * All of these are optional.
* pid overrides anything else. * pid overrides anything else.
@ -460,6 +467,6 @@ char *rc_strcatpaths(const char *, const char *, ...) SENTINEL;
* @param uid to check for * @param uid to check for
* @param pid to check for * @param pid to check for
* @return NULL terminated list of pids */ * @return NULL terminated list of pids */
pid_t *rc_find_pids(const char *const *, const char *, uid_t, pid_t); RC_PIDLIST *rc_find_pids(const char *const *, const char *, uid_t, pid_t);
#endif #endif

View File

@ -99,12 +99,7 @@ static RC_HOOK hook_out = 0;
struct termios *termios_orig = NULL; struct termios *termios_orig = NULL;
typedef struct piditem RC_PIDLIST service_pids;
{
pid_t pid;
LIST_ENTRY(piditem) entries;
} PIDITEM;
LIST_HEAD(, piditem) service_pids;
static void clean_failed(void) static void clean_failed(void)
{ {
@ -138,8 +133,8 @@ static void clean_failed(void)
static void cleanup(void) static void cleanup(void)
{ {
if (applet && strcmp(applet, "rc") == 0) { if (applet && strcmp(applet, "rc") == 0) {
PIDITEM *p1 = LIST_FIRST(&service_pids); RC_PID *p1 = LIST_FIRST(&service_pids);
PIDITEM *p2; RC_PID *p2;
if (hook_out) if (hook_out)
rc_plugin_run(hook_out, runlevel); rc_plugin_run(hook_out, runlevel);
@ -410,14 +405,14 @@ static int get_ksoftlevel(char *buffer, int buffer_len)
static void add_pid(pid_t pid) static void add_pid(pid_t pid)
{ {
PIDITEM *p = xmalloc(sizeof(*p)); RC_PID *p = xmalloc(sizeof(*p));
p->pid = pid; p->pid = pid;
LIST_INSERT_HEAD(&service_pids, p, entries); LIST_INSERT_HEAD(&service_pids, p, entries);
} }
static void remove_pid(pid_t pid) static void remove_pid(pid_t pid)
{ {
PIDITEM *p; RC_PID *p;
LIST_FOREACH(p, &service_pids, entries) LIST_FOREACH(p, &service_pids, entries)
if (p->pid == pid) { if (p->pid == pid) {
@ -437,7 +432,7 @@ static void handle_signal(int sig)
int serrno = errno; int serrno = errno;
char signame[10] = { '\0' }; char signame[10] = { '\0' };
pid_t pid; pid_t pid;
PIDITEM *pi; RC_PID *pi;
int status = 0; int status = 0;
struct winsize ws; struct winsize ws;
sigset_t sset; sigset_t sset;

View File

@ -73,6 +73,15 @@ static struct pam_conv conv = { NULL, NULL};
#include "rc.h" #include "rc.h"
#include "rc-misc.h" #include "rc-misc.h"
/* Some libc implementations don't define this */
#ifndef LIST_FOREACH_SAFE
#define LIST_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = LIST_FIRST((head)); \
(var) && ((tvar) = LIST_NEXT((var), field), 1); \
(var) = (tvar))
#endif
typedef struct scheduleitem typedef struct scheduleitem
{ {
enum enum
@ -301,11 +310,12 @@ static int do_stop(const char *const *argv, const char *cmd,
const char *pidfile, uid_t uid,int sig, const char *pidfile, uid_t uid,int sig,
bool quiet, bool verbose, bool test) bool quiet, bool verbose, bool test)
{ {
pid_t *pids; RC_PIDLIST *pids;
RC_PID *pi;
RC_PID *np;
bool killed; bool killed;
int nkilled = 0; int nkilled = 0;
pid_t pid = 0; pid_t pid = 0;
int i;
if (pidfile) { if (pidfile) {
if ((pid = get_pid(pidfile, quiet)) == -1) if ((pid = get_pid(pidfile, quiet)) == -1)
@ -317,21 +327,23 @@ static int do_stop(const char *const *argv, const char *cmd,
if (! pids) if (! pids)
return 0; return 0;
for (i = 0; pids[i]; i++) { LIST_FOREACH_SAFE(pi, pids, entries, np) {
if (test) { if (test) {
if (! quiet) if (! quiet)
einfo("Would send signal %d to PID %d", sig, pids[i]); einfo("Would send signal %d to PID %d",
sig, pi->pid);
nkilled++; nkilled++;
continue; } else {
}
if (verbose) if (verbose)
ebegin("Sending signal %d to PID %d", sig, pids[i]); ebegin("Sending signal %d to PID %d",
sig, pi->pid);
errno = 0; errno = 0;
killed = (kill(pids[i], sig) == 0 || errno == ESRCH ? true : false); killed = (kill(pi->pid, sig) == 0 ||
errno == ESRCH ? true : false);
if (verbose) if (verbose)
eend(killed ? 0 : 1, "%s: failed to send signal %d to PID %d: %s", eend(killed ? 0 : 1,
applet, sig, pids[i], strerror(errno)); "%s: failed to send signal %d to PID %d: %s",
applet, sig, pi->pid, strerror(errno));
if (! killed) { if (! killed) {
nkilled = -1; nkilled = -1;
} else { } else {
@ -339,6 +351,8 @@ static int do_stop(const char *const *argv, const char *cmd,
nkilled++; nkilled++;
} }
} }
free(pi);
}
free(pids); free(pids);
return nkilled; return nkilled;