Skip to content

Commit 4d79d84

Browse files
committed
Fix #438: refactor initctl ps/top to handle loooooong command lines
Signed-off-by: Joachim Wiberg <[email protected]>
1 parent d318aa0 commit 4d79d84

File tree

2 files changed

+38
-23
lines changed

2 files changed

+38
-23
lines changed

src/cgutil.c

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -58,34 +58,47 @@ int cgroup_avail(void)
5858
return fismnt(FINIT_CGPATH);
5959
}
6060

61-
char *pid_cmdline(int pid, char *buf, size_t len)
61+
static size_t flen(FILE *fp)
6262
{
63-
size_t i, sz;
64-
char *ptr;
63+
size_t total = 0, sz;
64+
char buf[512];
65+
66+
while ((sz = fread(buf, 1, sizeof(buf), fp)) > 0)
67+
total += sz;
68+
rewind(fp);
69+
70+
return total;
71+
}
72+
73+
char *pid_cmdline(int pid)
74+
{
75+
size_t i, len;
76+
char *buf;
6577
FILE *fp;
6678

6779
fp = fopenf("r", "/proc/%d/cmdline", pid);
68-
if (!fp) {
69-
buf[0] = 0;
70-
return buf;
71-
}
80+
if (!fp)
81+
return strdup(""); /* regular process */
7282

73-
sz = fread(buf, sizeof(buf[0]), len - 1, fp);
74-
fclose(fp);
75-
if (!sz)
83+
len = flen(fp);
84+
if (len == 0) {
85+
fail:
86+
fclose(fp);
7687
return NULL; /* kernel thread */
88+
}
7789

78-
buf[sz] = 0;
90+
buf = calloc(len + 1, 1);
91+
if (!buf)
92+
goto fail;
7993

80-
ptr = strchr(buf, 0);
81-
if (ptr && ptr != buf) {
82-
ptr++;
83-
sz -= ptr - buf;
84-
memmove(buf, ptr, sz + 1);
94+
if (fread(buf, 1, len, fp) < len) {
95+
free(buf);
96+
goto fail;
8597
}
8698

87-
for (i = 0; i < sz; i++) {
88-
if (buf[i] == 0)
99+
/* replace all NUL chars with space */
100+
for (i = 0; i < len; i++) {
101+
if (buf[i] == '\0')
89102
buf[i] = ' ';
90103
}
91104

@@ -423,16 +436,16 @@ int cgroup_tree(char *path, char *pfx, int mode, int pos)
423436

424437
i = 0;
425438
while (fgets(buf, sizeof(buf), fp)) {
426-
char comm[80] = { 0 };
439+
char *cmdline;
427440
pid_t pid;
428441

429442
pid = atoi(chomp(buf));
430443
if (pid <= 0)
431444
continue;
432445

433446
/* skip kernel threads for now (no cmdline) */
434-
pid_comm(pid, comm, sizeof(comm));
435-
if (pid_cmdline(pid, buf, sizeof(buf))) {
447+
cmdline = pid_cmdline(pid);
448+
if (cmdline) {
436449
char proc[ttcols];
437450

438451
switch (mode) {
@@ -450,7 +463,7 @@ int cgroup_tree(char *path, char *pfx, int mode, int pos)
450463
strlcat(row, pfx, rplen);
451464
strlcat(row, ++i == num ? END : FORK, rlen);
452465

453-
snprintf(proc, sizeof(proc), " %d %s %s", pid, comm, buf);
466+
snprintf(proc, sizeof(proc), " %d %s", pid, cmdline);
454467

455468
if (plain) {
456469
strlcat(row, proc, rplen);
@@ -468,6 +481,8 @@ int cgroup_tree(char *path, char *pfx, int mode, int pos)
468481
}
469482

470483
puts(row);
484+
485+
free(cmdline);
471486
}
472487

473488
if (mode == 1) {

src/cgutil.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ struct cg {
5454

5555
int cgroup_avail(void);
5656

57-
char *pid_cmdline (int pid, char *buf, size_t len);
57+
char *pid_cmdline (int pid);
5858
char *pid_comm (int pid, char *buf, size_t len);
5959
char *pid_cgroup (int pid, char *buf, size_t len);
6060

0 commit comments

Comments
 (0)