Magellan Linux

Diff of /trunk/mkinitrd-magellan/busybox/libbb/procps.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 816 by niro, Fri Apr 24 18:33:46 2009 UTC revision 984 by niro, Sun May 30 11:32:42 2010 UTC
# Line 13  Line 13 
13    
14    
15  typedef struct unsigned_to_name_map_t {  typedef struct unsigned_to_name_map_t {
16   unsigned id;   long id;
17   char name[USERNAME_MAX_SIZE];   char name[USERNAME_MAX_SIZE];
18  } unsigned_to_name_map_t;  } unsigned_to_name_map_t;
19    
# Line 52  static int get_cached(cache_t *cp, unsig Line 52  static int get_cached(cache_t *cp, unsig
52  }  }
53  #endif  #endif
54    
55  typedef char* FAST_FUNC ug_func(char *name, int bufsize, long uid);  static char* get_cached(cache_t *cp, long id,
56  static char* get_cached(cache_t *cp, unsigned id, ug_func* fp)   char* FAST_FUNC x2x_utoa(long id))
57  {  {
58   int i;   int i;
59   for (i = 0; i < cp->size; i++)   for (i = 0; i < cp->size; i++)
# Line 63  static char* get_cached(cache_t *cp, uns Line 63  static char* get_cached(cache_t *cp, uns
63   cp->cache = xrealloc_vector(cp->cache, 2, i);   cp->cache = xrealloc_vector(cp->cache, 2, i);
64   cp->cache[i].id = id;   cp->cache[i].id = id;
65   /* Never fails. Generates numeric string if name isn't found */   /* Never fails. Generates numeric string if name isn't found */
66   fp(cp->cache[i].name, sizeof(cp->cache[i].name), id);   safe_strncpy(cp->cache[i].name, x2x_utoa(id), sizeof(cp->cache[i].name));
67   return cp->cache[i].name;   return cp->cache[i].name;
68  }  }
69  const char* FAST_FUNC get_cached_username(uid_t uid)  const char* FAST_FUNC get_cached_username(uid_t uid)
70  {  {
71   return get_cached(&username, uid, bb_getpwuid);   return get_cached(&username, uid, uid2uname_utoa);
72  }  }
73  const char* FAST_FUNC get_cached_groupname(gid_t gid)  const char* FAST_FUNC get_cached_groupname(gid_t gid)
74  {  {
75   return get_cached(&groupname, gid, bb_getgrgid);   return get_cached(&groupname, gid, gid2group_utoa);
76  }  }
77    
78    
# Line 110  static procps_status_t* FAST_FUNC alloc_ Line 110  static procps_status_t* FAST_FUNC alloc_
110  void FAST_FUNC free_procps_scan(procps_status_t* sp)  void FAST_FUNC free_procps_scan(procps_status_t* sp)
111  {  {
112   closedir(sp->dir);   closedir(sp->dir);
113    #if ENABLE_FEATURE_SHOW_THREADS
114     if (sp->task_dir)
115     closedir(sp->task_dir);
116    #endif
117   free(sp->argv0);   free(sp->argv0);
118   USE_SELINUX(free(sp->context);)   free(sp->exe);
119     IF_SELINUX(free(sp->context);)
120   free(sp);   free(sp);
121  }  }
122    
# Line 133  static unsigned long fast_strtoul_16(cha Line 138  static unsigned long fast_strtoul_16(cha
138   return n;   return n;
139  }  }
140  /* TOPMEM uses fast_strtoul_10, so... */  /* TOPMEM uses fast_strtoul_10, so... */
141  #undef ENABLE_FEATURE_FAST_TOP  # undef ENABLE_FEATURE_FAST_TOP
142  #define ENABLE_FEATURE_FAST_TOP 1  # define ENABLE_FEATURE_FAST_TOP 1
143  #endif  #endif
144    
145  #if ENABLE_FEATURE_FAST_TOP  #if ENABLE_FEATURE_FAST_TOP
# Line 151  static unsigned long fast_strtoul_10(cha Line 156  static unsigned long fast_strtoul_10(cha
156   *endptr = str + 1; /* We skip trailing space! */   *endptr = str + 1; /* We skip trailing space! */
157   return n;   return n;
158  }  }
159    
160    static long fast_strtol_10(char **endptr)
161    {
162     if (**endptr != '-')
163     return fast_strtoul_10(endptr);
164    
165     (*endptr)++;
166     return - (long)fast_strtoul_10(endptr);
167    }
168    
169  static char *skip_fields(char *str, int count)  static char *skip_fields(char *str, int count)
170  {  {
171   do {   do {
# Line 178  procps_status_t* FAST_FUNC procps_scan(p Line 193  procps_status_t* FAST_FUNC procps_scan(p
193   sp = alloc_procps_scan();   sp = alloc_procps_scan();
194    
195   for (;;) {   for (;;) {
196    #if ENABLE_FEATURE_SHOW_THREADS
197     if ((flags & PSSCAN_TASKS) && sp->task_dir) {
198     entry = readdir(sp->task_dir);
199     if (entry)
200     goto got_entry;
201     closedir(sp->task_dir);
202     sp->task_dir = NULL;
203     }
204    #endif
205   entry = readdir(sp->dir);   entry = readdir(sp->dir);
206   if (entry == NULL) {   if (entry == NULL) {
207   free_procps_scan(sp);   free_procps_scan(sp);
208   return NULL;   return NULL;
209   }   }
210     IF_FEATURE_SHOW_THREADS(got_entry:)
211   pid = bb_strtou(entry->d_name, NULL, 10);   pid = bb_strtou(entry->d_name, NULL, 10);
212   if (errno)   if (errno)
213   continue;   continue;
214    #if ENABLE_FEATURE_SHOW_THREADS
215     if ((flags & PSSCAN_TASKS) && !sp->task_dir) {
216     /* We found another /proc/PID. Do not use it,
217     * there will be /proc/PID/task/PID (same PID!),
218     * so just go ahead and dive into /proc/PID/task. */
219     char task_dir[sizeof("/proc/%u/task") + sizeof(int)*3];
220     sprintf(task_dir, "/proc/%u/task", pid);
221     sp->task_dir = xopendir(task_dir);
222     continue;
223     }
224    #endif
225    
226   /* After this point we have to break, not continue   /* After this point we can:
227   * ("continue" would mean that current /proc/NNN   * "break": stop parsing, return the data
228   * is not a valid process info) */   * "continue": try next /proc/XXX
229     */
230    
231   memset(&sp->vsz, 0, sizeof(*sp) - offsetof(procps_status_t, vsz));   memset(&sp->vsz, 0, sizeof(*sp) - offsetof(procps_status_t, vsz));
232    
233   sp->pid = pid;   sp->pid = pid;
234   if (!(flags & ~PSSCAN_PID)) break;   if (!(flags & ~PSSCAN_PID))
235     break; /* we needed only pid, we got it */
236    
237  #if ENABLE_SELINUX  #if ENABLE_SELINUX
238   if (flags & PSSCAN_CONTEXT) {   if (flags & PSSCAN_CONTEXT) {
# Line 203  procps_status_t* FAST_FUNC procps_scan(p Line 241  procps_status_t* FAST_FUNC procps_scan(p
241   }   }
242  #endif  #endif
243    
244   filename_tail = filename + sprintf(filename, "/proc/%d", pid);   filename_tail = filename + sprintf(filename, "/proc/%u/", pid);
245    
246   if (flags & PSSCAN_UIDGID) {   if (flags & PSSCAN_UIDGID) {
247   if (stat(filename, &sb))   if (stat(filename, &sb))
248   break;   continue; /* process probably exited */
249   /* Need comment - is this effective or real UID/GID? */   /* Effective UID/GID, not real */
250   sp->uid = sb.st_uid;   sp->uid = sb.st_uid;
251   sp->gid = sb.st_gid;   sp->gid = sb.st_gid;
252   }   }
# Line 220  procps_status_t* FAST_FUNC procps_scan(p Line 258  procps_status_t* FAST_FUNC procps_scan(p
258   unsigned long vsz, rss;   unsigned long vsz, rss;
259  #endif  #endif
260   /* see proc(5) for some details on this */   /* see proc(5) for some details on this */
261   strcpy(filename_tail, "/stat");   strcpy(filename_tail, "stat");
262   n = read_to_buf(filename, buf);   n = read_to_buf(filename, buf);
263   if (n < 0)   if (n < 0)
264   break;   continue; /* process probably exited */
265   cp = strrchr(buf, ')'); /* split into "PID (cmd" and "<rest>" */   cp = strrchr(buf, ')'); /* split into "PID (cmd" and "<rest>" */
266   /*if (!cp || cp[1] != ' ')   /*if (!cp || cp[1] != ' ')
267   break;*/   continue;*/
268   cp[0] = '\0';   cp[0] = '\0';
269   if (sizeof(sp->comm) < 16)   if (sizeof(sp->comm) < 16)
270   BUG_comm_size();   BUG_comm_size();
# Line 246  procps_status_t* FAST_FUNC procps_scan(p Line 284  procps_status_t* FAST_FUNC procps_scan(p
284   "%lu "                 /* start_time */   "%lu "                 /* start_time */
285   "%lu "                 /* vsize */   "%lu "                 /* vsize */
286   "%lu "                 /* rss */   "%lu "                 /* rss */
287  #if ENABLE_FEATURE_TOP_SMP_PROCESS  # if ENABLE_FEATURE_TOP_SMP_PROCESS
288   "%*s %*s %*s %*s %*s %*s " /*rss_rlim, start_code, end_code, start_stack, kstk_esp, kstk_eip */   "%*s %*s %*s %*s %*s %*s " /*rss_rlim, start_code, end_code, start_stack, kstk_esp, kstk_eip */
289   "%*s %*s %*s %*s "         /*signal, blocked, sigignore, sigcatch */   "%*s %*s %*s %*s "         /*signal, blocked, sigignore, sigcatch */
290   "%*s %*s %*s %*s "         /*wchan, nswap, cnswap, exit_signal */   "%*s %*s %*s %*s "         /*wchan, nswap, cnswap, exit_signal */
291   "%d"                       /*cpu last seen on*/   "%d"                       /*cpu last seen on*/
292  #endif  # endif
293   ,   ,
294   sp->state, &sp->ppid,   sp->state, &sp->ppid,
295   &sp->pgid, &sp->sid, &tty,   &sp->pgid, &sp->sid, &tty,
# Line 260  procps_status_t* FAST_FUNC procps_scan(p Line 298  procps_status_t* FAST_FUNC procps_scan(p
298   &sp->start_time,   &sp->start_time,
299   &vsz,   &vsz,
300   &rss   &rss
301  #if ENABLE_FEATURE_TOP_SMP_PROCESS  # if ENABLE_FEATURE_TOP_SMP_PROCESS
302   , &sp->last_seen_on_cpu   , &sp->last_seen_on_cpu
303  #endif  # endif
304   );   );
305    
306   if (n < 11)   if (n < 11)
307   break;   continue; /* bogus data, get next /proc/XXX */
308  #if ENABLE_FEATURE_TOP_SMP_PROCESS  # if ENABLE_FEATURE_TOP_SMP_PROCESS
309   if (n < 11+15)   if (n < 11+15)
310   sp->last_seen_on_cpu = 0;   sp->last_seen_on_cpu = 0;
311  #endif  # endif
312    
313   /* vsz is in bytes and we want kb */   /* vsz is in bytes and we want kb */
314   sp->vsz = vsz >> 10;   sp->vsz = vsz >> 10;
# Line 293  procps_status_t* FAST_FUNC procps_scan(p Line 331  procps_status_t* FAST_FUNC procps_scan(p
331   sp->utime = fast_strtoul_10(&cp);   sp->utime = fast_strtoul_10(&cp);
332   sp->stime = fast_strtoul_10(&cp);   sp->stime = fast_strtoul_10(&cp);
333   cp = skip_fields(cp, 3); /* cutime, cstime, priority */   cp = skip_fields(cp, 3); /* cutime, cstime, priority */
334   tasknice = fast_strtoul_10(&cp);   tasknice = fast_strtol_10(&cp);
335   cp = skip_fields(cp, 2); /* timeout, it_real_value */   cp = skip_fields(cp, 2); /* timeout, it_real_value */
336   sp->start_time = fast_strtoul_10(&cp);   sp->start_time = fast_strtoul_10(&cp);
337   /* vsz is in bytes and we want kb */   /* vsz is in bytes and we want kb */
338   sp->vsz = fast_strtoul_10(&cp) >> 10;   sp->vsz = fast_strtoul_10(&cp) >> 10;
339   /* vsz is in bytes but rss is in *PAGES*! Can you believe that? */   /* vsz is in bytes but rss is in *PAGES*! Can you believe that? */
340   sp->rss = fast_strtoul_10(&cp) << sp->shift_pages_to_kb;   sp->rss = fast_strtoul_10(&cp) << sp->shift_pages_to_kb;
341  #if ENABLE_FEATURE_TOP_SMP_PROCESS  # if ENABLE_FEATURE_TOP_SMP_PROCESS
342   /* (6): rss_rlim, start_code, end_code, start_stack, kstk_esp, kstk_eip */   /* (6): rss_rlim, start_code, end_code, start_stack, kstk_esp, kstk_eip */
343   /* (4): signal, blocked, sigignore, sigcatch */   /* (4): signal, blocked, sigignore, sigcatch */
344   /* (4): wchan, nswap, cnswap, exit_signal */   /* (4): wchan, nswap, cnswap, exit_signal */
345   cp = skip_fields(cp, 14);   cp = skip_fields(cp, 14);
346  //FIXME: is it safe to assume this field exists?  //FIXME: is it safe to assume this field exists?
347   sp->last_seen_on_cpu = fast_strtoul_10(&cp);   sp->last_seen_on_cpu = fast_strtoul_10(&cp);
348  #endif  # endif
349  #endif /* end of !ENABLE_FEATURE_TOP_SMP_PROCESS */  #endif /* end of !ENABLE_FEATURE_TOP_SMP_PROCESS */
350    
351    #if ENABLE_FEATURE_PS_ADDITIONAL_COLUMNS
352     sp->niceness = tasknice;
353    #endif
354    
355   if (sp->vsz == 0 && sp->state[0] != 'Z')   if (sp->vsz == 0 && sp->state[0] != 'Z')
356   sp->state[1] = 'W';   sp->state[1] = 'W';
357   else   else
# Line 326  procps_status_t* FAST_FUNC procps_scan(p Line 368  procps_status_t* FAST_FUNC procps_scan(p
368   if (flags & (PSSCAN_SMAPS)) {   if (flags & (PSSCAN_SMAPS)) {
369   FILE *file;   FILE *file;
370    
371   strcpy(filename_tail, "/smaps");   strcpy(filename_tail, "smaps");
372   file = fopen_for_read(filename);   file = fopen_for_read(filename);
373   if (!file)   if (file) {
374   break;   while (fgets(buf, sizeof(buf), file)) {
375   while (fgets(buf, sizeof(buf), file)) {   unsigned long sz;
376   unsigned long sz;   char *tp;
377   char *tp;   char w;
  char w;  
378  #define SCAN(str, name) \  #define SCAN(str, name) \
379   if (strncmp(buf, str, sizeof(str)-1) == 0) { \   if (strncmp(buf, str, sizeof(str)-1) == 0) { \
380   tp = skip_whitespace(buf + sizeof(str)-1); \   tp = skip_whitespace(buf + sizeof(str)-1); \
381   sp->name += fast_strtoul_10(&tp); \   sp->name += fast_strtoul_10(&tp); \
382   continue; \   continue; \
383   }   }
384   SCAN("Shared_Clean:" , shared_clean );   SCAN("Shared_Clean:" , shared_clean );
385   SCAN("Shared_Dirty:" , shared_dirty );   SCAN("Shared_Dirty:" , shared_dirty );
386   SCAN("Private_Clean:", private_clean);   SCAN("Private_Clean:", private_clean);
387   SCAN("Private_Dirty:", private_dirty);   SCAN("Private_Dirty:", private_dirty);
388  #undef SCAN  #undef SCAN
389   // f7d29000-f7d39000 rw-s ADR M:m OFS FILE   // f7d29000-f7d39000 rw-s ADR M:m OFS FILE
390   tp = strchr(buf, '-');   tp = strchr(buf, '-');
391   if (tp) {   if (tp) {
392   *tp = ' ';   *tp = ' ';
393   tp = buf;   tp = buf;
394   sz = fast_strtoul_16(&tp); /* start */   sz = fast_strtoul_16(&tp); /* start */
395   sz = (fast_strtoul_16(&tp) - sz) >> 10; /* end - start */   sz = (fast_strtoul_16(&tp) - sz) >> 10; /* end - start */
396   // tp -> "rw-s" string   // tp -> "rw-s" string
397   w = tp[1];   w = tp[1];
398   // skipping "rw-s ADR M:m OFS "   // skipping "rw-s ADR M:m OFS "
399   tp = skip_whitespace(skip_fields(tp, 4));   tp = skip_whitespace(skip_fields(tp, 4));
400   // filter out /dev/something (something != zero)   // filter out /dev/something (something != zero)
401   if (strncmp(tp, "/dev/", 5) != 0 || strcmp(tp, "/dev/zero\n") == 0) {   if (strncmp(tp, "/dev/", 5) != 0 || strcmp(tp, "/dev/zero\n") == 0) {
402   if (w == 'w') {   if (w == 'w') {
403   sp->mapped_rw += sz;   sp->mapped_rw += sz;
404   } else if (w == '-') {   } else if (w == '-') {
405   sp->mapped_ro += sz;   sp->mapped_ro += sz;
406     }
407   }   }
  }  
408  //else printf("DROPPING %s (%s)\n", buf, tp);  //else printf("DROPPING %s (%s)\n", buf, tp);
409   if (strcmp(tp, "[stack]\n") == 0)   if (strcmp(tp, "[stack]\n") == 0)
410   sp->stack += sz;   sp->stack += sz;
411     }
412   }   }
413     fclose(file);
414   }   }
  fclose(file);  
415   }   }
416  #endif /* TOPMEM */  #endif /* TOPMEM */
417    #if ENABLE_FEATURE_PS_ADDITIONAL_COLUMNS
418     if (flags & PSSCAN_RUIDGID) {
419     FILE *file;
420    
421     strcpy(filename_tail, "status");
422     file = fopen_for_read(filename);
423     if (file) {
424     while (fgets(buf, sizeof(buf), file)) {
425     char *tp;
426    #define SCAN_TWO(str, name, statement) \
427     if (strncmp(buf, str, sizeof(str)-1) == 0) { \
428     tp = skip_whitespace(buf + sizeof(str)-1); \
429     sscanf(tp, "%u", &sp->name); \
430     statement; \
431     }
432     SCAN_TWO("Uid:", ruid, continue);
433     SCAN_TWO("Gid:", rgid, break);
434    #undef SCAN_TWO
435     }
436     fclose(file);
437     }
438     }
439    #endif /* PS_ADDITIONAL_COLUMNS */
440     if (flags & PSSCAN_EXE) {
441     strcpy(filename_tail, "exe");
442     free(sp->exe);
443     sp->exe = xmalloc_readlink(filename);
444     }
445     /* Note: if /proc/PID/cmdline is empty,
446     * code below "breaks". Therefore it must be
447     * the last code to parse /proc/PID/xxx data
448     * (we used to have /proc/PID/exe parsing after it
449     * and were getting stale sp->exe).
450     */
451  #if 0 /* PSSCAN_CMD is not used */  #if 0 /* PSSCAN_CMD is not used */
452   if (flags & (PSSCAN_CMD|PSSCAN_ARGV0)) {   if (flags & (PSSCAN_CMD|PSSCAN_ARGV0)) {
453   free(sp->argv0);   free(sp->argv0);
454   sp->argv0 = NULL;   sp->argv0 = NULL;
455   free(sp->cmd);   free(sp->cmd);
456   sp->cmd = NULL;   sp->cmd = NULL;
457   strcpy(filename_tail, "/cmdline");   strcpy(filename_tail, "cmdline");
458   /* TODO: to get rid of size limits, read into malloc buf,   /* TODO: to get rid of size limits, read into malloc buf,
459   * then realloc it down to real size. */   * then realloc it down to real size. */
460   n = read_to_buf(filename, buf);   n = read_to_buf(filename, buf);
# Line 400  procps_status_t* FAST_FUNC procps_scan(p Line 475  procps_status_t* FAST_FUNC procps_scan(p
475   if (flags & (PSSCAN_ARGV0|PSSCAN_ARGVN)) {   if (flags & (PSSCAN_ARGV0|PSSCAN_ARGVN)) {
476   free(sp->argv0);   free(sp->argv0);
477   sp->argv0 = NULL;   sp->argv0 = NULL;
478   strcpy(filename_tail, "/cmdline");   strcpy(filename_tail, "cmdline");
479   n = read_to_buf(filename, buf);   n = read_to_buf(filename, buf);
480   if (n <= 0)   if (n <= 0)
481   break;   break;
# Line 416  procps_status_t* FAST_FUNC procps_scan(p Line 491  procps_status_t* FAST_FUNC procps_scan(p
491   }   }
492  #endif  #endif
493   break;   break;
494   }   } /* for (;;) */
495    
496   return sp;   return sp;
497  }  }
498    
499  void FAST_FUNC read_cmdline(char *buf, int col, unsigned pid, const char *comm)  void FAST_FUNC read_cmdline(char *buf, int col, unsigned pid, const char *comm)
500  {  {
501   ssize_t sz;   int sz;
502   char filename[sizeof("/proc//cmdline") + sizeof(int)*3];   char filename[sizeof("/proc//cmdline") + sizeof(int)*3];
503    
504   sprintf(filename, "/proc/%u/cmdline", pid);   sprintf(filename, "/proc/%u/cmdline", pid);
505   sz = open_read_close(filename, buf, col);   sz = open_read_close(filename, buf, col - 1);
506   if (sz > 0) {   if (sz > 0) {
507   buf[sz] = '\0';   buf[sz] = '\0';
508   while (--sz >= 0)   while (--sz >= 0 && buf[sz] == '\0')
509     continue;
510     do {
511   if ((unsigned char)(buf[sz]) < ' ')   if ((unsigned char)(buf[sz]) < ' ')
512   buf[sz] = ' ';   buf[sz] = ' ';
513     } while (--sz >= 0);
514   } else {   } else {
515   snprintf(buf, col, "[%s]", comm);   snprintf(buf, col, "[%s]", comm);
516   }   }

Legend:
Removed from v.816  
changed lines
  Added in v.984