Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/procps
- Timestamp:
- Feb 25, 2011, 9:26:54 PM (13 years ago)
- 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 1 2 # 2 3 # For a description of the syntax of this configuration file, … … 6 7 menu "Process Utilities" 7 8 9 config IOSTAT 10 bool "iostat" 11 default y 12 help 13 Report CPU and I/O statistics 14 config MPSTAT 15 bool "mpstat" 16 default y 17 help 18 Per-processor statistics 19 config PMAP 20 bool "pmap" 21 default y 22 help 23 Display processes' memory mappings. 24 config POWERTOP 25 bool "powertop" 26 default y 27 help 28 Analyze power consumption on Intel-based laptops 29 config 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 8 36 config FREE 9 37 bool "free" 10 default n 38 default y 39 depends on PLATFORM_LINUX #sysinfo() 11 40 help 12 41 free displays the total amount of free and used physical and swap … … 16 45 config FUSER 17 46 bool "fuser" 18 default n47 default y 19 48 help 20 49 fuser lists all PIDs (Process IDs) that currently have a given 21 file open. 50 file open. fuser can also list all PIDs that have a given network 22 51 (TCP or UDP) port open. 23 52 24 53 config KILL 25 54 bool "kill" 26 default n55 default y 27 56 help 28 57 The command kill sends the specified signal to the specified 29 process or process group. 58 process or process group. If no signal is specified, the TERM 30 59 signal is sent. 31 60 32 61 config KILLALL 33 62 bool "killall" 34 default n63 default y 35 64 depends on KILL 36 65 help 37 66 killall sends a signal to all processes running any of the 38 specified commands. 67 specified commands. If no signal name is specified, SIGTERM is 39 68 sent. 40 69 41 70 config KILLALL5 42 71 bool "killall5" 43 default n72 default y 44 73 depends on KILL 45 74 46 75 config NMETER 47 76 bool "nmeter" 48 default n77 default y 49 78 help 50 79 Prints selected system stats continuously, one line per update. 80 81 config PGREP 82 bool "pgrep" 83 default y 84 help 85 Look for processes by name. 51 86 52 87 config PIDOF 53 88 bool "pidof" 54 default n89 default y 55 90 help 56 91 Pidof finds the process id's (pids) of the named programs. It prints … … 59 94 config FEATURE_PIDOF_SINGLE 60 95 bool "Enable argument for single shot (-s)" 61 default n96 default y 62 97 depends on PIDOF 63 98 help … … 66 101 config FEATURE_PIDOF_OMIT 67 102 bool "Enable argument for omitting pids (-o)" 68 default n103 default y 69 104 depends on PIDOF 70 105 help … … 73 108 of the pidof, in other words the calling shell or shell script. 74 109 110 config PKILL 111 bool "pkill" 112 default y 113 help 114 Send signals to processes by name. 115 75 116 config PS 76 117 bool "ps" 118 default y 119 help 120 ps gives a snapshot of the current processes. 121 122 config 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 131 config 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 138 config 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 145 config FEATURE_PS_UNUSUAL_SYSTEMS 146 bool "Support Linux prior to 2.4.0 and non-ELF systems" 77 147 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) 89 152 90 153 config RENICE 91 154 bool "renice" 92 default n155 default y 93 156 help 94 157 Renice alters the scheduling priority of one or more running … … 97 160 config BB_SYSCTL 98 161 bool "sysctl" 99 default n162 default y 100 163 help 101 164 Configure kernel parameters at runtime. … … 103 166 config TOP 104 167 bool "top" 105 default n168 default y 106 169 help 107 170 The top program provides a dynamic real-time view of a running … … 109 172 110 173 config FEATURE_TOP_CPU_USAGE_PERCENTAGE 111 bool "Show CPU per-process usage percentage (adds 2k bytes)"174 bool "Show CPU per-process usage percentage" 112 175 default y 113 176 depends on TOP 114 177 help 115 178 Make top display CPU usage for each process. 179 This adds about 2k. 116 180 117 181 config FEATURE_TOP_CPU_GLOBAL_PERCENTS 118 bool "Show CPU global usage percentage (adds 0.5k bytes)"182 bool "Show CPU global usage percentage" 119 183 default y 120 184 depends on FEATURE_TOP_CPU_USAGE_PERCENTAGE 121 185 help 122 186 Makes top display "CPU: NN% usr NN% sys..." line. 187 This adds about 0.5k. 188 189 config 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. 123 196 124 197 config FEATURE_TOP_DECIMALS 125 bool "Show 1/10th of a percent in CPU/mem statistics (adds 0.3k bytes)"126 default n198 bool "Show 1/10th of a percent in CPU/mem statistics" 199 default y 127 200 depends on FEATURE_TOP_CPU_USAGE_PERCENTAGE 128 201 help 129 202 Show 1/10th of a percent in CPU/mem statistics. 203 This adds about 0.3k. 204 205 config 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 213 config 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 220 config 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 130 226 131 227 config UPTIME 132 228 bool "uptime" 133 default n 229 default y 230 depends on PLATFORM_LINUX #sysinfo() 134 231 help 135 232 uptime gives a one line display of the current time, how long … … 139 236 config WATCH 140 237 bool "watch" 141 default n 142 #huh?? select DATE 238 default y 143 239 help 144 240 watch is used to execute a program periodically, showing 145 241 output to the screen. 146 242 147 148 243 endmenu 149 -
branches/2.2.9/mindi-busybox/procps/Kbuild
r1765 r2725 1 # DO NOT EDIT. This file is generated from Kbuild.src 1 2 # Makefile for busybox 2 3 # 3 4 # Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org> 4 5 # 5 # Licensed under the GPL v2, see the file LICENSE in this tarball.6 # Licensed under GPLv2, see file LICENSE in this source tree. 6 7 7 8 lib-y:= 9 10 lib-$(CONFIG_IOSTAT) += iostat.o 11 lib-$(CONFIG_MPSTAT) += mpstat.o 12 lib-$(CONFIG_PMAP) += pmap.o 13 lib-$(CONFIG_POWERTOP) += powertop.o 14 lib-$(CONFIG_SMEMCAP) += smemcap.o 8 15 lib-$(CONFIG_FREE) += free.o 9 16 lib-$(CONFIG_FUSER) += fuser.o … … 11 18 lib-$(CONFIG_ASH) += kill.o # used for built-in kill by ash 12 19 lib-$(CONFIG_NMETER) += nmeter.o 20 lib-$(CONFIG_PGREP) += pgrep.o 21 lib-$(CONFIG_PKILL) += pgrep.o 13 22 lib-$(CONFIG_PIDOF) += pidof.o 14 23 lib-$(CONFIG_PS) += ps.o -
branches/2.2.9/mindi-busybox/procps/free.c
r1765 r2725 5 5 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> 6 6 * 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. 8 8 */ 9 9 … … 12 12 #include "libbb.h" 13 13 14 int free_main(int argc, char **argv); 15 int free_main(int argc, char **argv) 14 struct 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 27 static unsigned long long scale(unsigned long d) 28 { 29 return ((unsigned long long)d * G.mem_unit) >> G_unit_steps; 30 } 31 32 33 int free_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 34 int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) 16 35 { 17 36 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 18 62 sysinfo(&info); 19 63 20 64 /* 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); 26 66 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 ); 48 77 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) 51 81 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 ); 66 105 #endif 67 106 return EXIT_SUCCESS; -
branches/2.2.9/mindi-busybox/procps/fuser.c
r1765 r2725 5 5 * Copyright 2004 Tony J. White 6 6 * 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. 9 8 */ 10 9 11 10 #include "libbb.h" 12 11 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" 15 enum { 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 }; 21 22 22 23 typedef struct inode_list { 24 struct inode_list *next; 23 25 ino_t inode; 24 26 dev_t dev; 25 struct inode_list *next;26 27 } inode_list; 27 28 28 29 typedef struct pid_list { 30 struct pid_list *next; 29 31 pid_t pid; 30 struct pid_list *next;31 32 } pid_list; 32 33 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 35 struct 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 43 static 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 57 static 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 75 static 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); 73 89 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); 152 93 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]; 155 98 if (sscanf(line, "%*d: %64[0-9A-Fa-f]:%x %*x:%*x %*x %*x:%*x " 156 99 "%*x:%*x %*x %*d %*d %llu", 157 100 addr, &tmp_port, &uint64_inode) == 3 158 101 ) { 159 if (strlen(addr) == 8 && (opts & FUSER_OPT_IP6)) 102 int len = strlen(addr); 103 if (len == 8 && (option_mask32 & OPT_IP6)) 160 104 continue; 161 if ( strlen(addr) > 8 && (opts & FUSER_OPT_IP4))105 if (len > 8 && (option_mask32 & OPT_IP4)) 162 106 continue; 163 107 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); 166 110 } 167 111 } 168 112 } 169 113 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 116 static 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; 185 128 } 186 129 return 0; 187 130 } 188 131 189 static int fuser_scan_pid_maps(int opts, const char *fname, pid_t pid, 190 inode_list *ilist, pid_list *plist) 132 static void scan_pid_maps(const char *fname, pid_t pid) 191 133 { 192 134 FILE *file; 193 char line[ FUSER_MAX_LINE + 1];135 char line[MAX_LINE + 1]; 194 136 int major, minor; 195 ino_t inode;196 137 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); 200 141 if (!file) 201 return 0; 202 while (fgets(line, FUSER_MAX_LINE, file)) { 142 return; 143 144 while (fgets(line, MAX_LINE, file)) { 203 145 if (sscanf(line, "%*s %*s %*s %x:%x %llu", &major, &minor, &uint64_inode) != 3) 204 146 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); 212 153 } 213 154 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 157 static 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 167 static void scan_dir_links(const char *dname, pid_t pid) 232 168 { 233 169 DIR *d; … … 237 173 d = opendir(dname); 238 174 if (!d) 239 return 0; 175 return; 176 240 177 while ((de = readdir(d)) != NULL) { 241 178 lname = concat_subpath_file(dname, de->d_name); 242 179 if (lname == NULL) 243 180 continue; 244 fuser_scan_link(opts, lname, pid, ilist, plist);181 scan_link(lname, pid); 245 182 free(lname); 246 183 } 247 184 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 */ 188 static void scan_proc_pids(void) 252 189 { 253 190 DIR *d; 254 191 struct dirent *de; 255 192 pid_t pid; 256 char *dname; 257 258 d = opendir( FUSER_PROC_DIR);193 194 xchdir("/proc"); 195 d = opendir("/proc"); 259 196 if (!d) 260 return 0; 197 return; 198 261 199 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"); 279 215 } 280 216 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 219 int fuser_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 220 int 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 /* 231 fuser [OPTIONS] FILE or PORT/PROTO 232 Find 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 } 312 304 } 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); 365 307 } 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 6 6 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> 7 7 * 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. 9 9 */ 10 10 … … 25 25 */ 26 26 27 int kill_main(int argc, char **argv);28 27 int kill_main(int argc, char **argv) 29 28 { … … 59 58 if (argc == 1) { 60 59 /* 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); 88 84 } 89 85 } … … 97 93 arg = *++argv; 98 94 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); 105 112 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); 107 114 return EXIT_FAILURE; 108 115 } … … 110 117 argc--; 111 118 112 do_it_now: 119 do_it_now: 120 pid = getpid(); 113 121 114 122 if (killall5) { 115 123 pid_t sid; 116 124 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 */ 119 130 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 */ 124 132 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: 128 167 /* And let them continue */ 129 168 kill(-1, SIGCONT); 130 return 0;169 return ret; 131 170 } 132 171 133 172 /* Pid or name is required for kill/killall */ 134 173 if (argc < 1) { 135 puts("You need to specify whom to kill");174 bb_error_msg("you need to specify whom to kill"); 136 175 return EXIT_FAILURE; 137 176 } … … 139 178 if (killall) { 140 179 /* Looks like they want to do a killall. Do that */ 141 pid = getpid();142 180 while (arg) { 143 181 pid_t* pidList; … … 158 196 errors++; 159 197 if (!quiet) 160 bb_perror_msg("can not kill pid %u", (unsigned)*pl);198 bb_perror_msg("can't kill pid %d", (int)*pl); 161 199 } 162 200 } … … 174 212 pid = bb_strtoi(arg, NULL, 10); 175 213 if (errno) { 176 bb_error_msg(" bad pid'%s'", arg);214 bb_error_msg("invalid number '%s'", arg); 177 215 errors++; 178 216 } else if (kill(pid, signo) != 0) { 179 bb_perror_msg("can not kill pid %d", (int)pid);217 bb_perror_msg("can't kill pid %d", (int)pid); 180 218 errors++; 181 219 } -
branches/2.2.9/mindi-busybox/procps/nmeter.c
r1765 r2725 1 1 /* 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 */ 7 8 8 9 //TODO: … … 18 19 // totalswap=134209536, freeswap=134209536, procs=157}) 19 20 20 #include <time.h>21 21 #include "libbb.h" 22 22 23 23 typedef unsigned long long ullong; 24 24 25 enum { PROC_FILE_SIZE = 4096 }; 25 enum { /* Preferably use powers of 2 */ 26 PROC_MIN_FILE_SIZE = 256, 27 PROC_MAX_FILE_SIZE = 16 * 1024, 28 }; 26 29 27 30 typedef struct proc_file { 28 31 char *file; 29 //const char *name;32 int file_sz; 30 33 smallint last_gen; 31 34 } proc_file; … … 76 79 #define proc_sys_fs_filenr (G.proc_sys_fs_filenr) 77 80 #define INIT_G() do { \ 78 PTR_TO_GLOBALS = xzalloc(sizeof(G)); \79 80 81 82 81 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ 82 cur_outbuf = outbuf; \ 83 final_str = "\n"; \ 84 deltanz = delta = 1000000; \ 85 } while (0) 83 86 84 87 // We depend on this being a char[], not char* - we take sizeof() of it … … 99 102 int sz = cur_outbuf - outbuf; 100 103 if (sz > 0) { 101 xwrite( 1, outbuf, sz);104 xwrite(STDOUT_FILENO, outbuf, sz); 102 105 cur_outbuf = outbuf; 103 106 } … … 125 128 } 126 129 127 static void readfile_z( char *buf, int sz, const char* fname)130 static void readfile_z(proc_file *pf, const char* fname) 128 131 { 129 132 // open_read_close() will do two reads in order to be sure we are at EOF, 130 133 // 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); 134 146 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; 140 159 } 141 160 … … 144 163 if (pf->last_gen != gen) { 145 164 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]); 152 166 } 153 167 return pf->file; 154 168 } 155 169 156 static inlineullong read_after_slash(const char *p)170 static ullong read_after_slash(const char *p) 157 171 { 158 172 p = strchr(p, '/'); … … 229 243 static int rdval_diskstats(const char* p, ullong *vec) 230 244 { 231 ullong rd = 0; // to avoid "warning: 'rd' might be used uninitialized"245 ullong rd = rd; // for compiler 232 246 int indexline = 0; 233 247 vec[0] = 0; … … 258 272 { 259 273 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'; 261 278 put(buf); 262 279 } … … 266 283 typedef struct a { \ 267 284 struct s_stat *next; \ 268 void (*collect)(struct a *s) ; \285 void (*collect)(struct a *s) FAST_FUNC; \ 269 286 const char *label; 270 287 #define S_STAT_END(a) } a; … … 273 290 S_STAT_END(s_stat) 274 291 275 static void collect_literal(s_stat *s)292 static void FAST_FUNC collect_literal(s_stat *s UNUSED_PARAM) 276 293 { 277 294 } … … 279 296 static s_stat* init_literal(void) 280 297 { 281 s_stat *s = x malloc(sizeof(s_stat));298 s_stat *s = xzalloc(sizeof(*s)); 282 299 s->collect = collect_literal; 283 300 return (s_stat*)s; … … 286 303 static s_stat* init_delay(const char *param) 287 304 { 288 delta = bb_strtoi(param, NULL, 0) * 1000;305 delta = strtoul(param, NULL, 0) * 1000; /* param can be "" */ 289 306 deltanz = delta > 0 ? delta : 1; 290 307 need_seconds = (1000000%deltanz) != 0; … … 292 309 } 293 310 294 static s_stat* init_cr(const char *param )311 static s_stat* init_cr(const char *param UNUSED_PARAM) 295 312 { 296 313 final_str = "\r"; … … 310 327 311 328 312 static void collect_cpu(cpu_stat *s)329 static void FAST_FUNC collect_cpu(cpu_stat *s) 313 330 { 314 331 ullong data[CPU_FIELDCNT] = { 0, 0, 0, 0, 0, 0, 0 }; … … 367 384 { 368 385 int sz; 369 cpu_stat *s = x malloc(sizeof(cpu_stat));386 cpu_stat *s = xzalloc(sizeof(*s)); 370 387 s->collect = collect_cpu; 371 sz = strto l(param, NULL, 0);388 sz = strtoul(param, NULL, 0); /* param can be "" */ 372 389 if (sz < 10) sz = 10; 373 390 if (sz > 1000) sz = 1000; 374 s->bar = x malloc(sz+1);375 s->bar[sz] = '\0';391 s->bar = xzalloc(sz+1); 392 /*s->bar[sz] = '\0'; - xzalloc did it */ 376 393 s->bar_sz = sz; 377 394 return (s_stat*)s; … … 384 401 S_STAT_END(int_stat) 385 402 386 static void collect_int(int_stat *s)403 static void FAST_FUNC collect_int(int_stat *s) 387 404 { 388 405 ullong data[1]; … … 402 419 static s_stat* init_int(const char *param) 403 420 { 404 int_stat *s = x malloc(sizeof(int_stat));421 int_stat *s = xzalloc(sizeof(*s)); 405 422 s->collect = collect_int; 406 if (param[0] =='\0') {423 if (param[0] == '\0') { 407 424 s->no = 1; 408 425 } else { 409 int n = strtoul(param, NULL, 0);410 s->no = n +2;426 int n = xatoi_positive(param); 427 s->no = n + 2; 411 428 } 412 429 return (s_stat*)s; … … 418 435 S_STAT_END(ctx_stat) 419 436 420 static void collect_ctx(ctx_stat *s)437 static void FAST_FUNC collect_ctx(ctx_stat *s) 421 438 { 422 439 ullong data[1]; … … 434 451 } 435 452 436 static s_stat* init_ctx(const char *param )437 { 438 ctx_stat *s = x malloc(sizeof(ctx_stat));453 static s_stat* init_ctx(const char *param UNUSED_PARAM) 454 { 455 ctx_stat *s = xzalloc(sizeof(*s)); 439 456 s->collect = collect_ctx; 440 457 return (s_stat*)s; … … 447 464 S_STAT_END(blk_stat) 448 465 449 static void collect_blk(blk_stat *s)466 static void FAST_FUNC collect_blk(blk_stat *s) 450 467 { 451 468 ullong data[2]; … … 476 493 } 477 494 478 static s_stat* init_blk(const char *param )479 { 480 blk_stat *s = x malloc(sizeof(blk_stat));495 static s_stat* init_blk(const char *param UNUSED_PARAM) 496 { 497 blk_stat *s = xzalloc(sizeof(*s)); 481 498 s->collect = collect_blk; 482 499 s->lookfor = "page"; … … 489 506 S_STAT_END(fork_stat) 490 507 491 static void collect_thread_nr(fork_stat *s)508 static void FAST_FUNC collect_thread_nr(fork_stat *s UNUSED_PARAM) 492 509 { 493 510 ullong data[1]; … … 500 517 } 501 518 502 static void collect_fork(fork_stat *s)519 static void FAST_FUNC collect_fork(fork_stat *s) 503 520 { 504 521 ullong data[1]; … … 518 535 static s_stat* init_fork(const char *param) 519 536 { 520 fork_stat *s = x malloc(sizeof(fork_stat));537 fork_stat *s = xzalloc(sizeof(*s)); 521 538 if (*param == 'n') { 522 539 s->collect = collect_thread_nr; … … 534 551 S_STAT_END(if_stat) 535 552 536 static void collect_if(if_stat *s)553 static void FAST_FUNC collect_if(if_stat *s) 537 554 { 538 555 ullong data[4]; … … 558 575 static s_stat* init_if(const char *device) 559 576 { 560 if_stat *s = x malloc(sizeof(if_stat));577 if_stat *s = xzalloc(sizeof(*s)); 561 578 562 579 if (!device || !device[0]) … … 565 582 566 583 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); 570 585 return (s_stat*)s; 571 586 } … … 611 626 //HugePages_Free: 0 612 627 //Hugepagesize: 4096 kB 613 static void collect_mem(mem_stat *s)628 static void FAST_FUNC collect_mem(mem_stat *s) 614 629 { 615 630 ullong m_total = 0; … … 623 638 return; 624 639 } 625 if (s->opt == ' f') {640 if (s->opt == 't') { 626 641 scale(m_total << 10); 627 642 return; … … 648 663 static s_stat* init_mem(const char *param) 649 664 { 650 mem_stat *s = x malloc(sizeof(mem_stat));665 mem_stat *s = xzalloc(sizeof(*s)); 651 666 s->collect = collect_mem; 652 667 s->opt = param[0]; … … 658 673 S_STAT_END(swp_stat) 659 674 660 static void collect_swp(swp_stat *s)675 static void FAST_FUNC collect_swp(swp_stat *s UNUSED_PARAM) 661 676 { 662 677 ullong s_total[1]; … … 671 686 } 672 687 673 static s_stat* init_swp(const char *param )674 { 675 swp_stat *s = x malloc(sizeof(swp_stat));688 static s_stat* init_swp(const char *param UNUSED_PARAM) 689 { 690 swp_stat *s = xzalloc(sizeof(*s)); 676 691 s->collect = collect_swp; 677 692 return (s_stat*)s; … … 682 697 S_STAT_END(fd_stat) 683 698 684 static void collect_fd(fd_stat *s)699 static void FAST_FUNC collect_fd(fd_stat *s UNUSED_PARAM) 685 700 { 686 701 ullong data[2]; … … 694 709 } 695 710 696 static s_stat* init_fd(const char *param )697 { 698 fd_stat *s = x malloc(sizeof(fd_stat));711 static s_stat* init_fd(const char *param UNUSED_PARAM) 712 { 713 fd_stat *s = xzalloc(sizeof(*s)); 699 714 s->collect = collect_fd; 700 715 return (s_stat*)s; … … 707 722 S_STAT_END(time_stat) 708 723 709 static void collect_time(time_stat *s)724 static void FAST_FUNC collect_time(time_stat *s) 710 725 { 711 726 char buf[sizeof("12:34:56.123456")]; … … 729 744 { 730 745 int prec; 731 time_stat *s = x malloc(sizeof(time_stat));746 time_stat *s = xzalloc(sizeof(*s)); 732 747 733 748 s->collect = collect_time; 734 prec = param[0] -'0';749 prec = param[0] - '0'; 735 750 if (prec < 0) prec = 0; 736 751 else if (prec > 6) prec = 6; … … 742 757 } 743 758 744 static void collect_info(s_stat *s)759 static void FAST_FUNC collect_info(s_stat *s) 745 760 { 746 761 gen ^= 1; … … 771 786 }; 772 787 773 int nmeter_main(int argc, char **argv) ;774 int nmeter_main(int argc , char **argv)788 int nmeter_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 789 int nmeter_main(int argc UNUSED_PARAM, char **argv) 775 790 { 776 791 char buf[32]; … … 784 799 xchdir("/proc"); 785 800 786 if ( argc != 2)801 if (!argv[1]) 787 802 bb_show_usage(); 788 803 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 } 791 808 792 809 // Can use argv[1] directly, but this will mess up … … 801 818 break; 802 819 if (cur[1] == '%') { // %% 803 strcpy(cur, cur+1);820 overlapping_strcpy(cur, cur + 1); 804 821 cur++; 805 822 goto again; … … 832 849 if (s) { 833 850 s->label = prev; 834 s->next = 0;851 /*s->next = NULL; - all initXXX funcs use xzalloc */ 835 852 if (!first) 836 853 first = s; … … 847 864 s = init_literal(); 848 865 s->label = prev; 849 s->next = 0;866 /*s->next = NULL; - all initXXX funcs use xzalloc */ 850 867 if (!first) 851 868 first = s; -
branches/2.2.9/mindi-busybox/procps/pidof.c
r1765 r2725 5 5 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> 6 6 * 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. 8 8 */ 9 9 … … 11 11 12 12 enum { 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, 17 17 }; 18 18 19 int pidof_main(int argc, char **argv) ;20 int pidof_main(int argc , char **argv)19 int pidof_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 20 int pidof_main(int argc UNUSED_PARAM, char **argv) 21 21 { 22 22 unsigned first = 1; 23 23 unsigned opt; 24 24 #if ENABLE_FEATURE_PIDOF_OMIT 25 char ppid_str[sizeof(int)*3 + 1];26 25 llist_t *omits = NULL; /* list of pids to omit */ 27 26 opt_complementary = "o::"; … … 30 29 /* do unconditional option parsing */ 31 30 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)); 34 33 35 34 #if ENABLE_FEATURE_PIDOF_OMIT … … 37 36 { 38 37 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; 40 42 /* 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()); 46 44 } 47 45 } 48 46 #endif 49 47 /* Looks like everything is set to go. */ 50 while (optind < argc) { 48 argv += optind; 49 while (*argv) { 51 50 pid_t *pidList; 52 51 pid_t *pl; 53 52 54 53 /* 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)); 56 55 for (pl = pidList; *pl; pl++) { 57 56 #if ENABLE_FEATURE_PIDOF_OMIT … … 59 58 llist_t *omits_p = omits; 60 59 while (omits_p) { 61 if (xatoul(omits_p->data) == *pl) {60 if (xatoul(omits_p->data) == (unsigned long)(*pl)) { 62 61 goto omitting; 63 62 } … … 75 74 } 76 75 free(pidList); 77 optind++;76 argv++; 78 77 } 79 putchar('\n'); 78 if (!first) 79 bb_putchar('\n'); 80 80 81 81 #if ENABLE_FEATURE_PIDOF_OMIT -
branches/2.2.9/mindi-busybox/procps/ps.c
r1765 r2725 5 5 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> 6 6 * Fix for SELinux Support:(c)2007 Hiroshi Shinji <shiroshi@my.email.ne.jp> 7 7 * (c)2007 Yuichi Nakamura <ynakam@hitachisoft.jp> 8 8 * 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. 10 10 */ 11 11 … … 17 17 #if ENABLE_DESKTOP 18 18 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 75 24 76 25 #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 103 31 104 32 typedef struct { 105 33 uint16_t width; 106 char name [6];34 char name6[6]; 107 35 const char *header; 108 36 void (*f)(char *buf, int size, const procps_status_t *ps); 109 37 int ps_flags; 110 38 } 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_SELINUX132 { 35 , "label" ,"LABEL" ,func_label ,PSSCAN_CONTEXT },133 #endif134 };135 136 #if ENABLE_SELINUX137 #define SELINIX_O_PREFIX "label,"138 #define DEFAULT_O_STR SELINIX_O_PREFIX "pid,user" /* TODO: ,vsz,stat */ ",args"139 #else140 #define DEFAULT_O_STR "pid,user" /* TODO: ,vsz,stat */ ",args"141 #endif142 39 143 40 struct globals { … … 148 45 char *buffer; 149 46 unsigned terminal_width; 47 #if ENABLE_FEATURE_PS_TIME 48 unsigned kernel_HZ; 49 unsigned long long seconds_since_boot; 50 #endif 150 51 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 */ 67 static 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 82 static 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 125 static inline unsigned get_HZ_by_waiting(void) 126 { 127 /* Better method? */ 128 return 100; 129 } 130 #endif 131 132 static 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 158 static 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 177 static 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 182 static void func_comm(char *buf, int size, const procps_status_t *ps) 183 { 184 safe_strncpy(buf, ps->comm, size+1); 185 } 186 187 static 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 192 static void func_pid(char *buf, int size, const procps_status_t *ps) 193 { 194 sprintf(buf, "%*u", size, ps->pid); 195 } 196 197 static void func_ppid(char *buf, int size, const procps_status_t *ps) 198 { 199 sprintf(buf, "%*u", size, ps->ppid); 200 } 201 202 static void func_pgid(char *buf, int size, const procps_status_t *ps) 203 { 204 sprintf(buf, "%*u", size, ps->pgid); 205 } 206 207 static 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 217 static void func_vsz(char *buf, int size, const procps_status_t *ps) 218 { 219 put_lu(buf, size, ps->vsz); 220 } 221 222 static void func_rss(char *buf, int size, const procps_status_t *ps) 223 { 224 put_lu(buf, size, ps->rss); 225 } 226 227 static 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 237 static 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 242 static 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 247 static 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 256 static 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 270 static 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 285 static 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 /* 292 static void func_nice(char *buf, int size, const procps_status_t *ps) 293 { 294 ps->??? 295 } 296 297 static void func_pcpu(char *buf, int size, const procps_status_t *ps) 298 { 299 } 300 */ 301 302 static 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 151 330 }; 152 #define G (*(struct globals*)&bb_common_bufsiz1)153 #define out (G.out )154 #define out_cnt (G.out_cnt )155 #define print_header (G.print_header )156 #define need_flags (G.need_flags )157 #define buffer (G.buffer )158 #define terminal_width (G.terminal_width)159 #define default_o (G.default_o )160 331 161 332 static ps_out_t* new_out_t(void) 162 333 { 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++]; 166 336 } 167 337 168 338 static const ps_out_t* find_out_spec(const char *name) 169 339 { 170 int i; 340 unsigned i; 341 char buf[ARRAY_SIZE(out_spec)*7 + 1]; 342 char *p = buf; 343 171 344 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) 173 346 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); 176 351 } 177 352 … … 215 390 } 216 391 217 static void post_process(void)392 static void alloc_line_buffer(void) 218 393 { 219 394 int i; … … 225 400 } 226 401 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 } 227 408 } 228 409 #if ENABLE_SELINUX … … 279 460 } 280 461 281 int ps_main(int argc, char **argv) ;282 int ps_main(int argc , char **argv)462 int ps_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 463 int ps_main(int argc UNUSED_PARAM, char **argv) 283 464 { 284 465 procps_status_t *p; 285 466 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(); 287 481 288 482 // POSIX: … … 291 485 // -A Write information for all processes 292 486 // -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) 294 488 // -f Generate a full listing 295 489 // -l Generate a long listing 296 490 // -o col1,col2,col3=header 297 491 // 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 */ 299 497 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); 301 499 if (opt_o) { 302 500 do { 303 parse_o(opt_o->data); 304 opt_o = opt_o->link; 501 parse_o(llist_pop(&opt_o)); 305 502 } while (opt_o); 306 503 } else { 307 504 /* Below: parse_o() needs char*, NOT const char*... */ 308 505 #if ENABLE_SELINUX 309 if (!(opt & 1) || !is_selinux_enabled()) {506 if (!(opt & OPT_Z) || !is_selinux_enabled()) { 310 507 /* no -Z or no SELinux: do not show LABEL */ 311 strcpy(default_o, DEFAULT_O_STR + sizeof(SELIN IX_O_PREFIX)-1);508 strcpy(default_o, DEFAULT_O_STR + sizeof(SELINUX_O_PREFIX)-1); 312 509 } else 313 510 #endif … … 317 514 parse_o(default_o); 318 515 } 319 post_process(); 516 #if ENABLE_FEATURE_SHOW_THREADS 517 if (opt & OPT_T) 518 need_flags |= PSSCAN_TASKS; 519 #endif 320 520 321 521 /* Was INT_MAX, but some libc's go belly up with printf("%.*s") … … 327 527 terminal_width = MAX_WIDTH; 328 528 } 529 alloc_line_buffer(); 329 530 format_header(); 330 531 331 532 p = NULL; 332 while ((p = procps_scan(p, need_flags)) ) {533 while ((p = procps_scan(p, need_flags)) != NULL) { 333 534 format_process(p); 334 535 } … … 341 542 342 543 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; 544 int ps_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 545 int 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 */ 354 560 int w_count = 0; 355 #endif356 357 #if ENABLE_FEATURE_PS_WIDE || ENABLE_SELINUX358 #if ENABLE_FEATURE_PS_WIDE359 561 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); 361 563 /* if w is given once, GNU ps sets the width to 132, 362 564 * if w is given more than once, it is "unlimited" 363 565 */ 364 566 if (w_count) { 365 terminal_width = (w_count ==1) ? 132 : MAX_WIDTH;567 terminal_width = (w_count == 1) ? 132 : MAX_WIDTH; 366 568 } else { 367 569 get_terminal_width_height(0, &terminal_width, NULL); … … 370 572 terminal_width = MAX_WIDTH; 371 573 } 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 375 581 #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; 394 598 #if ENABLE_SELINUX 395 if ( use_selinux) {396 len = printf("%5u %-32 s %s",599 if (psscan_flags & PSSCAN_CONTEXT) { 600 len = printf("%5u %-32.32s %s ", 397 601 p->pid, 398 602 p->context ? p->context : "unknown", … … 402 606 { 403 607 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 } 410 619 } 411 620 … … 422 631 } 423 632 424 #endif /* ENABLE_DESKTOP */633 #endif /* !ENABLE_DESKTOP */ -
branches/2.2.9/mindi-busybox/procps/renice.c
r1765 r2725 5 5 * Copyright (C) 2005 Manuel Novoa III <mjn3@codepoet.org> 6 6 * 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. 8 8 */ 9 9 … … 27 27 void BUG_bad_PRIO_USER(void); 28 28 29 int renice_main(int argc, char **argv) ;30 int renice_main(int argc , char **argv)29 int renice_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 30 int renice_main(int argc UNUSED_PARAM, char **argv) 31 31 { 32 32 static const char Xetpriority_msg[] ALIGN1 = "%cetpriority"; 33 33 34 34 int retval = EXIT_SUCCESS; 35 int which = PRIO_PROCESS; 35 int which = PRIO_PROCESS; /* Default 'which' value. */ 36 36 int use_relative = 0; 37 37 int adjustment, new_priority; … … 58 58 } 59 59 60 if (!arg) { 60 if (!arg) { /* No args? Then show usage. */ 61 61 bb_show_usage(); 62 62 } … … 85 85 p = getpwnam(arg); 86 86 if (!p) { 87 bb_error_msg("unknown user :%s", arg);87 bb_error_msg("unknown user %s", arg); 88 88 goto HAD_ERROR; 89 89 } … … 92 92 who = bb_strtou(arg, NULL, 10); 93 93 if (errno) { 94 bb_error_msg(" bad value: %s", arg);94 bb_error_msg("invalid number '%s'", arg); 95 95 goto HAD_ERROR; 96 96 } … … 101 101 int old_priority; 102 102 103 errno = 0; 103 errno = 0; /* Needed for getpriority error detection. */ 104 104 old_priority = getpriority(which, who); 105 105 if (errno) { -
branches/2.2.9/mindi-busybox/procps/sysctl.c
r1765 r2725 5 5 * Copyright 1999 George Staikos 6 6 * 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. 8 8 * 9 9 * 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> 15 12 */ 16 13 17 14 #include "libbb.h" 18 15 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(); 16 enum { 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 26 static 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; 102 63 } 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 71 static 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 209 108 if (fd < 0) { 210 109 switch (errno) { 211 110 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); 216 113 break; 217 114 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); 219 119 break; 220 120 } 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); 222 132 } else { 223 dwrite_str(fd, value); 133 char c; 134 135 value = cptr = xmalloc_read(fd, NULL); 224 136 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: 235 161 free(outname); 236 162 return retval; 237 } /* end sysctl_write_setting() */ 238 239 240 /* 241 * Read a sysctl setting 242 * 163 } 164 165 static 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 243 200 */ 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); 201 static 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 228 int sysctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 229 int 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 289 257 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 5 5 * This is written specifically for the linux /proc/<PID>/stat(m) 6 6 * files format. 7 7 * 8 8 * This reads the PIDs of all processes and their status and shows 9 9 * the status of processes (first ones that fit to screen) at given … … 17 17 * 18 18 * 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 * 23 26 * Copyright (c) 1992 Branko Lankester 24 27 * Copyright (c) 1992 Roger Binns 25 28 * Copyright (C) 1994-1996 Charles L. Blake. 26 29 * Copyright (C) 1992-1998 Michael K. Johnson 27 * May be distributed under the conditions of the28 * GNU Library General Public License30 * 31 * Licensed under GPLv2, see file LICENSE in this source tree. 29 32 */ 30 33 … … 42 45 char state[4]; 43 46 char comm[COMM_LEN]; 47 #if ENABLE_FEATURE_TOP_SMP_PROCESS 48 int last_seen_on_cpu; 49 #endif 44 50 } top_status_t; 45 51 46 52 typedef 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; 48 56 unsigned long long total; 49 57 unsigned long long busy; … … 54 62 typedef struct save_hist { 55 63 unsigned long ticks; 56 unsignedpid;64 pid_t pid; 57 65 } save_hist; 58 66 59 67 typedef int (*cmp_funcp)(top_status_t *P, top_status_t *Q); 60 68 69 61 70 enum { SORT_DEPTH = 3 }; 71 62 72 63 73 struct globals { 64 74 top_status_t *top; 65 75 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 66 83 #if ENABLE_FEATURE_USE_TERMIOS 67 84 struct termios initial_settings; 68 85 #endif 69 86 #if !ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE 70 cmp_funcp sort_function ;87 cmp_funcp sort_function[1]; 71 88 #else 72 89 cmp_funcp sort_function[SORT_DEPTH]; 73 90 struct save_hist *prev_hist; 74 91 int prev_hist_count; 75 jiffy_counts_t jif, prev_jif;92 jiffy_counts_t cur_jif, prev_jif; 76 93 /* int hist_iterations; */ 77 94 unsigned total_pcpu; 78 95 /* unsigned long total_vsz; */ 79 96 #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 104 enum { LINE_BUF_SIZE = COMMON_BUFSIZE - offsetof(struct globals, line_buf) }; 105 #define G (*(struct globals*)&bb_common_bufsiz1) 106 struct 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]; 80 109 }; 81 #define G (*(struct globals*)&bb_common_bufsiz1)110 #define INIT_G() do { } while (0) 82 111 #define top (G.top ) 83 112 #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 ) 87 117 #define sort_function (G.sort_function ) 88 #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE89 118 #define prev_hist (G.prev_hist ) 90 119 #define prev_hist_count (G.prev_hist_count ) 91 #define jif (G.jif)120 #define cur_jif (G.cur_jif ) 92 121 #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 ) 93 125 #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 128 enum { 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) 97 136 98 137 … … 142 181 } 143 182 183 static 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 } 144 207 145 208 static void get_jiffy_counts(void) 146 209 { 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 154 219 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 } 161 260 162 261 static void do_stats(void) … … 170 269 total_pcpu = 0; 171 270 /* total_vsz = 0; */ 172 new_hist = xmalloc(sizeof( struct save_hist)*ntop);271 new_hist = xmalloc(sizeof(new_hist[0]) * ntop); 173 272 /* 174 273 * Make a pass through the data to get stats. … … 211 310 prev_hist_count = ntop; 212 311 } 312 213 313 #endif /* FEATURE_TOP_CPU_USAGE_PERCENTAGE */ 214 314 … … 238 338 #endif 239 339 240 /* display generic info (meminfo / loadavg) */ 241 static unsigned long display_generic(int scr_width) 340 #if ENABLE_FEATURE_TOP_CPU_GLOBAL_PERCENTS 341 static 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 421 static unsigned long display_header(int scr_width, int *lines_rem_p) 242 422 { 243 423 FILE *fp; … … 245 425 char scrbuf[80]; 246 426 unsigned long total, used, mfree, shared, buffers, cached; 247 #if ENABLE_FEATURE_TOP_CPU_GLOBAL_PERCENTS248 unsigned total_diff;249 #endif250 427 251 428 /* read memory info */ 252 fp = xfopen ("meminfo", "r");429 fp = xfopen_for_read("meminfo"); 253 430 254 431 /* … … 280 457 * 2.6. 281 458 */ 282 283 459 fscanf(fp, "MemFree: %lu %s\n", &mfree, buf); 284 460 … … 298 474 299 475 /* output memory info */ 300 if (scr_width > sizeof(scrbuf))476 if (scr_width > (int)sizeof(scrbuf)) 301 477 scr_width = sizeof(scrbuf); 302 478 snprintf(scrbuf, scr_width, 303 479 "Mem: %luK used, %luK free, %luK shrd, %luK buff, %luK cached", 304 480 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 311 487 */ 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); 348 489 349 490 /* read load average as a string */ 350 491 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'; 353 495 snprintf(scrbuf, scr_width, "Load average: %s", buf); 354 496 puts(scrbuf); 497 (*lines_rem_p)--; 355 498 356 499 return total; 357 500 } 358 501 359 /* display process statuses */ 360 static void display_status(int count, int scr_width) 502 static NOINLINE void display_process_list(int lines_rem, int scr_width) 361 503 { 362 504 enum { 363 BITS_PER_INT = sizeof(int) *8505 BITS_PER_INT = sizeof(int) * 8 364 506 }; 365 507 366 top_status_t *s = top;508 top_status_t *s; 367 509 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? */ 369 511 /* xxx_shift and xxx_scale variables allow us to replace 370 512 * expensive divides with multiply and shift */ 371 513 unsigned pmem_shift, pmem_scale, pmem_half; 372 514 #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE 515 unsigned tmp_unsigned; 373 516 unsigned pcpu_shift, pcpu_scale, pcpu_half; 374 517 unsigned busy_jifs; 518 #endif 375 519 376 520 /* 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" 381 533 #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%%" 400 538 #endif 401 539 /* … … 411 549 pmem_half = (1U << pmem_shift) / (ENABLE_FEATURE_TOP_DECIMALS? 20 : 2); 412 550 #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE 413 busy_jifs = jif.busy - prev_jif.busy;551 busy_jifs = cur_jif.busy - prev_jif.busy; 414 552 /* This happens if there were lots of short-lived processes 415 553 * between two top updates (e.g. compilation) */ … … 420 558 * (pcpu is delta of sys+user time between samples) 421 559 */ 422 /* ( jif.xxx - prev_jif.xxx) and s->pcpu are560 /* (cur_jif.xxx - prev_jif.xxx) and s->pcpu are 423 561 * in 0..~64000 range (HZ*update_interval). 424 562 * we assume that unsigned is at least 32-bit. 425 563 */ 426 564 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))) { 429 569 pcpu_scale *= 4; 430 570 pcpu_shift += 2; 431 571 } 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; 433 575 /* we want (s->pcpu * pcpu_scale) to never overflow */ 434 576 while (pcpu_scale >= 1024) { … … 440 582 #endif 441 583 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; 445 591 CALC_STAT(pmem, (s->vsz*pmem_scale + pmem_half) >> pmem_shift); 446 592 #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE … … 448 594 #endif 449 595 450 if (s->vsz >= 100 *1024)451 sprintf(vsz_str_buf, "%6ld M", s->vsz/1024);596 if (s->vsz >= 100000) 597 sprintf(vsz_str_buf, "%6ldm", s->vsz/1024); 452 598 else 453 599 sprintf(vsz_str_buf, "%7ld", s->vsz); 454 / / PID PPID USER STAT VSZ %MEM [%CPU] COMMAND455 col -= printf("\n" "%5u%6u %-8.8s %s%s" FMT456 #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE 457 FMT458 #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) 459 605 " ", 460 606 s->pid, s->ppid, get_cached_username(s->uid), 461 607 s->state, vsz_str_buf, 462 608 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)) 466 611 ); 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); 472 615 /* 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); */ 474 617 s++; 475 618 } 476 619 /* 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(); 479 622 } 480 623 #undef UPSCALE … … 483 626 #undef FMT 484 627 485 486 628 static void clearmems(void) 487 629 { 488 630 clear_username_cache(); 489 631 free(top); 490 top = 0;632 top = NULL; 491 633 ntop = 0; 492 634 } 493 635 494 495 636 #if ENABLE_FEATURE_USE_TERMIOS 496 #include <termios.h>497 #include <signal.h>498 637 499 638 static void reset_term(void) 500 639 { 501 tcsetattr (0, TCSANOW, (void *)&initial_settings);502 #if ENABLE_FEATURE_CLEAN_UP 503 clearmems();504 # if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE505 free(prev_hist);506 # endif507 #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 649 static void sig_catcher(int sig UNUSED_PARAM) 511 650 { 512 651 reset_term(); 513 exit(1); 514 } 652 _exit(EXIT_FAILURE); 653 } 654 515 655 #endif /* FEATURE_USE_TERMIOS */ 516 656 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 661 typedef unsigned long mem_t; 662 663 typedef 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 676 enum { NUM_SORT_FIELD = 7 }; 677 678 #define topmem ((topmem_status_t*)top) 679 680 #if ENABLE_FEATURE_TOPMEM 681 682 static 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) */ 701 static 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 766 static 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 773 static 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 811 void display_topmem_process_list(int lines_rem, int scr_width); 812 int topmem_sort(char *a, char *b); 813 #endif /* TOPMEM */ 814 815 /* 816 * end TOPMEM support 817 */ 818 819 enum { 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 836 int top_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 837 int 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; 525 845 #if ENABLE_FEATURE_USE_TERMIOS 526 846 struct termios new_settings; 527 struct timeval tv; 528 fd_set readfds; 847 struct pollfd pfd[1]; 529 848 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 } 540 885 541 886 /* change to /proc */ … … 543 888 #if ENABLE_FEATURE_USE_TERMIOS 544 889 tcgetattr(0, (void *) &initial_settings); 545 memcpy(&new_settings, &initial_settings, sizeof( struct termios));890 memcpy(&new_settings, &initial_settings, sizeof(new_settings)); 546 891 /* unbuffered input, turn off echo */ 547 892 new_settings.c_lflag &= ~(ISIG | ICANON | ECHO | ECHONL); 548 893 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 554 897 555 898 #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE … … 558 901 sort_function[2] = time_sort; 559 902 #else 560 sort_function = mem_sort;561 #endif /* FEATURE_TOP_CPU_USAGE_PERCENTAGE */903 sort_function[0] = mem_sort; 904 #endif 562 905 563 906 while (1) { 564 907 procps_status_t *p = NULL; 565 908 566 /* Default to 25 lines - 5 lines for status */ 567 lines = 24 - 3 USE_FEATURE_TOP_CPU_GLOBAL_PERCENTS( - 1); 909 lines = 24; /* default */ 568 910 col = 79; 569 911 #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) { 572 915 sleep(interval); 573 916 continue; 574 917 } 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; 577 921 578 922 /* 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; 595 934 #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; 601 966 } 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 604 982 } 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); 611 986 } 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); 615 1003 #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]) 635 1013 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;) 638 1023 sort_function[0] = mem_sort; 1024 # if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE 639 1025 sort_function[1] = pcpu_sort; 640 1026 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;) 647 1039 sort_function[0] = pcpu_sort; 648 1040 sort_function[1] = mem_sort; 649 1041 sort_function[2] = time_sort; 650 1042 } 651 if (c == 'T') { 1043 if (c == 't') { 1044 IF_FEATURE_TOPMEM(scan_mask = TOP_MASK;) 652 1045 sort_function[0] = time_sort; 653 1046 sort_function[1] = mem_sort; 654 1047 sort_function[2] = pcpu_sort; 655 1048 } 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 664 1079 } 665 if (!--iterations)666 break;667 #else668 sleep(interval);669 1080 #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 675 1087 return EXIT_SUCCESS; 676 1088 } -
branches/2.2.9/mindi-busybox/procps/uptime.c
r1765 r2725 5 5 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> 6 6 * 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. 8 8 */ 9 9 … … 26 26 27 27 28 int uptime_main(int argc, char **argv) ;29 int uptime_main(int argc , char **argv)28 int uptime_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 29 int uptime_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) 30 30 { 31 31 int updays, uphours, upminutes; -
branches/2.2.9/mindi-busybox/procps/watch.c
r1765 r2725 6 6 * Copyrigjt (C) Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org) 7 7 * 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. 9 9 */ 10 10 … … 24 24 // (procps 3.x and procps 2.x are forks, not newer/older versions of the same) 25 25 26 int watch_main(int argc, char **argv) ;27 int watch_main(int argc , char **argv)26 int watch_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 27 int watch_main(int argc UNUSED_PARAM, char **argv) 28 28 { 29 29 unsigned opt; 30 30 unsigned period = 2; 31 unsigned cmdlen;32 char *header = NULL;31 unsigned width, new_width; 32 char *header; 33 33 char *cmd; 34 char *tmp;35 char **p;36 34 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); 42 44 argv += optind; 43 45 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 54 51 52 width = (unsigned)-1; // make sure first time new_width != width 53 header = NULL; 55 54 while (1) { 56 printf("\033[H\033[J"); 55 /* home; clear to the end of screen */ 56 printf("\033[H""\033[J"); 57 57 if (!(opt & 0x2)) { // no -t 58 int width, len; 59 char *thyme; 58 const unsigned time_len = sizeof("1234-67-90 23:56:89"); 60 59 time_t t; 61 60 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 } 66 69 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); 72 76 } 73 fflush (stdout);77 fflush_all(); 74 78 // TODO: 'real' watch pipes cmd's output to itself 75 79 // and does not allow it to overflow the screen
Note:
See TracChangeset
for help on using the changeset viewer.