rc_find_pids now returns RC_PIDLIST instead of a NULL terminated array.
This commit is contained in:
		| @@ -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 | ||||
|   | ||||
| @@ -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, | ||||
| 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,7 +200,7 @@ librc_hidden_def(rc_find_pids) | ||||
| #  define _KVM_FLAGS O_RDONLY | ||||
| # 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) | ||||
| { | ||||
| 	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 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) | ||||
| 			retval = true; | ||||
| 		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(argv); | ||||
| 		argv = NULL; | ||||
| 		rc_stringlist_free(list); | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
							
								
								
									
										17
									
								
								src/rc/rc.c
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								src/rc/rc.c
									
									
									
									
									
								
							| @@ -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; | ||||
|   | ||||
| @@ -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,21 +327,23 @@ 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; | ||||
| 		} | ||||
|  | ||||
| 		} else { | ||||
| 			if (verbose) | ||||
| 			ebegin("Sending signal %d to PID %d", sig, pids[i]); | ||||
| 				ebegin("Sending signal %d to PID %d", | ||||
| 				sig, pi->pid); | ||||
| 			errno = 0; | ||||
| 		killed = (kill(pids[i], sig) == 0 || errno == ESRCH ? true : false); | ||||
| 			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, pids[i], strerror(errno)); | ||||
| 				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 { | ||||
| @@ -339,6 +351,8 @@ static int do_stop(const char *const *argv, const char *cmd, | ||||
| 					nkilled++; | ||||
| 			} | ||||
| 		} | ||||
| 		free(pi); | ||||
| 	} | ||||
|  | ||||
| 	free(pids); | ||||
| 	return nkilled; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user