source: MondoRescue/branches/stable/mindi-busybox/procps/ps.c@ 1770

Last change on this file since 1770 was 1770, checked in by Bruno Cornec, 16 years ago
  • Better output for mindi-busybox revision
  • Remove dummy file created on NFS - report from Arnaud Tiger <arnaud.tiger_at_hp.com>
  • strace useful for debug
  • fix new versions for pb (2.0.0 for mindi and 1.7.2 for mindi-busybox)
  • fix build process for mindi-busybox + options used in that version (dd for label-partitions-as-necessary)
  • fix typo in label-partitions-as-necessary which doesn't seem to work
  • Update to busybox 1.7.2
  • perl is now required at restore time to support uuid swap partitions (and will be used for many other thigs

in the future for sure)

  • next mindi version will be 2.0.0 due to all the changes made in it (udev may break working distros)
  • small optimization in mindi on keyboard handling (one single find instead of multiple)
  • better interaction for USB device when launching mindi manually
  • attempt to automatically guess block disk size for ramdisk
  • fix typos in bkphw
  • Fix the remaining problem with UUID support for swap partitions
  • Updates mondoarchive man page for USB support
  • Adds preliminary Hardware support to mindi (Proliant SSSTK)
  • Tries to add udev support also for rhel4
  • Fix UUID support which was still broken.
  • Be conservative in test for the start-nfs script
  • Update config file for mindi-busybox for 1.7.2 migration
  • Try to run around a busybox bug (1.2.2 pb on inexistant links)
  • Add build content for mindi-busybox in pb
  • Remove distributions content for mindi-busybox
  • Fix a warning on inexistant raidtab
  • Solve problem on tmpfs in restore init (Problem of inexistant symlink and busybox)
  • Create MONDO_CACHE and use it everywhere + creation at start
  • Really never try to eject a USB device
  • Fix a issue with &> usage (replaced with 1> and 2>)
  • Adds magic file to depllist in order to have file working + ldd which helps for debugging issues
  • tty modes correct to avoid sh error messages
  • Use ext3 normally and not ext2 instead
  • USB device should be corrected after reading (take 1st part)
  • Adds a mount_USB_here function derived from mount_CDROM_here
  • usb detection place before /dev detection in device name at restore time
  • Fix when restoring from USB: media is asked in interactive mode
  • Adds USB support for mondorestore
  • mount_cdrom => mount_media
  • elilo.efi is now searched throughout /boot/efi and not in a fixed place as there is no standard
  • untar-and-softlink => untar (+ interface change)
  • suppress useless softlinks creation/removal in boot process
  • avoids udevd messages on groups
  • Increase # of disks to 99 as in mindi at restore time (should be a conf file parameter)
  • skip existing big file creation
  • seems to work correctly for USB mindi boot
  • Adds group and tty link to udev conf
  • Always load usb-torage (even 2.6) to initiate USB bus discovery
  • Better printing of messages
  • Attempt to fix a bug in supporting OpenSusE 10.3 kernel for initramfs (mindi may now use multiple regex for kernel initrd detection)
  • Links were not correctly done as non relative for modules in mindi
  • exclusion of modules denied now works
  • Also create modules in their ordinary place, so that classical modprobe works + copy modules.dep
  • Fix bugs for DENY_MODS handling
  • Add device /dev/console for udev
  • ide-generic should now really be excluded
  • Fix a bug in major number for tty
  • If udev then adds modprobe/insmod to rootfs
  • tty0 is also cretaed with udev
  • ide-generic put rather in DENY_MODS
  • udevd remove from deplist s handled in mindi directly
  • better default for mindi when using --usb
  • Handles dynamically linked busybox (in case we want to use it soon ;-)
  • Adds fixed devices to create for udev
  • ide-generic should not be part of the initrd when using libata v2
  • support a dynamically linked udev (case on Ubuntu 7.10 and Mandriva 2008.0 so should be quite generic) This will give incitation to move to dyn. linked binaries in the initrd which will help for other tasks (ia6 4)
  • Improvement in udev support (do not use cl options not available in busybox)
  • Udev in mindi
    • auto creation of the right links at boot time with udev-links.conf(from Mandriva 2008.0)
    • rework startup of udev as current makes kernel crash (from Mandriva 2008.0)
    • add support for 64 bits udev
  • Try to render MyInsmod silent at boot time
  • Adds udev support (mandatory for newest distributions to avoid remapping of devices in a different way as on the original system)
  • We also need vaft format support for USB boot
  • Adds libusual support (Ubuntu 7.10 needs it for USB)
  • Improve Ubuntu/Debian keyboard detection and support
  • pbinit adapted to new pb (0.8.10). Filtering of docs done in it
  • Suppress some mondo warnings and errors on USB again
  • Tries to fix lack of files in deb mindi package
  • Verify should now work for USB devices
  • More log/mesages improvement for USB support
  • - Supress g_erase_tmpdir_and_scratchdir
  • Improve some log messages for USB support
  • Try to improve install in mindi to avoid issues with isolinux.cfg not installed vene if in the pkg :-(
  • Improve mindi-busybox build
  • In conformity with pb 0.8.9
  • Add support for Ubuntu 7.10 in build process
  • Add USB Key button to Menu UI (CD streamer removed)
  • Attempt to fix error messages on tmp/scratch files at the end by removing those dir at the latest possible.
  • Fix a bug linked to the size of the -E param which could be used (Arnaud Tiger/René Ribaud).
  • Integrate ~/.pbrc content into mondorescue.pb (required project-builder >= 0.8.7)
  • Put mondorescue in conformity with new pb filtering rules
  • Add USB support at restore time (no test done yet). New start-usb script PB varibale added where useful
  • Unmounting USB device before removal of temporary scratchdir
  • Stil refining USB copy back to mondo (one command was not executed)
  • No need to have the image subdor in the csratchdir when USB.
  • umount the USB partition before attempting to use it
  • Remove useless copy from mindi to mondo at end of USB handling

(risky merge, we are raising the limits of 2 diverging branches. The status of stable is not completely sure as such. Will need lots of tests, but it's not yet done :-()
(merge -r1692:1769 $SVN_M/branches/2.2.5)

File size: 10.5 KB
Line 
1/* vi: set sw=4 ts=4: */
2/*
3 * Mini ps implementation(s) for busybox
4 *
5 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
6 * Fix for SELinux Support:(c)2007 Hiroshi Shinji <shiroshi@my.email.ne.jp>
7 (c)2007 Yuichi Nakamura <ynakam@hitachisoft.jp>
8 *
9 * Licensed under the GPL version 2, see the file LICENSE in this tarball.
10 */
11
12#include "libbb.h"
13
14/* Absolute maximum on output line length */
15enum { MAX_WIDTH = 2*1024 };
16
17#if ENABLE_DESKTOP
18
19/* Print value to buf, max size+1 chars (including trailing '\0') */
20
21static void func_user(char *buf, int size, const procps_status_t *ps)
22{
23 safe_strncpy(buf, get_cached_username(ps->uid), size+1);
24}
25
26static void func_comm(char *buf, int size, const procps_status_t *ps)
27{
28 safe_strncpy(buf, ps->comm, size+1);
29}
30
31static void func_args(char *buf, int size, const procps_status_t *ps)
32{
33 read_cmdline(buf, size, ps->pid, ps->comm);
34}
35
36static void func_pid(char *buf, int size, const procps_status_t *ps)
37{
38 sprintf(buf, "%*u", size, ps->pid);
39}
40
41static void func_ppid(char *buf, int size, const procps_status_t *ps)
42{
43 sprintf(buf, "%*u", size, ps->ppid);
44}
45
46static void func_pgid(char *buf, int size, const procps_status_t *ps)
47{
48 sprintf(buf, "%*u", size, ps->pgid);
49}
50
51static void put_u(char *buf, int size, unsigned u)
52{
53 char buf5[5];
54 smart_ulltoa5( ((unsigned long long)u) << 10, buf5);
55 sprintf(buf, "%.*s", size, buf5);
56}
57
58static void func_vsz(char *buf, int size, const procps_status_t *ps)
59{
60 put_u(buf, size, ps->vsz);
61}
62
63static void func_rss(char *buf, int size, const procps_status_t *ps)
64{
65 put_u(buf, size, ps->rss);
66}
67
68static void func_tty(char *buf, int size, const procps_status_t *ps)
69{
70 buf[0] = '?';
71 buf[1] = '\0';
72 if (ps->tty_major) /* tty field of "0" means "no tty" */
73 snprintf(buf, size+1, "%u,%u", ps->tty_major, ps->tty_minor);
74}
75
76#if ENABLE_SELINUX
77static void func_label(char *buf, int size, const procps_status_t *ps)
78{
79 safe_strncpy(buf, ps->context ? ps->context : "unknown", size+1);
80}
81#endif
82
83/*
84static void func_nice(char *buf, int size, const procps_status_t *ps)
85{
86 ps->???
87}
88
89static void func_etime(char *buf, int size, const procps_status_t *ps)
90{
91 elapled time [[dd-]hh:]mm:ss
92}
93
94static void func_time(char *buf, int size, const procps_status_t *ps)
95{
96 cumulative time [[dd-]hh:]mm:ss
97}
98
99static void func_pcpu(char *buf, int size, const procps_status_t *ps)
100{
101}
102*/
103
104typedef struct {
105 uint16_t width;
106 char name[6];
107 const char *header;
108 void (*f)(char *buf, int size, const procps_status_t *ps);
109 int ps_flags;
110} ps_out_t;
111
112static const ps_out_t out_spec[] = {
113// Mandated by POSIX:
114 { 8 , "user" ,"USER" ,func_user ,PSSCAN_UIDGID },
115 { 16 , "comm" ,"COMMAND",func_comm ,PSSCAN_COMM },
116 { 256 , "args" ,"COMMAND",func_args ,PSSCAN_COMM },
117 { 5 , "pid" ,"PID" ,func_pid ,PSSCAN_PID },
118 { 5 , "ppid" ,"PPID" ,func_ppid ,PSSCAN_PPID },
119 { 5 , "pgid" ,"PGID" ,func_pgid ,PSSCAN_PGID },
120// { sizeof("ELAPSED")-1, "etime" ,"ELAPSED",func_etime ,PSSCAN_ },
121// { sizeof("GROUP" )-1, "group" ,"GROUP" ,func_group ,PSSCAN_UIDGID },
122// { sizeof("NI" )-1, "nice" ,"NI" ,func_nice ,PSSCAN_ },
123// { sizeof("%CPU" )-1, "pcpu" ,"%CPU" ,func_pcpu ,PSSCAN_ },
124// { sizeof("RGROUP" )-1, "rgroup","RGROUP" ,func_rgroup,PSSCAN_UIDGID },
125// { sizeof("RUSER" )-1, "ruser" ,"RUSER" ,func_ruser ,PSSCAN_UIDGID },
126// { sizeof("TIME" )-1, "time" ,"TIME" ,func_time ,PSSCAN_ },
127 { 6 , "tty" ,"TT" ,func_tty ,PSSCAN_TTY },
128 { 4 , "vsz" ,"VSZ" ,func_vsz ,PSSCAN_VSZ },
129// Not mandated by POSIX, but useful:
130 { 4 , "rss" ,"RSS" ,func_rss ,PSSCAN_RSS },
131#if ENABLE_SELINUX
132 { 35 , "label" ,"LABEL" ,func_label ,PSSCAN_CONTEXT },
133#endif
134};
135
136#if ENABLE_SELINUX
137#define SELINIX_O_PREFIX "label,"
138#define DEFAULT_O_STR SELINIX_O_PREFIX "pid,user" /* TODO: ,vsz,stat */ ",args"
139#else
140#define DEFAULT_O_STR "pid,user" /* TODO: ,vsz,stat */ ",args"
141#endif
142
143struct globals {
144 ps_out_t* out;
145 int out_cnt;
146 int print_header;
147 int need_flags;
148 char *buffer;
149 unsigned terminal_width;
150 char default_o[sizeof(DEFAULT_O_STR)];
151};
152#define G (*(struct globals*)&bb_common_bufsiz1)
153#define out (G.out )
154#define out_cnt (G.out_cnt )
155#define print_header (G.print_header )
156#define need_flags (G.need_flags )
157#define buffer (G.buffer )
158#define terminal_width (G.terminal_width)
159#define default_o (G.default_o )
160
161static ps_out_t* new_out_t(void)
162{
163 int i = out_cnt++;
164 out = xrealloc(out, out_cnt * sizeof(*out));
165 return &out[i];
166}
167
168static const ps_out_t* find_out_spec(const char *name)
169{
170 int i;
171 for (i = 0; i < ARRAY_SIZE(out_spec); i++) {
172 if (!strcmp(name, out_spec[i].name))
173 return &out_spec[i];
174 }
175 bb_error_msg_and_die("bad -o argument '%s'", name);
176}
177
178static void parse_o(char* opt)
179{
180 ps_out_t* new;
181 // POSIX: "-o is blank- or comma-separated list" (FIXME)
182 char *comma, *equal;
183 while (1) {
184 comma = strchr(opt, ',');
185 equal = strchr(opt, '=');
186 if (comma && (!equal || equal > comma)) {
187 *comma = '\0';
188 *new_out_t() = *find_out_spec(opt);
189 *comma = ',';
190 opt = comma + 1;
191 continue;
192 }
193 break;
194 }
195 // opt points to last spec in comma separated list.
196 // This one can have =HEADER part.
197 new = new_out_t();
198 if (equal)
199 *equal = '\0';
200 *new = *find_out_spec(opt);
201 if (equal) {
202 *equal = '=';
203 new->header = equal + 1;
204 // POSIX: the field widths shall be ... at least as wide as
205 // the header text (default or overridden value).
206 // If the header text is null, such as -o user=,
207 // the field width shall be at least as wide as the
208 // default header text
209 if (new->header[0]) {
210 new->width = strlen(new->header);
211 print_header = 1;
212 }
213 } else
214 print_header = 1;
215}
216
217static void post_process(void)
218{
219 int i;
220 int width = 0;
221 for (i = 0; i < out_cnt; i++) {
222 need_flags |= out[i].ps_flags;
223 if (out[i].header[0]) {
224 print_header = 1;
225 }
226 width += out[i].width + 1; /* "FIELD " */
227 }
228#if ENABLE_SELINUX
229 if (!is_selinux_enabled())
230 need_flags &= ~PSSCAN_CONTEXT;
231#endif
232 buffer = xmalloc(width + 1); /* for trailing \0 */
233}
234
235static void format_header(void)
236{
237 int i;
238 ps_out_t* op;
239 char *p;
240
241 if (!print_header)
242 return;
243 p = buffer;
244 i = 0;
245 if (out_cnt) {
246 while (1) {
247 op = &out[i];
248 if (++i == out_cnt) /* do not pad last field */
249 break;
250 p += sprintf(p, "%-*s ", op->width, op->header);
251 }
252 strcpy(p, op->header);
253 }
254 printf("%.*s\n", terminal_width, buffer);
255}
256
257static void format_process(const procps_status_t *ps)
258{
259 int i, len;
260 char *p = buffer;
261 i = 0;
262 if (out_cnt) while (1) {
263 out[i].f(p, out[i].width, ps);
264 // POSIX: Any field need not be meaningful in all
265 // implementations. In such a case a hyphen ( '-' )
266 // should be output in place of the field value.
267 if (!p[0]) {
268 p[0] = '-';
269 p[1] = '\0';
270 }
271 len = strlen(p);
272 p += len;
273 len = out[i].width - len + 1;
274 if (++i == out_cnt) /* do not pad last field */
275 break;
276 p += sprintf(p, "%*s", len, "");
277 }
278 printf("%.*s\n", terminal_width, buffer);
279}
280
281int ps_main(int argc, char **argv);
282int ps_main(int argc, char **argv)
283{
284 procps_status_t *p;
285 llist_t* opt_o = NULL;
286 USE_SELINUX(int opt;)
287
288 // POSIX:
289 // -a Write information for all processes associated with terminals
290 // Implementations may omit session leaders from this list
291 // -A Write information for all processes
292 // -d Write information for all processes, except session leaders
293 // -e Write information for all processes (equivalent to -A.)
294 // -f Generate a full listing
295 // -l Generate a long listing
296 // -o col1,col2,col3=header
297 // Select which columns to display
298 /* We allow (and ignore) most of the above. FIXME */
299 opt_complementary = "o::";
300 USE_SELINUX(opt =) getopt32(argv, "Zo:aAdefl", &opt_o);
301 if (opt_o) {
302 do {
303 parse_o(opt_o->data);
304 opt_o = opt_o->link;
305 } while (opt_o);
306 } else {
307 /* Below: parse_o() needs char*, NOT const char*... */
308#if ENABLE_SELINUX
309 if (!(opt & 1) || !is_selinux_enabled()) {
310 /* no -Z or no SELinux: do not show LABEL */
311 strcpy(default_o, DEFAULT_O_STR + sizeof(SELINIX_O_PREFIX)-1);
312 } else
313#endif
314 {
315 strcpy(default_o, DEFAULT_O_STR);
316 }
317 parse_o(default_o);
318 }
319 post_process();
320
321 /* Was INT_MAX, but some libc's go belly up with printf("%.*s")
322 * and such large widths */
323 terminal_width = MAX_WIDTH;
324 if (isatty(1)) {
325 get_terminal_width_height(0, &terminal_width, NULL);
326 if (--terminal_width > MAX_WIDTH)
327 terminal_width = MAX_WIDTH;
328 }
329 format_header();
330
331 p = NULL;
332 while ((p = procps_scan(p, need_flags))) {
333 format_process(p);
334 }
335
336 return EXIT_SUCCESS;
337}
338
339
340#else /* !ENABLE_DESKTOP */
341
342
343int ps_main(int argc, char **argv);
344int ps_main(int argc, char **argv)
345{
346 procps_status_t *p = NULL;
347 int len;
348 SKIP_SELINUX(const) int use_selinux = 0;
349 USE_SELINUX(int i;)
350#if !ENABLE_FEATURE_PS_WIDE
351 enum { terminal_width = 79 };
352#else
353 int terminal_width;
354 int w_count = 0;
355#endif
356
357#if ENABLE_FEATURE_PS_WIDE || ENABLE_SELINUX
358#if ENABLE_FEATURE_PS_WIDE
359 opt_complementary = "-:ww";
360 USE_SELINUX(i =) getopt32(argv, USE_SELINUX("Z") "w", &w_count);
361 /* if w is given once, GNU ps sets the width to 132,
362 * if w is given more than once, it is "unlimited"
363 */
364 if (w_count) {
365 terminal_width = (w_count==1) ? 132 : MAX_WIDTH;
366 } else {
367 get_terminal_width_height(0, &terminal_width, NULL);
368 /* Go one less... */
369 if (--terminal_width > MAX_WIDTH)
370 terminal_width = MAX_WIDTH;
371 }
372#else /* only ENABLE_SELINUX */
373 i = getopt32(argv, "Z");
374#endif
375#if ENABLE_SELINUX
376 if ((i & 1) && is_selinux_enabled())
377 use_selinux = PSSCAN_CONTEXT;
378#endif
379#endif /* ENABLE_FEATURE_PS_WIDE || ENABLE_SELINUX */
380
381 if (use_selinux)
382 puts(" PID Context Stat Command");
383 else
384 puts(" PID Uid VSZ Stat Command");
385
386 while ((p = procps_scan(p, 0
387 | PSSCAN_PID
388 | PSSCAN_UIDGID
389 | PSSCAN_STATE
390 | PSSCAN_VSZ
391 | PSSCAN_COMM
392 | use_selinux
393 ))) {
394#if ENABLE_SELINUX
395 if (use_selinux) {
396 len = printf("%5u %-32s %s ",
397 p->pid,
398 p->context ? p->context : "unknown",
399 p->state);
400 } else
401#endif
402 {
403 const char *user = get_cached_username(p->uid);
404 if (p->vsz == 0)
405 len = printf("%5u %-8s %s ",
406 p->pid, user, p->state);
407 else
408 len = printf("%5u %-8s %6u %s ",
409 p->pid, user, p->vsz, p->state);
410 }
411
412 {
413 int sz = terminal_width - len;
414 char buf[sz + 1];
415 read_cmdline(buf, sz, p->pid, p->comm);
416 puts(buf);
417 }
418 }
419 if (ENABLE_FEATURE_CLEAN_UP)
420 clear_username_cache();
421 return EXIT_SUCCESS;
422}
423
424#endif /* ENABLE_DESKTOP */
Note: See TracBrowser for help on using the repository browser.