Explorar o código

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 %!s(int64=12) %!d(string=hai) anos
pai
achega
51e4a23b56
Modificáronse 2 ficheiros con 42 adicións e 17 borrados
  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
     Thanks to Christian Svensson <christian@cmd.nu>. Closes: #736717
   * Add support for FCFLAGS, OBJCFLAGS and OBJCXXFLAGS build flags.
   * Add support for FCFLAGS, OBJCFLAGS and OBJCXXFLAGS build flags.
     Closes: #744326
     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 ]
   [ Updated dpkg translations ]
   * German (Sven Joachim).
   * 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)
 #if defined(OSHurd)
 static void
 static void
 init_procset(void)
 init_procset(void)
@@ -1270,25 +1304,13 @@ pid_is_user(pid_t pid, uid_t uid)
 static bool
 static bool
 pid_is_cmd(pid_t pid, const char *name)
 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;
 		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)
 #elif defined(OSHurd)
 static bool
 static bool