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
.\" SUCH DAMAGE.
.\"
.Dd Feb 22, 2008
.Dd Mar 17, 2008
.Dt RC_FIND_PIDS 3 SMM
.Os OpenRC
.Sh NAME
@ -32,20 +32,22 @@
Run Command library (librc, -lrc)
.Sh SYNOPSIS
.In rc.h
.Ft "pid_t *" Fo rc_find_pids
.Fa "const char *exec"
.Ft "RC_PIDLIST *" Fo rc_find_pids
.Fa "const char *const *argv"
.Fa "const char *cmd"
.Fa "uid_t uid"
.Fa "pid_t pid"
.Fc
.Sh DESCRIPTION
.Fn rc_find_pids
returns a NULL terminated list of pids for processes matching the given
criteria. If
returns RC_PIDLIST, a structure based on the LIST macro from
.Xr queue 3
which contains all the pids found matching the given criteria.
If
.Fa pid
is given then only that pid is returned if it is running. Otherise we check
all instances of
.Fa exec
.Fa argv
with a process name of
.Fa cmd
owned by
@ -59,8 +61,10 @@ On BSD systems we use
and on Linux systems we use the
.Pa /proc
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
.Xr free 3 ,
.Xr malloc 3
.Xr queue 3
.Sh AUTHORS
.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;
}
pid_t *rc_find_pids(const char *const *argv, const char *cmd,
uid_t uid, pid_t pid)
RC_PIDLIST *rc_find_pids(const char *const *argv, const char *cmd,
uid_t uid, pid_t pid)
{
DIR *procdir;
struct dirent *entry;
int npids = 0;
pid_t p;
pid_t *pids = NULL;
pid_t *tmp = NULL;
char buffer[PATH_MAX];
struct stat sb;
pid_t runscript_pid = 0;
char *pp;
RC_PIDLIST *pids = NULL;
RC_PID *pi;
if ((procdir = opendir("/proc")) == 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))
continue;
if (argv && ! cmd && ! pid_is_exec(p, (const char *const *)argv))
if (argv && ! cmd && !
pid_is_exec(p, (const char *const *)argv))
continue;
tmp = realloc(pids, sizeof (pid_t) * (npids + 2));
if (! tmp) {
free(pids);
closedir(procdir);
errno = ENOMEM;
return NULL;
if (! pids) {
pids = xmalloc(sizeof(*pids));
LIST_INIT(pids);
}
pids = tmp;
pids[npids] = p;
pids[npids + 1] = 0;
npids++;
pi = xmalloc(sizeof(*pi));
pi->pid = p;
LIST_INSERT_HEAD(pids, pi, entries);
}
closedir(procdir);
@ -205,8 +200,8 @@ librc_hidden_def(rc_find_pids)
# define _KVM_FLAGS O_RDONLY
# endif
pid_t *rc_find_pids(const char *const *argv, const char *cmd,
uid_t uid, pid_t pid)
RC_PIDLIST *rc_find_pids(const char *const *argv, const char *cmd,
uid_t uid, pid_t pid)
{
static kvm_t *kd = NULL;
char errbuf[_POSIX2_LINE_MAX];
@ -215,8 +210,8 @@ pid_t *rc_find_pids(const char *const *argv, const char *cmd,
int processes = 0;
int pargc = 0;
char **pargv;
pid_t *pids = NULL;
pid_t *tmp;
RC_PIDLIST *pids = NULL;
RC_PID *pi;
pid_t p;
const char *const *arg;
int npids = 0;
@ -272,18 +267,13 @@ pid_t *rc_find_pids(const char *const *argv, const char *cmd,
continue;
}
tmp = realloc(pids, sizeof(pid_t) * (npids + 2));
if (! tmp) {
free(pids);
kvm_close(kd);
errno = ENOMEM;
return NULL;
if (! pids) {
pids = xmalloc(sizeof(*pids));
LIST_INIT(pids);
}
pids = tmp;
pids[npids] = p;
pids[npids + 1] = 0;
npids++;
pi = xmalloc(sizeof(*pi));
pi->pid = p;
LIST_INSERT_HEAD(pids, pi, entries);
}
kvm_close(kd);
@ -498,7 +488,9 @@ bool rc_service_daemons_crashed(const char *service)
char *name = NULL;
char *pidfile = NULL;
pid_t pid = 0;
pid_t *pids = NULL;
RC_PIDLIST *pids;
RC_PID *p1;
RC_PID *p2;
char *p;
char *token;
bool retval = false;
@ -604,9 +596,18 @@ bool rc_service_daemons_crashed(const char *service)
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,
name, 0, pid)) == NULL)
{
p1 = LIST_FIRST(pids);
while (p1) {
p2 = LIST_NEXT(p1, entries);
free(p1);
p1 = p2;
}
free(pids);
retval = true;
free(pids);
}
free(argv);
argv = NULL;
rc_stringlist_free(list);

View File

@ -451,6 +451,13 @@ void rc_stringlist_free(RC_STRINGLIST *);
* @return pointer to the new path */
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.
* All of these are optional.
* pid overrides anything else.
@ -460,6 +467,6 @@ char *rc_strcatpaths(const char *, const char *, ...) SENTINEL;
* @param uid to check for
* @param pid to check for
* @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

View File

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

View File

@ -73,6 +73,15 @@ static struct pam_conv conv = { NULL, NULL};
#include "rc.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
{
enum
@ -301,11 +310,12 @@ static int do_stop(const char *const *argv, const char *cmd,
const char *pidfile, uid_t uid,int sig,
bool quiet, bool verbose, bool test)
{
pid_t *pids;
RC_PIDLIST *pids;
RC_PID *pi;
RC_PID *np;
bool killed;
int nkilled = 0;
pid_t pid = 0;
int i;
if (pidfile) {
if ((pid = get_pid(pidfile, quiet)) == -1)
@ -317,27 +327,31 @@ static int do_stop(const char *const *argv, const char *cmd,
if (! pids)
return 0;
for (i = 0; pids[i]; i++) {
LIST_FOREACH_SAFE(pi, pids, entries, np) {
if (test) {
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++;
continue;
}
if (verbose)
ebegin("Sending signal %d to PID %d", sig, pids[i]);
errno = 0;
killed = (kill(pids[i], sig) == 0 || errno == ESRCH ? true : false);
if (verbose)
eend(killed ? 0 : 1, "%s: failed to send signal %d to PID %d: %s",
applet, sig, pids[i], strerror(errno));
if (! killed) {
nkilled = -1;
} else {
if (nkilled != -1)
nkilled++;
if (verbose)
ebegin("Sending signal %d to PID %d",
sig, pi->pid);
errno = 0;
killed = (kill(pi->pid, sig) == 0 ||
errno == ESRCH ? true : false);
if (verbose)
eend(killed ? 0 : 1,
"%s: failed to send signal %d to PID %d: %s",
applet, sig, pi->pid, strerror(errno));
if (! killed) {
nkilled = -1;
} else {
if (nkilled != -1)
nkilled++;
}
}
free(pi);
}
free(pids);