Bläddra i källkod

s-s-d: Refactor Linux comm retrieval and switch to use /proc/PID/status

This trades parsing ambiguities due to process names with ‘)’ for ones
with embedded ‘\n’. But it should be more robust and future proof in
general, and allows to retrieve any field by name, which makes the code
more clear and reusable.
Guillem Jover 12 år sedan
förälder
incheckning
51e4a23b56
2 ändrade filer med 42 tillägg och 17 borttagningar
  1. 3 0
      debian/changelog
  2. 39 17
      utils/start-stop-daemon.c

+ 3 - 0
debian/changelog

@@ -51,6 +51,9 @@ dpkg (1.17.7) UNRELEASED; urgency=low
     Thanks to Christian Svensson <christian@cmd.nu>. Closes: #736717
   * Add support for FCFLAGS, OBJCFLAGS and OBJCXXFLAGS build flags.
     Closes: #744326
+  * Improvements and portability fixes to start-stop-daemon:
+    - When using the Linux procfs switch to use /proc/PID/status instead of
+      /proc/PID/stat to read the process name.
 
   [ Updated dpkg translations ]
   * German (Sven Joachim).

+ 39 - 17
utils/start-stop-daemon.c

@@ -1068,6 +1068,40 @@ setup_options(void)
 	}
 }
 
+#if defined(OSLinux)
+static const char *
+proc_status_field(pid_t pid, const char *field)
+{
+	static char *line = NULL;
+	static size_t line_size = 0;
+
+	FILE *fp;
+	char filename[32];
+	char *value = NULL;
+	ssize_t line_len;
+	size_t field_len = strlen(field);
+
+	sprintf(filename, "/proc/%d/status", pid);
+	fp = fopen(filename, "r");
+	if (!fp)
+		return NULL;
+	while ((line_len = getline(&line, &line_size, fp)) >= 0) {
+		if (strncasecmp(line, field, field_len) == 0) {
+			line[line_len - 1] = '\0';
+
+			value = line + field_len;
+			while (isspace(*value))
+				value++;
+
+			break;
+		}
+	}
+	fclose(fp);
+
+	return value;
+}
+#endif
+
 #if defined(OSHurd)
 static void
 init_procset(void)
@@ -1270,25 +1304,13 @@ pid_is_user(pid_t pid, uid_t uid)
 static bool
 pid_is_cmd(pid_t pid, const char *name)
 {
-	char buf[32];
-	FILE *f;
-	int c;
+	const char *comm;
 
-	sprintf(buf, "/proc/%d/stat", pid);
-	f = fopen(buf, "r");
-	if (!f)
-		return false;
-	while ((c = getc(f)) != EOF && c != '(')
-		;
-	if (c != '(') {
-		fclose(f);
+	comm = proc_status_field(pid, "Name:");
+	if (comm == NULL)
 		return false;
-	}
-	/* This hopefully handles command names containing ‘)’. */
-	while ((c = getc(f)) != EOF && c == *name)
-		name++;
-	fclose(f);
-	return (c == ')' && *name == '\0');
+
+	return strcmp(comm, name) == 0;
 }
 #elif defined(OSHurd)
 static bool