We need to be able to locate pids by argv, instead of just argv0.
This commit is contained in:
		| @@ -58,7 +58,7 @@ static bool pid_is_cmd (pid_t pid, const char *cmd) | ||||
| 	return ((c == ')' && *cmd == '\0') ? true : false); | ||||
| } | ||||
|  | ||||
| static bool pid_is_exec (pid_t pid, const char *exec) | ||||
| static bool pid_is_exec (pid_t pid, const char *const *argv) | ||||
| { | ||||
| 	char cmdline[32]; | ||||
| 	char buffer[PATH_MAX]; | ||||
| @@ -68,6 +68,7 @@ static bool pid_is_exec (pid_t pid, const char *exec) | ||||
|  | ||||
| 	snprintf (cmdline, sizeof (cmdline), "/proc/%u/exe", pid); | ||||
| 	memset (buffer, 0, sizeof (buffer)); | ||||
| #if 0 | ||||
| 	if (readlink (cmdline, buffer, sizeof (buffer)) != -1) { | ||||
| 		if (strcmp (exec, buffer) == 0) | ||||
| 			return (true); | ||||
| @@ -82,22 +83,32 @@ static bool pid_is_exec (pid_t pid, const char *exec) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| 	snprintf (cmdline, sizeof (cmdline), "/proc/%u/cmdline", pid); | ||||
| 	if ((fd = open (cmdline, O_RDONLY)) < 0) | ||||
| 		return (false); | ||||
|  | ||||
| 	r = read(fd, buffer, sizeof (buffer)); | ||||
| 	r = read (fd, buffer, sizeof (buffer)); | ||||
| 	close (fd); | ||||
|  | ||||
| 	if (r == -1) | ||||
| 		return 0; | ||||
|  | ||||
| 	buffer[r] = 0; | ||||
| 	return (strcmp (exec, buffer) == 0 ? true : false); | ||||
| 	p = buffer; | ||||
| 	while (*argv) { | ||||
| 		if (strcmp (*argv, p) != 0) | ||||
| 			return (false); | ||||
| 		argv++; | ||||
| 		p += strlen (p) + 1; | ||||
| 		if (p - buffer > (unsigned) sizeof (buffer)) | ||||
| 			return (false); | ||||
| 	} | ||||
| 	return (true); | ||||
| } | ||||
|  | ||||
| pid_t *rc_find_pids (const char *exec, const char *cmd, | ||||
| pid_t *rc_find_pids (const char *const *argv, const char *cmd, | ||||
| 		     uid_t uid, pid_t pid) | ||||
| { | ||||
| 	DIR *procdir; | ||||
| @@ -149,7 +160,7 @@ pid_t *rc_find_pids (const char *exec, const char *cmd, | ||||
| 		if (cmd && ! pid_is_cmd (p, cmd)) | ||||
| 			continue; | ||||
|  | ||||
| 		if (exec && ! cmd && ! pid_is_exec (p, exec)) | ||||
| 		if (argv && ! cmd && ! pid_is_exec (p, (const char *const *)argv)) | ||||
| 			continue; | ||||
|  | ||||
| 		tmp = realloc (pids, sizeof (pid_t) * (npids + 2)); | ||||
| @@ -193,7 +204,7 @@ librc_hidden_def(rc_find_pids) | ||||
| #  define _KVM_PATH NULL | ||||
| # endif | ||||
|  | ||||
| pid_t *rc_find_pids (const char *exec, const char *cmd, | ||||
| pid_t *rc_find_pids (const char *const *argv, const char *cmd, | ||||
| 		     uid_t uid, pid_t pid) | ||||
| { | ||||
| 	static kvm_t *kd = NULL; | ||||
| @@ -201,11 +212,13 @@ pid_t *rc_find_pids (const char *exec, const char *cmd, | ||||
| 	struct _KINFO_PROC *kp; | ||||
| 	int i; | ||||
| 	int processes = 0; | ||||
| 	int argc = 0; | ||||
| 	char **argv; | ||||
| 	int pargc = 0; | ||||
| 	char **pargv; | ||||
| 	pid_t *pids = NULL; | ||||
| 	pid_t *tmp; | ||||
| 	char *arg; | ||||
| 	int npids = 0; | ||||
| 	int match; | ||||
|  | ||||
| 	if ((kd = kvm_openfiles (_KVM_PATH, _KVM_PATH, | ||||
| 				 NULL, O_RDONLY, errbuf)) == NULL) | ||||
| @@ -239,11 +252,21 @@ pid_t *rc_find_pids (const char *exec, const char *cmd, | ||||
| 				continue; | ||||
| 		} | ||||
|  | ||||
| 		if (exec && ! cmd) { | ||||
| 			if ((argv = _KVM_GETARGV (kd, &kp[i], argc)) == NULL || ! *argv) | ||||
| 		if (argv && ! cmd) { | ||||
| 			pargv = _KVM_GETARGV (kd, &kp[i], pargc); | ||||
| 			if (! pargv || ! *pargv) | ||||
| 				continue; | ||||
|  | ||||
| 			if (strcmp (*argv, exec) != 0) | ||||
| 			arg = argv; | ||||
| 			match = 1; | ||||
|  | ||||
| 			while (arg && *pargv) | ||||
| 				if (strcmp (arg++, *pargv++) != 0) { | ||||
| 					match = 0; | ||||
| 					break; | ||||
| 				} | ||||
|  | ||||
| 			if (! match) | ||||
| 				continue; | ||||
| 		} | ||||
|  | ||||
| @@ -312,7 +335,7 @@ static bool _match_daemon (const char *path, const char *file, | ||||
| 	return (m == 111 ? true : false); | ||||
| } | ||||
|  | ||||
| bool rc_service_daemon_set (const char *service, const char *exec, | ||||
| bool rc_service_daemon_set (const char *service, const char *const *argv, | ||||
| 			    const char *name, const char *pidfile, | ||||
| 			    bool started) | ||||
| { | ||||
| @@ -328,7 +351,7 @@ bool rc_service_daemon_set (const char *service, const char *exec, | ||||
| 	DIR *dp; | ||||
| 	struct dirent *d; | ||||
|  | ||||
| 	if (! exec && ! name && ! pidfile) { | ||||
| 	if (! argv && ! name && ! pidfile) { | ||||
| 		errno = EINVAL; | ||||
| 		return (false); | ||||
| 	} | ||||
| @@ -336,10 +359,10 @@ bool rc_service_daemon_set (const char *service, const char *exec, | ||||
| 	dirpath = rc_strcatpaths (RC_SVCDIR, "daemons", | ||||
| 				  basename_c (service), (char *) NULL); | ||||
|  | ||||
| 	if (exec) { | ||||
| 		l = strlen (exec) + 6; | ||||
| 	if (argv) { | ||||
| 		l = strlen (*argv) + 6; | ||||
| 		mexec = xmalloc (sizeof (char) * l); | ||||
| 		snprintf (mexec, l, "exec=%s", exec); | ||||
| 		snprintf (mexec, l, "exec=%s", *argv); | ||||
| 	} else | ||||
| 		mexec = xstrdup ("exec="); | ||||
|  | ||||
| @@ -464,6 +487,7 @@ bool rc_service_daemons_crashed (const char *service) | ||||
| 	char *path; | ||||
| 	FILE *fp; | ||||
| 	char *line; | ||||
| 	char **argv = NULL; | ||||
| 	char *exec = NULL; | ||||
| 	char *name = NULL; | ||||
| 	char *pidfile = NULL; | ||||
| @@ -506,7 +530,9 @@ bool rc_service_daemons_crashed (const char *service) | ||||
| 				continue; | ||||
| 			} | ||||
|  | ||||
| 			if (strcmp (token, "exec") == 0) { | ||||
| 			if (strcmp (token, "argv") == 0) { | ||||
| 				rc_strlist_add (&argv, p); | ||||
| 			} else if (strcmp (token, "exec") == 0) { | ||||
| 				if (exec) | ||||
| 					free (exec); | ||||
| 				exec = xstrdup (p); | ||||
| @@ -546,24 +572,35 @@ bool rc_service_daemons_crashed (const char *service) | ||||
| 			pidfile = NULL; | ||||
|  | ||||
| 			/* We have the pid, so no need to match on name */ | ||||
| 			rc_strlist_free (argv); | ||||
| 			argv = NULL; | ||||
| 			free (exec); | ||||
| 			exec = NULL; | ||||
| 			free (name); | ||||
| 			name = NULL; | ||||
| 		} | ||||
|  | ||||
| 		if ((pids = rc_find_pids (exec, name, 0, pid)) == NULL) { | ||||
| 		if (exec && ! argv) { | ||||
| 			rc_strlist_add (&argv, exec); | ||||
| 			free (exec); | ||||
| 			exec = NULL; | ||||
| 		} | ||||
|  | ||||
| 		if ((pids = rc_find_pids ((const char *const *)argv, name, 0, pid)) == NULL) { | ||||
| 			retval = true; | ||||
| 			break; | ||||
| 		} | ||||
| 		free (pids); | ||||
|  | ||||
| 		rc_strlist_free (argv); | ||||
| 		argv = NULL; | ||||
| 		free (exec); | ||||
| 		exec = NULL; | ||||
| 		free (name); | ||||
| 		name = NULL; | ||||
| 	} | ||||
|  | ||||
| 	rc_strlist_free (argv); | ||||
| 	free (exec); | ||||
| 	free (name); | ||||
| 	free (dirpath); | ||||
|   | ||||
| @@ -117,7 +117,7 @@ bool rc_service_delete (const char *runlevel, const char *service); | ||||
|  * @param name of the process (optional) | ||||
|  * @param pidfile of the process (optional) | ||||
|  * @param started if true, add the arguments otherwise remove existing matching arguments */ | ||||
| bool rc_service_daemon_set (const char *service, const char *exec, | ||||
| bool rc_service_daemon_set (const char *service, const char *const *argv, | ||||
|                             const char *name, const char *pidfile, | ||||
|                             bool started); | ||||
|  | ||||
| @@ -445,7 +445,7 @@ char *rc_strcatpaths (const char *path1, const char *paths, ...) SENTINEL; | ||||
|  * @param uid to check for | ||||
|  * @param pid to check for | ||||
|  * @return NULL terminated list of pids */ | ||||
| pid_t *rc_find_pids (const char *exec, const char *cmd, | ||||
| pid_t *rc_find_pids (const char *const *argv, const char *cmd, | ||||
|                      uid_t uid, pid_t pid); | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -305,7 +305,7 @@ static pid_t get_pid (const char *pidfile, bool quiet) | ||||
| } | ||||
|  | ||||
| /* return number of processed killed, -1 on error */ | ||||
| static int do_stop (const char *exec, const char *cmd, | ||||
| 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) | ||||
| { | ||||
| @@ -320,7 +320,7 @@ static int do_stop (const char *exec, const char *cmd, | ||||
| 			return (quiet ? 0 : -1); | ||||
| 		pids = rc_find_pids (NULL, NULL, 0, pid); | ||||
| 	} else | ||||
| 		pids = rc_find_pids (exec, cmd, uid, pid); | ||||
| 		pids = rc_find_pids (argv, cmd, uid, pid); | ||||
|  | ||||
| 	if (! pids) | ||||
| 		return (0); | ||||
| @@ -352,7 +352,7 @@ static int do_stop (const char *exec, const char *cmd, | ||||
| 	return (nkilled); | ||||
| } | ||||
|  | ||||
| static int run_stop_schedule (const char *exec, const char *cmd, | ||||
| static int run_stop_schedule (const char *const *argv, const char *cmd, | ||||
| 			      const char *pidfile, uid_t uid, | ||||
| 			      bool quiet, bool verbose, bool test) | ||||
| { | ||||
| @@ -368,8 +368,8 @@ static int run_stop_schedule (const char *exec, const char *cmd, | ||||
| 			einfo ("Will stop PID in pidfile `%s'", pidfile); | ||||
| 		if (uid) | ||||
| 			einfo ("Will stop processes owned by UID %d", uid); | ||||
| 		if (exec) | ||||
| 			einfo ("Will stop processes of `%s'", exec); | ||||
| 		if (argv) | ||||
| 			einfo ("Will stop processes of `%s'", *argv); | ||||
| 		if (cmd) | ||||
| 			einfo ("Will stop processes called `%s'", cmd); | ||||
| 	} | ||||
| @@ -382,7 +382,7 @@ static int run_stop_schedule (const char *exec, const char *cmd, | ||||
|  | ||||
| 			case schedule_signal: | ||||
| 				nrunning = 0; | ||||
| 				nkilled = do_stop (exec, cmd, pidfile, uid, item->value, | ||||
| 				nkilled = do_stop (argv, cmd, pidfile, uid, item->value, | ||||
| 						   quiet, verbose, test); | ||||
| 				if (nkilled == 0) { | ||||
| 					if (tkilled == 0) { | ||||
| @@ -407,7 +407,7 @@ static int run_stop_schedule (const char *exec, const char *cmd, | ||||
| 				ts.tv_nsec = POLL_INTERVAL; | ||||
|  | ||||
| 				while (nloops) { | ||||
| 					if ((nrunning = do_stop (exec, cmd, pidfile, | ||||
| 					if ((nrunning = do_stop (argv, cmd, pidfile, | ||||
| 								 uid, 0, true, false, true)) == 0) | ||||
| 						return (true); | ||||
|  | ||||
| @@ -496,6 +496,7 @@ static const struct option longopts[] = { | ||||
| 	{ "background",   0, NULL, 'b'}, | ||||
| 	{ "chuid",        1, NULL, 'c'}, | ||||
| 	{ "chdir",        1, NULL, 'd'}, | ||||
| 	{ "env",          1, NULL, 'e'}, | ||||
| 	{ "group",        1, NULL, 'g'}, | ||||
| 	{ "make-pidfile", 0, NULL, 'm'}, | ||||
| 	{ "name",         1, NULL, 'n'}, | ||||
| @@ -519,6 +520,7 @@ static const char * const longopts_help[] = { | ||||
| 	"Force daemon to background", | ||||
| 	"deprecated, use --user", | ||||
| 	"Change the PWD", | ||||
| 	"Set an environment string", | ||||
| 	"Change the process group", | ||||
| 	"Create a pidfile", | ||||
| 	"Match process name", | ||||
| @@ -574,6 +576,8 @@ int start_stop_daemon (int argc, char **argv) | ||||
| 	int i; | ||||
| 	char *svcname = getenv ("SVCNAME"); | ||||
| 	char *env; | ||||
| 	bool sethome = false; | ||||
| 	bool setuser = false; | ||||
|  | ||||
| 	atexit (cleanup); | ||||
|  | ||||
| @@ -585,7 +589,7 @@ int start_stop_daemon (int argc, char **argv) | ||||
| 		if (sscanf (env, "%d", &nicelevel) != 1) | ||||
| 			eerror ("%s: invalid nice level `%s' (SSD_NICELEVEL)", applet, env); | ||||
|  | ||||
| 	while ((opt = getopt_long (argc, argv, getoptstring, longopts, | ||||
| 	while ((opt = getopt_long (argc, argv, "e:" getoptstring, longopts, | ||||
| 				   (int *) 0)) != -1) | ||||
| 		switch (opt) { | ||||
| 			case 'K':  /* --stop */ | ||||
| @@ -648,6 +652,15 @@ int start_stop_daemon (int argc, char **argv) | ||||
| 				ch_dir = optarg; | ||||
| 				break; | ||||
|  | ||||
| 			case 'e': /* --env */ | ||||
| 				if (putenv (optarg) == 0) { | ||||
| 					if (strncmp ("HOME=", optarg, 5) == 0) | ||||
| 						sethome = true; | ||||
| 					else if (strncmp ("USER=", optarg, 5) == 0) | ||||
| 						setuser = true; | ||||
| 				} | ||||
| 				break; | ||||
|  | ||||
| 			case 'g':  /* --group <group>|<gid> */ | ||||
| 				{ | ||||
| 					struct group *gr = getgrnam (optarg); | ||||
| @@ -761,6 +774,9 @@ int start_stop_daemon (int argc, char **argv) | ||||
| 			free (tmp); | ||||
| 	} | ||||
|  | ||||
| 	/* Add exec to our arguments */ | ||||
| 	*--argv = exec; | ||||
|  | ||||
| 	if (stop) { | ||||
| 		int result; | ||||
|  | ||||
| @@ -771,7 +787,8 @@ int start_stop_daemon (int argc, char **argv) | ||||
| 				parse_schedule (NULL, sig); | ||||
| 		} | ||||
|  | ||||
| 		result = run_stop_schedule (exec, cmd, pidfile, uid, quiet, verbose, test); | ||||
| 		result = run_stop_schedule ((const char *const *)argv, cmd, | ||||
| 					    pidfile, uid, quiet, verbose, test); | ||||
| 		if (test || oknodo) | ||||
| 			return (result > 0 ? EXIT_SUCCESS : EXIT_FAILURE); | ||||
| 		if (result < 1) | ||||
| @@ -781,21 +798,24 @@ int start_stop_daemon (int argc, char **argv) | ||||
| 			unlink (pidfile); | ||||
|  | ||||
| 		if (svcname) | ||||
| 			rc_service_daemon_set (svcname, exec, cmd, pidfile, false); | ||||
| 			rc_service_daemon_set (svcname, | ||||
| 					       (const char *const *)argv, | ||||
| 					       cmd, pidfile, false); | ||||
|  | ||||
| 		exit (EXIT_SUCCESS); | ||||
| 	} | ||||
|  | ||||
| 	if (do_stop (exec, cmd, pidfile, uid, 0, true, false, true) > 0) | ||||
| 	if (do_stop ((const char * const *)argv, cmd, pidfile, uid, | ||||
| 		     0, true, false, true) > 0) | ||||
| 		eerrorx ("%s: %s is already running", applet, exec); | ||||
|  | ||||
| 	if (test) { | ||||
| 		if (quiet) | ||||
| 			exit (EXIT_SUCCESS); | ||||
|  | ||||
| 		einfon ("Would start %s", exec); | ||||
| 		while (argc-- > 0) | ||||
| 			printf("%s ", *argv++); | ||||
| 		einfon ("Would start"); | ||||
| 		while (argc-- >= 0) | ||||
| 			printf(" %s", *argv++); | ||||
| 		printf ("\n"); | ||||
| 		eindent (); | ||||
| 		if (uid != 0) | ||||
| @@ -824,7 +844,6 @@ int start_stop_daemon (int argc, char **argv) | ||||
| 	if (background) | ||||
| 		signal_setup (SIGCHLD, handle_signal); | ||||
|  | ||||
| 	*--argv = exec; | ||||
| 	if ((pid = fork ()) == -1) | ||||
| 		eerrorx ("%s: fork: %s", applet, strerror (errno)); | ||||
|  | ||||
| @@ -884,12 +903,16 @@ int start_stop_daemon (int argc, char **argv) | ||||
| 		else { | ||||
| 			struct passwd *passwd = getpwuid (uid); | ||||
| 			if (passwd) { | ||||
| 				unsetenv ("HOME"); | ||||
| 				if (passwd->pw_dir) | ||||
| 					setenv ("HOME", passwd->pw_dir, 1); | ||||
| 				unsetenv ("USER"); | ||||
| 				if (passwd->pw_name) | ||||
| 					setenv ("USER", passwd->pw_name, 1); | ||||
| 				if (! sethome) { | ||||
| 					unsetenv ("HOME"); | ||||
| 					if (passwd->pw_dir) | ||||
| 						setenv ("HOME", passwd->pw_dir, 1); | ||||
| 				} | ||||
| 				if (! setuser) { | ||||
| 					unsetenv ("USER"); | ||||
| 					if (passwd->pw_name) | ||||
| 						setenv ("USER", passwd->pw_name, 1); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| @@ -1056,7 +1079,8 @@ int start_stop_daemon (int argc, char **argv) | ||||
| 					} else | ||||
| 						nloopsp = 0; | ||||
| 				} | ||||
| 				if (do_stop (exec, cmd, pidfile, uid, 0, true, false, true) > 0) | ||||
| 				if (do_stop ((const char *const *)argv, cmd, | ||||
| 					     pidfile, uid, 0, true, false, true) > 0) | ||||
| 					alive = true; | ||||
| 			} | ||||
|  | ||||
| @@ -1066,7 +1090,7 @@ int start_stop_daemon (int argc, char **argv) | ||||
| 	} | ||||
|  | ||||
| 	if (svcname) | ||||
| 		rc_service_daemon_set (svcname, exec, cmd, pidfile, true); | ||||
| 		rc_service_daemon_set (svcname, (const char *const *)argv, cmd, pidfile, true); | ||||
|  | ||||
| 	exit (EXIT_SUCCESS); | ||||
| 	/* NOTREACHED */ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user