[PATCH] pstree: New applet, v2

Tito farmatito at tiscali.it
Sat Nov 6 13:54:51 UTC 2010


On Saturday 06 November 2010 10:26:45 Lauri Kasanen wrote:
> Hi
> 
> v2:
> 
> - struct globals
> - removed unneeded if() from maybe_free_buffers
> - use xzalloc instead of xmalloc
> - properly indent out_args
> - xmalloc, sprintf -> xasprintf
> - write the guru ?:?:?: open
> 
> $ size procps/pstree.o
>    text    data     bss     dec     hex filename
>    3053       0       0    3053     bed procps/pstree.o
> 
> Sorry 'bout the indent, it wasn't my code in the first place ;)
> 
> - Lauri
> 


From 48368988a7699655c5f08b3017ff836945568eac Mon Sep 17 00:00:00 2001
From: Lauri Kasanen <curaga at operamail.com>
Date: Thu, 4 Nov 2010 10:29:41 +0200
Subject: [PATCH] pstree: New applet

v2:

- struct globals
- removed unneeded if() from maybe_free_buffers
- use xzalloc instead of xmalloc
- properly indent out_args
- xmalloc, sprintf -> xasprintf
- write the guru ?:?:?: open

Signed-off-by: Lauri Kasanen <curaga at operamail.com>
---
 procps/pstree.c |  496 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 496 insertions(+), 0 deletions(-)
 create mode 100644 procps/pstree.c

snip

+
+/*
+ * read_proc now uses a similar method as procps for finding the process
+ * name in the /proc filesystem. My thanks to Albert and procps authors.
+ */
+static void read_proc(void)
+{
+  DIR *dir;
+  struct dirent *de;
+  FILE *file;
+  struct stat st;
+  char *path, *comm;
+  char readbuf[BUFSIZ + 1];
+  char *tmpptr;
+  pid_t pid, ppid;
+  int size;
+  int empty;
+
+  dir = xopendir(PROC_BASE);
+  empty = 1;
+  while ((de = readdir(dir)) != NULL)
+       if ((pid = (pid_t) atoi(de->d_name)) != 0) {
+         path = xasprintf("%s/%d/stat", PROC_BASE, pid);
+         if ((file = fopen(path, "r")) != NULL) {
+               empty = 0;
+               sprintf(path, "%s/%d", PROC_BASE, pid);
+               xstat(path, &st);

What happens here if program with PID == pid  exits before we do xstat,
seems to me the program run is interrupted (maybe better goto free(path)
or  fclose(file) and ignore ? ) 

+               size = fread(readbuf, 1, BUFSIZ, file);
+               if (ferror(file) == 0) {
+                 readbuf[size] = 0;
+                 /* commands may have spaces or ) in them.
+                  * so don't trust anything from the ( to the last ) */
+                 if ((comm = strchr(readbuf, '('))
+                       && (tmpptr = strrchr(comm, ')'))) {
+                       ++comm;
+                       *tmpptr = 0;
+                       /* We now have readbuf with pid and cmd, and tmpptr+2
+                        * with the rest */
+                       if (sscanf(tmpptr + 2, "%*c %d", &ppid) == 1) {
+                         DIR *taskdir;
+                         struct dirent *dt;
+                         char *taskpath = NULL;
+                         char *threadname = NULL;
+                         int thread;
+
+                         taskpath = xasprintf("%s/task", path);
+
+                         if ((taskdir = opendir(taskpath)) != 0) {
+                               /* if we have this dir, we're on 2.6 */
+                               threadname = xasprintf("{%.*s}", COMM_LEN-2, comm);
+                               while ((dt = readdir(taskdir)) != NULL) {
+                                 if ((thread = atoi(dt->d_name)) != 0) {
+                                       if (thread != pid) {
+                                               add_proc(threadname, thread, pid, st.st_uid,
+                                                       1);
+                                       }
+                                 }
+                               }
+                               free(threadname);
+                               (void) closedir(taskdir);
+                         }
+                         free(taskpath);
+                         add_proc(comm, pid, ppid, st.st_uid, 0);
+                       }
+                 }
+               }
+               (void) fclose(file);
+         }
+         free(path);
+       }
+  (void) closedir(dir);
+  if (empty) {

bb_error_msg_and_die()

+       fprintf(stderr, "%s is empty (not mounted ?)\n", PROC_BASE);
+       exit(1);
+  }
+}
+
+
+int pstree_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int pstree_main(int argc, char **argv)
+{
+       struct winsize winsz;
+       pid_t pid = 1;
+       long uid = 0;
+
+       SET_PTR_TO_GLOBALS(xzalloc(sizeof(G)));
+
+       G.sym = (struct sym_t) { "  ", "|-", "| ", "`-", "---", "-+-"};
+       G.output_width = 132;
+       G.cur_x = 1;
+

We have get_terminal_width_height() in libbb

+       if (ioctl(1, TIOCGWINSZ, &winsz) >= 0)
+               if (winsz.ws_col)
+                       G.output_width = winsz.ws_col;
+
+       if (argc > 2) bb_show_usage();
+       else if (argc == 2) {
+               if (*argv[1] >= '0' && *argv[1] <= '9') {

IIRC we have xatoi in libbb. 

+                       if (!(pid = (pid_t) atoi(argv[1])))
+                               bb_show_usage();
+               } else {
+                       uid = xuname2uid(argv[1]);
+               }
+       }
+
+       read_proc();
+       if (!uid)
+               dump_tree(find_proc(pid), 0, 1, 1, 1, 0);
+       else {
+               dump_by_user(find_proc(1), uid);
+               if (!G.dumped) {

bb_error_msg_and_die()

+                       fprintf(stderr, "No processes found.\n");
+                       return 1;
+               }
+       }
+       maybe_free_buffers();
+
+       return 0;
+}
-- 
1.7.2.1

Hi,
just my 0,2 cents.

Ciao,
Tito


More information about the busybox mailing list