Ver código fonte

s-s-d: Add a new --ppid matching option

This allows to check for processes with a specific parent PID.

Suggested-by: Alex Mestiashvili <mailatgoogl@gmail.com>
Guillem Jover 12 anos atrás
pai
commit
3fabf94e0b
3 arquivos alterados com 99 adições e 4 exclusões
  1. 2 0
      debian/changelog
  2. 6 2
      man/start-stop-daemon.8
  3. 91 2
      utils/start-stop-daemon.c

+ 2 - 0
debian/changelog

@@ -64,6 +64,8 @@ dpkg (1.17.7) UNRELEASED; urgency=low
     - Fix OpenBSD KVM code to use current kinfo_proc layout.
     - Detect system specific headers at configure time instead of hardcoding
       their usage depending on system macros.
+    - Add a new --ppid matching option to check for parent PID.
+      Suggested by Alex Mestiashvili <mailatgoogl@gmail.com>.
 
   [ Updated dpkg translations ]
   * German (Sven Joachim).

+ 6 - 2
man/start-stop-daemon.8

@@ -5,7 +5,7 @@
 .\" Copyright © 2000-2001 Wichert Akkerman <wakkerma@debian.org>
 .\" Copyright © 2002-2003 Adam Heath <doogie@debian.org>
 .\" Copyright © 2004 Scott James Remnant <keybuk@debian.org>
-.\" Copyright © 2008-2013 Guillem Jover <guillem@debian.org>
+.\" Copyright © 2008-2014 Guillem Jover <guillem@debian.org>
 .\"
 .\" This is free software; you can redistribute it and/or modify
 .\" it under the terms of the GNU General Public License as published by
@@ -20,7 +20,7 @@
 .\" You should have received a copy of the GNU General Public License
 .\" along with this program.  If not, see <https://www.gnu.org/licenses/>.
 .
-.TH start\-stop\-daemon 8 "2013-12-14" "Debian Project" "dpkg utilities"
+.TH start\-stop\-daemon 8 "2014-03-26" "Debian Project" "dpkg utilities"
 .SH NAME
 start\-stop\-daemon \- start and stop system daemon programs
 .
@@ -107,6 +107,10 @@ Show the program version and exit.
 Check for a process with the specified \fIpid\fP. The \fIpid\fP must be a
 number greater than 0.
 .TP
+.BR \-\-ppid " \fIppid\fP"
+Check for a process with the specified \fIppid\fP (parent pid).
+The \fIppid\fP must be a number greater than 0.
+.TP
 .BR \-p ", " \-\-pidfile " \fIpid-file\fP"
 Check whether a process has created the file \fIpid-file\fP. Note: using this
 matching option alone might cause unintended processes to be acted on, if the

+ 91 - 2
utils/start-stop-daemon.c

@@ -176,6 +176,7 @@ static const char *cmdname = NULL;
 static char *execname = NULL;
 static char *startas = NULL;
 static pid_t match_pid = -1;
+static pid_t match_ppid = -1;
 static const char *pidfile = NULL;
 static char what_stop[1024];
 static const char *progname = "";
@@ -440,6 +441,7 @@ usage(void)
 "\n"
 "Matching options (at least one is required):\n"
 "     --pid <pid>                pid to check\n"
+"     --ppid <ppid>              parent pid to check\n"
 "  -p|--pidfile <pid-file>       pid file to check\n"
 "  -x|--exec <executable>        program to start/check if it is running\n"
 "  -n|--name <process-name>      process name to check\n"
@@ -806,6 +808,7 @@ set_action(enum action_code new_action)
 }
 
 #define OPT_PID		500
+#define OPT_PPID	501
 
 static void
 parse_options(int argc, char * const *argv)
@@ -820,6 +823,7 @@ parse_options(int argc, char * const *argv)
 		{ "name",	  1, NULL, 'n'},
 		{ "oknodo",	  0, NULL, 'o'},
 		{ "pid",	  1, NULL, OPT_PID},
+		{ "ppid",	  1, NULL, OPT_PPID},
 		{ "pidfile",	  1, NULL, 'p'},
 		{ "quiet",	  0, NULL, 'q'},
 		{ "signal",	  1, NULL, 's'},
@@ -842,6 +846,7 @@ parse_options(int argc, char * const *argv)
 		{ NULL,		  0, NULL, 0  }
 	};
 	const char *pid_str = NULL;
