Magellan Linux

Annotation of /tags/mkinitrd-6_1_12/busybox/libbb/procps.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 532 - (hide annotations) (download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 9 months ago) by niro
Original Path: trunk/mkinitrd-magellan/busybox/libbb/procps.c
File MIME type: text/plain
File size: 5728 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd

1 niro 532 /* vi: set sw=4 ts=4: */
2     /*
3     * Utility routines.
4     *
5     * Copyright 1998 by Albert Cahalan; all rights reserved.
6     * Copyright (C) 2002 by Vladimir Oleynik <dzo@simtreas.ru>
7     *
8     * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
9     */
10    
11     #include "libbb.h"
12    
13    
14     typedef struct unsigned_to_name_map_t {
15     unsigned id;
16     char name[USERNAME_MAX_SIZE];
17     } unsigned_to_name_map_t;
18    
19     typedef struct cache_t {
20     unsigned_to_name_map_t *cache;
21     int size;
22     } cache_t;
23    
24     static cache_t username, groupname;
25    
26     static void clear_cache(cache_t *cp)
27     {
28     free(cp->cache);
29     cp->cache = NULL;
30     cp->size = 0;
31     }
32     void clear_username_cache(void)
33     {
34     clear_cache(&username);
35     clear_cache(&groupname);
36     }
37    
38     #if 0 /* more generic, but we don't need that yet */
39     /* Returns -N-1 if not found. */
40     /* cp->cache[N] is allocated and must be filled in this case */
41     static int get_cached(cache_t *cp, unsigned id)
42     {
43     int i;
44     for (i = 0; i < cp->size; i++)
45     if (cp->cache[i].id == id)
46     return i;
47     i = cp->size++;
48     cp->cache = xrealloc(cp->cache, cp->size * sizeof(*cp->cache));
49     cp->cache[i++].id = id;
50     return -i;
51     }
52     #endif
53    
54     typedef char* ug_func(char *name, long uid, int bufsize);
55     static char* get_cached(cache_t *cp, unsigned id, ug_func* fp)
56     {
57     int i;
58     for (i = 0; i < cp->size; i++)
59     if (cp->cache[i].id == id)
60     return cp->cache[i].name;
61     i = cp->size++;
62     cp->cache = xrealloc(cp->cache, cp->size * sizeof(*cp->cache));
63     cp->cache[i].id = id;
64     fp(cp->cache[i].name, id, sizeof(cp->cache[i].name));
65     return cp->cache[i].name;
66     }
67     const char* get_cached_username(uid_t uid)
68     {
69     return get_cached(&username, uid, bb_getpwuid);
70     }
71     const char* get_cached_groupname(gid_t gid)
72     {
73     return get_cached(&groupname, gid, bb_getgrgid);
74     }
75    
76    
77     #define PROCPS_BUFSIZE 1024
78    
79     static int read_to_buf(const char *filename, void *buf)
80     {
81     ssize_t ret;
82     ret = open_read_close(filename, buf, PROCPS_BUFSIZE-1);
83     ((char *)buf)[ret > 0 ? ret : 0] = '\0';
84     return ret;
85     }
86    
87     procps_status_t* alloc_procps_scan(int flags)
88     {
89     procps_status_t* sp = xzalloc(sizeof(procps_status_t));
90     sp->dir = xopendir("/proc");
91     return sp;
92     }
93    
94     void free_procps_scan(procps_status_t* sp)
95     {
96     closedir(sp->dir);
97     free(sp->cmd);
98     free(sp);
99     }
100    
101     void BUG_comm_size(void);
102     procps_status_t* procps_scan(procps_status_t* sp, int flags)
103     {
104     struct dirent *entry;
105     char buf[PROCPS_BUFSIZE];
106     char filename[sizeof("/proc//cmdline") + sizeof(int)*3];
107     char *filename_tail;
108     long tasknice;
109     unsigned pid;
110     int n;
111     struct stat sb;
112    
113     if (!sp)
114     sp = alloc_procps_scan(flags);
115    
116     for (;;) {
117     entry = readdir(sp->dir);
118     if (entry == NULL) {
119     free_procps_scan(sp);
120     return NULL;
121     }
122     pid = bb_strtou(entry->d_name, NULL, 10);
123     if (errno)
124     continue;
125    
126     /* After this point we have to break, not continue
127     * ("continue" would mean that current /proc/NNN
128     * is not a valid process info) */
129    
130     memset(&sp->rss, 0, sizeof(*sp) - offsetof(procps_status_t, rss));
131    
132     sp->pid = pid;
133     if (!(flags & ~PSSCAN_PID)) break;
134    
135     filename_tail = filename + sprintf(filename, "/proc/%d", pid);
136    
137     if (flags & PSSCAN_UIDGID) {
138     if (stat(filename, &sb))
139     break;
140     /* Need comment - is this effective or real UID/GID? */
141     sp->uid = sb.st_uid;
142     sp->gid = sb.st_gid;
143     }
144    
145     if (flags & PSSCAN_STAT) {
146     char *cp;
147     /* see proc(5) for some details on this */
148     strcpy(filename_tail, "/stat");
149     n = read_to_buf(filename, buf);
150     if (n < 0)
151     break;
152     cp = strrchr(buf, ')'); /* split into "PID (cmd" and "<rest>" */
153     if (!cp || cp[1] != ' ')
154     break;
155     cp[0] = '\0';
156     if (sizeof(sp->comm) < 16)
157     BUG_comm_size();
158     sscanf(buf, "%*s (%15c", sp->comm);
159     n = sscanf(cp+2,
160     "%c %u " /* state, ppid */
161     "%u %u %*s %*s " /* pgid, sid, tty, tpgid */
162     "%*s %*s %*s %*s %*s " /* flags, min_flt, cmin_flt, maj_flt, cmaj_flt */
163     "%lu %lu " /* utime, stime */
164     "%*s %*s %*s " /* cutime, cstime, priority */
165     "%ld " /* nice */
166     "%*s %*s %*s " /* timeout, it_real_value, start_time */
167     "%*s " /* vsize */
168     "%lu", /* rss */
169     sp->state, &sp->ppid,
170     &sp->pgid, &sp->sid,
171     &sp->utime, &sp->stime,
172     &tasknice,
173     &sp->rss);
174     if (n != 8)
175     break;
176    
177     if (sp->rss == 0 && sp->state[0] != 'Z')
178     sp->state[1] = 'W';
179     else
180     sp->state[1] = ' ';
181     if (tasknice < 0)
182     sp->state[2] = '<';
183     else if (tasknice > 0)
184     sp->state[2] = 'N';
185     else
186     sp->state[2] = ' ';
187    
188     #ifdef PAGE_SHIFT
189     sp->rss <<= (PAGE_SHIFT - 10); /* 2**10 = 1kb */
190     #else
191     sp->rss *= (getpagesize() >> 10); /* 2**10 = 1kb */
192     #endif
193     }
194    
195     if (flags & PSSCAN_CMD) {
196     free(sp->cmd);
197     sp->cmd = NULL;
198     strcpy(filename_tail, "/cmdline");
199     n = read_to_buf(filename, buf);
200     if (n <= 0)
201     break;
202     if (buf[n-1] == '\n') {
203     if (!--n)
204     break;
205     buf[n] = '\0';
206     }
207     do {
208     n--;
209     if ((unsigned char)(buf[n]) < ' ')
210     buf[n] = ' ';
211     } while (n);
212     sp->cmd = xstrdup(buf);
213     }
214     break;
215     }
216     return sp;
217     }
218     /* from kernel:
219     // pid comm S ppid pgid sid tty_nr tty_pgrp flg
220     sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \
221     %lu %lu %lu %lu %lu %ld %ld %ld %ld %d 0 %llu %lu %ld %lu %lu %lu %lu %lu \
222     %lu %lu %lu %lu %lu %lu %lu %lu %d %d %lu %lu %llu\n",
223     task->pid,
224     tcomm,
225     state,
226     ppid,
227     pgid,
228     sid,
229     tty_nr,
230     tty_pgrp,
231     task->flags,
232     min_flt,
233    
234     cmin_flt,
235     maj_flt,
236     cmaj_flt,
237     cputime_to_clock_t(utime),
238     cputime_to_clock_t(stime),
239     cputime_to_clock_t(cutime),
240     cputime_to_clock_t(cstime),
241     priority,
242     nice,
243     num_threads,
244     // 0,
245     start_time,
246     vsize,
247     mm ? get_mm_rss(mm) : 0,
248     rsslim,
249     mm ? mm->start_code : 0,
250     mm ? mm->end_code : 0,
251     mm ? mm->start_stack : 0,
252     esp,
253     eip,
254     the rest is some obsolete cruft
255     */