Contents of /trunk/mkinitrd-magellan/busybox/libbb/procps.c
Parent Directory | Revision Log
Revision 532 -
(show annotations)
(download)
Sat Sep 1 22:45:15 2007 UTC (17 years ago) by niro
File MIME type: text/plain
File size: 5728 byte(s)
Sat Sep 1 22:45:15 2007 UTC (17 years ago) by niro
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 | /* 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 | */ |