+	const char *ppid_str = NULL;
 	const char *umask_str = NULL;
 	const char *signal_str = NULL;
 	const char *schedule_str = NULL;
@@ -883,6 +888,9 @@ parse_options(int argc, char * const *argv)
 		case OPT_PID: /* --pid <pid> */
 			pid_str = optarg;
 			break;
+		case OPT_PPID: /* --ppid <ppid> */
+			ppid_str = optarg;
+			break;
 		case 'p':  /* --pidfile <pid-file> */
 			pidfile = optarg;
 			break;
@@ -955,6 +963,11 @@ parse_options(int argc, char * const *argv)
 			badusage("pid value must be a number greater than 0");
 	}
 
+	if (ppid_str != NULL) {
+		if (parse_pid(ppid_str, &match_ppid) != 0)
+			badusage("ppid value must be a number greater than 0");
+	}
+
 	if (signal_str != NULL) {
 		if (parse_signal(signal_str, &signal_nr) != 0)
 			badusage("signal value must be numeric or name"
@@ -979,8 +992,9 @@ parse_options(int argc, char * const *argv)
 	if (action == action_none)
 		badusage("need one of --start or --stop or --status");
 
-	if (!execname && !pid_str && !pidfile && !userspec && !cmdname)
-		badusage("need at least one of --exec, --pid, --pidfile, --user or --name");
+	if (!execname && !pid_str && !ppid_str && !pidfile && !userspec &&
+	    !cmdname)
+		badusage("need at least one of --exec, --pid, --ppid, --pidfile, --user or --name");
 
 #ifdef PROCESS_NAME_SIZE
 	if (cmdname && strlen(cmdname) > PROCESS_NAME_SIZE)
@@ -1273,6 +1287,79 @@ pid_is_exec(pid_t pid, const struct stat *esb)
 }
 #endif
 
+#if defined(OSLinux)
+static bool
+pid_is_child(pid_t pid, pid_t ppid)
+{
+	const char *ppid_str;
+	pid_t proc_ppid;
+	int rc;
+
+	ppid_str = proc_status_field(pid, "PPid:");
+	if (ppid_str == NULL)
+		return false;
+
+	rc = parse_pid(ppid_str, &proc_ppid);
+	if (rc < 0)
+		return false;
+
+	return proc_ppid == ppid;
+}
+#elif defined(OSHurd)
+static bool
+pid_is_child(pid_t pid, pid_t ppid)
+{
+	struct proc_stat *ps;
+	struct procinfo *pi;
+
+	ps = get_proc_stat(pid, PSTAT_PROC_INFO);
+	if (ps == NULL)
+		return false;
+
+	pi = proc_stat_proc_info(ps);
+
+	return pi->ppid == ppid;
+}
+#elif defined(OShpux)
+static bool
+pid_is_child(pid_t pid, pid_t ppid)
+{
+	struct pst_status pst;
+
+	if (pstat_getproc(&pst, sizeof(pst), (size_t)0, (int)pid) < 0)
+		return false;
+
+	return pst.pst_ppid == ppid;
+}
+#elif defined(HAVE_KVM_H)
+static bool
+pid_is_child(pid_t pid, pid_t ppid)
+{
+	kvm_t *kd;
+	int nentries;
+	struct kinfo_proc *kp;
+	char errbuf[_POSIX2_LINE_MAX];
+	pid_t proc_ppid;
+
+	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));
+
+#if defined(OSFreeBSD)
+	proc_ppid = kp->ki_ppid;
+#elif defined(OSOpenBSD)
+	proc_ppid = kp->p_ppid;
+#else
+	proc_ppid = kp->kp_proc.p_ppid;
+#endif
+
+	return proc_ppid == ppid;
+}
+#endif
+
 #if defined(OSLinux)
 static bool
 pid_is_user(pid_t pid, uid_t uid)
@@ -1444,6 +1531,8 @@ pid_check(pid_t pid)
 {
 	if (execname && !pid_is_exec(pid, &exec_stat))
 		return status_dead;
+	if (match_ppid > 0 && !pid_is_child(pid, match_ppid))
+		return status_dead;
 	if (userspec && !pid_is_user(pid, user_id))
 		return status_dead;
 	if (cmdname && !pid_is_cmd(pid, cmdname))