Changeset 1770 in MondoRescue for branches/stable/mindi-busybox/procps


Ignore:
Timestamp:
Nov 6, 2007, 11:01:53 AM (16 years ago)
Author:
Bruno Cornec
Message:
  • 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)

Location:
branches/stable/mindi-busybox/procps
Files:
2 deleted
10 edited
4 copied

Legend:

Unmodified
Added
Removed
  • branches/stable/mindi-busybox/procps/Config.in

    r821 r1770  
    66menu "Process Utilities"
    77
    8 config CONFIG_FREE
     8config FREE
    99    bool "free"
    1010    default n
     
    1414      The shared memory column should be ignored; it is obsolete.
    1515
    16 config CONFIG_FUSER
     16config FUSER
    1717    bool "fuser"
    1818    default n
     
    2222      (TCP or UDP) port open.
    2323
    24 config CONFIG_KILL
     24config KILL
    2525    bool "kill"
    2626    default n
     
    3030      signal is sent.
    3131
    32 config CONFIG_KILLALL
     32config KILLALL
    3333    bool "killall"
    3434    default n
    35     depends on CONFIG_KILL
     35    depends on KILL
    3636    help
    3737      killall sends a signal to all processes running any of the
     
    3939      sent.
    4040
    41 config CONFIG_PIDOF
     41config KILLALL5
     42    bool "killall5"
     43    default n
     44    depends on KILL
     45
     46config NMETER
     47    bool "nmeter"
     48    default n
     49    help
     50      Prints selected system stats continuously, one line per update.
     51
     52config PIDOF
    4253    bool "pidof"
    4354    default n
     
    4657      those id's on the standard output.
    4758
    48 config CONFIG_FEATURE_PIDOF_SINGLE
     59config FEATURE_PIDOF_SINGLE
    4960    bool "Enable argument for single shot (-s)"
    5061    default n
    51     depends on CONFIG_PIDOF
     62    depends on PIDOF
    5263    help
    5364      Support argument '-s' for returning only the first pid found.
    5465
    55 config CONFIG_FEATURE_PIDOF_OMIT
     66config FEATURE_PIDOF_OMIT
    5667    bool "Enable argument for omitting pids (-o)"
    5768    default n
    58     depends on CONFIG_PIDOF
     69    depends on PIDOF
    5970    help
    6071      Support argument '-o' for omitting the given pids in output.
     
    6273      of the pidof, in other words the calling shell or shell script.
    6374
    64 config CONFIG_PS
     75config PS
    6576    bool "ps"
    6677    default n
     
    6879      ps gives a snapshot of the current processes.
    6980
    70 config CONFIG_FEATURE_PS_WIDE
     81config FEATURE_PS_WIDE
    7182    bool "Enable argument for wide output (-w)"
    7283    default n
    73     depends on CONFIG_PS
     84    depends on PS
    7485    help
    7586      Support argument 'w' for wide output.
     
    7788      one, the length is unlimited.
    7889
    79 config CONFIG_RENICE
     90config RENICE
    8091    bool "renice"
    8192    default n
     
    8495      processes.
    8596
    86 config CONFIG_BB_SYSCTL
     97config BB_SYSCTL
    8798    bool "sysctl"
    8899    default n
     
    90101      Configure kernel parameters at runtime.
    91102
    92 config CONFIG_TOP
     103config TOP
    93104    bool "top"
    94105    default n
     
    97108      system.
    98109
    99 config CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
    100     bool "Support showing CPU usage percentage (add 2k bytes)"
     110config FEATURE_TOP_CPU_USAGE_PERCENTAGE
     111    bool "Show CPU per-process usage percentage (adds 2k bytes)"
    101112    default y
    102     depends on CONFIG_TOP
     113    depends on TOP
    103114    help
    104       Make top display CPU usage.
     115      Make top display CPU usage for each process.
    105116
    106 config CONFIG_UPTIME
     117config FEATURE_TOP_CPU_GLOBAL_PERCENTS
     118    bool "Show CPU global usage percentage (adds 0.5k bytes)"
     119    default y
     120    depends on FEATURE_TOP_CPU_USAGE_PERCENTAGE
     121    help
     122      Makes top display "CPU: NN% usr NN% sys..." line.
     123
     124config FEATURE_TOP_DECIMALS
     125    bool "Show 1/10th of a percent in CPU/mem statistics (adds 0.3k bytes)"
     126    default n
     127    depends on FEATURE_TOP_CPU_USAGE_PERCENTAGE
     128    help
     129      Show 1/10th of a percent in CPU/mem statistics.
     130
     131config UPTIME
    107132    bool "uptime"
    108133    default n
     
    112137      on, and the system load averages for the past 1, 5, and 15 minutes.
    113138
     139config WATCH
     140    bool "watch"
     141    default n
     142    #huh?? select DATE
     143    help
     144      watch is used to execute a program periodically, showing
     145      output to the screen.
     146
    114147
    115148endmenu
  • branches/stable/mindi-busybox/procps/free.c

    r821 r1770  
    55 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
    66 *
    7  * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
     7 * Licensed under the GPL version 2, see the file LICENSE in this tarball.
    88 */
    99
    1010/* getopt not needed */
    1111
    12 #include "busybox.h"
    13 #include <stdio.h>
    14 #include <errno.h>
    15 #include <stdlib.h>
     12#include "libbb.h"
    1613
     14int free_main(int argc, char **argv);
    1715int free_main(int argc, char **argv)
    1816{
     
    2119
    2220    /* Kernels prior to 2.4.x will return info.mem_unit==0, so cope... */
    23     if (info.mem_unit==0) {
     21    if (info.mem_unit == 0) {
    2422        info.mem_unit=1;
    2523    }
    26     if ( info.mem_unit == 1 ) {
     24    if (info.mem_unit == 1) {
    2725        info.mem_unit=1024;
    2826
     
    4947    }
    5048
    51     if (argc > 1 && **(argv + 1) == '-')
     49    if (argc > 1 && *argv[1] == '-')
    5250        bb_show_usage();
    5351
     
    6967    return EXIT_SUCCESS;
    7068}
    71 
  • branches/stable/mindi-busybox/procps/fuser.c

    r821 r1770  
    99 */
    1010
    11 #include "busybox.h"
    12 #include <stdio.h>
    13 #include <stdlib.h>
    14 #include <unistd.h>
    15 #include <string.h>
    16 #include <limits.h>
    17 #include <dirent.h>
    18 #include <signal.h>
    19 #include <sys/types.h>
    20 #include <sys/ioctl.h>
    21 #include <sys/stat.h>
    22 #include <sys/socket.h>
    23 #include <sys/sysmacros.h>
     11#include "libbb.h"
    2412
    2513#define FUSER_PROC_DIR "/proc"
     
    4735    int opt = 0;
    4836
    49     if(!(strlen(option))) return 0;
    50     if(option[0] != '-') return 0;
     37    if (!option[0])
     38        return 0;
     39    if (option[0] != '-')
     40        return 0;
    5141    ++option;
    52     while(*option != '\0') {
    53         if(*option == 'm') opt |= FUSER_OPT_MOUNT;
    54         else if(*option == 'k') opt |= FUSER_OPT_KILL;
    55         else if(*option == 's') opt |= FUSER_OPT_SILENT;
    56         else if(*option == '6') opt |= FUSER_OPT_IP6;
    57         else if(*option == '4') opt |= FUSER_OPT_IP4;
    58         else {
    59             bb_error_msg_and_die(
    60                 "Unsupported option '%c'", *option);
    61         }
     42    while (*option != '\0') {
     43        if (*option == 'm') opt |= FUSER_OPT_MOUNT;
     44        else if (*option == 'k') opt |= FUSER_OPT_KILL;
     45        else if (*option == 's') opt |= FUSER_OPT_SILENT;
     46        else if (*option == '6') opt |= FUSER_OPT_IP6;
     47        else if (*option == '4') opt |= FUSER_OPT_IP4;
     48        else
     49            bb_error_msg_and_die("unsupported option '%c'", *option);
    6250        ++option;
    6351    }
     
    6957{
    7058    struct stat f_stat;
    71     if((stat(filename, &f_stat)) < 0) return 0;
     59    if ((stat(filename, &f_stat)) < 0)
     60        return 0;
    7261    *inode = f_stat.st_ino;
    7362    *dev = f_stat.st_dev;
     
    8170
    8271    if (fd >= 0 && (fstat(fd, &buf)) == 0) {
    83         *dev =  buf.st_dev;
     72        *dev = buf.st_dev;
    8473        close(fd);
    8574        return 1;
     
    9382    char path[sizeof(FUSER_PROC_DIR)+12], tproto[5];
    9483
    95     if((sscanf(filename, "%d/%4s", port, tproto)) != 2) return 0;
    96     sprintf(path, "%s/net/%s", FUSER_PROC_DIR, tproto);
    97     if((access(path, R_OK)) != 0) return 0;
    98     *proto = bb_xstrdup(tproto);
     84    if ((sscanf(filename, "%d/%4s", port, tproto)) != 2)
     85        return 0;
     86    sprintf(path, FUSER_PROC_DIR "/net/%s", tproto);
     87    if ((access(path, R_OK)) != 0)
     88        return 0;
     89    *proto = xstrdup(tproto);
    9990    return 1;
    10091}
     
    10495    pid_list *curr = NULL, *last = NULL;
    10596
    106     if(plist->pid == 0) plist->pid = pid;
     97    if (plist->pid == 0)
     98        plist->pid = pid;
    10799    curr = plist;
    108     while(curr != NULL) {
    109         if(curr->pid == pid) return 1;
     100    while (curr != NULL) {
     101        if (curr->pid == pid)
     102            return 1;
    110103        last = curr;
    111104        curr = curr->next;
    112105    }
    113     curr = xmalloc(sizeof(pid_list));
     106    curr = xzalloc(sizeof(pid_list));
    114107    last->next = curr;
    115108    curr->pid = pid;
    116     curr->next = NULL;
     109    /*curr->next = NULL;*/
    117110    return 1;
    118111}
     
    122115    inode_list *curr = NULL, *last = NULL;
    123116
    124     if(!ilist->inode && !ilist->dev) {
     117    if (!ilist->inode && !ilist->dev) {
    125118        ilist->dev = dev;
    126119        ilist->inode = inode;
    127120    }
    128121    curr = ilist;
    129     while(curr != NULL) {
    130         if(curr->inode == inode && curr->dev == dev) return 1;
     122    while (curr != NULL) {
     123        if (curr->inode == inode && curr->dev == dev)
     124            return 1;
    131125        last = curr;
    132126        curr = curr->next;
    133127    }
    134     curr = xmalloc(sizeof(inode_list));
     128    curr = xzalloc(sizeof(inode_list));
    135129    last->next = curr;
    136130    curr->dev = dev;
    137131    curr->inode = inode;
    138     curr->next = NULL;
     132    /*curr->next = NULL;*/
    139133    return 1;
    140134}
     
    147141    ino_t tmp_inode;
    148142    dev_t tmp_dev;
    149     long long  uint64_inode;
     143    long long uint64_inode;
    150144    int tmp_port;
    151145    FILE *f;
    152146
    153     if(!fuser_find_socket_dev(&tmp_dev)) tmp_dev = 0;
    154     sprintf(path, "%s/net/%s", FUSER_PROC_DIR, proto);
    155 
    156     if (!(f = fopen(path, "r"))) return 0;
    157     while(fgets(line, FUSER_MAX_LINE, f)) {
    158         if(sscanf(line,
    159             "%*d: %64[0-9A-Fa-f]:%x %*x:%*x %*x %*x:%*x "
    160             "%*x:%*x %*x %*d %*d %llu",
    161             addr, &tmp_port, &uint64_inode) == 3) {
    162             if((strlen(addr) == 8) &&
    163                 (opts & FUSER_OPT_IP6)) continue;
    164             else if((strlen(addr) > 8) &&
    165                 (opts & FUSER_OPT_IP4)) continue;
    166             if(tmp_port == port) {
     147    if (!fuser_find_socket_dev(&tmp_dev))
     148        tmp_dev = 0;
     149    sprintf(path, FUSER_PROC_DIR "/net/%s", proto);
     150
     151    f = fopen(path, "r");
     152    if (!f)
     153        return 0;
     154    while (fgets(line, FUSER_MAX_LINE, f)) {
     155        if (sscanf(line, "%*d: %64[0-9A-Fa-f]:%x %*x:%*x %*x %*x:%*x "
     156                "%*x:%*x %*x %*d %*d %llu",
     157                addr, &tmp_port, &uint64_inode) == 3
     158        ) {
     159            if (strlen(addr) == 8 && (opts & FUSER_OPT_IP6))
     160                continue;
     161            if (strlen(addr) > 8 && (opts & FUSER_OPT_IP4))
     162                continue;
     163            if (tmp_port == port) {
    167164                tmp_inode = uint64_inode;
    168165                fuser_add_inode(ilist, tmp_dev, tmp_inode);
    169166            }
    170167        }
    171 
    172168    }
    173169    fclose(f);
     
    181177    curr = ilist;
    182178
    183     while(curr) {
    184         if((opts & FUSER_OPT_MOUNT) && curr->dev == dev)
     179    while (curr) {
     180        if ((opts & FUSER_OPT_MOUNT) && curr->dev == dev)
    185181            return 1;
    186         if(curr->inode == inode && curr->dev == dev)
     182        if (curr->inode == inode && curr->dev == dev)
    187183            return 1;
    188184        curr = curr->next;
     
    201197    dev_t dev;
    202198
    203     if (!(file = fopen(fname, "r"))) return 0;
     199    file = fopen(fname, "r");
     200    if (!file)
     201        return 0;
    204202    while (fgets(line, FUSER_MAX_LINE, file)) {
    205         if(sscanf(line, "%*s %*s %*s %x:%x %llu",
    206             &major, &minor, &uint64_inode) != 3) continue;
     203        if (sscanf(line, "%*s %*s %*s %x:%x %llu", &major, &minor, &uint64_inode) != 3)
     204            continue;
    207205        inode = uint64_inode;
    208         if(major == 0 && minor == 0 && inode == 0) continue;
     206        if (major == 0 && minor == 0 && inode == 0)
     207            continue;
    209208        dev = makedev(major, minor);
    210         if(fuser_search_dev_inode(opts, ilist, dev, inode)) {
     209        if (fuser_search_dev_inode(opts, ilist, dev, inode)) {
    211210            fuser_add_pid(plist, pid);
    212211        }
    213 
    214212    }
    215213    fclose(file);
     
    223221    dev_t dev;
    224222
    225     if(!fuser_file_to_dev_inode(lname, &dev, &inode)) return 0;
    226     if(fuser_search_dev_inode(opts, ilist, dev, inode))
     223    if (!fuser_file_to_dev_inode(lname, &dev, &inode))
     224        return 0;
     225    if (fuser_search_dev_inode(opts, ilist, dev, inode))
    227226        fuser_add_pid(plist, pid);
    228227    return 1;
     
    236235    char *lname;
    237236
    238     if((d = opendir(dname))) {
    239         while((de = readdir(d)) != NULL) {
    240             lname = concat_subpath_file(dname, de->d_name);
    241             if(lname == NULL)
    242                 continue;
    243             fuser_scan_link(opts, lname, pid, ilist, plist);
    244             free(lname);
    245         }
    246         closedir(d);
    247     }
    248     else return 0;
    249     return 1;
    250 
     237    d = opendir(dname);
     238    if (!d)
     239        return 0;
     240    while ((de = readdir(d)) != NULL) {
     241        lname = concat_subpath_file(dname, de->d_name);
     242        if (lname == NULL)
     243            continue;
     244        fuser_scan_link(opts, lname, pid, ilist, plist);
     245        free(lname);
     246    }
     247    closedir(d);
     248    return 1;
    251249}
    252250
     
    258256    char *dname;
    259257
    260     if(!(d = opendir(FUSER_PROC_DIR))) return 0;
    261     while((de = readdir(d)) != NULL) {
     258    d = opendir(FUSER_PROC_DIR);
     259    if (!d)
     260        return 0;
     261    while ((de = readdir(d)) != NULL) {
    262262        pid = (pid_t)atoi(de->d_name);
    263         if(!pid) continue;
     263        if (!pid)
     264            continue;
    264265        dname = concat_subpath_file(FUSER_PROC_DIR, de->d_name);
    265         if(chdir(dname) < 0) {
     266        if (chdir(dname) < 0) {
    266267            free(dname);
    267268            continue;
     
    285286    pid_list *curr = plist;
    286287
    287     if(plist == NULL) return 0;
    288     while(curr != NULL) {
    289         if(curr->pid > 0) printf("%d ", curr->pid);
    290         curr = curr->next;
    291     }
    292     printf("\n");
     288    if (plist == NULL)
     289        return 0;
     290    while (curr != NULL) {
     291        if (curr->pid > 0)
     292            printf("%d ", curr->pid);
     293        curr = curr->next;
     294    }
     295    puts("");
    293296    return 1;
    294297}
     
    300303    int success = 1;
    301304
    302     if(plist == NULL) return 0;
    303     while(curr != NULL) {
    304         if(curr->pid > 0 && curr->pid != mypid) {
     305    if (plist == NULL)
     306        return 0;
     307    while (curr != NULL) {
     308        if (curr->pid > 0 && curr->pid != mypid) {
    305309            if (kill(curr->pid, sig) != 0) {
    306                 bb_perror_msg(
    307                     "Could not kill pid '%d'", curr->pid);
     310                bb_perror_msg("kill pid '%d'", curr->pid);
    308311                success = 0;
    309312            }
     
    314317}
    315318
     319int fuser_main(int argc, char **argv);
    316320int fuser_main(int argc, char **argv)
    317321{
     322    /*static -- huh???*/ int opt = 0; /* FUSER_OPT_ */
     323
    318324    int port, i, optn;
    319325    int* fni; /* file name indexes of argv */
    320326    int fnic = 0;  /* file name index count */
    321327    const char *proto;
    322     static int opt = 0; /* FUSER_OPT_ */
    323328    dev_t dev;
    324329    ino_t inode;
     
    332337
    333338    fni = xmalloc(sizeof(int));
    334     for(i=1;i<argc;i++) {
     339    for (i = 1; i < argc; i++) {
    335340        optn = fuser_option(argv[i]);
    336         if(optn) opt |= optn;
    337         else if(argv[i][0] == '-') {
    338             if(!(u_signal_names(argv[i]+1, &killsig, 0)))
     341        if (optn)
     342            opt |= optn;
     343        else if (argv[i][0] == '-') {
     344            killsig = get_signum(argv[i]+1);
     345            if (killsig < 0)
    339346                killsig = SIGTERM;
    340         }
    341         else {
     347        } else {
    342348            fni = xrealloc(fni, sizeof(int) * (fnic+2));
    343349            fni[fnic++] = i;
    344350        }
    345351    }
    346     if(!fnic) return 1;
    347 
    348     pids = xmalloc(sizeof(pid_list));
     352
     353    if (!fnic)
     354        return 1;
     355
    349356    inodes = xmalloc(sizeof(inode_list));
    350     for(i=0;i<fnic;i++) {
    351         if(fuser_parse_net_arg(argv[fni[i]], &proto, &port)) {
     357    for (i = 0; i < fnic; i++) {
     358        if (fuser_parse_net_arg(argv[fni[i]], &proto, &port)) {
    352359            fuser_scan_proc_net(opt, proto, port, inodes);
    353         }
    354         else {
    355             if(!fuser_file_to_dev_inode(
    356                 argv[fni[i]], &dev, &inode)) {
    357                 free(pids);
    358                 free(inodes);
    359                 bb_perror_msg_and_die(
    360                     "Could not open '%s'", argv[fni[i]]);
     360        } else {
     361            if (!fuser_file_to_dev_inode(argv[fni[i]], &dev, &inode)) {
     362                if (ENABLE_FEATURE_CLEAN_UP)
     363                    free(inodes);
     364                bb_perror_msg_and_die("cannot open '%s'", argv[fni[i]]);
    361365            }
    362366            fuser_add_inode(inodes, dev, inode);
    363367        }
    364368    }
     369    pids = xmalloc(sizeof(pid_list));
    365370    success = fuser_scan_proc_pids(opt, inodes, pids);
    366371    /* if the first pid in the list is 0, none have been found */
    367     if(pids->pid == 0) success = 0;
    368     if(success) {
    369         if(opt & FUSER_OPT_KILL) {
     372    if (pids->pid == 0)
     373        success = 0;
     374    if (success) {
     375        if (opt & FUSER_OPT_KILL) {
    370376            success = fuser_kill_pid_list(pids, killsig);
    371         }
    372         else if(!(opt & FUSER_OPT_SILENT)) {
     377        } else if (!(opt & FUSER_OPT_SILENT)) {
    373378            success = fuser_print_pid_list(pids);
    374379        }
    375380    }
    376     free(pids);
    377     free(inodes);
     381    if (ENABLE_FEATURE_CLEAN_UP) {
     382        free(pids);
     383        free(inodes);
     384    }
    378385    /* return 0 on (success == 1) 1 otherwise */
    379386    return (success != 1);
  • branches/stable/mindi-busybox/procps/kill.c

    r821 r1770  
    11/* vi: set sw=4 ts=4: */
    22/*
    3  * Mini kill/killall implementation for busybox
     3 * Mini kill/killall[5] implementation for busybox
    44 *
    55 * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>.
     
    99 */
    1010
    11 #include "busybox.h"
    12 #include <stdio.h>
    13 #include <stdlib.h>
    14 #include <errno.h>
    15 #include <unistd.h>
    16 #include <signal.h>
    17 #include <ctype.h>
    18 #include <string.h>
    19 #include <unistd.h>
     11#include "libbb.h"
    2012
    21 #define KILL 0
    22 #define KILLALL 1
     13/* Note: kill_main is directly called from shell in order to implement
     14 * kill built-in. Shell substitutes job ids with process groups first.
     15 *
     16 * This brings some complications:
     17 *
     18 * + we can't use xfunc here
     19 * + we can't use applet_name
     20 * + we can't use bb_show_usage
     21 * (Above doesn't apply for killall[5] cases)
     22 *
     23 * kill %n gets translated into kill ' -<process group>' by shell (note space!)
     24 * This is needed to avoid collision with kill -9 ... syntax
     25 */
    2326
     27int kill_main(int argc, char **argv);
    2428int kill_main(int argc, char **argv)
    2529{
    26     int whichApp, signo = SIGTERM;
    27     const char *name;
    28     int errors = 0;
    29 
    30 #ifdef CONFIG_KILLALL
    31     int quiet=0;
    32     /* Figure out what we are trying to do here */
    33     whichApp = (strcmp(bb_applet_name, "killall") == 0)? KILLALL : KILL;
     30    char *arg;
     31    pid_t pid;
     32    int signo = SIGTERM, errors = 0, quiet = 0;
     33#if !ENABLE_KILLALL && !ENABLE_KILLALL5
     34#define killall 0
     35#define killall5 0
    3436#else
    35     whichApp = KILL;
     37/* How to determine who we are? find 3rd char from the end:
     38 * kill, killall, killall5
     39 *  ^i       ^a        ^l  - it's unique
     40 * (checking from the start is complicated by /bin/kill... case) */
     41    const char char3 = argv[0][strlen(argv[0]) - 3];
     42#define killall (ENABLE_KILLALL && char3 == 'a')
     43#define killall5 (ENABLE_KILLALL5 && char3 == 'l')
    3644#endif
    3745
    3846    /* Parse any options */
    39     if (argc < 2)
    40         bb_show_usage();
     47    argc--;
     48    arg = *++argv;
    4149
    42     if(argv[1][0] != '-'){
    43         argv++;
    44         argc--;
     50    if (argc < 1 || arg[0] != '-') {
    4551        goto do_it_now;
    4652    }
    4753
    48     /* The -l option, which prints out signal names. */
    49     if(argv[1][1]=='l' && argv[1][2]=='\0'){
    50         if(argc==2) {
     54    /* The -l option, which prints out signal names.
     55     * Intended usage in shell:
     56     * echo "Died of SIG`kill -l $?`"
     57     * We try to mimic what kill from coreutils-6.8 does */
     58    if (arg[1] == 'l' && arg[2] == '\0') {
     59        if (argc == 1) {
    5160            /* Print the whole signal list */
    52             int col = 0;
    53             for(signo=1; signo < NSIG; signo++) {
    54                 name = u_signal_names(0, &signo, 1);
    55                 if(name==NULL)  /* unnamed */
    56                     continue;
    57                 col += printf("%2d) %-16s", signo, name);
    58                 if (col > 60) {
    59                     printf("\n");
    60                     col = 0;
     61            for (signo = 1; signo < 32; signo++) {
     62                const char *name = get_signame(signo);
     63                if (!isdigit(name[0]))
     64                    puts(name);
     65            }
     66        } else { /* -l <sig list> */
     67            while ((arg = *++argv)) {
     68                if (isdigit(arg[0])) {
     69                    signo = bb_strtou(arg, NULL, 10);
     70                    if (errno) {
     71                        bb_error_msg("unknown signal '%s'", arg);
     72                        return EXIT_FAILURE;
     73                    }
     74                    /* Exitcodes >= 0x80 are to be treated
     75                     * as "killed by signal (exitcode & 0x7f)" */
     76                    puts(get_signame(signo & 0x7f));
     77                    /* TODO: 'bad' signal# - coreutils says:
     78                     * kill: 127: invalid signal
     79                     * we just print "127" instead */
     80                } else {
     81                    signo = get_signum(arg);
     82                    if (signo < 0) {
     83                        bb_error_msg("unknown signal '%s'", arg);
     84                        return EXIT_FAILURE;
     85                    }
     86                    printf("%d\n", signo);
    6187                }
    6288            }
    63             printf("\n");
    64 
    65         } else {
    66             for(argv++; *argv; argv++) {
    67                 name = u_signal_names(*argv, &signo, -1);
    68                 if(name!=NULL)
    69                     printf("%s\n", name);
    70             }
    7189        }
    72         /* If they specified -l, were all done */
     90        /* If they specified -l, we are all done */
    7391        return EXIT_SUCCESS;
    7492    }
    7593
    76 #ifdef CONFIG_KILLALL
    7794    /* The -q quiet option */
    78     if(whichApp != KILL && argv[1][1]=='q' && argv[1][2]=='\0'){
    79         quiet++;
    80         argv++;
     95    if (killall && arg[1] == 'q' && arg[2] == '\0') {
     96        quiet = 1;
     97        arg = *++argv;
    8198        argc--;
    82         if(argc<2 || argv[1][0] != '-'){
    83             goto do_it_now;
    84         }
     99        if (argc < 1) bb_show_usage();
     100        if (arg[0] != '-') goto do_it_now;
    85101    }
    86 #endif
    87102
    88     if(!u_signal_names(argv[1]+1, &signo, 0))
    89         bb_error_msg_and_die( "bad signal name '%s'", argv[1]+1);
    90     argv+=2;
    91     argc-=2;
     103    /* -SIG */
     104    signo = get_signum(&arg[1]);
     105    if (signo < 0) { /* || signo > MAX_SIGNUM ? */
     106        bb_error_msg("bad signal name '%s'", &arg[1]);
     107        return EXIT_FAILURE;
     108    }
     109    arg = *++argv;
     110    argc--;
    92111
    93112do_it_now:
    94113
    95     /* Pid or name required */
    96     if (argc <= 0)
    97         bb_show_usage();
     114    if (killall5) {
     115        pid_t sid;
     116        procps_status_t* p = NULL;
    98117
    99     if (whichApp == KILL) {
    100         /* Looks like they want to do a kill. Do that */
    101         while (--argc >= 0) {
    102             int pid;
     118        /* Now stop all processes */
     119        kill(-1, SIGSTOP);
     120        /* Find out our own session id */
     121        pid = getpid();
     122        sid = getsid(pid);
     123        /* Now kill all processes except our session */
     124        while ((p = procps_scan(p, PSSCAN_PID|PSSCAN_SID))) {
     125            if (p->sid != sid && p->pid != pid && p->pid != 1)
     126                kill(p->pid, signo);
     127        }
     128        /* And let them continue */
     129        kill(-1, SIGCONT);
     130        return 0;
     131    }
    103132
    104             if (!isdigit(**argv) && **argv != '-')
    105                 bb_error_msg_and_die( "Bad PID '%s'", *argv);
    106             pid = strtol(*argv, NULL, 0);
    107             if (kill(pid, signo) != 0) {
    108                 bb_perror_msg( "Could not kill pid '%d'", pid);
     133    /* Pid or name is required for kill/killall */
     134    if (argc < 1) {
     135        puts("You need to specify whom to kill");
     136        return EXIT_FAILURE;
     137    }
     138
     139    if (killall) {
     140        /* Looks like they want to do a killall.  Do that */
     141        pid = getpid();
     142        while (arg) {
     143            pid_t* pidList;
     144
     145            pidList = find_pid_by_name(arg);
     146            if (*pidList == 0) {
    109147                errors++;
    110             }
    111             argv++;
    112         }
     148                if (!quiet)
     149                    bb_error_msg("%s: no process killed", arg);
     150            } else {
     151                pid_t *pl;
    113152
    114     }
    115 #ifdef CONFIG_KILLALL
    116     else {
    117         pid_t myPid=getpid();
    118         /* Looks like they want to do a killall.  Do that */
    119         while (--argc >= 0) {
    120             long* pidList;
    121 
    122             pidList = find_pid_by_name(*argv);
    123             if (!pidList || *pidList<=0) {
    124                 errors++;
    125                 if (quiet==0)
    126                     bb_error_msg( "%s: no process killed", *argv);
    127             } else {
    128                 long *pl;
    129 
    130                 for(pl = pidList; *pl !=0 ; pl++) {
    131                     if (*pl==myPid)
     153                for (pl = pidList; *pl; pl++) {
     154                    if (*pl == pid)
    132155                        continue;
    133                     if (kill(*pl, signo) != 0) {
    134                         errors++;
    135                         if (quiet==0)
    136                             bb_perror_msg( "Could not kill pid '%ld'", *pl);
    137                     }
     156                    if (kill(*pl, signo) == 0)
     157                        continue;
     158                    errors++;
     159                    if (!quiet)
     160                        bb_perror_msg("cannot kill pid %u", (unsigned)*pl);
    138161                }
    139162            }
    140163            free(pidList);
    141             argv++;
     164            arg = *++argv;
    142165        }
     166        return errors;
    143167    }
    144 #endif
     168
     169    /* Looks like they want to do a kill. Do that */
     170    while (arg) {
     171        /* Support shell 'space' trick */
     172        if (arg[0] == ' ')
     173            arg++;
     174        pid = bb_strtoi(arg, NULL, 10);
     175        if (errno) {
     176            bb_error_msg("bad pid '%s'", arg);
     177            errors++;
     178        } else if (kill(pid, signo) != 0) {
     179            bb_perror_msg("cannot kill pid %d", (int)pid);
     180            errors++;
     181        }
     182        arg = *++argv;
     183    }
    145184    return errors;
    146185}
  • branches/stable/mindi-busybox/procps/pidof.c

    r821 r1770  
    55 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
    66 *
    7  * Licensed under the GPL v2, see the file LICENSE in this tarball.
     7 * Licensed under the GPL version 2, see the file LICENSE in this tarball.
    88 */
    99
    10 #include "busybox.h"
    11 #include <stdio.h>
    12 #include <stdlib.h>
    13 #include <errno.h>
    14 #include <unistd.h>
    15 #include <signal.h>
    16 #include <ctype.h>
    17 #include <string.h>
    18 #include <sys/types.h>
    19 #include <unistd.h>
     10#include "libbb.h"
    2011
    21 #if ENABLE_FEATURE_PIDOF_SINGLE
    22 #define _SINGLE_COMPL(a) a
    23 #define SINGLE (1<<0)
    24 #else
    25 #define _SINGLE_COMPL(a)
    26 #define SINGLE (0)
    27 #endif
     12enum {
     13    USE_FEATURE_PIDOF_SINGLE(OPTBIT_SINGLE,)
     14    USE_FEATURE_PIDOF_OMIT(  OPTBIT_OMIT  ,)
     15    OPT_SINGLE = USE_FEATURE_PIDOF_SINGLE((1<<OPTBIT_SINGLE)) + 0,
     16    OPT_OMIT   = USE_FEATURE_PIDOF_OMIT(  (1<<OPTBIT_OMIT  )) + 0,
     17};
    2818
    29 #if ENABLE_FEATURE_PIDOF_OMIT
    30 #define _OMIT_COMPL(a) a
    31 #define _OMIT(a) ,a
    32 #if ENABLE_FEATURE_PIDOF_SINGLE
    33 #define OMIT (1<<1)
    34 #else
    35 #define OMIT (1<<0)
    36 #endif
    37 #else
    38 #define _OMIT_COMPL(a) ""
    39 #define _OMIT(a)
    40 #define OMIT (0)
    41 #define omitted (0)
    42 #endif
    43 
     19int pidof_main(int argc, char **argv);
    4420int pidof_main(int argc, char **argv)
    4521{
    46     unsigned n = 0;
    47     unsigned fail = 1;
    48     unsigned long int opt;
     22    unsigned first = 1;
     23    unsigned opt;
    4924#if ENABLE_FEATURE_PIDOF_OMIT
     25    char ppid_str[sizeof(int)*3 + 1];
    5026    llist_t *omits = NULL; /* list of pids to omit */
    51     bb_opt_complementally = _OMIT_COMPL("o::");
     27    opt_complementary = "o::";
    5228#endif
    5329
    5430    /* do unconditional option parsing */
    55     opt = bb_getopt_ulflags(argc, argv,
    56                     _SINGLE_COMPL("s") _OMIT_COMPL("o:")
    57                     _OMIT(&omits));
     31    opt = getopt32(argv, ""
     32            USE_FEATURE_PIDOF_SINGLE ("s")
     33            USE_FEATURE_PIDOF_OMIT("o:", &omits));
    5834
    5935#if ENABLE_FEATURE_PIDOF_OMIT
    6036    /* fill omit list.  */
    6137    {
    62         char getppid_str[32];
    63         llist_t * omits_p = omits;
     38        llist_t *omits_p = omits;
    6439        while (omits_p) {
    6540            /* are we asked to exclude the parent's process ID?  */
    66             if (!strncmp(omits_p->data, "%PPID", 5)) {
    67                 llist_pop(&omits_p);
    68                 snprintf(getppid_str, sizeof(getppid_str), "%d", getppid());
    69                 llist_add_to(&omits_p, getppid_str);
     41            if (strcmp(omits_p->data, "%PPID") == 0) {
     42                sprintf(ppid_str, "%u", (unsigned)getppid());
     43                omits_p->data = ppid_str;
    7044            }
    7145            omits_p = omits_p->link;
     
    7448#endif
    7549    /* Looks like everything is set to go.  */
    76     while(optind < argc) {
    77         long *pidList;
    78         long *pl;
     50    while (optind < argc) {
     51        pid_t *pidList;
     52        pid_t *pl;
    7953
    8054        /* reverse the pidlist like GNU pidof does.  */
    8155        pidList = pidlist_reverse(find_pid_by_name(argv[optind]));
    82         for(pl = pidList; *pl > 0; pl++) {
     56        for (pl = pidList; *pl; pl++) {
    8357#if ENABLE_FEATURE_PIDOF_OMIT
    84             unsigned omitted = 0;
    85             if (opt & OMIT) {
     58            if (opt & OPT_OMIT) {
    8659                llist_t *omits_p = omits;
    87                 while (omits_p)
    88                     if (strtol(omits_p->data, NULL, 10) == *pl) {
    89                         omitted = 1; break;
    90                     } else
    91                         omits_p = omits_p->link;
     60                while (omits_p) {
     61                    if (xatoul(omits_p->data) == *pl) {
     62                        goto omitting;
     63                    }
     64                    omits_p = omits_p->link;
     65                }
    9266            }
    9367#endif
    94             if (!omitted) {
    95                 if (n) {
    96                     putchar(' ');
    97                 } else {
    98                     n = 1;
    99                 }
    100                 printf("%ld", *pl);
    101             }
    102             fail = (!ENABLE_FEATURE_PIDOF_OMIT && omitted);
    103 
    104             if (ENABLE_FEATURE_PIDOF_SINGLE && (opt & SINGLE))
     68            printf(" %u" + first, (unsigned)*pl);
     69            first = 0;
     70            if (ENABLE_FEATURE_PIDOF_SINGLE && (opt & OPT_SINGLE))
    10571                break;
     72#if ENABLE_FEATURE_PIDOF_OMIT
     73 omitting: ;
     74#endif
    10675        }
    10776        free(pidList);
     
    11483        llist_free(omits, NULL);
    11584#endif
    116     return fail ? EXIT_FAILURE : EXIT_SUCCESS;
     85    return first; /* 1 (failure) - no processes found */
    11786}
  • branches/stable/mindi-busybox/procps/ps.c

    r821 r1770  
    44 *
    55 * 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>
    68 *
    7  * Licensed under the GPL v2, see the file LICENSE in this tarball.
     9 * Licensed under the GPL version 2, see the file LICENSE in this tarball.
    810 */
    911
    10 #include "busybox.h"
    11 #include <stdio.h>
    12 #include <stdlib.h>
    13 #include <unistd.h>
    14 #include <dirent.h>
    15 #include <errno.h>
    16 #include <fcntl.h>
    17 #include <ctype.h>
    18 #include <string.h>
    19 #include <termios.h>
    20 #include <sys/ioctl.h>
    21 #if ENABLE_SELINUX
    22 #include <selinux/selinux.h>  /* for is_selinux_enabled()  */
    23 #endif
    24 
     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);
    25282int ps_main(int argc, char **argv)
    26283{
    27     procps_status_t * p;
    28     int i, len;
    29 
    30 #if ENABLE_SELINUX
    31     int use_selinux = 0;
    32     security_context_t sid=NULL;
    33 #endif
    34 
    35 #if ENABLE_FEATURE_PS_WIDE
     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
    36353    int terminal_width;
    37354    int w_count = 0;
    38 
    39     bb_opt_complementally="-:ww";
    40 #else
    41 # define terminal_width 79
    42355#endif
    43356
    44357#if ENABLE_FEATURE_PS_WIDE || ENABLE_SELINUX
    45     /* handle arguments */
    46 #if ENABLE_FEATURE_PS_WIDE && ENABLE_SELINUX
    47     i = bb_getopt_ulflags(argc, argv, "wc", &w_count);
    48 #elif ENABLE_FEATURE_PS_WIDE && !ENABLE_SELINUX
    49     bb_getopt_ulflags(argc, argv, "w", &w_count);
    50 #else /* !ENABLE_FEATURE_PS_WIDE && ENABLE_SELINUX */
    51     i = bb_getopt_ulflags(argc, argv, "c");
    52 #endif
    53358#if ENABLE_FEATURE_PS_WIDE
     359    opt_complementary = "-:ww";
     360    USE_SELINUX(i =) getopt32(argv, USE_SELINUX("Z") "w", &w_count);
    54361    /* if w is given once, GNU ps sets the width to 132,
    55362     * if w is given more than once, it is "unlimited"
    56363     */
    57     if(w_count) {
    58         terminal_width = (w_count==1) ? 132 : INT_MAX;
     364    if (w_count) {
     365        terminal_width = (w_count==1) ? 132 : MAX_WIDTH;
    59366    } else {
    60         get_terminal_width_height(1, &terminal_width, NULL);
     367        get_terminal_width_height(0, &terminal_width, NULL);
    61368        /* Go one less... */
    62         terminal_width--;
    63     }
    64 #endif
    65 #if ENABLE_SELINUX
    66     if ((i & (1+ENABLE_FEATURE_PS_WIDE)) && is_selinux_enabled())
    67         use_selinux = 1;
    68 #endif
    69 #endif  /* ENABLE_FEATURE_PS_WIDE || ENABLE_SELINUX */
    70 
    71 #if ENABLE_SELINUX
     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
    72381    if (use_selinux)
    73       printf("  PID Context                          Stat Command\n");
     382        puts("  PID Context                          Stat Command");
    74383    else
    75 #endif
    76       printf("  PID  Uid     VmSize Stat Command\n");
    77 
    78     while ((p = procps_scan(1)) != 0)  {
    79         char *namecmd = p->cmd;
    80 #if ENABLE_SELINUX
    81         if (use_selinux)
    82           {
    83             char sbuf[128];
    84             len = sizeof(sbuf);
    85 
    86             if (is_selinux_enabled()) {
    87               if (getpidcon(p->pid,&sid)<0)
    88                 sid=NULL;
    89             }
    90 
    91             if (sid) {
    92               /*  I assume sid initilized with NULL  */
    93               len = strlen(sid)+1;
    94               safe_strncpy(sbuf, sid, len);
    95               freecon(sid);
    96               sid=NULL;
    97             }else {
    98               safe_strncpy(sbuf, "unknown",7);
    99             }
    100             len = printf("%5d %-32s %s ", p->pid, sbuf, p->state);
    101         }
    102         else
    103 #endif
    104           if(p->rss == 0)
    105             len = printf("%5d %-8s        %s ", p->pid, p->user, p->state);
    106           else
    107             len = printf("%5d %-8s %6ld %s ", p->pid, p->user, p->rss, p->state);
    108 
    109         i = terminal_width-len;
    110 
    111         if(namecmd && namecmd[0]) {
    112             if(i < 0)
    113                 i = 0;
    114             if(strlen(namecmd) > (size_t)i)
    115                 namecmd[i] = 0;
    116             printf("%s\n", namecmd);
    117         } else {
    118             namecmd = p->short_cmd;
    119             if(i < 2)
    120                 i = 2;
    121             if(strlen(namecmd) > ((size_t)i-2))
    122                 namecmd[i-2] = 0;
    123             printf("[%s]\n", namecmd);
    124         }
    125         /* no check needed, but to make valgrind happy..  */
    126         if (ENABLE_FEATURE_CLEAN_UP && p->cmd)
    127             free(p->cmd);
    128     }
     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();
    129421    return EXIT_SUCCESS;
    130422}
     423
     424#endif /* ENABLE_DESKTOP */
  • branches/stable/mindi-busybox/procps/renice.c

    r821 r1770  
    2020 */
    2121
    22 #include "busybox.h"
    23 #include <stdio.h>
    24 #include <stdlib.h>
    25 #include <string.h>
    26 #include <limits.h>
    27 #include <errno.h>
    28 #include <unistd.h>
     22#include "libbb.h"
    2923#include <sys/resource.h>
    3024
    31 #if (PRIO_PROCESS < CHAR_MIN) || (PRIO_PROCESS > CHAR_MAX)
    32 #error Assumption violated : PRIO_PROCESS value
    33 #endif
    34 #if (PRIO_PGRP < CHAR_MIN) || (PRIO_PGRP > CHAR_MAX)
    35 #error Assumption violated : PRIO_PGRP value
    36 #endif
    37 #if (PRIO_USER < CHAR_MIN) || (PRIO_USER > CHAR_MAX)
    38 #error Assumption violated : PRIO_USER value
    39 #endif
     25void BUG_bad_PRIO_PROCESS(void);
     26void BUG_bad_PRIO_PGRP(void);
     27void BUG_bad_PRIO_USER(void);
    4028
    41 static inline int int_add_no_wrap(int a, int b)
    42 {
    43     int s = a + b;
    44 
    45     if (b < 0) {
    46         if (s > a) s = INT_MIN;
    47     } else {
    48         if (s < a) s = INT_MAX;
    49     }
    50 
    51     return s;
    52 }
    53 
     29int renice_main(int argc, char **argv);
    5430int renice_main(int argc, char **argv)
    5531{
    56     static const char Xetpriority_msg[] = "%d : %cetpriority";
     32    static const char Xetpriority_msg[] ALIGN1 = "%cetpriority";
    5733
    5834    int retval = EXIT_SUCCESS;
     
    6036    int use_relative = 0;
    6137    int adjustment, new_priority;
    62     id_t who;
     38    unsigned who;
     39    char *arg;
    6340
    64     ++argv;
     41    /* Yes, they are not #defines in glibc 2.4! #if won't work */
     42    if (PRIO_PROCESS < CHAR_MIN || PRIO_PROCESS > CHAR_MAX)
     43        BUG_bad_PRIO_PROCESS();
     44    if (PRIO_PGRP < CHAR_MIN || PRIO_PGRP > CHAR_MAX)
     45        BUG_bad_PRIO_PGRP();
     46    if (PRIO_USER < CHAR_MIN || PRIO_USER > CHAR_MAX)
     47        BUG_bad_PRIO_USER();
     48
     49    arg = *++argv;
    6550
    6651    /* Check if we are using a relative adjustment. */
    67     if (argv[0] && (argv[0][0] == '-') && (argv[0][1] == 'n') && !argv[0][2]) {
     52    if (arg && arg[0] == '-' && arg[1] == 'n') {
    6853        use_relative = 1;
    69         ++argv;
     54        if (!arg[2])
     55            arg = *++argv;
     56        else
     57            arg += 2;
    7058    }
    7159
    72     if (!*argv) {               /* No args?  Then show usage. */
     60    if (!arg) {             /* No args?  Then show usage. */
    7361        bb_show_usage();
    7462    }
    7563
    7664    /* Get the priority adjustment (absolute or relative). */
    77     adjustment = bb_xgetlarg(*argv, 10, INT_MIN, INT_MAX);
     65    adjustment = xatoi_range(arg, INT_MIN/2, INT_MAX/2);
    7866
    79     while (*++argv) {
     67    while ((arg = *++argv) != NULL) {
    8068        /* Check for a mode switch. */
    81         if ((argv[0][0] == '-') && argv[0][1] && !argv[0][2]) {
    82             static const char opts[]
    83                 = { 'p', 'g', 'u', 0, PRIO_PROCESS, PRIO_PGRP, PRIO_USER };
    84             const char *p;
    85             if ((p = strchr(opts, argv[0][1]))) {
     69        if (arg[0] == '-' && arg[1]) {
     70            static const char opts[] ALIGN1 = {
     71                'p', 'g', 'u', 0, PRIO_PROCESS, PRIO_PGRP, PRIO_USER
     72            };
     73            const char *p = strchr(opts, arg[1]);
     74            if (p) {
    8675                which = p[4];
    87                 continue;
     76                if (!arg[2])
     77                    continue;
     78                arg += 2;
    8879            }
    8980        }
     
    9283        if (which == PRIO_USER) {
    9384            struct passwd *p;
    94             if (!(p = getpwnam(*argv))) {
    95                 bb_error_msg("unknown user: %s", *argv);
     85            p = getpwnam(arg);
     86            if (!p) {
     87                bb_error_msg("unknown user: %s", arg);
    9688                goto HAD_ERROR;
    9789            }
    9890            who = p->pw_uid;
    9991        } else {
    100             char *e;
    101             errno = 0;
    102             who = strtoul(*argv, &e, 10);
    103             if (*e || (*argv == e) || errno) {
    104                 bb_error_msg("bad value: %s", *argv);
     92            who = bb_strtou(arg, NULL, 10);
     93            if (errno) {
     94                bb_error_msg("bad value: %s", arg);
    10595                goto HAD_ERROR;
    10696            }
     
    114104            old_priority = getpriority(which, who);
    115105            if (errno) {
    116                 bb_perror_msg(Xetpriority_msg, who, 'g');
     106                bb_perror_msg(Xetpriority_msg, 'g');
    117107                goto HAD_ERROR;
    118108            }
    119109
    120             new_priority = int_add_no_wrap(old_priority, adjustment);
     110            new_priority = old_priority + adjustment;
    121111        } else {
    122112            new_priority = adjustment;
     
    127117        }
    128118
    129         bb_perror_msg(Xetpriority_msg, who, 's');
    130     HAD_ERROR:
     119        bb_perror_msg(Xetpriority_msg, 's');
     120 HAD_ERROR:
    131121        retval = EXIT_FAILURE;
    132122    }
  • branches/stable/mindi-busybox/procps/sysctl.c

    r821 r1770  
    1515 */
    1616
    17 #include "busybox.h"
    18 #include <stdio.h>
    19 #include <stdlib.h>
    20 #include <unistd.h>
    21 #include <sys/stat.h>
    22 #include <sys/types.h>
    23 #include <dirent.h>
    24 #include <string.h>
    25 #include <errno.h>
    26 #include <fcntl.h>
     17#include "libbb.h"
    2718
    2819/*
     
    3728 *    Globals...
    3829 */
    39 static const char PROC_PATH[] = "/proc/sys/";
    40 static const char DEFAULT_PRELOAD[] = "/etc/sysctl.conf";
     30static const char PROC_PATH[] ALIGN1 = "/proc/sys/";
     31static const char DEFAULT_PRELOAD[] ALIGN1 = "/etc/sysctl.conf";
    4132
    4233/* error messages */
    43 static const char ERR_UNKNOWN_PARAMETER[] = "error: Unknown parameter '%s'\n";
    44 static const char ERR_MALFORMED_SETTING[] = "error: Malformed setting '%s'\n";
    45 static const char ERR_NO_EQUALS[] =
     34static const char ERR_UNKNOWN_PARAMETER[] ALIGN1 =
     35    "error: Unknown parameter '%s'\n";
     36static const char ERR_MALFORMED_SETTING[] ALIGN1 =
     37    "error: Malformed setting '%s'\n";
     38static const char ERR_NO_EQUALS[] ALIGN1 =
    4639    "error: '%s' must be of the form name=value\n";
    47 static const char ERR_INVALID_KEY[] = "error: '%s' is an unknown key\n";
    48 static const char ERR_UNKNOWN_WRITING[] =
     40static const char ERR_INVALID_KEY[] ALIGN1 =
     41    "error: '%s' is an unknown key\n";
     42static const char ERR_UNKNOWN_WRITING[] ALIGN1 =
    4943    "error: unknown error %d setting key '%s'\n";
    50 static const char ERR_UNKNOWN_READING[] =
     44static const char ERR_UNKNOWN_READING[] ALIGN1 =
    5145    "error: unknown error %d reading key '%s'\n";
    52 static const char ERR_PERMISSION_DENIED[] =
     46static const char ERR_PERMISSION_DENIED[] ALIGN1 =
    5347    "error: permission denied on key '%s'\n";
    54 static const char ERR_PRELOAD_FILE[] =
    55     "error: unable to open preload file '%s'\n";
    56 static const char WARN_BAD_LINE[] =
     48static const char ERR_PRELOAD_FILE[] ALIGN1 =
     49    "error: cannot open preload file '%s'\n";
     50static const char WARN_BAD_LINE[] ALIGN1 =
    5751    "warning: %s(%d): invalid syntax, continuing...\n";
    5852
     
    6660 *    sysctl_main()...
    6761 */
     62int sysctl_main(int argc, char **argv);
    6863int sysctl_main(int argc, char **argv)
    6964{
     
    139134
    140135    while (fgets(oneline, sizeof(oneline) - 1, fp)) {
    141         oneline[sizeof(oneline) - 1] = 0;
     136        oneline[sizeof(oneline) - 1] = '\0';
    142137        lineno++;
    143138        trim(oneline);
     
    166161        while ((*value == ' ' || *value == '\t') && *value != 0)
    167162            value++;
    168         strcpy(buffer, name);
    169         strcat(buffer, "=");
    170         strcat(buffer, value);
     163        /* safe because sizeof(oneline) == sizeof(buffer) */
     164        sprintf(buffer, "%s=%s", name, value);
    171165        sysctl_write_setting(buffer, output);
    172166    }
     
    203197    }
    204198
    205     tmpname = bb_xasprintf("%s%.*s", PROC_PATH, (int)(equals - name), name);
    206     outname = bb_xstrdup(tmpname + strlen(PROC_PATH));
     199    tmpname = xasprintf("%s%.*s", PROC_PATH, (int)(equals - name), name);
     200    outname = xstrdup(tmpname + strlen(PROC_PATH));
    207201
    208202    while ((cptr = strchr(tmpname, '.')) != NULL)
     
    212206        *cptr = '.';
    213207
    214     if ((fd = open(tmpname, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) {
     208    fd = open(tmpname, O_WRONLY | O_CREAT | O_TRUNC, 0666);
     209    if (fd < 0) {
    215210        switch (errno) {
    216211        case ENOENT:
     
    259254
    260255    tmpname = concat_path_file(PROC_PATH, name);
    261     outname = bb_xstrdup(tmpname + strlen(PROC_PATH));
     256    outname = xstrdup(tmpname + strlen(PROC_PATH));
    262257
    263258    while ((cptr = strchr(tmpname, '.')) != NULL)
     
    310305    struct stat ts;
    311306
    312     if (!(dp = bb_opendir(path))) {
     307    dp = opendir(path);
     308    if (!dp) {
    313309        retval = -1;
    314310    } else {
    315311        while ((de = readdir(dp)) != NULL) {
    316312            tmpdir = concat_subpath_file(path, de->d_name);
    317             if(tmpdir == NULL)
     313            if (tmpdir == NULL)
    318314                continue;
    319             if ((retval2 = stat(tmpdir, &ts)) != 0)
     315            retval2 = stat(tmpdir, &ts);
     316            if (retval2 != 0)
    320317                bb_perror_msg(tmpdir);
    321318            else {
  • branches/stable/mindi-busybox/procps/top.c

    r821 r1770  
    2929 */
    3030
    31 #include "busybox.h"
    32 #include <sys/types.h>
    33 #include <stdio.h>
    34 #include <stdlib.h>
    35 #include <unistd.h>
    36 #include <string.h>
    37 #include <sys/ioctl.h>
    38 
    39 //#define CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE  /* + 2k */
    40 
    41 #ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
    42 #include <time.h>
    43 #include <fcntl.h>
    44 #include <netinet/in.h>  /* htons */
    45 #endif
    46 
    47 
    48 typedef int (*cmp_t)(procps_status_t *P, procps_status_t *Q);
    49 
    50 static procps_status_t *top;   /* Hehe */
    51 static int ntop;
    52 
    53 #ifdef CONFIG_FEATURE_USE_TERMIOS
    54 static int pid_sort(procps_status_t *P, procps_status_t *Q)
    55 {
     31#include "libbb.h"
     32
     33
     34typedef struct top_status_t {
     35    unsigned long vsz;
     36#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
     37    unsigned long ticks;
     38    unsigned pcpu; /* delta of ticks */
     39#endif
     40    unsigned pid, ppid;
     41    unsigned uid;
     42    char state[4];
     43    char comm[COMM_LEN];
     44} top_status_t;
     45
     46typedef struct jiffy_counts_t {
     47    unsigned long long usr,nic,sys,idle,iowait,irq,softirq,steal;
     48    unsigned long long total;
     49    unsigned long long busy;
     50} jiffy_counts_t;
     51
     52/* This structure stores some critical information from one frame to
     53   the next. Used for finding deltas. */
     54typedef struct save_hist {
     55    unsigned long ticks;
     56    unsigned pid;
     57} save_hist;
     58
     59typedef int (*cmp_funcp)(top_status_t *P, top_status_t *Q);
     60
     61enum { SORT_DEPTH = 3 };
     62
     63struct globals {
     64    top_status_t *top;
     65    int ntop;
     66#if ENABLE_FEATURE_USE_TERMIOS
     67    struct termios initial_settings;
     68#endif
     69#if !ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
     70    cmp_funcp sort_function;
     71#else
     72    cmp_funcp sort_function[SORT_DEPTH];
     73    struct save_hist *prev_hist;
     74    int prev_hist_count;
     75    jiffy_counts_t jif, prev_jif;
     76    /* int hist_iterations; */
     77    unsigned total_pcpu;
     78    /* unsigned long total_vsz; */
     79#endif
     80};
     81#define G (*(struct globals*)&bb_common_bufsiz1)
     82#define top              (G.top               )
     83#define ntop             (G.ntop              )
     84#if ENABLE_FEATURE_USE_TERMIOS
     85#define initial_settings (G. initial_settings )
     86#endif
     87#define sort_function    (G.sort_function     )
     88#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
     89#define prev_hist        (G.prev_hist         )
     90#define prev_hist_count  (G.prev_hist_count   )
     91#define jif              (G.jif               )
     92#define prev_jif         (G.prev_jif          )
     93#define total_pcpu       (G.total_pcpu        )
     94#endif
     95
     96#define OPT_BATCH_MODE (option_mask32 & 0x4)
     97
     98
     99#if ENABLE_FEATURE_USE_TERMIOS
     100static int pid_sort(top_status_t *P, top_status_t *Q)
     101{
     102    /* Buggy wrt pids with high bit set */
     103    /* (linux pids are in [1..2^15-1]) */
    56104    return (Q->pid - P->pid);
    57105}
    58106#endif
    59107
    60 static int mem_sort(procps_status_t *P, procps_status_t *Q)
    61 {
    62     return (int)(Q->rss - P->rss);
    63 }
    64 
    65 #ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
    66 
    67 #define sort_depth 3
    68 static cmp_t sort_function[sort_depth];
    69 
    70 static int pcpu_sort(procps_status_t *P, procps_status_t *Q)
    71 {
    72     return (Q->pcpu - P->pcpu);
    73 }
    74 
    75 static int time_sort(procps_status_t *P, procps_status_t *Q)
    76 {
    77     return (int)((Q->stime + Q->utime) - (P->stime + P->utime));
    78 }
    79 
    80 static int mult_lvl_cmp(void* a, void* b) {
     108static int mem_sort(top_status_t *P, top_status_t *Q)
     109{
     110    /* We want to avoid unsigned->signed and truncation errors */
     111    if (Q->vsz < P->vsz) return -1;
     112    return Q->vsz != P->vsz; /* 0 if ==, 1 if > */
     113}
     114
     115
     116#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
     117
     118static int pcpu_sort(top_status_t *P, top_status_t *Q)
     119{
     120    /* Buggy wrt ticks with high bit set */
     121    /* Affects only processes for which ticks overflow */
     122    return (int)Q->pcpu - (int)P->pcpu;
     123}
     124
     125static int time_sort(top_status_t *P, top_status_t *Q)
     126{
     127    /* We want to avoid unsigned->signed and truncation errors */
     128    if (Q->ticks < P->ticks) return -1;
     129    return Q->ticks != P->ticks; /* 0 if ==, 1 if > */
     130}
     131
     132static int mult_lvl_cmp(void* a, void* b)
     133{
    81134    int i, cmp_val;
    82135
    83     for (i = 0; i < sort_depth; i++) {
     136    for (i = 0; i < SORT_DEPTH; i++) {
    84137        cmp_val = (*sort_function[i])(a, b);
    85138        if (cmp_val != 0)
     
    89142}
    90143
    91 /* This structure stores some critical information from one frame to
    92    the next. mostly used for sorting. Added cumulative and resident fields. */
    93 struct save_hist {
    94     int ticks;
    95     int pid;
    96 };
    97 
    98 /*
    99  * Calculates percent cpu usage for each task.
    100  */
    101 
    102 static struct save_hist *prev_hist;
    103 static int prev_hist_count;
    104 /* static int hist_iterations; */
    105 
    106 
    107 static unsigned total_pcpu;
    108 /* static unsigned long total_rss; */
    109 
    110 struct jiffy_counts {
    111     unsigned long long usr,nic,sys,idle,iowait,irq,softirq,steal;
    112     unsigned long long total;
    113     unsigned long long busy;
    114 };
    115 static struct jiffy_counts jif, prev_jif;
    116144
    117145static void get_jiffy_counts(void)
    118146{
    119     FILE* fp = bb_xfopen("stat", "r");
     147    FILE* fp = xfopen("stat", "r");
    120148    prev_jif = jif;
    121149    if (fscanf(fp, "cpu  %lld %lld %lld %lld %lld %lld %lld %lld",
    122150            &jif.usr,&jif.nic,&jif.sys,&jif.idle,
    123151            &jif.iowait,&jif.irq,&jif.softirq,&jif.steal) < 4) {
    124         bb_error_msg_and_die("failed to read 'stat'");
     152        bb_error_msg_and_die("failed to read /proc/stat");
    125153    }
    126154    fclose(fp);
     
    131159}
    132160
     161
    133162static void do_stats(void)
    134163{
    135     procps_status_t *cur;
    136     int pid, total_time, i, last_i, n;
     164    top_status_t *cur;
     165    pid_t pid;
     166    int i, last_i, n;
    137167    struct save_hist *new_hist;
    138168
    139169    get_jiffy_counts();
    140170    total_pcpu = 0;
    141     /* total_rss = 0; */
     171    /* total_vsz = 0; */
    142172    new_hist = xmalloc(sizeof(struct save_hist)*ntop);
    143173    /*
     
    154184         */
    155185        pid = cur->pid;
    156         total_time = cur->stime + cur->utime;
    157         new_hist[n].ticks = total_time;
     186        new_hist[n].ticks = cur->ticks;
    158187        new_hist[n].pid = pid;
    159188
     
    165194        if (prev_hist_count) do {
    166195            if (prev_hist[i].pid == pid) {
    167                 cur->pcpu = total_time - prev_hist[i].ticks;
     196                cur->pcpu = cur->ticks - prev_hist[i].ticks;
     197                total_pcpu += cur->pcpu;
    168198                break;
    169199            }
     
    171201            /* hist_iterations++; */
    172202        } while (i != last_i);
    173         total_pcpu += cur->pcpu;
    174         /* total_rss += cur->rss; */
     203        /* total_vsz += cur->vsz; */
    175204    }
    176205
     
    182211    prev_hist_count = ntop;
    183212}
    184 #else
    185 static cmp_t sort_function;
    186 #endif /* CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE */
     213#endif /* FEATURE_TOP_CPU_USAGE_PERCENTAGE */
     214
     215#if ENABLE_FEATURE_TOP_CPU_GLOBAL_PERCENTS && ENABLE_FEATURE_TOP_DECIMALS
     216/* formats 7 char string (8 with terminating NUL) */
     217static char *fmt_100percent_8(char pbuf[8], unsigned value, unsigned total)
     218{
     219    unsigned t;
     220    if (value >= total) { /* 100% ? */
     221        strcpy(pbuf, "  100% ");
     222        return pbuf;
     223    }
     224    /* else generate " [N/space]N.N% " string */
     225    value = 1000 * value / total;
     226    t = value / 100;
     227    value = value % 100;
     228    pbuf[0] = ' ';
     229    pbuf[1] = t ? t + '0' : ' ';
     230    pbuf[2] = '0' + (value / 10);
     231    pbuf[3] = '.';
     232    pbuf[4] = '0' + (value % 10);
     233    pbuf[5] = '%';
     234    pbuf[6] = ' ';
     235    pbuf[7] = '\0';
     236    return pbuf;
     237}
     238#endif
    187239
    188240/* display generic info (meminfo / loadavg) */
     
    192244    char buf[80];
    193245    char scrbuf[80];
    194     char *end;
    195246    unsigned long total, used, mfree, shared, buffers, cached;
    196     unsigned int needs_conversion = 1;
     247#if ENABLE_FEATURE_TOP_CPU_GLOBAL_PERCENTS
     248    unsigned total_diff;
     249#endif
    197250
    198251    /* read memory info */
    199     fp = bb_xfopen("meminfo", "r");
     252    fp = xfopen("meminfo", "r");
    200253
    201254    /*
     
    213266
    214267        fscanf(fp, "Mem: %lu %lu %lu %lu %lu %lu",
    215            &total, &used, &mfree, &shared, &buffers, &cached);
    216     } else {
    217         /*
    218          * Revert to manual parsing, which incidentally already has the
    219          * sizes in kilobytes. This should be safe for both 2.4 and
    220          * 2.6.
    221          */
    222         needs_conversion = 0;
    223 
    224         fscanf(fp, "MemFree: %lu %s\n", &mfree, buf);
    225 
    226         /*
    227          * MemShared: is no longer present in 2.6. Report this as 0,
    228          * to maintain consistent behavior with normal procps.
    229          */
    230         if (fscanf(fp, "MemShared: %lu %s\n", &shared, buf) != 2)
    231             shared = 0;
    232 
    233         fscanf(fp, "Buffers: %lu %s\n", &buffers, buf);
    234         fscanf(fp, "Cached: %lu %s\n", &cached, buf);
    235 
    236         used = total - mfree;
    237     }
    238     fclose(fp);
    239 
    240     /* read load average as a string */
    241     fp = bb_xfopen("loadavg", "r");
    242     buf[0] = '\0';
    243     fgets(buf, sizeof(buf), fp);
    244     end = strchr(buf, ' ');
    245     if (end) end = strchr(end+1, ' ');
    246     if (end) end = strchr(end+1, ' ');
    247     if (end) *end = '\0';
    248     fclose(fp);
    249 
    250     if (needs_conversion) {
     268            &total, &used, &mfree, &shared, &buffers, &cached);
    251269        /* convert to kilobytes */
    252270        used /= 1024;
     
    256274        cached /= 1024;
    257275        total /= 1024;
    258     }
    259 
    260     /* output memory info and load average */
    261     /* clear screen & go to top */
     276    } else {
     277        /*
     278         * Revert to manual parsing, which incidentally already has the
     279         * sizes in kilobytes. This should be safe for both 2.4 and
     280         * 2.6.
     281         */
     282
     283        fscanf(fp, "MemFree: %lu %s\n", &mfree, buf);
     284
     285        /*
     286         * MemShared: is no longer present in 2.6. Report this as 0,
     287         * to maintain consistent behavior with normal procps.
     288         */
     289        if (fscanf(fp, "MemShared: %lu %s\n", &shared, buf) != 2)
     290            shared = 0;
     291
     292        fscanf(fp, "Buffers: %lu %s\n", &buffers, buf);
     293        fscanf(fp, "Cached: %lu %s\n", &cached, buf);
     294
     295        used = total - mfree;
     296    }
     297    fclose(fp);
     298
     299    /* output memory info */
    262300    if (scr_width > sizeof(scrbuf))
    263301        scr_width = sizeof(scrbuf);
    264302    snprintf(scrbuf, scr_width,
    265         "Mem: %ldK used, %ldK free, %ldK shrd, %ldK buff, %ldK cached",
     303        "Mem: %luK used, %luK free, %luK shrd, %luK buff, %luK cached",
    266304        used, mfree, shared, buffers, cached);
    267     printf("\e[H\e[J%s\n", scrbuf);
    268     snprintf(scrbuf, scr_width,
    269         "Load average: %s  (Status: S=sleeping R=running, W=waiting)", buf);
    270     printf("%s\n", scrbuf);
     305    /* clear screen & go to top */
     306    printf(OPT_BATCH_MODE ? "%s\n" : "\e[H\e[J%s\n", scrbuf);
     307
     308#if ENABLE_FEATURE_TOP_CPU_GLOBAL_PERCENTS
     309    /*
     310     * xxx% = (jif.xxx - prev_jif.xxx) / (jif.total - prev_jif.total) * 100%
     311     */
     312    /* using (unsigned) casts to make operations cheaper */
     313    total_diff = ((unsigned)(jif.total - prev_jif.total) ? : 1);
     314#if ENABLE_FEATURE_TOP_DECIMALS
     315/* Generated code is approx +0.3k */
     316#define CALC_STAT(xxx) char xxx[8]
     317#define SHOW_STAT(xxx) fmt_100percent_8(xxx, (unsigned)(jif.xxx - prev_jif.xxx), total_diff)
     318#define FMT "%s"
     319#else
     320#define CALC_STAT(xxx) unsigned xxx = 100 * (unsigned)(jif.xxx - prev_jif.xxx) / total_diff
     321#define SHOW_STAT(xxx) xxx
     322#define FMT "%4u%% "
     323#endif
     324    { /* need block: CALC_STAT are declarations */
     325        CALC_STAT(usr);
     326        CALC_STAT(sys);
     327        CALC_STAT(nic);
     328        CALC_STAT(idle);
     329        CALC_STAT(iowait);
     330        CALC_STAT(irq);
     331        CALC_STAT(softirq);
     332        //CALC_STAT(steal);
     333
     334        snprintf(scrbuf, scr_width,
     335            /* Barely fits in 79 chars when in "decimals" mode. */
     336            "CPU:"FMT"usr"FMT"sys"FMT"nice"FMT"idle"FMT"io"FMT"irq"FMT"softirq",
     337            SHOW_STAT(usr), SHOW_STAT(sys), SHOW_STAT(nic), SHOW_STAT(idle),
     338            SHOW_STAT(iowait), SHOW_STAT(irq), SHOW_STAT(softirq)
     339            //, SHOW_STAT(steal) - what is this 'steal' thing?
     340            // I doubt anyone wants to know it
     341        );
     342    }
     343    puts(scrbuf);
     344#undef SHOW_STAT
     345#undef CALC_STAT
     346#undef FMT
     347#endif
     348
     349    /* read load average as a string */
     350    buf[0] = '\0';
     351    open_read_close("loadavg", buf, sizeof("N.NN N.NN N.NN")-1);
     352    buf[sizeof("N.NN N.NN N.NN")-1] = '\0';
     353    snprintf(scrbuf, scr_width, "Load average: %s", buf);
     354    puts(scrbuf);
    271355
    272356    return total;
    273357}
    274 
    275358
    276359/* display process statuses */
     
    278361{
    279362    enum {
    280         bits_per_int = sizeof(int)*8
     363        BITS_PER_INT = sizeof(int)*8
    281364    };
    282365
    283     procps_status_t *s = top;
    284     char rss_str_buf[8];
    285     unsigned long total_memory = display_generic(scr_width); /* or use total_rss? */
    286     unsigned pmem_shift, pmem_scale;
    287 
    288 #ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
    289     unsigned pcpu_shift, pcpu_scale;
     366    top_status_t *s = top;
     367    char vsz_str_buf[8];
     368    unsigned long total_memory = display_generic(scr_width); /* or use total_vsz? */
     369    /* xxx_shift and xxx_scale variables allow us to replace
     370     * expensive divides with multiply and shift */
     371    unsigned pmem_shift, pmem_scale, pmem_half;
     372#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
     373    unsigned pcpu_shift, pcpu_scale, pcpu_half;
     374    unsigned busy_jifs;
    290375
    291376    /* what info of the processes is shown */
    292     printf("\e[7m%.*s\e[0m", scr_width,
    293         "  PID USER     STATUS   RSS  PPID %CPU %MEM COMMAND");
     377    printf(OPT_BATCH_MODE ? "%.*s" : "\e[7m%.*s\e[0m", scr_width,
     378        "  PID  PPID USER     STAT   VSZ %MEM %CPU COMMAND");
    294379#define MIN_WIDTH \
    295     sizeof( "  PID USER     STATUS   RSS  PPID %CPU %MEM C")
    296 #else
    297     printf("\e[7m%.*s\e[0m", scr_width,
    298         "  PID USER     STATUS   RSS  PPID %MEM COMMAND");
     380    sizeof( "  PID  PPID USER     STAT   VSZ %MEM %CPU C")
     381#else
     382
     383    /* !CPU_USAGE_PERCENTAGE */
     384    printf(OPT_BATCH_MODE ? "%.*s" : "\e[7m%.*s\e[0m", scr_width,
     385        "  PID  PPID USER     STAT   VSZ %MEM COMMAND");
    299386#define MIN_WIDTH \
    300     sizeof( "  PID USER     STATUS   RSS  PPID %MEM C")
    301 #endif
    302 
     387    sizeof( "  PID  PPID USER     STAT   VSZ %MEM C")
     388#endif
     389
     390#if ENABLE_FEATURE_TOP_DECIMALS
     391#define UPSCALE 1000
     392#define CALC_STAT(name, val) div_t name = div((val), 10)
     393#define SHOW_STAT(name) name.quot, '0'+name.rem
     394#define FMT "%3u.%c"
     395#else
     396#define UPSCALE 100
     397#define CALC_STAT(name, val) unsigned name = (val)
     398#define SHOW_STAT(name) name
     399#define FMT "%4u%%"
     400#endif
    303401    /*
    304      * MEM% = s->rss/MemTotal
     402     * MEM% = s->vsz/MemTotal
    305403     */
    306     pmem_shift = bits_per_int-11;
    307     pmem_scale = 1000*(1U<<(bits_per_int-11)) / total_memory;
    308     /* s->rss is in kb. we want (s->rss * pmem_scale) to never overflow */
     404    pmem_shift = BITS_PER_INT-11;
     405    pmem_scale = UPSCALE*(1U<<(BITS_PER_INT-11)) / total_memory;
     406    /* s->vsz is in kb. we want (s->vsz * pmem_scale) to never overflow */
    309407    while (pmem_scale >= 512) {
    310408        pmem_scale /= 4;
    311409        pmem_shift -= 2;
    312410    }
    313 #ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
     411    pmem_half = (1U << pmem_shift) / (ENABLE_FEATURE_TOP_DECIMALS? 20 : 2);
     412#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
     413    busy_jifs = jif.busy - prev_jif.busy;
     414    /* This happens if there were lots of short-lived processes
     415     * between two top updates (e.g. compilation) */
     416    if (total_pcpu < busy_jifs) total_pcpu = busy_jifs;
     417
    314418    /*
    315419     * CPU% = s->pcpu/sum(s->pcpu) * busy_cpu_ticks/total_cpu_ticks
     
    321425     */
    322426    pcpu_shift = 6;
    323     pcpu_scale = (1000*64*(uint16_t)(jif.busy-prev_jif.busy) ? : 1);
    324     while (pcpu_scale < (1U<<(bits_per_int-2))) {
     427    pcpu_scale = (UPSCALE*64*(uint16_t)busy_jifs ? : 1);
     428    while (pcpu_scale < (1U<<(BITS_PER_INT-2))) {
    325429        pcpu_scale *= 4;
    326430        pcpu_shift += 2;
     
    332436        pcpu_shift -= 2;
    333437    }
     438    pcpu_half = (1U << pcpu_shift) / (ENABLE_FEATURE_TOP_DECIMALS? 20 : 2);
    334439    /* printf(" pmem_scale=%u pcpu_scale=%u ", pmem_scale, pcpu_scale); */
    335440#endif
    336441
    337     while (count--) {
    338         div_t pmem = div( (s->rss*pmem_scale) >> pmem_shift, 10);
    339         int col = scr_width+1;
    340         USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE(div_t pcpu;)
    341 
    342         if (s->rss >= 100*1024)
    343             sprintf(rss_str_buf, "%6ldM", s->rss/1024);
     442    /* Ok, all prelim data is ready, go thru the list */
     443    while (count-- > 0) {
     444        int col = scr_width;
     445        CALC_STAT(pmem, (s->vsz*pmem_scale + pmem_half) >> pmem_shift);
     446#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
     447        CALC_STAT(pcpu, (s->pcpu*pcpu_scale + pcpu_half) >> pcpu_shift);
     448#endif
     449
     450        if (s->vsz >= 100*1024)
     451            sprintf(vsz_str_buf, "%6ldM", s->vsz/1024);
    344452        else
    345             sprintf(rss_str_buf, "%7ld", s->rss);
    346         USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE(pcpu = div((s->pcpu*pcpu_scale) >> pcpu_shift, 10);)
    347         col -= printf("\n%5d %-8s %s  %s%6d%3u.%c" \
    348                 USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE("%3u.%c") " ",
    349                 s->pid, s->user, s->state, rss_str_buf, s->ppid,
    350                 USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE(pcpu.quot, '0'+pcpu.rem,)
    351                 pmem.quot, '0'+pmem.rem);
    352         if (col>0)
    353             printf("%.*s", col, s->short_cmd);
     453            sprintf(vsz_str_buf, "%7ld", s->vsz);
     454        // PID PPID USER STAT VSZ %MEM [%CPU] COMMAND
     455        col -= printf("\n" "%5u%6u %-8.8s %s%s" FMT
     456#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
     457                FMT
     458#endif
     459                " ",
     460                s->pid, s->ppid, get_cached_username(s->uid),
     461                s->state, vsz_str_buf,
     462                SHOW_STAT(pmem)
     463#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
     464                , SHOW_STAT(pcpu)
     465#endif
     466        );
     467        if (col > 0) {
     468            char buf[col + 1];
     469            read_cmdline(buf, col, s->pid, s->comm);
     470            fputs(buf, stdout);
     471        }
    354472        /* printf(" %d/%d %lld/%lld", s->pcpu, total_pcpu,
    355473            jif.busy - prev_jif.busy, jif.total - prev_jif.total); */
     
    357475    }
    358476    /* printf(" %d", hist_iterations); */
    359     putchar('\r');
     477    putchar(OPT_BATCH_MODE ? '\n' : '\r');
    360478    fflush(stdout);
    361479}
     480#undef UPSCALE
     481#undef SHOW_STAT
     482#undef CALC_STAT
     483#undef FMT
     484
    362485
    363486static void clearmems(void)
    364487{
     488    clear_username_cache();
    365489    free(top);
    366490    top = 0;
     
    368492}
    369493
    370 #ifdef CONFIG_FEATURE_USE_TERMIOS
     494
     495#if ENABLE_FEATURE_USE_TERMIOS
    371496#include <termios.h>
    372497#include <signal.h>
    373498
    374 
    375 static struct termios initial_settings;
    376 
    377499static void reset_term(void)
    378500{
    379501    tcsetattr(0, TCSANOW, (void *) &initial_settings);
    380 #ifdef CONFIG_FEATURE_CLEAN_UP
     502#if ENABLE_FEATURE_CLEAN_UP
    381503    clearmems();
    382 #ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
     504#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
    383505    free(prev_hist);
    384506#endif
    385 #endif /* CONFIG_FEATURE_CLEAN_UP */
     507#endif /* FEATURE_CLEAN_UP */
    386508}
    387509
     
    391513    exit(1);
    392514}
    393 #endif /* CONFIG_FEATURE_USE_TERMIOS */
    394 
    395 
     515#endif /* FEATURE_USE_TERMIOS */
     516
     517
     518int top_main(int argc, char **argv);
    396519int top_main(int argc, char **argv)
    397520{
    398     int opt, interval, lines, col;
    399     char *sinterval;
    400 #ifdef CONFIG_FEATURE_USE_TERMIOS
     521    int count, lines, col;
     522    unsigned interval = 5; /* default update rate is 5 seconds */
     523    unsigned iterations = UINT_MAX; /* 2^32 iterations by default :) */
     524    char *sinterval, *siterations;
     525#if ENABLE_FEATURE_USE_TERMIOS
    401526    struct termios new_settings;
    402527    struct timeval tv;
    403528    fd_set readfds;
    404529    unsigned char c;
    405 #endif /* CONFIG_FEATURE_USE_TERMIOS */
     530#endif /* FEATURE_USE_TERMIOS */
     531
     532    interval = 5;
    406533
    407534    /* do normal option parsing */
    408     opt = bb_getopt_ulflags(argc, argv, "d:", &sinterval);
    409     if ((opt & 1)) {
    410         interval = atoi(sinterval);
    411     } else {
    412         /* Default update rate is 5 seconds */
    413         interval = 5;
    414     }
     535    opt_complementary = "-";
     536    getopt32(argv, "d:n:b", &sinterval, &siterations);
     537    if (option_mask32 & 0x1) interval = xatou(sinterval); // -d
     538    if (option_mask32 & 0x2) iterations = xatou(siterations); // -n
     539    //if (option_mask32 & 0x4) // -b
    415540
    416541    /* change to /proc */
    417     bb_xchdir("/proc");
    418 #ifdef CONFIG_FEATURE_USE_TERMIOS
     542    xchdir("/proc");
     543#if ENABLE_FEATURE_USE_TERMIOS
    419544    tcgetattr(0, (void *) &initial_settings);
    420545    memcpy(&new_settings, &initial_settings, sizeof(struct termios));
    421     new_settings.c_lflag &= ~(ISIG | ICANON); /* unbuffered input */
    422     /* Turn off echoing */
    423     new_settings.c_lflag &= ~(ECHO | ECHONL);
     546    /* unbuffered input, turn off echo */
     547    new_settings.c_lflag &= ~(ISIG | ICANON | ECHO | ECHONL);
    424548
    425549    signal(SIGTERM, sig_catcher);
     
    427551    tcsetattr(0, TCSANOW, (void *) &new_settings);
    428552    atexit(reset_term);
    429 #endif /* CONFIG_FEATURE_USE_TERMIOS */
    430 
    431 #ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
     553#endif /* FEATURE_USE_TERMIOS */
     554
     555#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
    432556    sort_function[0] = pcpu_sort;
    433557    sort_function[1] = mem_sort;
     
    435559#else
    436560    sort_function = mem_sort;
    437 #endif /* CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE */
     561#endif /* FEATURE_TOP_CPU_USAGE_PERCENTAGE */
    438562
    439563    while (1) {
    440         procps_status_t *p;
     564        procps_status_t *p = NULL;
    441565
    442566        /* Default to 25 lines - 5 lines for status */
    443         lines = 24 - 3;
     567        lines = 24 - 3 USE_FEATURE_TOP_CPU_GLOBAL_PERCENTS( - 1);
    444568        col = 79;
    445 #ifdef CONFIG_FEATURE_USE_TERMIOS
     569#if ENABLE_FEATURE_USE_TERMIOS
    446570        get_terminal_width_height(0, &col, &lines);
    447571        if (lines < 5 || col < MIN_WIDTH) {
     
    449573            continue;
    450574        }
    451         lines -= 3;
    452 #endif /* CONFIG_FEATURE_USE_TERMIOS */
     575        lines -= 3 USE_FEATURE_TOP_CPU_GLOBAL_PERCENTS( + 1);
     576#endif /* FEATURE_USE_TERMIOS */
    453577
    454578        /* read process IDs & status for all the processes */
    455         while ((p = procps_scan(0)) != 0) {
     579        while ((p = procps_scan(p, 0
     580                | PSSCAN_PID
     581                | PSSCAN_PPID
     582                | PSSCAN_VSZ
     583                | PSSCAN_STIME
     584                | PSSCAN_UTIME
     585                | PSSCAN_STATE
     586                | PSSCAN_COMM
     587                | PSSCAN_SID
     588                | PSSCAN_UIDGID
     589        ))) {
    456590            int n = ntop;
    457 
    458             top = xrealloc(top, (++ntop)*sizeof(procps_status_t));
    459             memcpy(top + n, p, sizeof(procps_status_t));
     591            top = xrealloc(top, (++ntop) * sizeof(*top));
     592            top[n].pid = p->pid;
     593            top[n].ppid = p->ppid;
     594            top[n].vsz = p->vsz;
     595#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
     596            top[n].ticks = p->stime + p->utime;
     597#endif
     598            top[n].uid = p->uid;
     599            strcpy(top[n].state, p->state);
     600            strcpy(top[n].comm, p->comm);
    460601        }
    461602        if (ntop == 0) {
    462             bb_error_msg_and_die("Can't find process info in /proc");
     603            bb_error_msg_and_die("no process info in /proc");
    463604        }
    464 #ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
     605#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
    465606        if (!prev_hist_count) {
    466607            do_stats();
     
    470611        }
    471612        do_stats();
    472         qsort(top, ntop, sizeof(procps_status_t), (void*)mult_lvl_cmp);
    473 #else
    474         qsort(top, ntop, sizeof(procps_status_t), (void*)sort_function);
    475 #endif /* CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE */
    476         opt = lines;
    477         if (opt > ntop) {
    478             opt = ntop;
     613/* TODO: we don't need to sort all 10000 processes, we need to find top 24! */
     614        qsort(top, ntop, sizeof(top_status_t), (void*)mult_lvl_cmp);
     615#else
     616        qsort(top, ntop, sizeof(top_status_t), (void*)sort_function);
     617#endif /* FEATURE_TOP_CPU_USAGE_PERCENTAGE */
     618        count = lines;
     619        if (OPT_BATCH_MODE || count > ntop) {
     620            count = ntop;
    479621        }
    480622        /* show status for each of the processes */
    481         display_status(opt, col);
    482 #ifdef CONFIG_FEATURE_USE_TERMIOS
     623        display_status(count, col);
     624#if ENABLE_FEATURE_USE_TERMIOS
    483625        tv.tv_sec = interval;
    484626        tv.tv_usec = 0;
     
    493635                break;
    494636            if (c == 'M') {
    495 #ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
     637#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
    496638                sort_function[0] = mem_sort;
    497639                sort_function[1] = pcpu_sort;
     
    501643#endif
    502644            }
    503 #ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
     645#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
    504646            if (c == 'P') {
    505647                sort_function[0] = pcpu_sort;
     
    514656#endif
    515657            if (c == 'N') {
    516 #ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE
     658#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
    517659                sort_function[0] = pid_sort;
    518660#else
     
    521663            }
    522664        }
     665        if (!--iterations)
     666            break;
    523667#else
    524668        sleep(interval);
    525 #endif /* CONFIG_FEATURE_USE_TERMIOS */
     669#endif /* FEATURE_USE_TERMIOS */
    526670        clearmems();
    527671    }
  • branches/stable/mindi-busybox/procps/uptime.c

    r821 r1770  
    55 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
    66 *
    7  * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
     7 * Licensed under the GPL version 2, see the file LICENSE in this tarball.
    88 */
    99
     
    1616/* getopt not needed */
    1717
    18 #include "busybox.h"
    19 #include <stdio.h>
    20 #include <time.h>
    21 #include <errno.h>
    22 #include <stdlib.h>
     18#include "libbb.h"
    2319
    2420#ifndef FSHIFT
     
    3026
    3127
     28int uptime_main(int argc, char **argv);
    3229int uptime_main(int argc, char **argv)
    3330{
     
    5047    uphours = (upminutes / 60) % 24;
    5148    upminutes %= 60;
    52     if(uphours)
     49    if (uphours)
    5350        printf("%2d:%02d, ", uphours, upminutes);
    5451    else
Note: See TracChangeset for help on using the changeset viewer.