Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/procps


Ignore:
Timestamp:
Feb 25, 2011, 9:26:54 PM (13 years ago)
Author:
Bruno Cornec
Message:
  • Update mindi-busybox to 1.18.3 to avoid problems with the tar command which is now failing on recent versions with busybox 1.7.3
Location:
branches/2.2.9/mindi-busybox/procps
Files:
8 added
13 edited

Legend:

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

    r1765 r2725  
     1# DO NOT EDIT. This file is generated from Config.src
    12#
    23# For a description of the syntax of this configuration file,
     
    67menu "Process Utilities"
    78
     9config IOSTAT
     10    bool "iostat"
     11    default y
     12    help
     13      Report CPU and I/O statistics
     14config MPSTAT
     15    bool "mpstat"
     16    default y
     17    help
     18      Per-processor statistics
     19config PMAP
     20       bool "pmap"
     21       default y
     22       help
     23         Display processes' memory mappings.
     24config POWERTOP
     25    bool "powertop"
     26    default y
     27    help
     28      Analyze power consumption on Intel-based laptops
     29config SMEMCAP
     30    bool "smemcap"
     31    default y
     32    help
     33      smemcap is a tool for capturing process data for smem,
     34      a memory usage statistic tool.
     35
    836config FREE
    937    bool "free"
    10     default n
     38    default y
     39    depends on PLATFORM_LINUX #sysinfo()
    1140    help
    1241      free displays the total amount of free and used physical and swap
     
    1645config FUSER
    1746    bool "fuser"
    18     default n
     47    default y
    1948    help
    2049      fuser lists all PIDs (Process IDs) that currently have a given
    21       file open.  fuser can also list all PIDs that have a given network
     50      file open. fuser can also list all PIDs that have a given network
    2251      (TCP or UDP) port open.
    2352
    2453config KILL
    2554    bool "kill"
    26     default n
     55    default y
    2756    help
    2857      The command kill sends the specified signal to the specified
    29       process or process group.  If no signal is specified, the TERM
     58      process or process group. If no signal is specified, the TERM
    3059      signal is sent.
    3160
    3261config KILLALL
    3362    bool "killall"
    34     default n
     63    default y
    3564    depends on KILL
    3665    help
    3766      killall sends a signal to all processes running any of the
    38       specified commands.  If no signal name is specified, SIGTERM is
     67      specified commands. If no signal name is specified, SIGTERM is
    3968      sent.
    4069
    4170config KILLALL5
    4271    bool "killall5"
    43     default n
     72    default y
    4473    depends on KILL
    4574
    4675config NMETER
    4776    bool "nmeter"
    48     default n
     77    default y
    4978    help
    5079      Prints selected system stats continuously, one line per update.
     80
     81config PGREP
     82    bool "pgrep"
     83    default y
     84    help
     85      Look for processes by name.
    5186
    5287config PIDOF
    5388    bool "pidof"
    54     default n
     89    default y
    5590    help
    5691      Pidof finds the process id's (pids) of the named programs. It prints
     
    5994config FEATURE_PIDOF_SINGLE
    6095    bool "Enable argument for single shot (-s)"
    61     default n
     96    default y
    6297    depends on PIDOF
    6398    help
     
    66101config FEATURE_PIDOF_OMIT
    67102    bool "Enable argument for omitting pids (-o)"
    68     default n
     103    default y
    69104    depends on PIDOF
    70105    help
     
    73108      of the pidof, in other words the calling shell or shell script.
    74109
     110config PKILL
     111    bool "pkill"
     112    default y
     113    help
     114      Send signals to processes by name.
     115
    75116config PS
    76117    bool "ps"
     118    default y
     119    help
     120      ps gives a snapshot of the current processes.
     121
     122config FEATURE_PS_WIDE
     123    bool "Enable wide output option (-w)"
     124    default y
     125    depends on PS
     126    help
     127      Support argument 'w' for wide output.
     128      If given once, 132 chars are printed, and if given more
     129      than once, the length is unlimited.
     130
     131config FEATURE_PS_TIME
     132    bool "Enable time and elapsed time output"
     133    default y
     134    depends on PS && DESKTOP && PLATFORM_LINUX #sysinfo()
     135    help
     136      Support -o time and -o etime output specifiers.
     137
     138config FEATURE_PS_ADDITIONAL_COLUMNS
     139    bool "Enable additional ps columns"
     140    default y
     141    depends on PS && DESKTOP
     142    help
     143      Support -o rgroup, -o ruser, -o nice output specifiers.
     144
     145config FEATURE_PS_UNUSUAL_SYSTEMS
     146    bool "Support Linux prior to 2.4.0 and non-ELF systems"
    77147    default n
    78     help
    79       ps gives a snapshot of the current processes.
    80 
    81 config FEATURE_PS_WIDE
    82     bool "Enable argument for wide output (-w)"
    83     default n
    84     depends on PS
    85     help
    86       Support argument 'w' for wide output.
    87       If given once, 132 chars are printed and given more than
    88       one, the length is unlimited.
     148    depends on FEATURE_PS_TIME
     149    help
     150      Include support for measuring HZ on old kernels and non-ELF systems
     151      (if you are on Linux 2.4.0+ and use ELF, you don't need this)
    89152
    90153config RENICE
    91154    bool "renice"
    92     default n
     155    default y
    93156    help
    94157      Renice alters the scheduling priority of one or more running
     
    97160config BB_SYSCTL
    98161    bool "sysctl"
    99     default n
     162    default y
    100163    help
    101164      Configure kernel parameters at runtime.
     
    103166config TOP
    104167    bool "top"
    105     default n
     168    default y
    106169    help
    107170      The top program provides a dynamic real-time view of a running
     
    109172
    110173config FEATURE_TOP_CPU_USAGE_PERCENTAGE
    111     bool "Show CPU per-process usage percentage (adds 2k bytes)"
     174    bool "Show CPU per-process usage percentage"
    112175    default y
    113176    depends on TOP
    114177    help
    115178      Make top display CPU usage for each process.
     179      This adds about 2k.
    116180
    117181config FEATURE_TOP_CPU_GLOBAL_PERCENTS
    118     bool "Show CPU global usage percentage (adds 0.5k bytes)"
     182    bool "Show CPU global usage percentage"
    119183    default y
    120184    depends on FEATURE_TOP_CPU_USAGE_PERCENTAGE
    121185    help
    122186      Makes top display "CPU: NN% usr NN% sys..." line.
     187      This adds about 0.5k.
     188
     189config FEATURE_TOP_SMP_CPU
     190    bool "SMP CPU usage display ('c' key)"
     191    default y
     192    depends on FEATURE_TOP_CPU_GLOBAL_PERCENTS
     193    help
     194      Allow 'c' key to switch between individual/cumulative CPU stats
     195      This adds about 0.5k.
    123196
    124197config FEATURE_TOP_DECIMALS
    125     bool "Show 1/10th of a percent in CPU/mem statistics (adds 0.3k bytes)"
    126     default n
     198    bool "Show 1/10th of a percent in CPU/mem statistics"
     199    default y
    127200    depends on FEATURE_TOP_CPU_USAGE_PERCENTAGE
    128201    help
    129202      Show 1/10th of a percent in CPU/mem statistics.
     203      This adds about 0.3k.
     204
     205config FEATURE_TOP_SMP_PROCESS
     206    bool "Show CPU process runs on ('j' field)"
     207    default y
     208    depends on TOP
     209    help
     210      Show CPU where process was last found running on.
     211      This is the 'j' field.
     212
     213config FEATURE_TOPMEM
     214    bool "Topmem command ('s' key)"
     215    default y
     216    depends on TOP
     217    help
     218      Enable 's' in top (gives lots of memory info).
     219
     220config FEATURE_SHOW_THREADS
     221    bool "Support for showing threads in ps/top"
     222    default y
     223    depends on PS || TOP
     224    help
     225      Enables ps -T option and 'h' command in top
    130226
    131227config UPTIME
    132228    bool "uptime"
    133     default n
     229    default y
     230    depends on PLATFORM_LINUX #sysinfo()
    134231    help
    135232      uptime gives a one line display of the current time, how long
     
    139236config WATCH
    140237    bool "watch"
    141     default n
    142     #huh?? select DATE
     238    default y
    143239    help
    144240      watch is used to execute a program periodically, showing
    145241      output to the screen.
    146242
    147 
    148243endmenu
    149 
  • branches/2.2.9/mindi-busybox/procps/Kbuild

    r1765 r2725  
     1# DO NOT EDIT. This file is generated from Kbuild.src
    12# Makefile for busybox
    23#
    34# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
    45#
    5 # Licensed under the GPL v2, see the file LICENSE in this tarball.
     6# Licensed under GPLv2, see file LICENSE in this source tree.
    67
    78lib-y:=
     9
     10lib-$(CONFIG_IOSTAT) += iostat.o
     11lib-$(CONFIG_MPSTAT) += mpstat.o
     12lib-$(CONFIG_PMAP)     += pmap.o
     13lib-$(CONFIG_POWERTOP) += powertop.o
     14lib-$(CONFIG_SMEMCAP) += smemcap.o
    815lib-$(CONFIG_FREE)  += free.o
    916lib-$(CONFIG_FUSER) += fuser.o
     
    1118lib-$(CONFIG_ASH)   += kill.o  # used for built-in kill by ash
    1219lib-$(CONFIG_NMETER)    += nmeter.o
     20lib-$(CONFIG_PGREP) += pgrep.o
     21lib-$(CONFIG_PKILL) += pgrep.o
    1322lib-$(CONFIG_PIDOF) += pidof.o
    1423lib-$(CONFIG_PS)    += ps.o
  • branches/2.2.9/mindi-busybox/procps/free.c

    r1765 r2725  
    55 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
    66 *
    7  * Licensed under the GPL version 2, see the file LICENSE in this tarball.
     7 * Licensed under GPLv2, see file LICENSE in this source tree.
    88 */
    99
     
    1212#include "libbb.h"
    1313
    14 int free_main(int argc, char **argv);
    15 int free_main(int argc, char **argv)
     14struct globals {
     15    unsigned mem_unit;
     16#if ENABLE_DESKTOP
     17    unsigned unit_steps;
     18# define G_unit_steps G.unit_steps
     19#else
     20# define G_unit_steps 10
     21#endif
     22};
     23#define G (*(struct globals*)&bb_common_bufsiz1)
     24#define INIT_G() do { } while (0)
     25
     26
     27static unsigned long long scale(unsigned long d)
     28{
     29    return ((unsigned long long)d * G.mem_unit) >> G_unit_steps;
     30}
     31
     32
     33int free_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     34int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM))
    1635{
    1736    struct sysinfo info;
     37
     38    INIT_G();
     39
     40#if ENABLE_DESKTOP
     41    G.unit_steps = 10;
     42    if (argv[1] && argv[1][0] == '-') {
     43        switch (argv[1][1]) {
     44        case 'b':
     45            G.unit_steps = 0;
     46            break;
     47        case 'k': /* 2^10 */
     48            /* G.unit_steps = 10; - already is */
     49            break;
     50        case 'm': /* 2^(2*10) */
     51            G.unit_steps = 20;
     52            break;
     53        case 'g': /* 2^(3*10) */
     54            G.unit_steps = 30;
     55            break;
     56        default:
     57            bb_show_usage();
     58        }
     59    }
     60#endif
     61
    1862    sysinfo(&info);
    1963
    2064    /* Kernels prior to 2.4.x will return info.mem_unit==0, so cope... */
    21     if (info.mem_unit == 0) {
    22         info.mem_unit=1;
    23     }
    24     if (info.mem_unit == 1) {
    25         info.mem_unit=1024;
     65    G.mem_unit = (info.mem_unit ? info.mem_unit : 1);
    2666
    27         /* TODO:  Make all this stuff not overflow when mem >= 4 Gib */
    28         info.totalram/=info.mem_unit;
    29         info.freeram/=info.mem_unit;
    30 #ifndef __uClinux__
    31         info.totalswap/=info.mem_unit;
    32         info.freeswap/=info.mem_unit;
    33 #endif
    34         info.sharedram/=info.mem_unit;
    35         info.bufferram/=info.mem_unit;
    36     } else {
    37         info.mem_unit/=1024;
    38         /* TODO:  Make all this stuff not overflow when mem >= 4 Gib */
    39         info.totalram*=info.mem_unit;
    40         info.freeram*=info.mem_unit;
    41 #ifndef __uClinux__
    42         info.totalswap*=info.mem_unit;
    43         info.freeswap*=info.mem_unit;
    44 #endif
    45         info.sharedram*=info.mem_unit;
    46         info.bufferram*=info.mem_unit;
    47     }
     67    printf("     %13s%13s%13s%13s%13s\n",
     68        "total",
     69        "used",
     70        "free",
     71        "shared", "buffers" /* swap and total don't have these columns */
     72        /* procps version 3.2.8 also shows "cached" column, but
     73         * sysinfo() does not provide this value, need to parse
     74         * /proc/meminfo instead and get "Cached: NNN kB" from there.
     75         */
     76    );
    4877
    49     if (argc > 1 && *argv[1] == '-')
    50         bb_show_usage();
     78#define FIELDS_5 "%13llu%13llu%13llu%13llu%13llu\n"
     79#define FIELDS_3 (FIELDS_5 + 2*6)
     80#define FIELDS_2 (FIELDS_5 + 3*6)
    5181
    52     printf("%6s%13s%13s%13s%13s%13s\n", "", "total", "used", "free",
    53             "shared", "buffers");
    54 
    55     printf("%6s%13ld%13ld%13ld%13ld%13ld\n", "Mem:", info.totalram,
    56             info.totalram-info.freeram, info.freeram,
    57             info.sharedram, info.bufferram);
    58 
    59 #ifndef __uClinux__
    60     printf("%6s%13ld%13ld%13ld\n", "Swap:", info.totalswap,
    61             info.totalswap-info.freeswap, info.freeswap);
    62 
    63     printf("%6s%13ld%13ld%13ld\n", "Total:", info.totalram+info.totalswap,
    64             (info.totalram-info.freeram)+(info.totalswap-info.freeswap),
    65             info.freeram+info.freeswap);
     82    printf("Mem: ");
     83    printf(FIELDS_5,
     84        scale(info.totalram),
     85        scale(info.totalram - info.freeram),
     86        scale(info.freeram),
     87        scale(info.sharedram),
     88        scale(info.bufferram)
     89    );
     90    /* Show alternate, more meaningful busy/free numbers by counting
     91     * buffer cache as free memory (make it "-/+ buffers/cache"
     92     * if/when we add support for "cached" column): */
     93    printf("-/+ buffers:      ");
     94    printf(FIELDS_2,
     95        scale(info.totalram - info.freeram - info.bufferram),
     96        scale(info.freeram + info.bufferram)
     97    );
     98#if BB_MMU
     99    printf("Swap:");
     100    printf(FIELDS_3,
     101        scale(info.totalswap),
     102        scale(info.totalswap - info.freeswap),
     103        scale(info.freeswap)
     104    );
    66105#endif
    67106    return EXIT_SUCCESS;
  • branches/2.2.9/mindi-busybox/procps/fuser.c

    r1765 r2725  
    55 * Copyright 2004 Tony J. White
    66 *
    7  * May be distributed under the conditions of the
    8  * GNU Library General Public License
     7 * Licensed under GPLv2, see file LICENSE in this source tree.
    98 */
    109
    1110#include "libbb.h"
    1211
    13 #define FUSER_PROC_DIR "/proc"
    14 #define FUSER_MAX_LINE 255
    15 
    16 #define FUSER_OPT_MOUNT  1
    17 #define FUSER_OPT_KILL   2
    18 #define FUSER_OPT_SILENT 4
    19 #define FUSER_OPT_IP6    8
    20 #define FUSER_OPT_IP4    16
     12#define MAX_LINE 255
     13
     14#define OPTION_STRING "mks64"
     15enum {
     16    OPT_MOUNT  = (1 << 0),
     17    OPT_KILL   = (1 << 1),
     18    OPT_SILENT = (1 << 2),
     19    OPT_IP6    = (1 << 3),
     20    OPT_IP4    = (1 << 4),
     21};
    2122
    2223typedef struct inode_list {
     24    struct inode_list *next;
    2325    ino_t inode;
    2426    dev_t dev;
    25     struct inode_list *next;
    2627} inode_list;
    2728
    2829typedef struct pid_list {
     30    struct pid_list *next;
    2931    pid_t pid;
    30     struct pid_list *next;
    3132} pid_list;
    3233
    33 static int fuser_option(char *option)
    34 {
    35     int opt = 0;
    36 
    37     if (!option[0])
    38         return 0;
    39     if (option[0] != '-')
    40         return 0;
    41     ++option;
    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);
    50         ++option;
    51     }
    52     return opt;
    53 }
    54 
    55 static int fuser_file_to_dev_inode(const char *filename,
    56      dev_t *dev, ino_t *inode)
    57 {
    58     struct stat f_stat;
    59     if ((stat(filename, &f_stat)) < 0)
    60         return 0;
    61     *inode = f_stat.st_ino;
    62     *dev = f_stat.st_dev;
    63     return 1;
    64 }
    65 
    66 static int fuser_find_socket_dev(dev_t *dev)
    67 {
    68     int fd = socket(PF_INET, SOCK_DGRAM,0);
    69     struct stat buf;
    70 
    71     if (fd >= 0 && (fstat(fd, &buf)) == 0) {
    72         *dev = buf.st_dev;
     34
     35struct globals {
     36    pid_list *pid_list_head;
     37    inode_list *inode_list_head;
     38};
     39#define G (*(struct globals*)&bb_common_bufsiz1)
     40#define INIT_G() do { } while (0)
     41
     42
     43static void add_pid(const pid_t pid)
     44{
     45    pid_list **curr = &G.pid_list_head;
     46
     47    while (*curr) {
     48        if ((*curr)->pid == pid)
     49            return;
     50        curr = &(*curr)->next;
     51    }
     52
     53    *curr = xzalloc(sizeof(pid_list));
     54    (*curr)->pid = pid;
     55}
     56
     57static void add_inode(const struct stat *st)
     58{
     59    inode_list **curr = &G.inode_list_head;
     60
     61    while (*curr) {
     62        if ((*curr)->dev == st->st_dev
     63         && (*curr)->inode == st->st_ino
     64        ) {
     65            return;
     66        }
     67        curr = &(*curr)->next;
     68    }
     69
     70    *curr = xzalloc(sizeof(inode_list));
     71    (*curr)->dev = st->st_dev;
     72    (*curr)->inode = st->st_ino;
     73}
     74
     75static void scan_proc_net(const char *path, unsigned port)
     76{
     77    char line[MAX_LINE + 1];
     78    long long uint64_inode;
     79    unsigned tmp_port;
     80    FILE *f;
     81    struct stat st;
     82    int fd;
     83
     84    /* find socket dev */
     85    st.st_dev = 0;
     86    fd = socket(AF_INET, SOCK_DGRAM, 0);
     87    if (fd >= 0) {
     88        fstat(fd, &st);
    7389        close(fd);
    74         return 1;
    75     }
    76     return 0;
    77 }
    78 
    79 static int fuser_parse_net_arg(const char *filename,
    80     const char **proto, int *port)
    81 {
    82     char path[sizeof(FUSER_PROC_DIR)+12], tproto[5];
    83 
    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);
    90     return 1;
    91 }
    92 
    93 static int fuser_add_pid(pid_list *plist, pid_t pid)
    94 {
    95     pid_list *curr = NULL, *last = NULL;
    96 
    97     if (plist->pid == 0)
    98         plist->pid = pid;
    99     curr = plist;
    100     while (curr != NULL) {
    101         if (curr->pid == pid)
    102             return 1;
    103         last = curr;
    104         curr = curr->next;
    105     }
    106     curr = xzalloc(sizeof(pid_list));
    107     last->next = curr;
    108     curr->pid = pid;
    109     /*curr->next = NULL;*/
    110     return 1;
    111 }
    112 
    113 static int fuser_add_inode(inode_list *ilist, dev_t dev, ino_t inode)
    114 {
    115     inode_list *curr = NULL, *last = NULL;
    116 
    117     if (!ilist->inode && !ilist->dev) {
    118         ilist->dev = dev;
    119         ilist->inode = inode;
    120     }
    121     curr = ilist;
    122     while (curr != NULL) {
    123         if (curr->inode == inode && curr->dev == dev)
    124             return 1;
    125         last = curr;
    126         curr = curr->next;
    127     }
    128     curr = xzalloc(sizeof(inode_list));
    129     last->next = curr;
    130     curr->dev = dev;
    131     curr->inode = inode;
    132     /*curr->next = NULL;*/
    133     return 1;
    134 }
    135 
    136 static int fuser_scan_proc_net(int opts, const char *proto,
    137     int port, inode_list *ilist)
    138 {
    139     char path[sizeof(FUSER_PROC_DIR)+12], line[FUSER_MAX_LINE+1];
    140     char addr[128];
    141     ino_t tmp_inode;
    142     dev_t tmp_dev;
    143     long long uint64_inode;
    144     int tmp_port;
    145     FILE *f;
    146 
    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");
     90    }
     91
     92    f = fopen_for_read(path);
    15293    if (!f)
    153         return 0;
    154     while (fgets(line, FUSER_MAX_LINE, f)) {
     94        return;
     95
     96    while (fgets(line, MAX_LINE, f)) {
     97        char addr[68];
    15598        if (sscanf(line, "%*d: %64[0-9A-Fa-f]:%x %*x:%*x %*x %*x:%*x "
    15699                "%*x:%*x %*x %*d %*d %llu",
    157100                addr, &tmp_port, &uint64_inode) == 3
    158101        ) {
    159             if (strlen(addr) == 8 && (opts & FUSER_OPT_IP6))
     102            int len = strlen(addr);
     103            if (len == 8 && (option_mask32 & OPT_IP6))
    160104                continue;
    161             if (strlen(addr) > 8 && (opts & FUSER_OPT_IP4))
     105            if (len > 8 && (option_mask32 & OPT_IP4))
    162106                continue;
    163107            if (tmp_port == port) {
    164                 tmp_inode = uint64_inode;
    165                 fuser_add_inode(ilist, tmp_dev, tmp_inode);
     108                st.st_ino = uint64_inode;
     109                add_inode(&st);
    166110            }
    167111        }
    168112    }
    169113    fclose(f);
    170     return 1;
    171 }
    172 
    173 static int fuser_search_dev_inode(int opts, inode_list *ilist,
    174     dev_t dev, ino_t inode)
    175 {
    176     inode_list *curr;
    177     curr = ilist;
    178 
    179     while (curr) {
    180         if ((opts & FUSER_OPT_MOUNT) && curr->dev == dev)
    181             return 1;
    182         if (curr->inode == inode && curr->dev == dev)
    183             return 1;
    184         curr = curr->next;
     114}
     115
     116static int search_dev_inode(const struct stat *st)
     117{
     118    inode_list *ilist = G.inode_list_head;
     119
     120    while (ilist) {
     121        if (ilist->dev == st->st_dev) {
     122            if (option_mask32 & OPT_MOUNT)
     123                return 1;
     124            if (ilist->inode == st->st_ino)
     125                return 1;
     126        }
     127        ilist = ilist->next;
    185128    }
    186129    return 0;
    187130}
    188131
    189 static int fuser_scan_pid_maps(int opts, const char *fname, pid_t pid,
    190     inode_list *ilist, pid_list *plist)
     132static void scan_pid_maps(const char *fname, pid_t pid)
    191133{
    192134    FILE *file;
    193     char line[FUSER_MAX_LINE + 1];
     135    char line[MAX_LINE + 1];
    194136    int major, minor;
    195     ino_t inode;
    196137    long long uint64_inode;
    197     dev_t dev;
    198 
    199     file = fopen(fname, "r");
     138    struct stat st;
     139
     140    file = fopen_for_read(fname);
    200141    if (!file)
    201         return 0;
    202     while (fgets(line, FUSER_MAX_LINE, file)) {
     142        return;
     143
     144    while (fgets(line, MAX_LINE, file)) {
    203145        if (sscanf(line, "%*s %*s %*s %x:%x %llu", &major, &minor, &uint64_inode) != 3)
    204146            continue;
    205         inode = uint64_inode;
    206         if (major == 0 && minor == 0 && inode == 0)
    207             continue;
    208         dev = makedev(major, minor);
    209         if (fuser_search_dev_inode(opts, ilist, dev, inode)) {
    210             fuser_add_pid(plist, pid);
    211         }
     147        st.st_ino = uint64_inode;
     148        if (major == 0 && minor == 0 && st.st_ino == 0)
     149            continue;
     150        st.st_dev = makedev(major, minor);
     151        if (search_dev_inode(&st))
     152            add_pid(pid);
    212153    }
    213154    fclose(file);
    214     return 1;
    215 }
    216 
    217 static int fuser_scan_link(int opts, const char *lname, pid_t pid,
    218     inode_list *ilist, pid_list *plist)
    219 {
    220     ino_t inode;
    221     dev_t dev;
    222 
    223     if (!fuser_file_to_dev_inode(lname, &dev, &inode))
    224         return 0;
    225     if (fuser_search_dev_inode(opts, ilist, dev, inode))
    226         fuser_add_pid(plist, pid);
    227     return 1;
    228 }
    229 
    230 static int fuser_scan_dir_links(int opts, const char *dname, pid_t pid,
    231     inode_list *ilist, pid_list *plist)
     155}
     156
     157static void scan_link(const char *lname, pid_t pid)
     158{
     159    struct stat st;
     160
     161    if (stat(lname, &st) >= 0) {
     162        if (search_dev_inode(&st))
     163            add_pid(pid);
     164    }
     165}
     166
     167static void scan_dir_links(const char *dname, pid_t pid)
    232168{
    233169    DIR *d;
     
    237173    d = opendir(dname);
    238174    if (!d)
    239         return 0;
     175        return;
     176
    240177    while ((de = readdir(d)) != NULL) {
    241178        lname = concat_subpath_file(dname, de->d_name);
    242179        if (lname == NULL)
    243180            continue;
    244         fuser_scan_link(opts, lname, pid, ilist, plist);
     181        scan_link(lname, pid);
    245182        free(lname);
    246183    }
    247184    closedir(d);
    248     return 1;
    249 }
    250 
    251 static int fuser_scan_proc_pids(int opts, inode_list *ilist, pid_list *plist)
     185}
     186
     187/* NB: does chdir internally */
     188static void scan_proc_pids(void)
    252189{
    253190    DIR *d;
    254191    struct dirent *de;
    255192    pid_t pid;
    256     char *dname;
    257 
    258     d = opendir(FUSER_PROC_DIR);
     193
     194    xchdir("/proc");
     195    d = opendir("/proc");
    259196    if (!d)
    260         return 0;
     197        return;
     198
    261199    while ((de = readdir(d)) != NULL) {
    262         pid = (pid_t)atoi(de->d_name);
    263         if (!pid)
    264             continue;
    265         dname = concat_subpath_file(FUSER_PROC_DIR, de->d_name);
    266         if (chdir(dname) < 0) {
    267             free(dname);
    268             continue;
    269         }
    270         free(dname);
    271         fuser_scan_link(opts, "cwd", pid, ilist, plist);
    272         fuser_scan_link(opts, "exe", pid, ilist, plist);
    273         fuser_scan_link(opts, "root", pid, ilist, plist);
    274         fuser_scan_dir_links(opts, "fd", pid, ilist, plist);
    275         fuser_scan_dir_links(opts, "lib", pid, ilist, plist);
    276         fuser_scan_dir_links(opts, "mmap", pid, ilist, plist);
    277         fuser_scan_pid_maps(opts, "maps", pid, ilist, plist);
    278         chdir("..");
     200        pid = (pid_t)bb_strtou(de->d_name, NULL, 10);
     201        if (errno)
     202            continue;
     203        if (chdir(de->d_name) < 0)
     204            continue;
     205        scan_link("cwd", pid);
     206        scan_link("exe", pid);
     207        scan_link("root", pid);
     208
     209        scan_dir_links("fd", pid);
     210        scan_dir_links("lib", pid);
     211        scan_dir_links("mmap", pid);
     212
     213        scan_pid_maps("maps", pid);
     214        xchdir("/proc");
    279215    }
    280216    closedir(d);
    281     return 1;
    282 }
    283 
    284 static int fuser_print_pid_list(pid_list *plist)
    285 {
    286     pid_list *curr = plist;
    287 
    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("");
    296     return 1;
    297 }
    298 
    299 static int fuser_kill_pid_list(pid_list *plist, int sig)
    300 {
    301     pid_list *curr = plist;
    302     pid_t mypid = getpid();
    303     int success = 1;
    304 
    305     if (plist == NULL)
    306         return 0;
    307     while (curr != NULL) {
    308         if (curr->pid > 0 && curr->pid != mypid) {
    309             if (kill(curr->pid, sig) != 0) {
    310                 bb_perror_msg("kill pid '%d'", curr->pid);
    311                 success = 0;
     217}
     218
     219int fuser_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     220int fuser_main(int argc UNUSED_PARAM, char **argv)
     221{
     222    pid_list *plist;
     223    pid_t mypid;
     224    char **pp;
     225    struct stat st;
     226    unsigned port;
     227    int opt;
     228    int exitcode;
     229    int killsig;
     230/*
     231fuser [OPTIONS] FILE or PORT/PROTO
     232Find processes which use FILEs or PORTs
     233        -m      Find processes which use same fs as FILEs
     234        -4      Search only IPv4 space
     235        -6      Search only IPv6 space
     236        -s      Don't display PIDs
     237        -k      Kill found processes
     238        -SIGNAL Signal to send (default: KILL)
     239*/
     240    /* Handle -SIGNAL. Oh my... */
     241    killsig = SIGKILL; /* yes, the default is not SIGTERM */
     242    pp = argv;
     243    while (*++pp) {
     244        char *arg = *pp;
     245        if (arg[0] != '-')
     246            continue;
     247        if (arg[1] == '-' && arg[2] == '\0') /* "--" */
     248            break;
     249        if ((arg[1] == '4' || arg[1] == '6') && arg[2] == '\0')
     250            continue; /* it's "-4" or "-6" */
     251        opt = get_signum(&arg[1]);
     252        if (opt < 0)
     253            continue;
     254        /* "-SIGNAL" option found. Remove it and bail out */
     255        killsig = opt;
     256        do {
     257            pp[0] = arg = pp[1];
     258            pp++;
     259        } while (arg);
     260        break;
     261    }
     262
     263    opt_complementary = "-1"; /* at least one param */
     264    opt = getopt32(argv, OPTION_STRING);
     265    argv += optind;
     266
     267    pp = argv;
     268    while (*pp) {
     269        /* parse net arg */
     270        char path[20], tproto[5];
     271        if (sscanf(*pp, "%u/%4s", &port, tproto) != 2)
     272            goto file;
     273        sprintf(path, "/proc/net/%s", tproto);
     274        if (access(path, R_OK) != 0) { /* PORT/PROTO */
     275            scan_proc_net(path, port);
     276        } else { /* FILE */
     277 file:
     278            xstat(*pp, &st);
     279            add_inode(&st);
     280        }
     281        pp++;
     282    }
     283
     284    scan_proc_pids(); /* changes dir to "/proc" */
     285
     286    mypid = getpid();
     287    plist = G.pid_list_head;
     288    while (1) {
     289        if (!plist)
     290            return EXIT_FAILURE;
     291        if (plist->pid != mypid)
     292            break;
     293        plist = plist->next;
     294    }
     295
     296    exitcode = EXIT_SUCCESS;
     297    do {
     298        if (plist->pid != mypid) {
     299            if (opt & OPT_KILL) {
     300                if (kill(plist->pid, killsig) != 0) {
     301                    bb_perror_msg("kill pid %u", (unsigned)plist->pid);
     302                    exitcode = EXIT_FAILURE;
     303                }
    312304            }
    313         }
    314         curr = curr->next;
    315     }
    316     return success;
    317 }
    318 
    319 int fuser_main(int argc, char **argv);
    320 int fuser_main(int argc, char **argv)
    321 {
    322     /*static -- huh???*/ int opt = 0; /* FUSER_OPT_ */
    323 
    324     int port, i, optn;
    325     int* fni; /* file name indexes of argv */
    326     int fnic = 0;  /* file name index count */
    327     const char *proto;
    328     dev_t dev;
    329     ino_t inode;
    330     pid_list *pids;
    331     inode_list *inodes;
    332     int killsig = SIGTERM;
    333     int success = 1;
    334 
    335     if (argc < 2)
    336         bb_show_usage();
    337 
    338     fni = xmalloc(sizeof(int));
    339     for (i = 1; i < argc; i++) {
    340         optn = fuser_option(argv[i]);
    341         if (optn)
    342             opt |= optn;
    343         else if (argv[i][0] == '-') {
    344             killsig = get_signum(argv[i]+1);
    345             if (killsig < 0)
    346                 killsig = SIGTERM;
    347         } else {
    348             fni = xrealloc(fni, sizeof(int) * (fnic+2));
    349             fni[fnic++] = i;
    350         }
    351     }
    352 
    353     if (!fnic)
    354         return 1;
    355 
    356     inodes = xmalloc(sizeof(inode_list));
    357     for (i = 0; i < fnic; i++) {
    358         if (fuser_parse_net_arg(argv[fni[i]], &proto, &port)) {
    359             fuser_scan_proc_net(opt, proto, port, inodes);
    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]]);
     305            if (!(opt & OPT_SILENT)) {
     306                printf("%u ", (unsigned)plist->pid);
    365307            }
    366             fuser_add_inode(inodes, dev, inode);
    367         }
    368     }
    369     pids = xmalloc(sizeof(pid_list));
    370     success = fuser_scan_proc_pids(opt, inodes, pids);
    371     /* if the first pid in the list is 0, none have been found */
    372     if (pids->pid == 0)
    373         success = 0;
    374     if (success) {
    375         if (opt & FUSER_OPT_KILL) {
    376             success = fuser_kill_pid_list(pids, killsig);
    377         } else if (!(opt & FUSER_OPT_SILENT)) {
    378             success = fuser_print_pid_list(pids);
    379         }
    380     }
    381     if (ENABLE_FEATURE_CLEAN_UP) {
    382         free(pids);
    383         free(inodes);
    384     }
    385     /* return 0 on (success == 1) 1 otherwise */
    386     return (success != 1);
    387 }
     308        }
     309        plist = plist->next;
     310    } while (plist);
     311
     312    if (!(opt & (OPT_SILENT))) {
     313        bb_putchar('\n');
     314    }
     315
     316    return exitcode;
     317}
  • branches/2.2.9/mindi-busybox/procps/kill.c

    r1765 r2725  
    66 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
    77 *
    8  * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
     8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    99 */
    1010
     
    2525 */
    2626
    27 int kill_main(int argc, char **argv);
    2827int kill_main(int argc, char **argv)
    2928{
     
    5958        if (argc == 1) {
    6059            /* Print the whole signal list */
    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);
    87                 }
     60            print_signames();
     61            return 0;
     62        }
     63        /* -l <sig list> */
     64        while ((arg = *++argv)) {
     65            if (isdigit(arg[0])) {
     66                signo = bb_strtou(arg, NULL, 10);
     67                if (errno) {
     68                    bb_error_msg("unknown signal '%s'", arg);
     69                    return EXIT_FAILURE;
     70                }
     71                /* Exitcodes >= 0x80 are to be treated
     72                 * as "killed by signal (exitcode & 0x7f)" */
     73                puts(get_signame(signo & 0x7f));
     74                /* TODO: 'bad' signal# - coreutils says:
     75                 * kill: 127: invalid signal
     76                 * we just print "127" instead */
     77            } else {
     78                signo = get_signum(arg);
     79                if (signo < 0) {
     80                    bb_error_msg("unknown signal '%s'", arg);
     81                    return EXIT_FAILURE;
     82                }
     83                printf("%d\n", signo);
    8884            }
    8985        }
     
    9793        arg = *++argv;
    9894        argc--;
    99         if (argc < 1) bb_show_usage();
    100         if (arg[0] != '-') goto do_it_now;
    101     }
    102 
    103     /* -SIG */
    104     signo = get_signum(&arg[1]);
     95        if (argc < 1)
     96            bb_show_usage();
     97        if (arg[0] != '-')
     98            goto do_it_now;
     99    }
     100
     101    arg++; /* skip '-' */
     102
     103    /* -o PID? (if present, it always is at the end of command line) */
     104    if (killall5 && arg[0] == 'o')
     105        goto do_it_now;
     106
     107    if (argc > 1 && arg[0] == 's' && arg[1] == '\0') { /* -s SIG? */
     108        argc--;
     109        arg = *++argv;
     110    } /* else it must be -SIG */
     111    signo = get_signum(arg);
    105112    if (signo < 0) { /* || signo > MAX_SIGNUM ? */
    106         bb_error_msg("bad signal name '%s'", &arg[1]);
     113        bb_error_msg("bad signal name '%s'", arg);
    107114        return EXIT_FAILURE;
    108115    }
     
    110117    argc--;
    111118
    112 do_it_now:
     119 do_it_now:
     120    pid = getpid();
    113121
    114122    if (killall5) {
    115123        pid_t sid;
    116124        procps_status_t* p = NULL;
    117 
    118         /* Now stop all processes */
     125        int ret = 0;
     126
     127        /* Find out our session id */
     128        sid = getsid(pid);
     129        /* Stop all processes */
    119130        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 */
     131        /* Signal all processes except those in our session */
    124132        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         }
     133            int i;
     134
     135            if (p->sid == (unsigned)sid
     136             || p->pid == (unsigned)pid
     137             || p->pid == 1)
     138                continue;
     139
     140            /* All remaining args must be -o PID options.
     141             * Check p->pid against them. */
     142            for (i = 0; i < argc; i++) {
     143                pid_t omit;
     144
     145                arg = argv[i];
     146                if (arg[0] != '-' || arg[1] != 'o') {
     147                    bb_error_msg("bad option '%s'", arg);
     148                    ret = 1;
     149                    goto resume;
     150                }
     151                arg += 2;
     152                if (!arg[0] && argv[++i])
     153                    arg = argv[i];
     154                omit = bb_strtoi(arg, NULL, 10);
     155                if (errno) {
     156                    bb_error_msg("invalid number '%s'", arg);
     157                    ret = 1;
     158                    goto resume;
     159                }
     160                if (p->pid == omit)
     161                    goto dont_kill;
     162            }
     163            kill(p->pid, signo);
     164 dont_kill: ;
     165        }
     166 resume:
    128167        /* And let them continue */
    129168        kill(-1, SIGCONT);
    130         return 0;
     169        return ret;
    131170    }
    132171
    133172    /* Pid or name is required for kill/killall */
    134173    if (argc < 1) {
    135         puts("You need to specify whom to kill");
     174        bb_error_msg("you need to specify whom to kill");
    136175        return EXIT_FAILURE;
    137176    }
     
    139178    if (killall) {
    140179        /* Looks like they want to do a killall.  Do that */
    141         pid = getpid();
    142180        while (arg) {
    143181            pid_t* pidList;
     
    158196                    errors++;
    159197                    if (!quiet)
    160                         bb_perror_msg("cannot kill pid %u", (unsigned)*pl);
     198                        bb_perror_msg("can't kill pid %d", (int)*pl);
    161199                }
    162200            }
     
    174212        pid = bb_strtoi(arg, NULL, 10);
    175213        if (errno) {
    176             bb_error_msg("bad pid '%s'", arg);
     214            bb_error_msg("invalid number '%s'", arg);
    177215            errors++;
    178216        } else if (kill(pid, signo) != 0) {
    179             bb_perror_msg("cannot kill pid %d", (int)pid);
     217            bb_perror_msg("can't kill pid %d", (int)pid);
    180218            errors++;
    181219        }
  • branches/2.2.9/mindi-busybox/procps/nmeter.c

    r1765 r2725  
    11/*
    2 ** Licensed under the GPL v2, see the file LICENSE in this tarball
    3 **
    4 ** Based on nanotop.c from floppyfw project
    5 **
    6 ** Contact me: vda.linux@googlemail.com */
     2 * Licensed under GPLv2, see file LICENSE in this source tree.
     3 *
     4 * Based on nanotop.c from floppyfw project
     5 *
     6 * Contact me: vda.linux@googlemail.com
     7 */
    78
    89//TODO:
     
    1819//  totalswap=134209536, freeswap=134209536, procs=157})
    1920
    20 #include <time.h>
    2121#include "libbb.h"
    2222
    2323typedef unsigned long long ullong;
    2424
    25 enum { PROC_FILE_SIZE = 4096 };
     25enum {  /* Preferably use powers of 2 */
     26    PROC_MIN_FILE_SIZE = 256,
     27    PROC_MAX_FILE_SIZE = 16 * 1024,
     28};
    2629
    2730typedef struct proc_file {
    2831    char *file;
    29     //const char *name;
     32    int file_sz;
    3033    smallint last_gen;
    3134} proc_file;
     
    7679#define proc_sys_fs_filenr (G.proc_sys_fs_filenr)
    7780#define INIT_G() do { \
    78         PTR_TO_GLOBALS = xzalloc(sizeof(G)); \
    79         cur_outbuf = outbuf; \
    80         final_str = "\n"; \
    81         deltanz = delta = 1000000; \
    82     } while (0)
     81    SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
     82    cur_outbuf = outbuf; \
     83    final_str = "\n"; \
     84    deltanz = delta = 1000000; \
     85} while (0)
    8386
    8487// We depend on this being a char[], not char* - we take sizeof() of it
     
    99102    int sz = cur_outbuf - outbuf;
    100103    if (sz > 0) {
    101         xwrite(1, outbuf, sz);
     104        xwrite(STDOUT_FILENO, outbuf, sz);
    102105        cur_outbuf = outbuf;
    103106    }
     
    125128}
    126129
    127 static void readfile_z(char *buf, int sz, const char* fname)
     130static void readfile_z(proc_file *pf, const char* fname)
    128131{
    129132// open_read_close() will do two reads in order to be sure we are at EOF,
    130133// and we don't need/want that.
    131 //  sz = open_read_close(fname, buf, sz-1);
    132 
    133     int fd = xopen(fname, O_RDONLY);
     134    int fd;
     135    int sz, rdsz;
     136    char *buf;
     137
     138    sz = pf->file_sz;
     139    buf = pf->file;
     140    if (!buf) {
     141        buf = xmalloc(PROC_MIN_FILE_SIZE);
     142        sz = PROC_MIN_FILE_SIZE;
     143    }
     144 again:
     145    fd = xopen(fname, O_RDONLY);
    134146    buf[0] = '\0';
    135     if (fd >= 0) {
    136         sz = read(fd, buf, sz-1);
    137         if (sz > 0) buf[sz] = '\0';
    138         close(fd);
    139     }
     147    rdsz = read(fd, buf, sz-1);
     148    close(fd);
     149    if (rdsz > 0) {
     150        if (rdsz == sz-1 && sz < PROC_MAX_FILE_SIZE) {
     151            sz *= 2;
     152            buf = xrealloc(buf, sz);
     153            goto again;
     154        }
     155        buf[rdsz] = '\0';
     156    }
     157    pf->file_sz = sz;
     158    pf->file = buf;
    140159}
    141160
     
    144163    if (pf->last_gen != gen) {
    145164        pf->last_gen = gen;
    146         // We allocate PROC_FILE_SIZE bytes. This wastes memory,
    147         // but allows us to allocate only once (at first sample)
    148         // per proc file, and reuse buffer for each sample
    149         if (!pf->file)
    150             pf->file = xmalloc(PROC_FILE_SIZE);
    151         readfile_z(pf->file, PROC_FILE_SIZE, proc_name[pf - &first_proc_file]);
     165        readfile_z(pf, proc_name[pf - &first_proc_file]);
    152166    }
    153167    return pf->file;
    154168}
    155169
    156 static inline ullong read_after_slash(const char *p)
     170static ullong read_after_slash(const char *p)
    157171{
    158172    p = strchr(p, '/');
     
    229243static int rdval_diskstats(const char* p, ullong *vec)
    230244{
    231     ullong rd = 0; // to avoid "warning: 'rd' might be used uninitialized"
     245    ullong rd = rd; // for compiler
    232246    int indexline = 0;
    233247    vec[0] = 0;
     
    258272{
    259273    char buf[5];
    260     smart_ulltoa5(ul, buf);
     274
     275    /* see http://en.wikipedia.org/wiki/Tera */
     276    smart_ulltoa4(ul, buf, " kmgtpezy");
     277    buf[4] = '\0';
    261278    put(buf);
    262279}
     
    266283typedef struct a { \
    267284    struct s_stat *next; \
    268     void (*collect)(struct a *s); \
     285    void (*collect)(struct a *s) FAST_FUNC; \
    269286    const char *label;
    270287#define S_STAT_END(a) } a;
     
    273290S_STAT_END(s_stat)
    274291
    275 static void collect_literal(s_stat *s)
     292static void FAST_FUNC collect_literal(s_stat *s UNUSED_PARAM)
    276293{
    277294}
     
    279296static s_stat* init_literal(void)
    280297{
    281     s_stat *s = xmalloc(sizeof(s_stat));
     298    s_stat *s = xzalloc(sizeof(*s));
    282299    s->collect = collect_literal;
    283300    return (s_stat*)s;
     
    286303static s_stat* init_delay(const char *param)
    287304{
    288     delta = bb_strtoi(param, NULL, 0) * 1000;
     305    delta = strtoul(param, NULL, 0) * 1000; /* param can be "" */
    289306    deltanz = delta > 0 ? delta : 1;
    290307    need_seconds = (1000000%deltanz) != 0;
     
    292309}
    293310
    294 static s_stat* init_cr(const char *param)
     311static s_stat* init_cr(const char *param UNUSED_PARAM)
    295312{
    296313    final_str = "\r";
     
    310327
    311328
    312 static void collect_cpu(cpu_stat *s)
     329static void FAST_FUNC collect_cpu(cpu_stat *s)
    313330{
    314331    ullong data[CPU_FIELDCNT] = { 0, 0, 0, 0, 0, 0, 0 };
     
    367384{
    368385    int sz;
    369     cpu_stat *s = xmalloc(sizeof(cpu_stat));
     386    cpu_stat *s = xzalloc(sizeof(*s));
    370387    s->collect = collect_cpu;
    371     sz = strtol(param, NULL, 0);
     388    sz = strtoul(param, NULL, 0); /* param can be "" */
    372389    if (sz < 10) sz = 10;
    373390    if (sz > 1000) sz = 1000;
    374     s->bar = xmalloc(sz+1);
    375     s->bar[sz] = '\0';
     391    s->bar = xzalloc(sz+1);
     392    /*s->bar[sz] = '\0'; - xzalloc did it */
    376393    s->bar_sz = sz;
    377394    return (s_stat*)s;
     
    384401S_STAT_END(int_stat)
    385402
    386 static void collect_int(int_stat *s)
     403static void FAST_FUNC collect_int(int_stat *s)
    387404{
    388405    ullong data[1];
     
    402419static s_stat* init_int(const char *param)
    403420{
    404     int_stat *s = xmalloc(sizeof(int_stat));
     421    int_stat *s = xzalloc(sizeof(*s));
    405422    s->collect = collect_int;
    406     if (param[0]=='\0') {
     423    if (param[0] == '\0') {
    407424        s->no = 1;
    408425    } else {
    409         int n = strtoul(param, NULL, 0);
    410         s->no = n+2;
     426        int n = xatoi_positive(param);
     427        s->no = n + 2;
    411428    }
    412429    return (s_stat*)s;
     
    418435S_STAT_END(ctx_stat)
    419436
    420 static void collect_ctx(ctx_stat *s)
     437static void FAST_FUNC collect_ctx(ctx_stat *s)
    421438{
    422439    ullong data[1];
     
    434451}
    435452
    436 static s_stat* init_ctx(const char *param)
    437 {
    438     ctx_stat *s = xmalloc(sizeof(ctx_stat));
     453static s_stat* init_ctx(const char *param UNUSED_PARAM)
     454{
     455    ctx_stat *s = xzalloc(sizeof(*s));
    439456    s->collect = collect_ctx;
    440457    return (s_stat*)s;
     
    447464S_STAT_END(blk_stat)
    448465
    449 static void collect_blk(blk_stat *s)
     466static void FAST_FUNC collect_blk(blk_stat *s)
    450467{
    451468    ullong data[2];
     
    476493}
    477494
    478 static s_stat* init_blk(const char *param)
    479 {
    480     blk_stat *s = xmalloc(sizeof(blk_stat));
     495static s_stat* init_blk(const char *param UNUSED_PARAM)
     496{
     497    blk_stat *s = xzalloc(sizeof(*s));
    481498    s->collect = collect_blk;
    482499    s->lookfor = "page";
     
    489506S_STAT_END(fork_stat)
    490507
    491 static void collect_thread_nr(fork_stat *s)
     508static void FAST_FUNC collect_thread_nr(fork_stat *s UNUSED_PARAM)
    492509{
    493510    ullong data[1];
     
    500517}
    501518
    502 static void collect_fork(fork_stat *s)
     519static void FAST_FUNC collect_fork(fork_stat *s)
    503520{
    504521    ullong data[1];
     
    518535static s_stat* init_fork(const char *param)
    519536{
    520     fork_stat *s = xmalloc(sizeof(fork_stat));
     537    fork_stat *s = xzalloc(sizeof(*s));
    521538    if (*param == 'n') {
    522539        s->collect = collect_thread_nr;
     
    534551S_STAT_END(if_stat)
    535552
    536 static void collect_if(if_stat *s)
     553static void FAST_FUNC collect_if(if_stat *s)
    537554{
    538555    ullong data[4];
     
    558575static s_stat* init_if(const char *device)
    559576{
    560     if_stat *s = xmalloc(sizeof(if_stat));
     577    if_stat *s = xzalloc(sizeof(*s));
    561578
    562579    if (!device || !device[0])
     
    565582
    566583    s->device = device;
    567     s->device_colon = xmalloc(strlen(device)+2);
    568     strcpy(s->device_colon, device);
    569     strcat(s->device_colon, ":");
     584    s->device_colon = xasprintf("%s:", device);
    570585    return (s_stat*)s;
    571586}
     
    611626//HugePages_Free:      0
    612627//Hugepagesize:     4096 kB
    613 static void collect_mem(mem_stat *s)
     628static void FAST_FUNC collect_mem(mem_stat *s)
    614629{
    615630    ullong m_total = 0;
     
    623638        return;
    624639    }
    625     if (s->opt == 'f') {
     640    if (s->opt == 't') {
    626641        scale(m_total << 10);
    627642        return;
     
    648663static s_stat* init_mem(const char *param)
    649664{
    650     mem_stat *s = xmalloc(sizeof(mem_stat));
     665    mem_stat *s = xzalloc(sizeof(*s));
    651666    s->collect = collect_mem;
    652667    s->opt = param[0];
     
    658673S_STAT_END(swp_stat)
    659674
    660 static void collect_swp(swp_stat *s)
     675static void FAST_FUNC collect_swp(swp_stat *s UNUSED_PARAM)
    661676{
    662677    ullong s_total[1];
     
    671686}
    672687
    673 static s_stat* init_swp(const char *param)
    674 {
    675     swp_stat *s = xmalloc(sizeof(swp_stat));
     688static s_stat* init_swp(const char *param UNUSED_PARAM)
     689{
     690    swp_stat *s = xzalloc(sizeof(*s));
    676691    s->collect = collect_swp;
    677692    return (s_stat*)s;
     
    682697S_STAT_END(fd_stat)
    683698
    684 static void collect_fd(fd_stat *s)
     699static void FAST_FUNC collect_fd(fd_stat *s UNUSED_PARAM)
    685700{
    686701    ullong data[2];
     
    694709}
    695710
    696 static s_stat* init_fd(const char *param)
    697 {
    698     fd_stat *s = xmalloc(sizeof(fd_stat));
     711static s_stat* init_fd(const char *param UNUSED_PARAM)
     712{
     713    fd_stat *s = xzalloc(sizeof(*s));
    699714    s->collect = collect_fd;
    700715    return (s_stat*)s;
     
    707722S_STAT_END(time_stat)
    708723
    709 static void collect_time(time_stat *s)
     724static void FAST_FUNC collect_time(time_stat *s)
    710725{
    711726    char buf[sizeof("12:34:56.123456")];
     
    729744{
    730745    int prec;
    731     time_stat *s = xmalloc(sizeof(time_stat));
     746    time_stat *s = xzalloc(sizeof(*s));
    732747
    733748    s->collect = collect_time;
    734     prec = param[0]-'0';
     749    prec = param[0] - '0';
    735750    if (prec < 0) prec = 0;
    736751    else if (prec > 6) prec = 6;
     
    742757}
    743758
    744 static void collect_info(s_stat *s)
     759static void FAST_FUNC collect_info(s_stat *s)
    745760{
    746761    gen ^= 1;
     
    771786};
    772787
    773 int nmeter_main(int argc, char **argv);
    774 int nmeter_main(int argc, char **argv)
     788int nmeter_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     789int nmeter_main(int argc UNUSED_PARAM, char **argv)
    775790{
    776791    char buf[32];
     
    784799    xchdir("/proc");
    785800
    786     if (argc != 2)
     801    if (!argv[1])
    787802        bb_show_usage();
    788803
    789     if (open_read_close("version", buf, sizeof(buf)) > 0)
    790         is26 = (strstr(buf, " 2.4.")==NULL);
     804    if (open_read_close("version", buf, sizeof(buf)-1) > 0) {
     805        buf[sizeof(buf)-1] = '\0';
     806        is26 = (strstr(buf, " 2.4.") == NULL);
     807    }
    791808
    792809    // Can use argv[1] directly, but this will mess up
     
    801818            break;
    802819        if (cur[1] == '%') {    // %%
    803             strcpy(cur, cur+1);
     820            overlapping_strcpy(cur, cur + 1);
    804821            cur++;
    805822            goto again;
     
    832849        if (s) {
    833850            s->label = prev;
    834             s->next = 0;
     851            /*s->next = NULL; - all initXXX funcs use xzalloc */
    835852            if (!first)
    836853                first = s;
     
    847864        s = init_literal();
    848865        s->label = prev;
    849         s->next = 0;
     866        /*s->next = NULL; - all initXXX funcs use xzalloc */
    850867        if (!first)
    851868            first = s;
  • branches/2.2.9/mindi-busybox/procps/pidof.c

    r1765 r2725  
    55 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
    66 *
    7  * Licensed under the GPL version 2, see the file LICENSE in this tarball.
     7 * Licensed under GPLv2, see file LICENSE in this source tree.
    88 */
    99
     
    1111
    1212enum {
    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,
     13    IF_FEATURE_PIDOF_SINGLE(OPTBIT_SINGLE,)
     14    IF_FEATURE_PIDOF_OMIT(  OPTBIT_OMIT  ,)
     15    OPT_SINGLE = IF_FEATURE_PIDOF_SINGLE((1<<OPTBIT_SINGLE)) + 0,
     16    OPT_OMIT   = IF_FEATURE_PIDOF_OMIT(  (1<<OPTBIT_OMIT  )) + 0,
    1717};
    1818
    19 int pidof_main(int argc, char **argv);
    20 int pidof_main(int argc, char **argv)
     19int pidof_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     20int pidof_main(int argc UNUSED_PARAM, char **argv)
    2121{
    2222    unsigned first = 1;
    2323    unsigned opt;
    2424#if ENABLE_FEATURE_PIDOF_OMIT
    25     char ppid_str[sizeof(int)*3 + 1];
    2625    llist_t *omits = NULL; /* list of pids to omit */
    2726    opt_complementary = "o::";
     
    3029    /* do unconditional option parsing */
    3130    opt = getopt32(argv, ""
    32             USE_FEATURE_PIDOF_SINGLE ("s")
    33             USE_FEATURE_PIDOF_OMIT("o:", &omits));
     31            IF_FEATURE_PIDOF_SINGLE ("s")
     32            IF_FEATURE_PIDOF_OMIT("o:", &omits));
    3433
    3534#if ENABLE_FEATURE_PIDOF_OMIT
     
    3736    {
    3837        llist_t *omits_p = omits;
    39         while (omits_p) {
     38        while (1) {
     39            omits_p = llist_find_str(omits_p, "%PPID");
     40            if (!omits_p)
     41                break;
    4042            /* are we asked to exclude the parent's process ID?  */
    41             if (strcmp(omits_p->data, "%PPID") == 0) {
    42                 sprintf(ppid_str, "%u", (unsigned)getppid());
    43                 omits_p->data = ppid_str;
    44             }
    45             omits_p = omits_p->link;
     43            omits_p->data = utoa((unsigned)getppid());
    4644        }
    4745    }
    4846#endif
    4947    /* Looks like everything is set to go.  */
    50     while (optind < argc) {
     48    argv += optind;
     49    while (*argv) {
    5150        pid_t *pidList;
    5251        pid_t *pl;
    5352
    5453        /* reverse the pidlist like GNU pidof does.  */
    55         pidList = pidlist_reverse(find_pid_by_name(argv[optind]));
     54        pidList = pidlist_reverse(find_pid_by_name(*argv));
    5655        for (pl = pidList; *pl; pl++) {
    5756#if ENABLE_FEATURE_PIDOF_OMIT
     
    5958                llist_t *omits_p = omits;
    6059                while (omits_p) {
    61                     if (xatoul(omits_p->data) == *pl) {
     60                    if (xatoul(omits_p->data) == (unsigned long)(*pl)) {
    6261                        goto omitting;
    6362                    }
     
    7574        }
    7675        free(pidList);
    77         optind++;
     76        argv++;
    7877    }
    79     putchar('\n');
     78    if (!first)
     79        bb_putchar('\n');
    8080
    8181#if ENABLE_FEATURE_PIDOF_OMIT
  • branches/2.2.9/mindi-busybox/procps/ps.c

    r1765 r2725  
    55 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
    66 * Fix for SELinux Support:(c)2007 Hiroshi Shinji <shiroshi@my.email.ne.jp>
    7                            (c)2007 Yuichi Nakamura <ynakam@hitachisoft.jp>
     7 *                         (c)2007 Yuichi Nakamura <ynakam@hitachisoft.jp>
    88 *
    9  * Licensed under the GPL version 2, see the file LICENSE in this tarball.
     9 * Licensed under GPLv2, see file LICENSE in this source tree.
    1010 */
    1111
     
    1717#if ENABLE_DESKTOP
    1818
    19 /* Print value to buf, max size+1 chars (including trailing '\0') */
    20 
    21 static 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 
    26 static void func_comm(char *buf, int size, const procps_status_t *ps)
    27 {
    28     safe_strncpy(buf, ps->comm, size+1);
    29 }
    30 
    31 static void func_args(char *buf, int size, const procps_status_t *ps)
    32 {
    33     read_cmdline(buf, size, ps->pid, ps->comm);
    34 }
    35 
    36 static void func_pid(char *buf, int size, const procps_status_t *ps)
    37 {
    38     sprintf(buf, "%*u", size, ps->pid);
    39 }
    40 
    41 static void func_ppid(char *buf, int size, const procps_status_t *ps)
    42 {
    43     sprintf(buf, "%*u", size, ps->ppid);
    44 }
    45 
    46 static void func_pgid(char *buf, int size, const procps_status_t *ps)
    47 {
    48     sprintf(buf, "%*u", size, ps->pgid);
    49 }
    50 
    51 static 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 
    58 static void func_vsz(char *buf, int size, const procps_status_t *ps)
    59 {
    60     put_u(buf, size, ps->vsz);
    61 }
    62 
    63 static void func_rss(char *buf, int size, const procps_status_t *ps)
    64 {
    65     put_u(buf, size, ps->rss);
    66 }
    67 
    68 static 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 }
     19#include <sys/times.h> /* for times() */
     20#ifndef AT_CLKTCK
     21#define AT_CLKTCK 17
     22#endif
     23
    7524
    7625#if ENABLE_SELINUX
    77 static 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 /*
    84 static void func_nice(char *buf, int size, const procps_status_t *ps)
    85 {
    86     ps->???
    87 }
    88 
    89 static void func_etime(char *buf, int size, const procps_status_t *ps)
    90 {
    91     elapled time [[dd-]hh:]mm:ss
    92 }
    93 
    94 static void func_time(char *buf, int size, const procps_status_t *ps)
    95 {
    96     cumulative time [[dd-]hh:]mm:ss
    97 }
    98 
    99 static void func_pcpu(char *buf, int size, const procps_status_t *ps)
    100 {
    101 }
    102 */
     26#define SELINUX_O_PREFIX "label,"
     27#define DEFAULT_O_STR    (SELINUX_O_PREFIX "pid,user" IF_FEATURE_PS_TIME(",time") ",args")
     28#else
     29#define DEFAULT_O_STR    ("pid,user" IF_FEATURE_PS_TIME(",time") ",args")
     30#endif
    10331
    10432typedef struct {
    10533    uint16_t width;
    106     char name[6];
     34    char name6[6];
    10735    const char *header;
    10836    void (*f)(char *buf, int size, const procps_status_t *ps);
    10937    int ps_flags;
    11038} ps_out_t;
    111 
    112 static 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
    14239
    14340struct globals {
     
    14845    char *buffer;
    14946    unsigned terminal_width;
     47#if ENABLE_FEATURE_PS_TIME
     48    unsigned kernel_HZ;
     49    unsigned long long seconds_since_boot;
     50#endif
    15051    char default_o[sizeof(DEFAULT_O_STR)];
     52} FIX_ALIASING;
     53#define G (*(struct globals*)&bb_common_bufsiz1)
     54#define out                (G.out               )
     55#define out_cnt            (G.out_cnt           )
     56#define print_header       (G.print_header      )
     57#define need_flags         (G.need_flags        )
     58#define buffer             (G.buffer            )
     59#define terminal_width     (G.terminal_width    )
     60#define kernel_HZ          (G.kernel_HZ         )
     61#define seconds_since_boot (G.seconds_since_boot)
     62#define default_o          (G.default_o         )
     63#define INIT_G() do { } while (0)
     64
     65#if ENABLE_FEATURE_PS_TIME
     66/* for ELF executables, notes are pushed before environment and args */
     67static ptrdiff_t find_elf_note(ptrdiff_t findme)
     68{
     69    ptrdiff_t *ep = (ptrdiff_t *) environ;
     70
     71    while (*ep++);
     72    while (*ep) {
     73        if (ep[0] == findme) {
     74            return ep[1];
     75        }
     76        ep += 2;
     77    }
     78    return -1;
     79}
     80
     81#if ENABLE_FEATURE_PS_UNUSUAL_SYSTEMS
     82static unsigned get_HZ_by_waiting(void)
     83{
     84    struct timeval tv1, tv2;
     85    unsigned t1, t2, r, hz;
     86    unsigned cnt = cnt; /* for compiler */
     87    int diff;
     88
     89    r = 0;
     90
     91    /* Wait for times() to reach new tick */
     92    t1 = times(NULL);
     93    do {
     94        t2 = times(NULL);
     95    } while (t2 == t1);
     96    gettimeofday(&tv2, NULL);
     97
     98    do {
     99        t1 = t2;
     100        tv1.tv_usec = tv2.tv_usec;
     101
     102        /* Wait exactly one times() tick */
     103        do {
     104            t2 = times(NULL);
     105        } while (t2 == t1);
     106        gettimeofday(&tv2, NULL);
     107
     108        /* Calculate ticks per sec, rounding up to even */
     109        diff = tv2.tv_usec - tv1.tv_usec;
     110        if (diff <= 0) diff += 1000000;
     111        hz = 1000000u / (unsigned)diff;
     112        hz = (hz+1) & ~1;
     113
     114        /* Count how many same hz values we saw */
     115        if (r != hz) {
     116            r = hz;
     117            cnt = 0;
     118        }
     119        cnt++;
     120    } while (cnt < 3); /* exit if saw 3 same values */
     121
     122    return r;
     123}
     124#else
     125static inline unsigned get_HZ_by_waiting(void)
     126{
     127    /* Better method? */
     128    return 100;
     129}
     130#endif
     131
     132static unsigned get_kernel_HZ(void)
     133{
     134    //char buf[64];
     135    struct sysinfo info;
     136
     137    if (kernel_HZ)
     138        return kernel_HZ;
     139
     140    /* Works for ELF only, Linux 2.4.0+ */
     141    kernel_HZ = find_elf_note(AT_CLKTCK);
     142    if (kernel_HZ == (unsigned)-1)
     143        kernel_HZ = get_HZ_by_waiting();
     144
     145    //if (open_read_close("/proc/uptime", buf, sizeof(buf)) <= 0)
     146    //  bb_perror_msg_and_die("can't read %s", "/proc/uptime");
     147    //buf[sizeof(buf)-1] = '\0';
     148    ///sscanf(buf, "%llu", &seconds_since_boot);
     149    sysinfo(&info);
     150    seconds_since_boot = info.uptime;
     151
     152    return kernel_HZ;
     153}
     154#endif
     155
     156/* Print value to buf, max size+1 chars (including trailing '\0') */
     157
     158static void func_user(char *buf, int size, const procps_status_t *ps)
     159{
     160#if 1
     161    safe_strncpy(buf, get_cached_username(ps->uid), size+1);
     162#else
     163    /* "compatible" version, but it's larger */
     164    /* procps 2.18 shows numeric UID if name overflows the field */
     165    /* TODO: get_cached_username() returns numeric string if
     166     * user has no passwd record, we will display it
     167     * left-justified here; too long usernames are shown
     168     * as _right-justified_ IDs. Is it worth fixing? */
     169    const char *user = get_cached_username(ps->uid);
     170    if (strlen(user) <= size)
     171        safe_strncpy(buf, user, size+1);
     172    else
     173        sprintf(buf, "%*u", size, (unsigned)ps->uid);
     174#endif
     175}
     176
     177static void func_group(char *buf, int size, const procps_status_t *ps)
     178{
     179    safe_strncpy(buf, get_cached_groupname(ps->gid), size+1);
     180}
     181
     182static void func_comm(char *buf, int size, const procps_status_t *ps)
     183{
     184    safe_strncpy(buf, ps->comm, size+1);
     185}
     186
     187static void func_args(char *buf, int size, const procps_status_t *ps)
     188{
     189    read_cmdline(buf, size+1, ps->pid, ps->comm);
     190}
     191
     192static void func_pid(char *buf, int size, const procps_status_t *ps)
     193{
     194    sprintf(buf, "%*u", size, ps->pid);
     195}
     196
     197static void func_ppid(char *buf, int size, const procps_status_t *ps)
     198{
     199    sprintf(buf, "%*u", size, ps->ppid);
     200}
     201
     202static void func_pgid(char *buf, int size, const procps_status_t *ps)
     203{
     204    sprintf(buf, "%*u", size, ps->pgid);
     205}
     206
     207static void put_lu(char *buf, int size, unsigned long u)
     208{
     209    char buf4[5];
     210
     211    /* see http://en.wikipedia.org/wiki/Tera */
     212    smart_ulltoa4(u, buf4, " mgtpezy");
     213    buf4[4] = '\0';
     214    sprintf(buf, "%.*s", size, buf4);
     215}
     216
     217static void func_vsz(char *buf, int size, const procps_status_t *ps)
     218{
     219    put_lu(buf, size, ps->vsz);
     220}
     221
     222static void func_rss(char *buf, int size, const procps_status_t *ps)
     223{
     224    put_lu(buf, size, ps->rss);
     225}
     226
     227static void func_tty(char *buf, int size, const procps_status_t *ps)
     228{
     229    buf[0] = '?';
     230    buf[1] = '\0';
     231    if (ps->tty_major) /* tty field of "0" means "no tty" */
     232        snprintf(buf, size+1, "%u,%u", ps->tty_major, ps->tty_minor);
     233}
     234
     235#if ENABLE_FEATURE_PS_ADDITIONAL_COLUMNS
     236
     237static void func_rgroup(char *buf, int size, const procps_status_t *ps)
     238{
     239    safe_strncpy(buf, get_cached_groupname(ps->rgid), size+1);
     240}
     241
     242static void func_ruser(char *buf, int size, const procps_status_t *ps)
     243{
     244    safe_strncpy(buf, get_cached_username(ps->ruid), size+1);
     245}
     246
     247static void func_nice(char *buf, int size, const procps_status_t *ps)
     248{
     249    sprintf(buf, "%*d", size, ps->niceness);
     250}
     251
     252#endif
     253
     254#if ENABLE_FEATURE_PS_TIME
     255
     256static void func_etime(char *buf, int size, const procps_status_t *ps)
     257{
     258    /* elapsed time [[dd-]hh:]mm:ss; here only mm:ss */
     259    unsigned long mm;
     260    unsigned ss;
     261
     262    mm = ps->start_time / get_kernel_HZ();
     263    /* must be after get_kernel_HZ()! */
     264    mm = seconds_since_boot - mm;
     265    ss = mm % 60;
     266    mm /= 60;
     267    snprintf(buf, size+1, "%3lu:%02u", mm, ss);
     268}
     269
     270static void func_time(char *buf, int size, const procps_status_t *ps)
     271{
     272    /* cumulative time [[dd-]hh:]mm:ss; here only mm:ss */
     273    unsigned long mm;
     274    unsigned ss;
     275
     276    mm = (ps->utime + ps->stime) / get_kernel_HZ();
     277    ss = mm % 60;
     278    mm /= 60;
     279    snprintf(buf, size+1, "%3lu:%02u", mm, ss);
     280}
     281
     282#endif
     283
     284#if ENABLE_SELINUX
     285static void func_label(char *buf, int size, const procps_status_t *ps)
     286{
     287    safe_strncpy(buf, ps->context ? ps->context : "unknown", size+1);
     288}
     289#endif
     290
     291/*
     292static void func_nice(char *buf, int size, const procps_status_t *ps)
     293{
     294    ps->???
     295}
     296
     297static void func_pcpu(char *buf, int size, const procps_status_t *ps)
     298{
     299}
     300*/
     301
     302static const ps_out_t out_spec[] = {
     303// Mandated by POSIX:
     304    { 8                  , "user"  ,"USER"   ,func_user  ,PSSCAN_UIDGID  },
     305    { 8                  , "group" ,"GROUP"  ,func_group ,PSSCAN_UIDGID  },
     306    { 16                 , "comm"  ,"COMMAND",func_comm  ,PSSCAN_COMM    },
     307    { MAX_WIDTH          , "args"  ,"COMMAND",func_args  ,PSSCAN_COMM    },
     308    { 5                  , "pid"   ,"PID"    ,func_pid   ,PSSCAN_PID     },
     309    { 5                  , "ppid"  ,"PPID"   ,func_ppid  ,PSSCAN_PPID    },
     310    { 5                  , "pgid"  ,"PGID"   ,func_pgid  ,PSSCAN_PGID    },
     311#if ENABLE_FEATURE_PS_TIME
     312    { sizeof("ELAPSED")-1, "etime" ,"ELAPSED",func_etime ,PSSCAN_START_TIME },
     313#endif
     314#if ENABLE_FEATURE_PS_ADDITIONAL_COLUMNS
     315    { 5                  , "nice"  ,"NI"     ,func_nice  ,PSSCAN_NICE    },
     316    { 8                  , "rgroup","RGROUP" ,func_rgroup,PSSCAN_RUIDGID },
     317    { 8                  , "ruser" ,"RUSER"  ,func_ruser ,PSSCAN_RUIDGID },
     318//  { 5                  , "pcpu"  ,"%CPU"   ,func_pcpu  ,PSSCAN_        },
     319#endif
     320#if ENABLE_FEATURE_PS_TIME
     321    { 6                  , "time"  ,"TIME"   ,func_time  ,PSSCAN_STIME | PSSCAN_UTIME },
     322#endif
     323    { 6                  , "tty"   ,"TT"     ,func_tty   ,PSSCAN_TTY     },
     324    { 4                  , "vsz"   ,"VSZ"    ,func_vsz   ,PSSCAN_VSZ     },
     325// Not mandated by POSIX, but useful:
     326    { 4                  , "rss"   ,"RSS"    ,func_rss   ,PSSCAN_RSS     },
     327#if ENABLE_SELINUX
     328    { 35                 , "label" ,"LABEL"  ,func_label ,PSSCAN_CONTEXT },
     329#endif
    151330};
    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     )
    160331
    161332static ps_out_t* new_out_t(void)
    162333{
    163     int i = out_cnt++;
    164     out = xrealloc(out, out_cnt * sizeof(*out));
    165     return &out[i];
     334    out = xrealloc_vector(out, 2, out_cnt);
     335    return &out[out_cnt++];
    166336}
    167337
    168338static const ps_out_t* find_out_spec(const char *name)
    169339{
    170     int i;
     340    unsigned i;
     341    char buf[ARRAY_SIZE(out_spec)*7 + 1];
     342    char *p = buf;
     343
    171344    for (i = 0; i < ARRAY_SIZE(out_spec); i++) {
    172         if (!strcmp(name, out_spec[i].name))
     345        if (strncmp(name, out_spec[i].name6, 6) == 0)
    173346            return &out_spec[i];
    174     }
    175     bb_error_msg_and_die("bad -o argument '%s'", name);
     347        p += sprintf(p, "%.6s,", out_spec[i].name6);
     348    }
     349    p[-1] = '\0';
     350    bb_error_msg_and_die("bad -o argument '%s', supported arguments: %s", name, buf);
    176351}
    177352
     
    215390}
    216391
    217 static void post_process(void)
     392static void alloc_line_buffer(void)
    218393{
    219394    int i;
     
    225400        }
    226401        width += out[i].width + 1; /* "FIELD " */
     402        if ((int)(width - terminal_width) > 0) {
     403            /* The rest does not fit on the screen */
     404            //out[i].width -= (width - terminal_width - 1);
     405            out_cnt = i + 1;
     406            break;
     407        }
    227408    }
    228409#if ENABLE_SELINUX
     
    279460}
    280461
    281 int ps_main(int argc, char **argv);
    282 int ps_main(int argc, char **argv)
     462int ps_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     463int ps_main(int argc UNUSED_PARAM, char **argv)
    283464{
    284465    procps_status_t *p;
    285466    llist_t* opt_o = NULL;
    286     USE_SELINUX(int opt;)
     467    int opt;
     468    enum {
     469        OPT_Z = (1 << 0),
     470        OPT_o = (1 << 1),
     471        OPT_a = (1 << 2),
     472        OPT_A = (1 << 3),
     473        OPT_d = (1 << 4),
     474        OPT_e = (1 << 5),
     475        OPT_f = (1 << 6),
     476        OPT_l = (1 << 7),
     477        OPT_T = (1 << 8) * ENABLE_FEATURE_SHOW_THREADS,
     478    };
     479
     480    INIT_G();
    287481
    288482    // POSIX:
     
    291485    // -A  Write information for all processes
    292486    // -d  Write information for all processes, except session leaders
    293     // -e  Write information for all processes (equivalent to -A.)
     487    // -e  Write information for all processes (equivalent to -A)
    294488    // -f  Generate a full listing
    295489    // -l  Generate a long listing
    296490    // -o col1,col2,col3=header
    297491    //     Select which columns to display
    298     /* We allow (and ignore) most of the above. FIXME */
     492    /* We allow (and ignore) most of the above. FIXME.
     493     * -T is picked for threads (POSIX hasn't it standardized).
     494     * procps v3.2.7 supports -T and shows tids as SPID column,
     495     * it also supports -L where it shows tids as LWP column.
     496     */
    299497    opt_complementary = "o::";
    300     USE_SELINUX(opt =) getopt32(argv, "Zo:aAdefl", &opt_o);
     498    opt = getopt32(argv, "Zo:aAdefl"IF_FEATURE_SHOW_THREADS("T"), &opt_o);
    301499    if (opt_o) {
    302500        do {
    303             parse_o(opt_o->data);
    304             opt_o = opt_o->link;
     501            parse_o(llist_pop(&opt_o));
    305502        } while (opt_o);
    306503    } else {
    307504        /* Below: parse_o() needs char*, NOT const char*... */
    308505#if ENABLE_SELINUX
    309         if (!(opt & 1) || !is_selinux_enabled()) {
     506        if (!(opt & OPT_Z) || !is_selinux_enabled()) {
    310507            /* no -Z or no SELinux: do not show LABEL */
    311             strcpy(default_o, DEFAULT_O_STR + sizeof(SELINIX_O_PREFIX)-1);
     508            strcpy(default_o, DEFAULT_O_STR + sizeof(SELINUX_O_PREFIX)-1);
    312509        } else
    313510#endif
     
    317514        parse_o(default_o);
    318515    }
    319     post_process();
     516#if ENABLE_FEATURE_SHOW_THREADS
     517    if (opt & OPT_T)
     518        need_flags |= PSSCAN_TASKS;
     519#endif
    320520
    321521    /* Was INT_MAX, but some libc's go belly up with printf("%.*s")
     
    327527            terminal_width = MAX_WIDTH;
    328528    }
     529    alloc_line_buffer();
    329530    format_header();
    330531
    331532    p = NULL;
    332     while ((p = procps_scan(p, need_flags))) {
     533    while ((p = procps_scan(p, need_flags)) != NULL) {
    333534        format_process(p);
    334535    }
     
    341542
    342543
    343 int ps_main(int argc, char **argv);
    344 int ps_main(int argc, char **argv)
    345 {
    346     procps_status_t *p = NULL;
    347     int len;
    348     SKIP_SELINUX(const) int use_selinux = 0;
    349     USE_SELINUX(int i;)
    350 #if !ENABLE_FEATURE_PS_WIDE
    351     enum { terminal_width = 79 };
    352 #else
    353     int terminal_width;
     544int ps_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     545int ps_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
     546{
     547    procps_status_t *p;
     548    int psscan_flags = PSSCAN_PID | PSSCAN_UIDGID
     549            | PSSCAN_STATE | PSSCAN_VSZ | PSSCAN_COMM;
     550    unsigned terminal_width IF_NOT_FEATURE_PS_WIDE(= 79);
     551    enum {
     552        OPT_Z = (1 << 0) * ENABLE_SELINUX,
     553        OPT_T = (1 << ENABLE_SELINUX) * ENABLE_FEATURE_SHOW_THREADS,
     554    };
     555    int opts = 0;
     556    /* If we support any options, parse argv */
     557#if ENABLE_SELINUX || ENABLE_FEATURE_SHOW_THREADS || ENABLE_FEATURE_PS_WIDE
     558# if ENABLE_FEATURE_PS_WIDE
     559    /* -w is a bit complicated */
    354560    int w_count = 0;
    355 #endif
    356 
    357 #if ENABLE_FEATURE_PS_WIDE || ENABLE_SELINUX
    358 #if ENABLE_FEATURE_PS_WIDE
    359561    opt_complementary = "-:ww";
    360     USE_SELINUX(i =) getopt32(argv, USE_SELINUX("Z") "w", &w_count);
     562    opts = getopt32(argv, IF_SELINUX("Z")IF_FEATURE_SHOW_THREADS("T")"w", &w_count);
    361563    /* if w is given once, GNU ps sets the width to 132,
    362564     * if w is given more than once, it is "unlimited"
    363565     */
    364566    if (w_count) {
    365         terminal_width = (w_count==1) ? 132 : MAX_WIDTH;
     567        terminal_width = (w_count == 1) ? 132 : MAX_WIDTH;
    366568    } else {
    367569        get_terminal_width_height(0, &terminal_width, NULL);
     
    370572            terminal_width = MAX_WIDTH;
    371573    }
    372 #else /* only ENABLE_SELINUX */
    373     i = getopt32(argv, "Z");
    374 #endif
     574# else
     575    /* -w is not supported, only -Z and/or -T */
     576    opt_complementary = "-";
     577    opts = getopt32(argv, IF_SELINUX("Z")IF_FEATURE_SHOW_THREADS("T"));
     578# endif
     579#endif
     580
    375581#if ENABLE_SELINUX
    376     if ((i & 1) && is_selinux_enabled())
    377         use_selinux = PSSCAN_CONTEXT;
    378 #endif
    379 #endif /* ENABLE_FEATURE_PS_WIDE || ENABLE_SELINUX */
    380 
    381     if (use_selinux)
    382         puts("  PID Context                          Stat Command");
    383     else
    384         puts("  PID  Uid        VSZ Stat Command");
    385 
    386     while ((p = procps_scan(p, 0
    387             | PSSCAN_PID
    388             | PSSCAN_UIDGID
    389             | PSSCAN_STATE
    390             | PSSCAN_VSZ
    391             | PSSCAN_COMM
    392             | use_selinux
    393     ))) {
     582    if ((opts & OPT_Z) && is_selinux_enabled()) {
     583        psscan_flags = PSSCAN_PID | PSSCAN_CONTEXT
     584                | PSSCAN_STATE | PSSCAN_COMM;
     585        puts("  PID CONTEXT                          STAT COMMAND");
     586    } else
     587#endif
     588    {
     589        puts("  PID USER       VSZ STAT COMMAND");
     590    }
     591    if (opts & OPT_T) {
     592        psscan_flags |= PSSCAN_TASKS;
     593    }
     594
     595    p = NULL;
     596    while ((p = procps_scan(p, psscan_flags)) != NULL) {
     597        int len;
    394598#if ENABLE_SELINUX
    395         if (use_selinux) {
    396             len = printf("%5u %-32s %s ",
     599        if (psscan_flags & PSSCAN_CONTEXT) {
     600            len = printf("%5u %-32.32s %s ",
    397601                    p->pid,
    398602                    p->context ? p->context : "unknown",
     
    402606        {
    403607            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);
     608            //if (p->vsz == 0)
     609            //  len = printf("%5u %-8.8s        %s ",
     610            //      p->pid, user, p->state);
     611            //else
     612            {
     613                char buf6[6];
     614                smart_ulltoa5(p->vsz, buf6, " mgtpezy");
     615                buf6[5] = '\0';
     616                len = printf("%5u %-8.8s %s %s  ",
     617                    p->pid, user, buf6, p->state);
     618            }
    410619        }
    411620
     
    422631}
    423632
    424 #endif /* ENABLE_DESKTOP */
     633#endif /* !ENABLE_DESKTOP */
  • branches/2.2.9/mindi-busybox/procps/renice.c

    r1765 r2725  
    55 * Copyright (C) 2005  Manuel Novoa III  <mjn3@codepoet.org>
    66 *
    7  * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
     
    2727void BUG_bad_PRIO_USER(void);
    2828
    29 int renice_main(int argc, char **argv);
    30 int renice_main(int argc, char **argv)
     29int renice_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     30int renice_main(int argc UNUSED_PARAM, char **argv)
    3131{
    3232    static const char Xetpriority_msg[] ALIGN1 = "%cetpriority";
    3333
    3434    int retval = EXIT_SUCCESS;
    35     int which = PRIO_PROCESS;   /* Default 'which' value. */
     35    int which = PRIO_PROCESS;  /* Default 'which' value. */
    3636    int use_relative = 0;
    3737    int adjustment, new_priority;
     
    5858    }
    5959
    60     if (!arg) {             /* No args?  Then show usage. */
     60    if (!arg) {  /* No args?  Then show usage. */
    6161        bb_show_usage();
    6262    }
     
    8585            p = getpwnam(arg);
    8686            if (!p) {
    87                 bb_error_msg("unknown user: %s", arg);
     87                bb_error_msg("unknown user %s", arg);
    8888                goto HAD_ERROR;
    8989            }
     
    9292            who = bb_strtou(arg, NULL, 10);
    9393            if (errno) {
    94                 bb_error_msg("bad value: %s", arg);
     94                bb_error_msg("invalid number '%s'", arg);
    9595                goto HAD_ERROR;
    9696            }
     
    101101            int old_priority;
    102102
    103             errno = 0;  /* Needed for getpriority error detection. */
     103            errno = 0;  /* Needed for getpriority error detection. */
    104104            old_priority = getpriority(which, who);
    105105            if (errno) {
  • branches/2.2.9/mindi-busybox/procps/sysctl.c

    r1765 r2725  
    55 * Copyright 1999 George Staikos
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 *
    99 * Changelog:
    10  *  v1.01:
    11  *      - added -p <preload> to preload values from a file
    12  *  v1.01.1
    13  *      - busybox applet aware by <solar@gentoo.org>
    14  *
     10 * v1.01   - added -p <preload> to preload values from a file
     11 * v1.01.1 - busybox applet aware by <solar@gentoo.org>
    1512 */
    1613
    1714#include "libbb.h"
    1815
    19 /*
    20  *    Function Prototypes
    21  */
    22 static int sysctl_read_setting(const char *setting, int output);
    23 static int sysctl_write_setting(const char *setting, int output);
    24 static int sysctl_preload_file(const char *filename, int output);
    25 static int sysctl_display_all(const char *path, int output, int show_table);
    26 
    27 /*
    28  *    Globals...
    29  */
    30 static const char PROC_PATH[] ALIGN1 = "/proc/sys/";
    31 static const char DEFAULT_PRELOAD[] ALIGN1 = "/etc/sysctl.conf";
    32 
    33 /* error messages */
    34 static const char ERR_UNKNOWN_PARAMETER[] ALIGN1 =
    35     "error: Unknown parameter '%s'\n";
    36 static const char ERR_MALFORMED_SETTING[] ALIGN1 =
    37     "error: Malformed setting '%s'\n";
    38 static const char ERR_NO_EQUALS[] ALIGN1 =
    39     "error: '%s' must be of the form name=value\n";
    40 static const char ERR_INVALID_KEY[] ALIGN1 =
    41     "error: '%s' is an unknown key\n";
    42 static const char ERR_UNKNOWN_WRITING[] ALIGN1 =
    43     "error: unknown error %d setting key '%s'\n";
    44 static const char ERR_UNKNOWN_READING[] ALIGN1 =
    45     "error: unknown error %d reading key '%s'\n";
    46 static const char ERR_PERMISSION_DENIED[] ALIGN1 =
    47     "error: permission denied on key '%s'\n";
    48 static const char ERR_PRELOAD_FILE[] ALIGN1 =
    49     "error: cannot open preload file '%s'\n";
    50 static const char WARN_BAD_LINE[] ALIGN1 =
    51     "warning: %s(%d): invalid syntax, continuing...\n";
    52 
    53 
    54 static void dwrite_str(int fd, const char *buf)
    55 {
    56     write(fd, buf, strlen(buf));
    57 }
    58 
    59 /*
    60  *    sysctl_main()...
    61  */
    62 int sysctl_main(int argc, char **argv);
    63 int sysctl_main(int argc, char **argv)
    64 {
    65     int retval = 0;
    66     int output = 1;
    67     int write_mode = 0;
    68     int switches_allowed = 1;
    69 
    70     if (argc < 2)
    71         bb_show_usage();
    72 
    73     argv++;
    74 
    75     for (; argv && *argv && **argv; argv++) {
    76         if (switches_allowed && **argv == '-') {    /* we have a switch */
    77             switch ((*argv)[1]) {
    78             case 'n':
    79                 output = 0;
    80                 break;
    81             case 'w':
    82                 write_mode = 1;
    83                 switches_allowed = 0;
    84                 break;
    85             case 'p':
    86                 argv++;
    87                 return
    88                     sysctl_preload_file(((argv && *argv
    89                                           && **argv) ? *argv :
    90                                          DEFAULT_PRELOAD), output);
    91             case 'a':
    92             case 'A':
    93                 switches_allowed = 0;
    94                 return sysctl_display_all(PROC_PATH, output,
    95                                           ((*argv)[1] == 'a') ? 0 : 1);
    96             case 'h':
    97             case '?':
    98                 bb_show_usage();
    99             default:
    100                 bb_error_msg(ERR_UNKNOWN_PARAMETER, *argv);
    101                 bb_show_usage();
     16enum {
     17    FLAG_SHOW_KEYS       = 1 << 0,
     18    FLAG_SHOW_KEY_ERRORS = 1 << 1,
     19    FLAG_TABLE_FORMAT    = 1 << 2, /* not implemented */
     20    FLAG_SHOW_ALL        = 1 << 3,
     21    FLAG_PRELOAD_FILE    = 1 << 4,
     22    FLAG_WRITE           = 1 << 5,
     23};
     24#define OPTION_STR "neAapw"
     25
     26static void sysctl_dots_to_slashes(char *name)
     27{
     28    char *cptr, *last_good, *end;
     29
     30    /* Convert minimum number of '.' to '/' so that
     31     * we end up with existing file's name.
     32     *
     33     * Example from bug 3894:
     34     * net.ipv4.conf.eth0.100.mc_forwarding ->
     35     * net/ipv4/conf/eth0.100/mc_forwarding
     36     * NB: net/ipv4/conf/eth0/mc_forwarding *also exists*,
     37     * therefore we must start from the end, and if
     38     * we replaced even one . -> /, start over again,
     39     * but never replace dots before the position
     40     * where last replacement occurred.
     41     *
     42     * Another bug we later had is that
     43     * net.ipv4.conf.eth0.100
     44     * (without .mc_forwarding) was mishandled.
     45     *
     46     * To set up testing: modprobe 8021q; vconfig add eth0 100
     47     */
     48    end = name + strlen(name);
     49    last_good = name - 1;
     50    *end = '.'; /* trick the loop into trying full name too */
     51
     52 again:
     53    cptr = end;
     54    while (cptr > last_good) {
     55        if (*cptr == '.') {
     56            *cptr = '\0';
     57            //bb_error_msg("trying:'%s'", name);
     58            if (access(name, F_OK) == 0) {
     59                *cptr = '/';
     60                //bb_error_msg("replaced:'%s'", name);
     61                last_good = cptr;
     62                goto again;
    10263            }
    103         } else {
    104             switches_allowed = 0;
    105             if (write_mode)
    106                 retval = sysctl_write_setting(*argv, output);
    107             else
    108                 sysctl_read_setting(*argv, output);
    109         }
    110     }
    111     return retval;
    112 }                       /* end sysctl_main() */
    113 
    114 
    115 
    116 /*
    117  *     sysctl_preload_file
    118  *  preload the sysctl's from a conf file
    119  *           - we parse the file and then reform it (strip out whitespace)
    120  */
    121 #define PRELOAD_BUF 256
    122 
    123 int sysctl_preload_file(const char *filename, int output)
    124 {
    125     int lineno = 0;
    126     char oneline[PRELOAD_BUF];
    127     char buffer[PRELOAD_BUF];
    128     char *name, *value, *ptr;
    129     FILE *fp = NULL;
    130 
    131     if (!filename || ((fp = fopen(filename, "r")) == NULL)) {
    132         bb_error_msg_and_die(ERR_PRELOAD_FILE, filename);
    133     }
    134 
    135     while (fgets(oneline, sizeof(oneline) - 1, fp)) {
    136         oneline[sizeof(oneline) - 1] = '\0';
    137         lineno++;
    138         trim(oneline);
    139         ptr = (char *) oneline;
    140 
    141         if (*ptr == '#' || *ptr == ';')
    142             continue;
    143 
    144         if (strlen(ptr) < 2)
    145             continue;
    146 
    147         name = strtok(ptr, "=");
    148         if (!name || !*name) {
    149             bb_error_msg(WARN_BAD_LINE, filename, lineno);
    150             continue;
    151         }
    152 
    153         trim(name);
    154 
    155         value = strtok(NULL, "\n\r");
    156         if (!value || !*value) {
    157             bb_error_msg(WARN_BAD_LINE, filename, lineno);
    158             continue;
    159         }
    160 
    161         while ((*value == ' ' || *value == '\t') && *value != 0)
    162             value++;
    163         /* safe because sizeof(oneline) == sizeof(buffer) */
    164         sprintf(buffer, "%s=%s", name, value);
    165         sysctl_write_setting(buffer, output);
    166     }
    167     fclose(fp);
    168     return 0;
    169 }                       /* end sysctl_preload_file() */
    170 
    171 
    172 /*
    173  *     Write a single sysctl setting
    174  */
    175 int sysctl_write_setting(const char *setting, int output)
    176 {
    177     int retval = 0;
    178     const char *name = setting;
    179     const char *value;
    180     const char *equals;
    181     char *tmpname, *outname, *cptr;
    182     int fd = -1;
    183 
    184     if (!name)          /* probably dont' want to display this  err */
    185         return 0;
    186 
    187     if (!(equals = strchr(setting, '='))) {
    188         bb_error_msg(ERR_NO_EQUALS, setting);
    189         return -1;
    190     }
    191 
    192     value = equals + sizeof(char);  /* point to the value in name=value */
    193 
    194     if (!*name || !*value || name == equals) {
    195         bb_error_msg(ERR_MALFORMED_SETTING, setting);
    196         return -2;
    197     }
    198 
    199     tmpname = xasprintf("%s%.*s", PROC_PATH, (int)(equals - name), name);
    200     outname = xstrdup(tmpname + strlen(PROC_PATH));
    201 
    202     while ((cptr = strchr(tmpname, '.')) != NULL)
    203         *cptr = '/';
    204 
    205     while ((cptr = strchr(outname, '/')) != NULL)
    206         *cptr = '.';
    207 
    208     fd = open(tmpname, O_WRONLY | O_CREAT | O_TRUNC, 0666);
     64            *cptr = '.';
     65        }
     66        cptr--;
     67    }
     68    *end = '\0';
     69}
     70
     71static int sysctl_act_on_setting(char *setting)
     72{
     73    int fd, retval = EXIT_SUCCESS;
     74    char *cptr, *outname;
     75    char *value = value; /* for compiler */
     76
     77    outname = xstrdup(setting);
     78
     79    cptr = outname;
     80    while (*cptr) {
     81        if (*cptr == '/')
     82            *cptr = '.';
     83        cptr++;
     84    }
     85
     86    if (option_mask32 & FLAG_WRITE) {
     87        cptr = strchr(setting, '=');
     88        if (cptr == NULL) {
     89            bb_error_msg("error: '%s' must be of the form name=value",
     90                outname);
     91            retval = EXIT_FAILURE;
     92            goto end;
     93        }
     94        value = cptr + 1;  /* point to the value in name=value */
     95        if (setting == cptr || !*value) {
     96            bb_error_msg("error: malformed setting '%s'", outname);
     97            retval = EXIT_FAILURE;
     98            goto end;
     99        }
     100        *cptr = '\0';
     101        outname[cptr - setting] = '\0';
     102        /* procps 3.2.7 actually uses these flags */
     103        fd = open(setting, O_WRONLY|O_CREAT|O_TRUNC, 0666);
     104    } else {
     105        fd = open(setting, O_RDONLY);
     106    }
     107
    209108    if (fd < 0) {
    210109        switch (errno) {
    211110        case ENOENT:
    212             bb_error_msg(ERR_INVALID_KEY, outname);
    213             break;
    214         case EACCES:
    215             bb_perror_msg(ERR_PERMISSION_DENIED, outname);
     111            if (option_mask32 & FLAG_SHOW_KEY_ERRORS)
     112                bb_error_msg("error: '%s' is an unknown key", outname);
    216113            break;
    217114        default:
    218             bb_error_msg(ERR_UNKNOWN_WRITING, errno, outname);
     115            bb_perror_msg("error %sing key '%s'",
     116                    option_mask32 & FLAG_WRITE ?
     117                        "sett" : "read",
     118                    outname);
    219119            break;
    220120        }
    221         retval = -1;
     121        retval = EXIT_FAILURE;
     122        goto end;
     123    }
     124
     125    if (option_mask32 & FLAG_WRITE) {
     126//TODO: procps 3.2.7 writes "value\n", note trailing "\n"
     127        xwrite_str(fd, value);
     128        close(fd);
     129        if (option_mask32 & FLAG_SHOW_KEYS)
     130            printf("%s = ", outname);
     131        puts(value);
    222132    } else {
    223         dwrite_str(fd, value);
     133        char c;
     134
     135        value = cptr = xmalloc_read(fd, NULL);
    224136        close(fd);
    225         if (output) {
    226             dwrite_str(STDOUT_FILENO, outname);
    227             dwrite_str(STDOUT_FILENO, " = ");
    228         }
    229         dwrite_str(STDOUT_FILENO, value);
    230         dwrite_str(STDOUT_FILENO, "\n");
    231     }
    232 
    233     /* cleanup */
    234     free(tmpname);
     137        if (value == NULL) {
     138            bb_perror_msg("error reading key '%s'", outname);
     139            goto end;
     140        }
     141
     142        /* dev.cdrom.info and sunrpc.transports, for example,
     143         * are multi-line. Try "sysctl sunrpc.transports"
     144         */
     145        while ((c = *cptr) != '\0') {
     146            if (option_mask32 & FLAG_SHOW_KEYS)
     147                printf("%s = ", outname);
     148            while (1) {
     149                fputc(c, stdout);
     150                cptr++;
     151                if (c == '\n')
     152                    break;
     153                c = *cptr;
     154                if (c == '\0')
     155                    break;
     156            }
     157        }
     158        free(value);
     159    }
     160 end:
    235161    free(outname);
    236162    return retval;
    237 }                       /* end sysctl_write_setting() */
    238 
    239 
    240 /*
    241  *     Read a sysctl setting
    242  *
     163}
     164
     165static int sysctl_act_recursive(const char *path)
     166{
     167    DIR *dirp;
     168    struct stat buf;
     169    struct dirent *entry;
     170    char *next;
     171    int retval = 0;
     172
     173    stat(path, &buf);
     174    if (S_ISDIR(buf.st_mode) && !(option_mask32 & FLAG_WRITE)) {
     175        dirp = opendir(path);
     176        if (dirp == NULL)
     177            return -1;
     178        while ((entry = readdir(dirp)) != NULL) {
     179            next = concat_subpath_file(path, entry->d_name);
     180            if (next == NULL)
     181                continue; /* d_name is "." or ".." */
     182            /* if path was ".", drop "./" prefix: */
     183            retval |= sysctl_act_recursive((next[0] == '.' && next[1] == '/') ?
     184                        next + 2 : next);
     185            free(next);
     186        }
     187        closedir(dirp);
     188    } else {
     189        char *name = xstrdup(path);
     190        retval |= sysctl_act_on_setting(name);
     191        free(name);
     192    }
     193
     194    return retval;
     195}
     196
     197/* Set sysctl's from a conf file. Format example:
     198 * # Controls IP packet forwarding
     199 * net.ipv4.ip_forward = 0
    243200 */
    244 int sysctl_read_setting(const char *setting, int output)
    245 {
    246     int retval = 0;
    247     char *tmpname, *outname, *cptr;
    248     char inbuf[1025];
    249     const char *name = setting;
    250     FILE *fp;
    251 
    252     if (!setting || !*setting)
    253         bb_error_msg(ERR_INVALID_KEY, setting);
    254 
    255     tmpname = concat_path_file(PROC_PATH, name);
    256     outname = xstrdup(tmpname + strlen(PROC_PATH));
    257 
    258     while ((cptr = strchr(tmpname, '.')) != NULL)
    259         *cptr = '/';
    260     while ((cptr = strchr(outname, '/')) != NULL)
    261         *cptr = '.';
    262 
    263     if ((fp = fopen(tmpname, "r")) == NULL) {
    264         switch (errno) {
    265         case ENOENT:
    266             bb_error_msg(ERR_INVALID_KEY, outname);
    267             break;
    268         case EACCES:
    269             bb_error_msg(ERR_PERMISSION_DENIED, outname);
    270             break;
    271         default:
    272             bb_error_msg(ERR_UNKNOWN_READING, errno, outname);
    273             break;
    274         }
    275         retval = -1;
    276     } else {
    277         while (fgets(inbuf, sizeof(inbuf) - 1, fp)) {
    278             if (output) {
    279                 dwrite_str(STDOUT_FILENO, outname);
    280                 dwrite_str(STDOUT_FILENO, " = ");
    281             }
    282             dwrite_str(STDOUT_FILENO, inbuf);
    283         }
    284         fclose(fp);
    285     }
    286 
    287     free(tmpname);
    288     free(outname);
     201static int sysctl_handle_preload_file(const char *filename)
     202{
     203    char *token[2];
     204    parser_t *parser;
     205
     206    parser = config_open(filename);
     207    /* Must do it _after_ config_open(): */
     208    xchdir("/proc/sys");
     209    /* xchroot(".") - if you are paranoid */
     210
     211//TODO: ';' is comment char too
     212//TODO: comment may be only at line start. "var=1 #abc" - "1 #abc" is the value
     213// (but _whitespace_ from ends should be trimmed first (and we do it right))
     214//TODO: "var==1" is mishandled (must use "=1" as a value, but uses "1")
     215// can it be fixed by removing PARSE_COLLAPSE bit?
     216    while (config_read(parser, token, 2, 2, "# \t=", PARSE_NORMAL)) {
     217        char *tp;
     218        sysctl_dots_to_slashes(token[0]);
     219        tp = xasprintf("%s=%s", token[0], token[1]);
     220        sysctl_act_recursive(tp);
     221        free(tp);
     222    }
     223    if (ENABLE_FEATURE_CLEAN_UP)
     224        config_close(parser);
     225    return 0;
     226}
     227
     228int sysctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     229int sysctl_main(int argc UNUSED_PARAM, char **argv)
     230{
     231    int retval;
     232    int opt;
     233
     234    opt = getopt32(argv, "+" OPTION_STR); /* '+' - stop on first non-option */
     235    argv += optind;
     236    opt ^= (FLAG_SHOW_KEYS | FLAG_SHOW_KEY_ERRORS);
     237    option_mask32 = opt;
     238
     239    if (opt & FLAG_PRELOAD_FILE) {
     240        option_mask32 |= FLAG_WRITE;
     241        /* xchdir("/proc/sys") is inside */
     242        return sysctl_handle_preload_file(*argv ? *argv : "/etc/sysctl.conf");
     243    }
     244    xchdir("/proc/sys");
     245    /* xchroot(".") - if you are paranoid */
     246    if (opt & (FLAG_TABLE_FORMAT | FLAG_SHOW_ALL)) {
     247        return sysctl_act_recursive(".");
     248    }
     249
     250    retval = 0;
     251    while (*argv) {
     252        sysctl_dots_to_slashes(*argv);
     253        retval |= sysctl_act_recursive(*argv);
     254        argv++;
     255    }
     256
    289257    return retval;
    290 }                       /* end sysctl_read_setting() */
    291 
    292 
    293 
    294 /*
    295  *     Display all the sysctl settings
    296  *
    297  */
    298 int sysctl_display_all(const char *path, int output, int show_table)
    299 {
    300     int retval = 0;
    301     int retval2;
    302     DIR *dp;
    303     struct dirent *de;
    304     char *tmpdir;
    305     struct stat ts;
    306 
    307     dp = opendir(path);
    308     if (!dp) {
    309         retval = -1;
    310     } else {
    311         while ((de = readdir(dp)) != NULL) {
    312             tmpdir = concat_subpath_file(path, de->d_name);
    313             if (tmpdir == NULL)
    314                 continue;
    315             retval2 = stat(tmpdir, &ts);
    316             if (retval2 != 0)
    317                 bb_perror_msg(tmpdir);
    318             else {
    319                 if (S_ISDIR(ts.st_mode)) {
    320                     sysctl_display_all(tmpdir, output, show_table);
    321                 } else
    322                     retval |=
    323                         sysctl_read_setting(tmpdir + strlen(PROC_PATH),
    324                                             output);
    325 
    326             }
    327             free(tmpdir);
    328         }               /* end while */
    329         closedir(dp);
    330     }
    331 
    332     return retval;
    333 }                       /* end sysctl_display_all() */
     258}
  • branches/2.2.9/mindi-busybox/procps/top.c

    r1765 r2725  
    55 * This is written specifically for the linux /proc/<PID>/stat(m)
    66 * files format.
    7 
     7 *
    88 * This reads the PIDs of all processes and their status and shows
    99 * the status of processes (first ones that fit to screen) at given
     
    1717 *
    1818 * Rewritten by Vladimir Oleynik (C) 2002 <dzo@simtreas.ru>
    19  */
    20 
    21 /* Original code Copyrights */
    22 /*
     19 *
     20 * Sept 2008: Vineet Gupta <vineet.gupta@arc.com>
     21 * Added Support for reporting SMP Information
     22 * - CPU where Process was last seen running
     23 *   (to see effect of sched_setaffinity() etc)
     24 * - CPU Time Split (idle/IO/wait etc) PER CPU
     25 *
    2326 * Copyright (c) 1992 Branko Lankester
    2427 * Copyright (c) 1992 Roger Binns
    2528 * Copyright (C) 1994-1996 Charles L. Blake.
    2629 * Copyright (C) 1992-1998 Michael K. Johnson
    27  * May be distributed under the conditions of the
    28  * GNU Library General Public License
     30 *
     31 * Licensed under GPLv2, see file LICENSE in this source tree.
    2932 */
    3033
     
    4245    char state[4];
    4346    char comm[COMM_LEN];
     47#if ENABLE_FEATURE_TOP_SMP_PROCESS
     48    int last_seen_on_cpu;
     49#endif
    4450} top_status_t;
    4551
    4652typedef struct jiffy_counts_t {
    47     unsigned long long usr,nic,sys,idle,iowait,irq,softirq,steal;
     53    /* Linux 2.4.x has only first four */
     54    unsigned long long usr, nic, sys, idle;
     55    unsigned long long iowait, irq, softirq, steal;
    4856    unsigned long long total;
    4957    unsigned long long busy;
     
    5462typedef struct save_hist {
    5563    unsigned long ticks;
    56     unsigned pid;
     64    pid_t pid;
    5765} save_hist;
    5866
    5967typedef int (*cmp_funcp)(top_status_t *P, top_status_t *Q);
    6068
     69
    6170enum { SORT_DEPTH = 3 };
     71
    6272
    6373struct globals {
    6474    top_status_t *top;
    6575    int ntop;
     76#if ENABLE_FEATURE_TOPMEM
     77    smallint sort_field;
     78    smallint inverted;
     79#endif
     80#if ENABLE_FEATURE_TOP_SMP_CPU
     81    smallint smp_cpu_info; /* one/many cpu info lines? */
     82#endif
    6683#if ENABLE_FEATURE_USE_TERMIOS
    6784    struct termios initial_settings;
    6885#endif
    6986#if !ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
    70     cmp_funcp sort_function;
     87    cmp_funcp sort_function[1];
    7188#else
    7289    cmp_funcp sort_function[SORT_DEPTH];
    7390    struct save_hist *prev_hist;
    7491    int prev_hist_count;
    75     jiffy_counts_t jif, prev_jif;
     92    jiffy_counts_t cur_jif, prev_jif;
    7693    /* int hist_iterations; */
    7794    unsigned total_pcpu;
    7895    /* unsigned long total_vsz; */
    7996#endif
     97#if ENABLE_FEATURE_TOP_SMP_CPU
     98    /* Per CPU samples: current and last */
     99    jiffy_counts_t *cpu_jif, *cpu_prev_jif;
     100    int num_cpus;
     101#endif
     102    char line_buf[80];
     103}; //FIX_ALIASING; - large code growth
     104enum { LINE_BUF_SIZE = COMMON_BUFSIZE - offsetof(struct globals, line_buf) };
     105#define G (*(struct globals*)&bb_common_bufsiz1)
     106struct BUG_bad_size {
     107    char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1];
     108    char BUG_line_buf_too_small[LINE_BUF_SIZE > 80 ? 1 : -1];
    80109};
    81 #define G (*(struct globals*)&bb_common_bufsiz1)
     110#define INIT_G() do { } while (0)
    82111#define top              (G.top               )
    83112#define ntop             (G.ntop              )
    84 #if ENABLE_FEATURE_USE_TERMIOS
    85 #define initial_settings (G. initial_settings )
    86 #endif
     113#define sort_field       (G.sort_field        )
     114#define inverted         (G.inverted          )
     115#define smp_cpu_info     (G.smp_cpu_info      )
     116#define initial_settings (G.initial_settings  )
    87117#define sort_function    (G.sort_function     )
    88 #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
    89118#define prev_hist        (G.prev_hist         )
    90119#define prev_hist_count  (G.prev_hist_count   )
    91 #define jif              (G.jif               )
     120#define cur_jif          (G.cur_jif           )
    92121#define prev_jif         (G.prev_jif          )
     122#define cpu_jif          (G.cpu_jif           )
     123#define cpu_prev_jif     (G.cpu_prev_jif      )
     124#define num_cpus         (G.num_cpus          )
    93125#define total_pcpu       (G.total_pcpu        )
    94 #endif
    95 
    96 #define OPT_BATCH_MODE (option_mask32 & 0x4)
     126#define line_buf         (G.line_buf          )
     127
     128enum {
     129    OPT_d = (1 << 0),
     130    OPT_n = (1 << 1),
     131    OPT_b = (1 << 2),
     132    OPT_m = (1 << 3),
     133    OPT_EOF = (1 << 4), /* pseudo: "we saw EOF in stdin" */
     134};
     135#define OPT_BATCH_MODE (option_mask32 & OPT_b)
    97136
    98137
     
    142181}
    143182
     183static NOINLINE int read_cpu_jiffy(FILE *fp, jiffy_counts_t *p_jif)
     184{
     185#if !ENABLE_FEATURE_TOP_SMP_CPU
     186    static const char fmt[] = "cpu %llu %llu %llu %llu %llu %llu %llu %llu";
     187#else
     188    static const char fmt[] = "cp%*s %llu %llu %llu %llu %llu %llu %llu %llu";
     189#endif
     190    int ret;
     191
     192    if (!fgets(line_buf, LINE_BUF_SIZE, fp) || line_buf[0] != 'c' /* not "cpu" */)
     193        return 0;
     194    ret = sscanf(line_buf, fmt,
     195            &p_jif->usr, &p_jif->nic, &p_jif->sys, &p_jif->idle,
     196            &p_jif->iowait, &p_jif->irq, &p_jif->softirq,
     197            &p_jif->steal);
     198    if (ret >= 4) {
     199        p_jif->total = p_jif->usr + p_jif->nic + p_jif->sys + p_jif->idle
     200            + p_jif->iowait + p_jif->irq + p_jif->softirq + p_jif->steal;
     201        /* procps 2.x does not count iowait as busy time */
     202        p_jif->busy = p_jif->total - p_jif->idle - p_jif->iowait;
     203    }
     204
     205    return ret;
     206}
    144207
    145208static void get_jiffy_counts(void)
    146209{
    147     FILE* fp = xfopen("stat", "r");
    148     prev_jif = jif;
    149     if (fscanf(fp, "cpu  %lld %lld %lld %lld %lld %lld %lld %lld",
    150             &jif.usr,&jif.nic,&jif.sys,&jif.idle,
    151             &jif.iowait,&jif.irq,&jif.softirq,&jif.steal) < 4) {
    152         bb_error_msg_and_die("failed to read /proc/stat");
    153     }
     210    FILE* fp = xfopen_for_read("stat");
     211
     212    /* We need to parse cumulative counts even if SMP CPU display is on,
     213     * they are used to calculate per process CPU% */
     214    prev_jif = cur_jif;
     215    if (read_cpu_jiffy(fp, &cur_jif) < 4)
     216        bb_error_msg_and_die("can't read /proc/stat");
     217
     218#if !ENABLE_FEATURE_TOP_SMP_CPU
    154219    fclose(fp);
    155     jif.total = jif.usr + jif.nic + jif.sys + jif.idle
    156             + jif.iowait + jif.irq + jif.softirq + jif.steal;
    157     /* procps 2.x does not count iowait as busy time */
    158     jif.busy = jif.total - jif.idle - jif.iowait;
    159 }
    160 
     220    return;
     221#else
     222    if (!smp_cpu_info) {
     223        fclose(fp);
     224        return;
     225    }
     226
     227    if (!num_cpus) {
     228        /* First time here. How many CPUs?
     229         * There will be at least 1 /proc/stat line with cpu%d
     230         */
     231        while (1) {
     232            cpu_jif = xrealloc_vector(cpu_jif, 1, num_cpus);
     233            if (read_cpu_jiffy(fp, &cpu_jif[num_cpus]) <= 4)
     234                break;
     235            num_cpus++;
     236        }
     237        if (num_cpus == 0) /* /proc/stat with only "cpu ..." line?! */
     238            smp_cpu_info = 0;
     239
     240        cpu_prev_jif = xzalloc(sizeof(cpu_prev_jif[0]) * num_cpus);
     241
     242        /* Otherwise the first per cpu display shows all 100% idles */
     243        usleep(50000);
     244    } else { /* Non first time invocation */
     245        jiffy_counts_t *tmp;
     246        int i;
     247
     248        /* First switch the sample pointers: no need to copy */
     249        tmp = cpu_prev_jif;
     250        cpu_prev_jif = cpu_jif;
     251        cpu_jif = tmp;
     252
     253        /* Get the new samples */
     254        for (i = 0; i < num_cpus; i++)
     255            read_cpu_jiffy(fp, &cpu_jif[i]);
     256    }
     257#endif
     258    fclose(fp);
     259}
    161260
    162261static void do_stats(void)
     
    170269    total_pcpu = 0;
    171270    /* total_vsz = 0; */
    172     new_hist = xmalloc(sizeof(struct save_hist)*ntop);
     271    new_hist = xmalloc(sizeof(new_hist[0]) * ntop);
    173272    /*
    174273     * Make a pass through the data to get stats.
     
    211310    prev_hist_count = ntop;
    212311}
     312
    213313#endif /* FEATURE_TOP_CPU_USAGE_PERCENTAGE */
    214314
     
    238338#endif
    239339
    240 /* display generic info (meminfo / loadavg) */
    241 static unsigned long display_generic(int scr_width)
     340#if ENABLE_FEATURE_TOP_CPU_GLOBAL_PERCENTS
     341static void display_cpus(int scr_width, char *scrbuf, int *lines_rem_p)
     342{
     343    /*
     344     * xxx% = (cur_jif.xxx - prev_jif.xxx) / (cur_jif.total - prev_jif.total) * 100%
     345     */
     346    unsigned total_diff;
     347    jiffy_counts_t *p_jif, *p_prev_jif;
     348    int i;
     349# if ENABLE_FEATURE_TOP_SMP_CPU
     350    int n_cpu_lines;
     351# endif
     352
     353    /* using (unsigned) casts to make operations cheaper */
     354# define  CALC_TOTAL_DIFF do { \
     355    total_diff = (unsigned)(p_jif->total - p_prev_jif->total); \
     356    if (total_diff == 0) total_diff = 1; \
     357} while (0)
     358
     359# if ENABLE_FEATURE_TOP_DECIMALS
     360#  define CALC_STAT(xxx) char xxx[8]
     361#  define SHOW_STAT(xxx) fmt_100percent_8(xxx, (unsigned)(p_jif->xxx - p_prev_jif->xxx), total_diff)
     362#  define FMT "%s"
     363# else
     364#  define CALC_STAT(xxx) unsigned xxx = 100 * (unsigned)(p_jif->xxx - p_prev_jif->xxx) / total_diff
     365#  define SHOW_STAT(xxx) xxx
     366#  define FMT "%4u%% "
     367# endif
     368
     369# if !ENABLE_FEATURE_TOP_SMP_CPU
     370    {
     371        i = 1;
     372        p_jif = &cur_jif;
     373        p_prev_jif = &prev_jif;
     374# else
     375    /* Loop thru CPU(s) */
     376    n_cpu_lines = smp_cpu_info ? num_cpus : 1;
     377    if (n_cpu_lines > *lines_rem_p)
     378        n_cpu_lines = *lines_rem_p;
     379
     380    for (i = 0; i < n_cpu_lines; i++) {
     381        p_jif = &cpu_jif[i];
     382        p_prev_jif = &cpu_prev_jif[i];
     383# endif
     384        CALC_TOTAL_DIFF;
     385
     386        { /* Need a block: CALC_STAT are declarations */
     387            CALC_STAT(usr);
     388            CALC_STAT(sys);
     389            CALC_STAT(nic);
     390            CALC_STAT(idle);
     391            CALC_STAT(iowait);
     392            CALC_STAT(irq);
     393            CALC_STAT(softirq);
     394            /*CALC_STAT(steal);*/
     395
     396            snprintf(scrbuf, scr_width,
     397                /* Barely fits in 79 chars when in "decimals" mode. */
     398# if ENABLE_FEATURE_TOP_SMP_CPU
     399                "CPU%s:"FMT"usr"FMT"sys"FMT"nic"FMT"idle"FMT"io"FMT"irq"FMT"sirq",
     400                (smp_cpu_info ? utoa(i) : ""),
     401# else
     402                "CPU:"FMT"usr"FMT"sys"FMT"nic"FMT"idle"FMT"io"FMT"irq"FMT"sirq",
     403# endif
     404                SHOW_STAT(usr), SHOW_STAT(sys), SHOW_STAT(nic), SHOW_STAT(idle),
     405                SHOW_STAT(iowait), SHOW_STAT(irq), SHOW_STAT(softirq)
     406                /*, SHOW_STAT(steal) - what is this 'steal' thing? */
     407                /* I doubt anyone wants to know it */
     408            );
     409            puts(scrbuf);
     410        }
     411    }
     412# undef SHOW_STAT
     413# undef CALC_STAT
     414# undef FMT
     415    *lines_rem_p -= i;
     416}
     417#else  /* !ENABLE_FEATURE_TOP_CPU_GLOBAL_PERCENTS */
     418# define display_cpus(scr_width, scrbuf, lines_rem) ((void)0)
     419#endif
     420
     421static unsigned long display_header(int scr_width, int *lines_rem_p)
    242422{
    243423    FILE *fp;
     
    245425    char scrbuf[80];
    246426    unsigned long total, used, mfree, shared, buffers, cached;
    247 #if ENABLE_FEATURE_TOP_CPU_GLOBAL_PERCENTS
    248     unsigned total_diff;
    249 #endif
    250427
    251428    /* read memory info */
    252     fp = xfopen("meminfo", "r");
     429    fp = xfopen_for_read("meminfo");
    253430
    254431    /*
     
    280457         * 2.6.
    281458         */
    282 
    283459        fscanf(fp, "MemFree: %lu %s\n", &mfree, buf);
    284460
     
    298474
    299475    /* output memory info */
    300     if (scr_width > sizeof(scrbuf))
     476    if (scr_width > (int)sizeof(scrbuf))
    301477        scr_width = sizeof(scrbuf);
    302478    snprintf(scrbuf, scr_width,
    303479        "Mem: %luK used, %luK free, %luK shrd, %luK buff, %luK cached",
    304480        used, mfree, shared, buffers, cached);
    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%
     481    /* go to top & clear to the end of screen */
     482    printf(OPT_BATCH_MODE ? "%s\n" : "\033[H\033[J%s\n", scrbuf);
     483    (*lines_rem_p)--;
     484
     485    /* Display CPU time split as percentage of total time
     486     * This displays either a cumulative line or one line per CPU
    311487     */
    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
     488    display_cpus(scr_width, scrbuf, lines_rem_p);
    348489
    349490    /* read load average as a string */
    350491    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';
     492    open_read_close("loadavg", buf, sizeof(buf) - 1);
     493    buf[sizeof(buf) - 1] = '\n';
     494    *strchr(buf, '\n') = '\0';
    353495    snprintf(scrbuf, scr_width, "Load average: %s", buf);
    354496    puts(scrbuf);
     497    (*lines_rem_p)--;
    355498
    356499    return total;
    357500}
    358501
    359 /* display process statuses */
    360 static void display_status(int count, int scr_width)
     502static NOINLINE void display_process_list(int lines_rem, int scr_width)
    361503{
    362504    enum {
    363         BITS_PER_INT = sizeof(int)*8
     505        BITS_PER_INT = sizeof(int) * 8
    364506    };
    365507
    366     top_status_t *s = top;
     508    top_status_t *s;
    367509    char vsz_str_buf[8];
    368     unsigned long total_memory = display_generic(scr_width); /* or use total_vsz? */
     510    unsigned long total_memory = display_header(scr_width, &lines_rem); /* or use total_vsz? */
    369511    /* xxx_shift and xxx_scale variables allow us to replace
    370512     * expensive divides with multiply and shift */
    371513    unsigned pmem_shift, pmem_scale, pmem_half;
    372514#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
     515    unsigned tmp_unsigned;
    373516    unsigned pcpu_shift, pcpu_scale, pcpu_half;
    374517    unsigned busy_jifs;
     518#endif
    375519
    376520    /* what info of the processes is shown */
    377     printf(OPT_BATCH_MODE ? "%.*s" : "\e[7m%.*s\e[0m", scr_width,
    378         "  PID  PPID USER     STAT   VSZ %MEM %CPU COMMAND");
    379 #define MIN_WIDTH \
    380     sizeof( "  PID  PPID USER     STAT   VSZ %MEM %CPU C")
     521    printf(OPT_BATCH_MODE ? "%.*s" : "\033[7m%.*s\033[0m", scr_width,
     522        "  PID  PPID USER     STAT   VSZ %MEM"
     523        IF_FEATURE_TOP_SMP_PROCESS(" CPU")
     524        IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE(" %CPU")
     525        " COMMAND");
     526    lines_rem--;
     527
     528#if ENABLE_FEATURE_TOP_DECIMALS
     529# define UPSCALE 1000
     530# define CALC_STAT(name, val) div_t name = div((val), 10)
     531# define SHOW_STAT(name) name.quot, '0'+name.rem
     532# define FMT "%3u.%c"
    381533#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");
    386 #define MIN_WIDTH \
    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%%"
     534# define UPSCALE 100
     535# define CALC_STAT(name, val) unsigned name = (val)
     536# define SHOW_STAT(name) name
     537# define FMT "%4u%%"
    400538#endif
    401539    /*
     
    411549    pmem_half = (1U << pmem_shift) / (ENABLE_FEATURE_TOP_DECIMALS? 20 : 2);
    412550#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
    413     busy_jifs = jif.busy - prev_jif.busy;
     551    busy_jifs = cur_jif.busy - prev_jif.busy;
    414552    /* This happens if there were lots of short-lived processes
    415553     * between two top updates (e.g. compilation) */
     
    420558     * (pcpu is delta of sys+user time between samples)
    421559     */
    422     /* (jif.xxx - prev_jif.xxx) and s->pcpu are
     560    /* (cur_jif.xxx - prev_jif.xxx) and s->pcpu are
    423561     * in 0..~64000 range (HZ*update_interval).
    424562     * we assume that unsigned is at least 32-bit.
    425563     */
    426564    pcpu_shift = 6;
    427     pcpu_scale = (UPSCALE*64*(uint16_t)busy_jifs ? : 1);
    428     while (pcpu_scale < (1U<<(BITS_PER_INT-2))) {
     565    pcpu_scale = UPSCALE*64 * (uint16_t)busy_jifs;
     566    if (pcpu_scale == 0)
     567        pcpu_scale = 1;
     568    while (pcpu_scale < (1U << (BITS_PER_INT-2))) {
    429569        pcpu_scale *= 4;
    430570        pcpu_shift += 2;
    431571    }
    432     pcpu_scale /= ( (uint16_t)(jif.total-prev_jif.total)*total_pcpu ? : 1);
     572    tmp_unsigned = (uint16_t)(cur_jif.total - prev_jif.total) * total_pcpu;
     573    if (tmp_unsigned != 0)
     574        pcpu_scale /= tmp_unsigned;
    433575    /* we want (s->pcpu * pcpu_scale) to never overflow */
    434576    while (pcpu_scale >= 1024) {
     
    440582#endif
    441583
    442     /* Ok, all prelim data is ready, go thru the list */
    443     while (count-- > 0) {
    444         int col = scr_width;
     584    /* Ok, all preliminary data is ready, go through the list */
     585    scr_width += 2; /* account for leading '\n' and trailing NUL */
     586    if (lines_rem > ntop)
     587        lines_rem = ntop;
     588    s = top;
     589    while (--lines_rem >= 0) {
     590        unsigned col;
    445591        CALC_STAT(pmem, (s->vsz*pmem_scale + pmem_half) >> pmem_shift);
    446592#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
     
    448594#endif
    449595
    450         if (s->vsz >= 100*1024)
    451             sprintf(vsz_str_buf, "%6ldM", s->vsz/1024);
     596        if (s->vsz >= 100000)
     597            sprintf(vsz_str_buf, "%6ldm", s->vsz/1024);
    452598        else
    453599            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
     600        /* PID PPID USER STAT VSZ %MEM [%CPU] COMMAND */
     601        col = snprintf(line_buf, scr_width,
     602                "\n" "%5u%6u %-8.8s %s%s" FMT
     603                IF_FEATURE_TOP_SMP_PROCESS(" %3d")
     604                IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE(FMT)
    459605                " ",
    460606                s->pid, s->ppid, get_cached_username(s->uid),
    461607                s->state, vsz_str_buf,
    462608                SHOW_STAT(pmem)
    463 #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
    464                 , SHOW_STAT(pcpu)
    465 #endif
     609                IF_FEATURE_TOP_SMP_PROCESS(, s->last_seen_on_cpu)
     610                IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE(, SHOW_STAT(pcpu))
    466611        );
    467         if (col > 0) {
    468             char buf[col + 1];
    469             read_cmdline(buf, col, s->pid, s->comm);
    470             fputs(buf, stdout);
    471         }
     612        if ((int)(col + 1) < scr_width)
     613            read_cmdline(line_buf + col, scr_width - col, s->pid, s->comm);
     614        fputs(line_buf, stdout);
    472615        /* printf(" %d/%d %lld/%lld", s->pcpu, total_pcpu,
    473             jif.busy - prev_jif.busy, jif.total - prev_jif.total); */
     616            cur_jif.busy - prev_jif.busy, cur_jif.total - prev_jif.total); */
    474617        s++;
    475618    }
    476619    /* printf(" %d", hist_iterations); */
    477     putchar(OPT_BATCH_MODE ? '\n' : '\r');
    478     fflush(stdout);
     620    bb_putchar(OPT_BATCH_MODE ? '\n' : '\r');
     621    fflush_all();
    479622}
    480623#undef UPSCALE
     
    483626#undef FMT
    484627
    485 
    486628static void clearmems(void)
    487629{
    488630    clear_username_cache();
    489631    free(top);
    490     top = 0;
     632    top = NULL;
    491633    ntop = 0;
    492634}
    493635
    494 
    495636#if ENABLE_FEATURE_USE_TERMIOS
    496 #include <termios.h>
    497 #include <signal.h>
    498637
    499638static void reset_term(void)
    500639{
    501     tcsetattr(0, TCSANOW, (void *) &initial_settings);
    502 #if ENABLE_FEATURE_CLEAN_UP
    503     clearmems();
    504 #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
    505     free(prev_hist);
    506 #endif
    507 #endif /* FEATURE_CLEAN_UP */
    508 }
    509 
    510 static void sig_catcher(int sig ATTRIBUTE_UNUSED)
     640    tcsetattr_stdin_TCSANOW(&initial_settings);
     641    if (ENABLE_FEATURE_CLEAN_UP) {
     642        clearmems();
     643# if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
     644        free(prev_hist);
     645# endif
     646    }
     647}
     648
     649static void sig_catcher(int sig UNUSED_PARAM)
    511650{
    512651    reset_term();
    513     exit(1);
    514 }
     652    _exit(EXIT_FAILURE);
     653}
     654
    515655#endif /* FEATURE_USE_TERMIOS */
    516656
    517 
    518 int top_main(int argc, char **argv);
    519 int top_main(int argc, char **argv)
    520 {
    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;
     657/*
     658 * TOPMEM support
     659 */
     660
     661typedef unsigned long mem_t;
     662
     663typedef struct topmem_status_t {
     664    unsigned pid;
     665    char comm[COMM_LEN];
     666    /* vsz doesn't count /dev/xxx mappings except /dev/zero */
     667    mem_t vsz     ;
     668    mem_t vszrw   ;
     669    mem_t rss     ;
     670    mem_t rss_sh  ;
     671    mem_t dirty   ;
     672    mem_t dirty_sh;
     673    mem_t stack   ;
     674} topmem_status_t;
     675
     676enum { NUM_SORT_FIELD = 7 };
     677
     678#define topmem ((topmem_status_t*)top)
     679
     680#if ENABLE_FEATURE_TOPMEM
     681
     682static int topmem_sort(char *a, char *b)
     683{
     684    int n;
     685    mem_t l, r;
     686
     687    n = offsetof(topmem_status_t, vsz) + (sort_field * sizeof(mem_t));
     688    l = *(mem_t*)(a + n);
     689    r = *(mem_t*)(b + n);
     690    if (l == r) {
     691        l = ((topmem_status_t*)a)->dirty;
     692        r = ((topmem_status_t*)b)->dirty;
     693    }
     694    /* We want to avoid unsigned->signed and truncation errors */
     695    /* l>r: -1, l=r: 0, l<r: 1 */
     696    n = (l > r) ? -1 : (l != r);
     697    return inverted ? -n : n;
     698}
     699
     700/* display header info (meminfo / loadavg) */
     701static void display_topmem_header(int scr_width, int *lines_rem_p)
     702{
     703    enum {
     704        TOTAL = 0, MFREE, BUF, CACHE,
     705        SWAPTOTAL, SWAPFREE, DIRTY,
     706        MWRITE, ANON, MAP, SLAB,
     707        NUM_FIELDS
     708    };
     709    static const char match[NUM_FIELDS][12] = {
     710        "\x09" "MemTotal:",  // TOTAL
     711        "\x08" "MemFree:",   // MFREE
     712        "\x08" "Buffers:",   // BUF
     713        "\x07" "Cached:",    // CACHE
     714        "\x0a" "SwapTotal:", // SWAPTOTAL
     715        "\x09" "SwapFree:",  // SWAPFREE
     716        "\x06" "Dirty:",     // DIRTY
     717        "\x0a" "Writeback:", // MWRITE
     718        "\x0a" "AnonPages:", // ANON
     719        "\x07" "Mapped:",    // MAP
     720        "\x05" "Slab:",      // SLAB
     721    };
     722    char meminfo_buf[4 * 1024];
     723    const char *Z[NUM_FIELDS];
     724    unsigned i;
     725    int sz;
     726
     727    for (i = 0; i < NUM_FIELDS; i++)
     728        Z[i] = "?";
     729
     730    /* read memory info */
     731    sz = open_read_close("meminfo", meminfo_buf, sizeof(meminfo_buf) - 1);
     732    if (sz >= 0) {
     733        char *p = meminfo_buf;
     734        meminfo_buf[sz] = '\0';
     735        /* Note that fields always appear in the match[] order */
     736        for (i = 0; i < NUM_FIELDS; i++) {
     737            char *found = strstr(p, match[i] + 1);
     738            if (found) {
     739                /* Cut "NNNN" out of "    NNNN kb" */
     740                char *s = skip_whitespace(found + match[i][0]);
     741                p = skip_non_whitespace(s);
     742                *p++ = '\0';
     743                Z[i] = s;
     744            }
     745        }
     746    }
     747
     748    snprintf(line_buf, LINE_BUF_SIZE,
     749        "Mem total:%s anon:%s map:%s free:%s",
     750        Z[TOTAL], Z[ANON], Z[MAP], Z[MFREE]);
     751    printf(OPT_BATCH_MODE ? "%.*s\n" : "\033[H\033[J%.*s\n", scr_width, line_buf);
     752
     753    snprintf(line_buf, LINE_BUF_SIZE,
     754        " slab:%s buf:%s cache:%s dirty:%s write:%s",
     755        Z[SLAB], Z[BUF], Z[CACHE], Z[DIRTY], Z[MWRITE]);
     756    printf("%.*s\n", scr_width, line_buf);
     757
     758    snprintf(line_buf, LINE_BUF_SIZE,
     759        "Swap total:%s free:%s", // TODO: % used?
     760        Z[SWAPTOTAL], Z[SWAPFREE]);
     761    printf("%.*s\n", scr_width, line_buf);
     762
     763    (*lines_rem_p) -= 3;
     764}
     765
     766static void ulltoa6_and_space(unsigned long long ul, char buf[6])
     767{
     768    /* see http://en.wikipedia.org/wiki/Tera */
     769    smart_ulltoa5(ul, buf, " mgtpezy");
     770    buf[5] = ' ';
     771}
     772
     773static NOINLINE void display_topmem_process_list(int lines_rem, int scr_width)
     774{
     775#define HDR_STR "  PID   VSZ VSZRW   RSS (SHR) DIRTY (SHR) STACK"
     776#define MIN_WIDTH sizeof(HDR_STR)
     777    const topmem_status_t *s = topmem;
     778
     779    display_topmem_header(scr_width, &lines_rem);
     780    strcpy(line_buf, HDR_STR " COMMAND");
     781    line_buf[5 + sort_field * 6] = '*';
     782    printf(OPT_BATCH_MODE ? "%.*s" : "\e[7m%.*s\e[0m", scr_width, line_buf);
     783    lines_rem--;
     784
     785    if (lines_rem > ntop)
     786        lines_rem = ntop;
     787    while (--lines_rem >= 0) {
     788        /* PID VSZ VSZRW RSS (SHR) DIRTY (SHR) COMMAND */
     789        ulltoa6_and_space(s->pid     , &line_buf[0*6]);
     790        ulltoa6_and_space(s->vsz     , &line_buf[1*6]);
     791        ulltoa6_and_space(s->vszrw   , &line_buf[2*6]);
     792        ulltoa6_and_space(s->rss     , &line_buf[3*6]);
     793        ulltoa6_and_space(s->rss_sh  , &line_buf[4*6]);
     794        ulltoa6_and_space(s->dirty   , &line_buf[5*6]);
     795        ulltoa6_and_space(s->dirty_sh, &line_buf[6*6]);
     796        ulltoa6_and_space(s->stack   , &line_buf[7*6]);
     797        line_buf[8*6] = '\0';
     798        if (scr_width > (int)MIN_WIDTH) {
     799            read_cmdline(&line_buf[8*6], scr_width - MIN_WIDTH, s->pid, s->comm);
     800        }
     801        printf("\n""%.*s", scr_width, line_buf);
     802        s++;
     803    }
     804    bb_putchar(OPT_BATCH_MODE ? '\n' : '\r');
     805    fflush_all();
     806#undef HDR_STR
     807#undef MIN_WIDTH
     808}
     809
     810#else
     811void display_topmem_process_list(int lines_rem, int scr_width);
     812int topmem_sort(char *a, char *b);
     813#endif /* TOPMEM */
     814
     815/*
     816 * end TOPMEM support
     817 */
     818
     819enum {
     820    TOP_MASK = 0
     821        | PSSCAN_PID
     822        | PSSCAN_PPID
     823        | PSSCAN_VSZ
     824        | PSSCAN_STIME
     825        | PSSCAN_UTIME
     826        | PSSCAN_STATE
     827        | PSSCAN_COMM
     828        | PSSCAN_CPU
     829        | PSSCAN_UIDGID,
     830    TOPMEM_MASK = 0
     831        | PSSCAN_PID
     832        | PSSCAN_SMAPS
     833        | PSSCAN_COMM,
     834};
     835
     836int top_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     837int top_main(int argc UNUSED_PARAM, char **argv)
     838{
     839    int iterations;
     840    unsigned lines, col;
     841    int lines_rem;
     842    unsigned interval;
     843    char *str_interval, *str_iterations;
     844    unsigned scan_mask = TOP_MASK;
    525845#if ENABLE_FEATURE_USE_TERMIOS
    526846    struct termios new_settings;
    527     struct timeval tv;
    528     fd_set readfds;
     847    struct pollfd pfd[1];
    529848    unsigned char c;
    530 #endif /* FEATURE_USE_TERMIOS */
    531 
    532     interval = 5;
    533 
    534     /* do normal option parsing */
    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
     849
     850    pfd[0].fd = 0;
     851    pfd[0].events = POLLIN;
     852#endif
     853
     854    INIT_G();
     855
     856    interval = 5; /* default update interval is 5 seconds */
     857    iterations = 0; /* infinite */
     858#if ENABLE_FEATURE_TOP_SMP_CPU
     859    /*num_cpus = 0;*/
     860    /*smp_cpu_info = 0;*/  /* to start with show aggregate */
     861    cpu_jif = &cur_jif;
     862    cpu_prev_jif = &prev_jif;
     863#endif
     864
     865    /* all args are options; -n NUM */
     866    opt_complementary = "-"; /* options can be specified w/o dash */
     867    col = getopt32(argv, "d:n:b"IF_FEATURE_TOPMEM("m"), &str_interval, &str_iterations);
     868#if ENABLE_FEATURE_TOPMEM
     869    if (col & OPT_m) /* -m (busybox specific) */
     870        scan_mask = TOPMEM_MASK;
     871#endif
     872    if (col & OPT_d) {
     873        /* work around for "-d 1" -> "-d -1" done by getopt32
     874         * (opt_complementary == "-" does this) */
     875        if (str_interval[0] == '-')
     876            str_interval++;
     877        /* Need to limit it to not overflow poll timeout */
     878        interval = xatou16(str_interval);
     879    }
     880    if (col & OPT_n) {
     881        if (str_iterations[0] == '-')
     882            str_iterations++;
     883        iterations = xatou(str_iterations);
     884    }
    540885
    541886    /* change to /proc */
     
    543888#if ENABLE_FEATURE_USE_TERMIOS
    544889    tcgetattr(0, (void *) &initial_settings);
    545     memcpy(&new_settings, &initial_settings, sizeof(struct termios));
     890    memcpy(&new_settings, &initial_settings, sizeof(new_settings));
    546891    /* unbuffered input, turn off echo */
    547892    new_settings.c_lflag &= ~(ISIG | ICANON | ECHO | ECHONL);
    548893
    549     signal(SIGTERM, sig_catcher);
    550     signal(SIGINT, sig_catcher);
    551     tcsetattr(0, TCSANOW, (void *) &new_settings);
    552     atexit(reset_term);
    553 #endif /* FEATURE_USE_TERMIOS */
     894    bb_signals(BB_FATAL_SIGS, sig_catcher);
     895    tcsetattr_stdin_TCSANOW(&new_settings);
     896#endif
    554897
    555898#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
     
    558901    sort_function[2] = time_sort;
    559902#else
    560     sort_function = mem_sort;
    561 #endif /* FEATURE_TOP_CPU_USAGE_PERCENTAGE */
     903    sort_function[0] = mem_sort;
     904#endif
    562905
    563906    while (1) {
    564907        procps_status_t *p = NULL;
    565908
    566         /* Default to 25 lines - 5 lines for status */
    567         lines = 24 - 3 USE_FEATURE_TOP_CPU_GLOBAL_PERCENTS( - 1);
     909        lines = 24; /* default */
    568910        col = 79;
    569911#if ENABLE_FEATURE_USE_TERMIOS
    570         get_terminal_width_height(0, &col, &lines);
    571         if (lines < 5 || col < MIN_WIDTH) {
     912        /* We output to stdout, we need size of stdout (not stdin)! */
     913        get_terminal_width_height(STDOUT_FILENO, &col, &lines);
     914        if (lines < 5 || col < 10) {
    572915            sleep(interval);
    573916            continue;
    574917        }
    575         lines -= 3 USE_FEATURE_TOP_CPU_GLOBAL_PERCENTS( + 1);
    576 #endif /* FEATURE_USE_TERMIOS */
     918#endif
     919        if (col > LINE_BUF_SIZE-2) /* +2 bytes for '\n', NUL, */
     920            col = LINE_BUF_SIZE-2;
    577921
    578922        /* read process IDs & status for all the processes */
    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         ))) {
    590             int n = ntop;
    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;
     923        while ((p = procps_scan(p, scan_mask)) != NULL) {
     924            int n;
     925#if ENABLE_FEATURE_TOPMEM
     926            if (scan_mask != TOPMEM_MASK)
     927#endif
     928            {
     929                n = ntop;
     930                top = xrealloc_vector(top, 6, ntop++);
     931                top[n].pid = p->pid;
     932                top[n].ppid = p->ppid;
     933                top[n].vsz = p->vsz;
    595934#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);
     935                top[n].ticks = p->stime + p->utime;
     936#endif
     937                top[n].uid = p->uid;
     938                strcpy(top[n].state, p->state);
     939                strcpy(top[n].comm, p->comm);
     940#if ENABLE_FEATURE_TOP_SMP_PROCESS
     941                top[n].last_seen_on_cpu = p->last_seen_on_cpu;
     942#endif
     943            }
     944#if ENABLE_FEATURE_TOPMEM
     945            else { /* TOPMEM */
     946                if (!(p->smaps.mapped_ro | p->smaps.mapped_rw))
     947                    continue; /* kernel threads are ignored */
     948                n = ntop;
     949                /* No bug here - top and topmem are the same */
     950                top = xrealloc_vector(topmem, 6, ntop++);
     951                strcpy(topmem[n].comm, p->comm);
     952                topmem[n].pid      = p->pid;
     953                topmem[n].vsz      = p->smaps.mapped_rw + p->smaps.mapped_ro;
     954                topmem[n].vszrw    = p->smaps.mapped_rw;
     955                topmem[n].rss_sh   = p->smaps.shared_clean + p->smaps.shared_dirty;
     956                topmem[n].rss      = p->smaps.private_clean + p->smaps.private_dirty + topmem[n].rss_sh;
     957                topmem[n].dirty    = p->smaps.private_dirty + p->smaps.shared_dirty;
     958                topmem[n].dirty_sh = p->smaps.shared_dirty;
     959                topmem[n].stack    = p->smaps.stack;
     960            }
     961#endif
     962        } /* end of "while we read /proc" */
     963        if (ntop == 0) {
     964            bb_error_msg("no process info in /proc");
     965            break;
    601966        }
    602         if (ntop == 0) {
    603             bb_error_msg_and_die("no process info in /proc");
     967
     968        if (scan_mask != TOPMEM_MASK) {
     969#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
     970            if (!prev_hist_count) {
     971                do_stats();
     972                usleep(100000);
     973                clearmems();
     974                continue;
     975            }
     976            do_stats();
     977            /* TODO: we don't need to sort all 10000 processes, we need to find top 24! */
     978            qsort(top, ntop, sizeof(top_status_t), (void*)mult_lvl_cmp);
     979#else
     980            qsort(top, ntop, sizeof(top_status_t), (void*)(sort_function[0]));
     981#endif
    604982        }
    605 #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
    606         if (!prev_hist_count) {
    607             do_stats();
    608             sleep(1);
    609             clearmems();
    610             continue;
     983#if ENABLE_FEATURE_TOPMEM
     984        else { /* TOPMEM */
     985            qsort(topmem, ntop, sizeof(topmem_status_t), (void*)topmem_sort);
    611986        }
    612         do_stats();
    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);
     987#endif
     988        lines_rem = lines;
     989        if (OPT_BATCH_MODE) {
     990            lines_rem = INT_MAX;
     991        }
     992        if (scan_mask != TOPMEM_MASK)
     993            display_process_list(lines_rem, col);
     994#if ENABLE_FEATURE_TOPMEM
     995        else
     996            display_topmem_process_list(lines_rem, col);
     997#endif
     998        clearmems();
     999        if (iterations >= 0 && !--iterations)
     1000            break;
     1001#if !ENABLE_FEATURE_USE_TERMIOS
     1002        sleep(interval);
    6151003#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;
    621         }
    622         /* show status for each of the processes */
    623         display_status(count, col);
    624 #if ENABLE_FEATURE_USE_TERMIOS
    625         tv.tv_sec = interval;
    626         tv.tv_usec = 0;
    627         FD_ZERO(&readfds);
    628         FD_SET(0, &readfds);
    629         select(1, &readfds, NULL, NULL, &tv);
    630         if (FD_ISSET(0, &readfds)) {
    631             if (read(0, &c, 1) <= 0) {   /* signal */
    632                 return EXIT_FAILURE;
    633             }
    634             if (c == 'q' || c == initial_settings.c_cc[VINTR])
     1004        if (option_mask32 & (OPT_b|OPT_EOF))
     1005             /* batch mode, or EOF on stdin ("top </dev/null") */
     1006            sleep(interval);
     1007        else if (safe_poll(pfd, 1, interval * 1000) > 0) {
     1008            if (safe_read(STDIN_FILENO, &c, 1) != 1) { /* error/EOF? */
     1009                option_mask32 |= OPT_EOF;
     1010                continue;
     1011            }
     1012            if (c == initial_settings.c_cc[VINTR])
    6351013                break;
    636             if (c == 'M') {
    637 #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
     1014            c |= 0x20; /* lowercase */
     1015            if (c == 'q')
     1016                break;
     1017            if (c == 'n') {
     1018                IF_FEATURE_TOPMEM(scan_mask = TOP_MASK;)
     1019                sort_function[0] = pid_sort;
     1020            }
     1021            if (c == 'm') {
     1022                IF_FEATURE_TOPMEM(scan_mask = TOP_MASK;)
    6381023                sort_function[0] = mem_sort;
     1024# if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
    6391025                sort_function[1] = pcpu_sort;
    6401026                sort_function[2] = time_sort;
    641 #else
    642                 sort_function = mem_sort;
    643 #endif
    644             }
    645 #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
    646             if (c == 'P') {
     1027# endif
     1028            }
     1029# if ENABLE_FEATURE_SHOW_THREADS
     1030            if (c == 'h'
     1031             IF_FEATURE_TOPMEM(&& scan_mask != TOPMEM_MASK)
     1032            ) {
     1033                scan_mask ^= PSSCAN_TASKS;
     1034            }
     1035# endif
     1036# if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
     1037            if (c == 'p') {
     1038                IF_FEATURE_TOPMEM(scan_mask = TOP_MASK;)
    6471039                sort_function[0] = pcpu_sort;
    6481040                sort_function[1] = mem_sort;
    6491041                sort_function[2] = time_sort;
    6501042            }
    651             if (c == 'T') {
     1043            if (c == 't') {
     1044                IF_FEATURE_TOPMEM(scan_mask = TOP_MASK;)
    6521045                sort_function[0] = time_sort;
    6531046                sort_function[1] = mem_sort;
    6541047                sort_function[2] = pcpu_sort;
    6551048            }
    656 #endif
    657             if (c == 'N') {
    658 #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
    659                 sort_function[0] = pid_sort;
    660 #else
    661                 sort_function = pid_sort;
    662 #endif
    663             }
     1049#  if ENABLE_FEATURE_TOPMEM
     1050            if (c == 's') {
     1051                scan_mask = TOPMEM_MASK;
     1052                free(prev_hist);
     1053                prev_hist = NULL;
     1054                prev_hist_count = 0;
     1055                sort_field = (sort_field + 1) % NUM_SORT_FIELD;
     1056            }
     1057            if (c == 'r')
     1058                inverted ^= 1;
     1059#  endif
     1060#  if ENABLE_FEATURE_TOP_SMP_CPU
     1061            /* procps-2.0.18 uses 'C', 3.2.7 uses '1' */
     1062            if (c == 'c' || c == '1') {
     1063                /* User wants to toggle per cpu <> aggregate */
     1064                if (smp_cpu_info) {
     1065                    free(cpu_prev_jif);
     1066                    free(cpu_jif);
     1067                    cpu_jif = &cur_jif;
     1068                    cpu_prev_jif = &prev_jif;
     1069                } else {
     1070                    /* Prepare for xrealloc() */
     1071                    cpu_jif = cpu_prev_jif = NULL;
     1072                }
     1073                num_cpus = 0;
     1074                smp_cpu_info = !smp_cpu_info;
     1075                get_jiffy_counts();
     1076            }
     1077#  endif
     1078# endif
    6641079        }
    665         if (!--iterations)
    666             break;
    667 #else
    668         sleep(interval);
    6691080#endif /* FEATURE_USE_TERMIOS */
    670         clearmems();
    671     }
    672     if (ENABLE_FEATURE_CLEAN_UP)
    673         clearmems();
    674     putchar('\n');
     1081    } /* end of "while (1)" */
     1082
     1083    bb_putchar('\n');
     1084#if ENABLE_FEATURE_USE_TERMIOS
     1085    reset_term();
     1086#endif
    6751087    return EXIT_SUCCESS;
    6761088}
  • branches/2.2.9/mindi-busybox/procps/uptime.c

    r1765 r2725  
    55 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
    66 *
    7  * Licensed under the GPL version 2, see the file LICENSE in this tarball.
     7 * Licensed under GPLv2, see file LICENSE in this source tree.
    88 */
    99
     
    2626
    2727
    28 int uptime_main(int argc, char **argv);
    29 int uptime_main(int argc, char **argv)
     28int uptime_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     29int uptime_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
    3030{
    3131    int updays, uphours, upminutes;
  • branches/2.2.9/mindi-busybox/procps/watch.c

    r1765 r2725  
    66 * Copyrigjt (C) Mar 16, 2003 Manuel Novoa III   (mjn3@codepoet.org)
    77 *
    8  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    99 */
    1010
     
    2424// (procps 3.x and procps 2.x are forks, not newer/older versions of the same)
    2525
    26 int watch_main(int argc, char **argv);
    27 int watch_main(int argc, char **argv)
     26int watch_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     27int watch_main(int argc UNUSED_PARAM, char **argv)
    2828{
    2929    unsigned opt;
    3030    unsigned period = 2;
    31     unsigned cmdlen;
    32     char *header = NULL;
     31    unsigned width, new_width;
     32    char *header;
    3333    char *cmd;
    34     char *tmp;
    35     char **p;
    3634
    37     opt_complementary = "-1"; // at least one param please
    38     opt = getopt32(argv, "+dtn:", &tmp);
    39     //if (opt & 0x1) // -d (ignore)
    40     //if (opt & 0x2) // -t
    41     if (opt & 0x4) period = xatou(tmp);
     35#if 0 // maybe ENABLE_DESKTOP?
     36    // procps3 compat - "echo TEST | watch cat" doesn't show TEST:
     37    close(STDIN_FILENO);
     38    xopen("/dev/null", O_RDONLY);
     39#endif
     40
     41    opt_complementary = "-1:n+"; // at least one param; -n NUM
     42    // "+": stop at first non-option (procps 3.x only)
     43    opt = getopt32(argv, "+dtn:", &period);
    4244    argv += optind;
    4345
    44     p = argv;
    45     cmdlen = 1; // 1 for terminal NUL
    46     while (*p)
    47         cmdlen += strlen(*p++) + 1;
    48     tmp = cmd = xmalloc(cmdlen);
    49     while (*argv) {
    50         tmp += sprintf(tmp, " %s", *argv);
    51         argv++;
    52     }
    53     cmd++; // skip initial space
     46    // watch from both procps 2.x and 3.x does concatenation. Example:
     47    // watch ls -l "a /tmp" "2>&1" - ls won't see "a /tmp" as one param
     48    cmd = *argv;
     49    while (*++argv)
     50        cmd = xasprintf("%s %s", cmd, *argv); // leaks cmd
    5451
     52    width = (unsigned)-1; // make sure first time new_width != width
     53    header = NULL;
    5554    while (1) {
    56         printf("\033[H\033[J");
     55        /* home; clear to the end of screen */
     56        printf("\033[H""\033[J");
    5757        if (!(opt & 0x2)) { // no -t
    58             int width, len;
    59             char *thyme;
     58            const unsigned time_len = sizeof("1234-67-90 23:56:89");
    6059            time_t t;
    6160
    62             get_terminal_width_height(STDIN_FILENO, &width, 0);
    63             header = xrealloc(header, width--);
    64             // '%-*s' pads header with spaces to the full width
    65             snprintf(header, width, "Every %ds: %-*s", period, width, cmd);
     61            // STDERR_FILENO is procps3 compat:
     62            // "watch ls 2>/dev/null" does not detect tty size
     63            get_terminal_width_height(STDERR_FILENO, &new_width, NULL);
     64            if (new_width != width) {
     65                width = new_width;
     66                free(header);
     67                header = xasprintf("Every %us: %-*s", period, (int)width, cmd);
     68            }
    6669            time(&t);
    67             thyme = ctime(&t);
    68             len = strlen(thyme);
    69             if (len < width)
    70                 strcpy(header + width - len, thyme);
    71             puts(header);
     70            if (time_len < width)
     71                strftime(header + width - time_len, time_len,
     72                    "%Y-%m-%d %H:%M:%S", localtime(&t));
     73
     74            // compat: empty line between header and cmd output
     75            printf("%s\n\n", header);
    7276        }
    73         fflush(stdout);
     77        fflush_all();
    7478        // TODO: 'real' watch pipes cmd's output to itself
    7579        // and does not allow it to overflow the screen
Note: See TracChangeset for help on using the changeset viewer.