summaryrefslogtreecommitdiff
path: root/i/pc104/initrd/conf/busybox/procps
diff options
context:
space:
mode:
Diffstat (limited to 'i/pc104/initrd/conf/busybox/procps')
-rw-r--r--i/pc104/initrd/conf/busybox/procps/Config.in121
-rw-r--r--i/pc104/initrd/conf/busybox/procps/Kbuild16
-rw-r--r--i/pc104/initrd/conf/busybox/procps/free.c69
-rw-r--r--i/pc104/initrd/conf/busybox/procps/fuser.c368
-rw-r--r--i/pc104/initrd/conf/busybox/procps/kill.c156
-rw-r--r--i/pc104/initrd/conf/busybox/procps/pidof.c91
-rw-r--r--i/pc104/initrd/conf/busybox/procps/ps.c388
-rw-r--r--i/pc104/initrd/conf/busybox/procps/ps.posix175
-rw-r--r--i/pc104/initrd/conf/busybox/procps/renice.c127
-rw-r--r--i/pc104/initrd/conf/busybox/procps/sysctl.c327
-rw-r--r--i/pc104/initrd/conf/busybox/procps/top.c570
-rw-r--r--i/pc104/initrd/conf/busybox/procps/uptime.c60
12 files changed, 2468 insertions, 0 deletions
diff --git a/i/pc104/initrd/conf/busybox/procps/Config.in b/i/pc104/initrd/conf/busybox/procps/Config.in
new file mode 100644
index 0000000..e58b89f
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/procps/Config.in
@@ -0,0 +1,121 @@
+#
+# For a description of the syntax of this configuration file,
+# see scripts/kbuild/config-language.txt.
+#
+
+menu "Process Utilities"
+
+config FREE
+ bool "free"
+ default n
+ help
+ free displays the total amount of free and used physical and swap
+ memory in the system, as well as the buffers used by the kernel.
+ The shared memory column should be ignored; it is obsolete.
+
+config FUSER
+ bool "fuser"
+ default n
+ help
+ fuser lists all PIDs (Process IDs) that currently have a given
+ file open. fuser can also list all PIDs that have a given network
+ (TCP or UDP) port open.
+
+config KILL
+ bool "kill"
+ default n
+ help
+ The command kill sends the specified signal to the specified
+ process or process group. If no signal is specified, the TERM
+ signal is sent.
+
+config KILLALL
+ bool "killall"
+ default n
+ depends on KILL
+ help
+ killall sends a signal to all processes running any of the
+ specified commands. If no signal name is specified, SIGTERM is
+ sent.
+
+config KILLALL5
+ bool "killall5"
+ default n
+ depends on KILL
+
+config PIDOF
+ bool "pidof"
+ default n
+ help
+ Pidof finds the process id's (pids) of the named programs. It prints
+ those id's on the standard output.
+
+config FEATURE_PIDOF_SINGLE
+ bool "Enable argument for single shot (-s)"
+ default n
+ depends on PIDOF
+ help
+ Support argument '-s' for returning only the first pid found.
+
+config FEATURE_PIDOF_OMIT
+ bool "Enable argument for omitting pids (-o)"
+ default n
+ depends on PIDOF
+ help
+ Support argument '-o' for omitting the given pids in output.
+ The special pid %PPID can be used to name the parent process
+ of the pidof, in other words the calling shell or shell script.
+
+config PS
+ bool "ps"
+ default n
+ help
+ ps gives a snapshot of the current processes.
+
+config FEATURE_PS_WIDE
+ bool "Enable argument for wide output (-w)"
+ default n
+ depends on PS
+ help
+ Support argument 'w' for wide output.
+ If given once, 132 chars are printed and given more than
+ one, the length is unlimited.
+
+config RENICE
+ bool "renice"
+ default n
+ help
+ Renice alters the scheduling priority of one or more running
+ processes.
+
+config BB_SYSCTL
+ bool "sysctl"
+ default n
+ help
+ Configure kernel parameters at runtime.
+
+config TOP
+ bool "top"
+ default n
+ help
+ The top program provides a dynamic real-time view of a running
+ system.
+
+config FEATURE_TOP_CPU_USAGE_PERCENTAGE
+ bool "Support showing CPU usage percentage (add 2k bytes)"
+ default y
+ depends on TOP
+ help
+ Make top display CPU usage.
+
+config UPTIME
+ bool "uptime"
+ default n
+ help
+ uptime gives a one line display of the current time, how long
+ the system has been running, how many users are currently logged
+ on, and the system load averages for the past 1, 5, and 15 minutes.
+
+
+endmenu
+
diff --git a/i/pc104/initrd/conf/busybox/procps/Kbuild b/i/pc104/initrd/conf/busybox/procps/Kbuild
new file mode 100644
index 0000000..6a9a866
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/procps/Kbuild
@@ -0,0 +1,16 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+lib-y:=
+lib-$(CONFIG_FREE) += free.o
+lib-$(CONFIG_KILL) += kill.o
+lib-$(CONFIG_PIDOF) += pidof.o
+lib-$(CONFIG_PS) += ps.o
+lib-$(CONFIG_RENICE) += renice.o
+lib-$(CONFIG_BB_SYSCTL) += sysctl.o
+lib-$(CONFIG_TOP) += top.o
+lib-$(CONFIG_UPTIME) += uptime.o
+lib-$(CONFIG_FUSER) += fuser.o
diff --git a/i/pc104/initrd/conf/busybox/procps/free.c b/i/pc104/initrd/conf/busybox/procps/free.c
new file mode 100644
index 0000000..860f573
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/procps/free.c
@@ -0,0 +1,69 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini free implementation for busybox
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
+ *
+ * Licensed under the GPL version 2, see the file LICENSE in this tarball.
+ */
+
+/* getopt not needed */
+
+#include "busybox.h"
+
+int free_main(int argc, char **argv);
+int free_main(int argc, char **argv)
+{
+ struct sysinfo info;
+ sysinfo(&info);
+
+ /* Kernels prior to 2.4.x will return info.mem_unit==0, so cope... */
+ if (info.mem_unit==0) {
+ info.mem_unit=1;
+ }
+ if ( info.mem_unit == 1 ) {
+ info.mem_unit=1024;
+
+ /* TODO: Make all this stuff not overflow when mem >= 4 Gib */
+ info.totalram/=info.mem_unit;
+ info.freeram/=info.mem_unit;
+#ifndef __uClinux__
+ info.totalswap/=info.mem_unit;
+ info.freeswap/=info.mem_unit;
+#endif
+ info.sharedram/=info.mem_unit;
+ info.bufferram/=info.mem_unit;
+ } else {
+ info.mem_unit/=1024;
+ /* TODO: Make all this stuff not overflow when mem >= 4 Gib */
+ info.totalram*=info.mem_unit;
+ info.freeram*=info.mem_unit;
+#ifndef __uClinux__
+ info.totalswap*=info.mem_unit;
+ info.freeswap*=info.mem_unit;
+#endif
+ info.sharedram*=info.mem_unit;
+ info.bufferram*=info.mem_unit;
+ }
+
+ if (argc > 1 && **(argv + 1) == '-')
+ bb_show_usage();
+
+ printf("%6s%13s%13s%13s%13s%13s\n", "", "total", "used", "free",
+ "shared", "buffers");
+
+ printf("%6s%13ld%13ld%13ld%13ld%13ld\n", "Mem:", info.totalram,
+ info.totalram-info.freeram, info.freeram,
+ info.sharedram, info.bufferram);
+
+#ifndef __uClinux__
+ printf("%6s%13ld%13ld%13ld\n", "Swap:", info.totalswap,
+ info.totalswap-info.freeswap, info.freeswap);
+
+ printf("%6s%13ld%13ld%13ld\n", "Total:", info.totalram+info.totalswap,
+ (info.totalram-info.freeram)+(info.totalswap-info.freeswap),
+ info.freeram+info.freeswap);
+#endif
+ return EXIT_SUCCESS;
+}
+
diff --git a/i/pc104/initrd/conf/busybox/procps/fuser.c b/i/pc104/initrd/conf/busybox/procps/fuser.c
new file mode 100644
index 0000000..c91ae21
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/procps/fuser.c
@@ -0,0 +1,368 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * tiny fuser implementation
+ *
+ * Copyright 2004 Tony J. White
+ *
+ * May be distributed under the conditions of the
+ * GNU Library General Public License
+ */
+
+#include "busybox.h"
+
+#define FUSER_PROC_DIR "/proc"
+#define FUSER_MAX_LINE 255
+
+#define FUSER_OPT_MOUNT 1
+#define FUSER_OPT_KILL 2
+#define FUSER_OPT_SILENT 4
+#define FUSER_OPT_IP6 8
+#define FUSER_OPT_IP4 16
+
+typedef struct inode_list {
+ ino_t inode;
+ dev_t dev;
+ struct inode_list *next;
+} inode_list;
+
+typedef struct pid_list {
+ pid_t pid;
+ struct pid_list *next;
+} pid_list;
+
+static int fuser_option(char *option)
+{
+ int opt = 0;
+
+ if(!(strlen(option))) return 0;
+ if(option[0] != '-') return 0;
+ ++option;
+ while(*option != '\0') {
+ if(*option == 'm') opt |= FUSER_OPT_MOUNT;
+ else if(*option == 'k') opt |= FUSER_OPT_KILL;
+ else if(*option == 's') opt |= FUSER_OPT_SILENT;
+ else if(*option == '6') opt |= FUSER_OPT_IP6;
+ else if(*option == '4') opt |= FUSER_OPT_IP4;
+ else {
+ bb_error_msg_and_die(
+ "Unsupported option '%c'", *option);
+ }
+ ++option;
+ }
+ return opt;
+}
+
+static int fuser_file_to_dev_inode(const char *filename,
+ dev_t *dev, ino_t *inode)
+{
+ struct stat f_stat;
+ if((stat(filename, &f_stat)) < 0) return 0;
+ *inode = f_stat.st_ino;
+ *dev = f_stat.st_dev;
+ return 1;
+}
+
+static int fuser_find_socket_dev(dev_t *dev)
+{
+ int fd = socket(PF_INET, SOCK_DGRAM,0);
+ struct stat buf;
+
+ if (fd >= 0 && (fstat(fd, &buf)) == 0) {
+ *dev = buf.st_dev;
+ close(fd);
+ return 1;
+ }
+ return 0;
+}
+
+static int fuser_parse_net_arg(const char *filename,
+ const char **proto, int *port)
+{
+ char path[sizeof(FUSER_PROC_DIR)+12], tproto[5];
+
+ if((sscanf(filename, "%d/%4s", port, tproto)) != 2) return 0;
+ sprintf(path, "%s/net/%s", FUSER_PROC_DIR, tproto);
+ if((access(path, R_OK)) != 0) return 0;
+ *proto = xstrdup(tproto);
+ return 1;
+}
+
+static int fuser_add_pid(pid_list *plist, pid_t pid)
+{
+ pid_list *curr = NULL, *last = NULL;
+
+ if(plist->pid == 0) plist->pid = pid;
+ curr = plist;
+ while(curr != NULL) {
+ if(curr->pid == pid) return 1;
+ last = curr;
+ curr = curr->next;
+ }
+ curr = xmalloc(sizeof(pid_list));
+ last->next = curr;
+ curr->pid = pid;
+ curr->next = NULL;
+ return 1;
+}
+
+static int fuser_add_inode(inode_list *ilist, dev_t dev, ino_t inode)
+{
+ inode_list *curr = NULL, *last = NULL;
+
+ if(!ilist->inode && !ilist->dev) {
+ ilist->dev = dev;
+ ilist->inode = inode;
+ }
+ curr = ilist;
+ while(curr != NULL) {
+ if(curr->inode == inode && curr->dev == dev) return 1;
+ last = curr;
+ curr = curr->next;
+ }
+ curr = xmalloc(sizeof(inode_list));
+ last->next = curr;
+ curr->dev = dev;
+ curr->inode = inode;
+ curr->next = NULL;
+ return 1;
+}
+
+static int fuser_scan_proc_net(int opts, const char *proto,
+ int port, inode_list *ilist)
+{
+ char path[sizeof(FUSER_PROC_DIR)+12], line[FUSER_MAX_LINE+1];
+ char addr[128];
+ ino_t tmp_inode;
+ dev_t tmp_dev;
+ long long uint64_inode;
+ int tmp_port;
+ FILE *f;
+
+ if(!fuser_find_socket_dev(&tmp_dev)) tmp_dev = 0;
+ sprintf(path, "%s/net/%s", FUSER_PROC_DIR, proto);
+
+ if (!(f = fopen(path, "r"))) return 0;
+ while(fgets(line, FUSER_MAX_LINE, f)) {
+ if(sscanf(line,
+ "%*d: %64[0-9A-Fa-f]:%x %*x:%*x %*x %*x:%*x "
+ "%*x:%*x %*x %*d %*d %llu",
+ addr, &tmp_port, &uint64_inode) == 3) {
+ if((strlen(addr) == 8) &&
+ (opts & FUSER_OPT_IP6)) continue;
+ else if((strlen(addr) > 8) &&
+ (opts & FUSER_OPT_IP4)) continue;
+ if(tmp_port == port) {
+ tmp_inode = uint64_inode;
+ fuser_add_inode(ilist, tmp_dev, tmp_inode);
+ }
+ }
+
+ }
+ fclose(f);
+ return 1;
+}
+
+static int fuser_search_dev_inode(int opts, inode_list *ilist,
+ dev_t dev, ino_t inode)
+{
+ inode_list *curr;
+ curr = ilist;
+
+ while(curr) {
+ if((opts & FUSER_OPT_MOUNT) && curr->dev == dev)
+ return 1;
+ if(curr->inode == inode && curr->dev == dev)
+ return 1;
+ curr = curr->next;
+ }
+ return 0;
+}
+
+static int fuser_scan_pid_maps(int opts, const char *fname, pid_t pid,
+ inode_list *ilist, pid_list *plist)
+{
+ FILE *file;
+ char line[FUSER_MAX_LINE + 1];
+ int major, minor;
+ ino_t inode;
+ long long uint64_inode;
+ dev_t dev;
+
+ if (!(file = fopen(fname, "r"))) return 0;
+ while (fgets(line, FUSER_MAX_LINE, file)) {
+ if(sscanf(line, "%*s %*s %*s %x:%x %llu",
+ &major, &minor, &uint64_inode) != 3) continue;
+ inode = uint64_inode;
+ if(major == 0 && minor == 0 && inode == 0) continue;
+ dev = makedev(major, minor);
+ if(fuser_search_dev_inode(opts, ilist, dev, inode)) {
+ fuser_add_pid(plist, pid);
+ }
+
+ }
+ fclose(file);
+ return 1;
+}
+
+static int fuser_scan_link(int opts, const char *lname, pid_t pid,
+ inode_list *ilist, pid_list *plist)
+{
+ ino_t inode;
+ dev_t dev;
+
+ if(!fuser_file_to_dev_inode(lname, &dev, &inode)) return 0;
+ if(fuser_search_dev_inode(opts, ilist, dev, inode))
+ fuser_add_pid(plist, pid);
+ return 1;
+}
+
+static int fuser_scan_dir_links(int opts, const char *dname, pid_t pid,
+ inode_list *ilist, pid_list *plist)
+{
+ DIR *d;
+ struct dirent *de;
+ char *lname;
+
+ if((d = opendir(dname))) {
+ while((de = readdir(d)) != NULL) {
+ lname = concat_subpath_file(dname, de->d_name);
+ if(lname == NULL)
+ continue;
+ fuser_scan_link(opts, lname, pid, ilist, plist);
+ free(lname);
+ }
+ closedir(d);
+ }
+ else return 0;
+ return 1;
+
+}
+
+static int fuser_scan_proc_pids(int opts, inode_list *ilist, pid_list *plist)
+{
+ DIR *d;
+ struct dirent *de;
+ pid_t pid;
+ char *dname;
+
+ if(!(d = opendir(FUSER_PROC_DIR))) return 0;
+ while((de = readdir(d)) != NULL) {
+ pid = (pid_t)atoi(de->d_name);
+ if(!pid) continue;
+ dname = concat_subpath_file(FUSER_PROC_DIR, de->d_name);
+ if(chdir(dname) < 0) {
+ free(dname);
+ continue;
+ }
+ free(dname);
+ fuser_scan_link(opts, "cwd", pid, ilist, plist);
+ fuser_scan_link(opts, "exe", pid, ilist, plist);
+ fuser_scan_link(opts, "root", pid, ilist, plist);
+ fuser_scan_dir_links(opts, "fd", pid, ilist, plist);
+ fuser_scan_dir_links(opts, "lib", pid, ilist, plist);
+ fuser_scan_dir_links(opts, "mmap", pid, ilist, plist);
+ fuser_scan_pid_maps(opts, "maps", pid, ilist, plist);
+ chdir("..");
+ }
+ closedir(d);
+ return 1;
+}
+
+static int fuser_print_pid_list(pid_list *plist)
+{
+ pid_list *curr = plist;
+
+ if(plist == NULL) return 0;
+ while(curr != NULL) {
+ if(curr->pid > 0) printf("%d ", curr->pid);
+ curr = curr->next;
+ }
+ puts("");
+ return 1;
+}
+
+static int fuser_kill_pid_list(pid_list *plist, int sig)
+{
+ pid_list *curr = plist;
+ pid_t mypid = getpid();
+ int success = 1;
+
+ if(plist == NULL) return 0;
+ while(curr != NULL) {
+ if(curr->pid > 0 && curr->pid != mypid) {
+ if (kill(curr->pid, sig) != 0) {
+ bb_perror_msg(
+ "cannot kill pid '%d'", curr->pid);
+ success = 0;
+ }
+ }
+ curr = curr->next;
+ }
+ return success;
+}
+
+int fuser_main(int argc, char **argv);
+int fuser_main(int argc, char **argv)
+{
+ int port, i, optn;
+ int* fni; /* file name indexes of argv */
+ int fnic = 0; /* file name index count */
+ const char *proto;
+ static int opt = 0; /* FUSER_OPT_ */
+ dev_t dev;
+ ino_t inode;
+ pid_list *pids;
+ inode_list *inodes;
+ int killsig = SIGTERM;
+ int success = 1;
+
+ if (argc < 2)
+ bb_show_usage();
+
+ fni = xmalloc(sizeof(int));
+ for (i=1;i<argc;i++) {
+ optn = fuser_option(argv[i]);
+ if(optn) opt |= optn;
+ else if(argv[i][0] == '-') {
+ killsig = get_signum(argv[i]+1);
+ if(0 > killsig)
+ killsig = SIGTERM;
+ }
+ else {
+ fni = xrealloc(fni, sizeof(int) * (fnic+2));
+ fni[fnic++] = i;
+ }
+ }
+ if(!fnic) return 1;
+
+ inodes = xmalloc(sizeof(inode_list));
+ for (i=0;i<fnic;i++) {
+ if(fuser_parse_net_arg(argv[fni[i]], &proto, &port)) {
+ fuser_scan_proc_net(opt, proto, port, inodes);
+ }
+ else {
+ if(!fuser_file_to_dev_inode(
+ argv[fni[i]], &dev, &inode)) {
+ if (ENABLE_FEATURE_CLEAN_UP) free(inodes);
+ bb_perror_msg_and_die("cannot open '%s'", argv[fni[i]]);
+ }
+ fuser_add_inode(inodes, dev, inode);
+ }
+ }
+ pids = xmalloc(sizeof(pid_list));
+ success = fuser_scan_proc_pids(opt, inodes, pids);
+ /* if the first pid in the list is 0, none have been found */
+ if(pids->pid == 0) success = 0;
+ if(success) {
+ if(opt & FUSER_OPT_KILL) {
+ success = fuser_kill_pid_list(pids, killsig);
+ }
+ else if(!(opt & FUSER_OPT_SILENT)) {
+ success = fuser_print_pid_list(pids);
+ }
+ }
+ free(pids);
+ free(inodes);
+ /* return 0 on (success == 1) 1 otherwise */
+ return (success != 1);
+}
diff --git a/i/pc104/initrd/conf/busybox/procps/kill.c b/i/pc104/initrd/conf/busybox/procps/kill.c
new file mode 100644
index 0000000..9a6e936
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/procps/kill.c
@@ -0,0 +1,156 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini kill/killall implementation for busybox
+ *
+ * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>.
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+#include "busybox.h"
+
+int kill_main(int argc, char **argv);
+int kill_main(int argc, char **argv)
+{
+ char *arg;
+ pid_t pid;
+ int signo = SIGTERM, errors = 0, quiet = 0;
+ const int killall = (ENABLE_KILLALL && applet_name[4] == 'a'
+ && (!ENABLE_KILLALL5 || applet_name[7] != '5'));
+ const int killall5 = (ENABLE_KILLALL5 && applet_name[4] == 'a'
+ && (!ENABLE_KILLALL || applet_name[7] == '5'));
+
+ /* Parse any options */
+ argc--;
+ arg = *++argv;
+
+ if (argc < 1 || arg[0] != '-') {
+ goto do_it_now;
+ }
+
+ /* The -l option, which prints out signal names. */
+ if (arg[1] == 'l' && arg[2] == '\0') {
+ const char *name;
+ if (argc == 1) {
+ /* Print the whole signal list */
+ int col = 0;
+ for (signo = 1; signo < 32; signo++) {
+ name = get_signame(signo);
+ if (isdigit(name[0])) continue;
+ if (col > 66) {
+ puts("");
+ col = 0;
+ }
+ col += printf("%2d) %-6s", signo, name);
+ }
+ puts("");
+ } else { /* -l <sig list> */
+ while ((arg = *++argv)) {
+ if (isdigit(arg[0])) {
+ signo = xatoi_u(arg);
+ name = get_signame(signo);
+ } else {
+ signo = get_signum(arg);
+ if (signo < 0)
+ bb_error_msg_and_die("unknown signal '%s'", arg);
+ name = get_signame(signo);
+ }
+ printf("%2d) %s\n", signo, name);
+ }
+ }
+ /* If they specified -l, we are all done */
+ return EXIT_SUCCESS;
+ }
+
+ /* The -q quiet option */
+ if (killall && arg[1] == 'q' && arg[2] == '\0') {
+ quiet = 1;
+ arg = *++argv;
+ argc--;
+ if (argc < 1) bb_show_usage();
+ if (arg[0] != '-') goto do_it_now;
+ }
+
+ /* -SIG */
+ signo = get_signum(&arg[1]);
+ if (signo < 0)
+ bb_error_msg_and_die("bad signal name '%s'", &arg[1]);
+ arg = *++argv;
+ argc--;
+
+do_it_now:
+
+ if (killall5) {
+ pid_t sid;
+ procps_status_t* p = NULL;
+
+// Cannot happen anyway? We don't TERM ourself, we STOP
+// /* kill(-1, sig) on Linux (at least 2.1.x)
+// * might send signal to the calling process too */
+// signal(SIGTERM, SIG_IGN);
+ /* Now stop all processes */
+ kill(-1, SIGSTOP);
+ /* Find out our own session id */
+ pid = getpid();
+ sid = getsid(pid);
+ /* Now kill all processes except our session */
+ while ((p = procps_scan(p, PSSCAN_PID|PSSCAN_SID))) {
+ if (p->sid != sid && p->pid != pid && p->pid != 1)
+ kill(p->pid, signo);
+ }
+ /* And let them continue */
+ kill(-1, SIGCONT);
+ return 0;
+ }
+
+ /* Pid or name required for kill/killall */
+ if (argc < 1)
+ bb_show_usage();
+
+ if (killall) {
+ /* Looks like they want to do a killall. Do that */
+ pid = getpid();
+ while (arg) {
+ pid_t* pidList;
+
+ pidList = find_pid_by_name(arg);
+ if (*pidList == 0) {
+ errors++;
+ if (!quiet)
+ bb_error_msg("%s: no process killed", arg);
+ } else {
+ pid_t *pl;
+
+ for (pl = pidList; *pl; pl++) {
+ if (*pl == pid)
+ continue;
+ if (kill(*pl, signo) == 0)
+ continue;
+ errors++;
+ if (!quiet)
+ bb_perror_msg("cannot kill pid %u", (unsigned)*pl);
+ }
+ }
+ free(pidList);
+ arg = *++argv;
+ }
+ return errors;
+ }
+
+ /* Looks like they want to do a kill. Do that */
+ while (arg) {
+ /* Huh?
+ if (!isdigit(arg[0]) && arg[0] != '-')
+ bb_error_msg_and_die("bad pid '%s'", arg);
+ */
+ pid = xatou(arg);
+ /* FIXME: better overflow check? */
+ if (kill(pid, signo) != 0) {
+ bb_perror_msg("cannot kill pid %u", (unsigned)pid);
+ errors++;
+ }
+ arg = *++argv;
+ }
+ return errors;
+}
diff --git a/i/pc104/initrd/conf/busybox/procps/pidof.c b/i/pc104/initrd/conf/busybox/procps/pidof.c
new file mode 100644
index 0000000..ea2520a
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/procps/pidof.c
@@ -0,0 +1,91 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * pidof implementation for busybox
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
+ *
+ * Licensed under the GPL version 2, see the file LICENSE in this tarball.
+ */
+
+#include "busybox.h"
+
+enum {
+ USE_FEATURE_PIDOF_SINGLE(OPTBIT_SINGLE,)
+ USE_FEATURE_PIDOF_OMIT( OPTBIT_OMIT ,)
+ OPT_SINGLE = USE_FEATURE_PIDOF_SINGLE((1<<OPTBIT_SINGLE)) + 0,
+ OPT_OMIT = USE_FEATURE_PIDOF_OMIT( (1<<OPTBIT_OMIT )) + 0,
+};
+
+int pidof_main(int argc, char **argv);
+int pidof_main(int argc, char **argv)
+{
+ unsigned first = 1;
+ unsigned fail = 1;
+ unsigned opt;
+#if ENABLE_FEATURE_PIDOF_OMIT
+ llist_t *omits = NULL; /* list of pids to omit */
+ opt_complementary = "o::";
+#endif
+
+ /* do unconditional option parsing */
+ opt = getopt32(argc, argv, ""
+ USE_FEATURE_PIDOF_SINGLE ("s")
+ USE_FEATURE_PIDOF_OMIT("o:", &omits));
+
+#if ENABLE_FEATURE_PIDOF_OMIT
+ /* fill omit list. */
+ {
+ char getppid_str[sizeof(int)*3 + 1];
+ llist_t * omits_p = omits;
+ while (omits_p) {
+ /* are we asked to exclude the parent's process ID? */
+ if (!strncmp(omits_p->data, "%PPID", 5)) {
+ llist_pop(&omits_p);
+ snprintf(getppid_str, sizeof(getppid_str), "%u", (unsigned)getppid());
+ llist_add_to(&omits_p, getppid_str);
+ }
+ omits_p = omits_p->link;
+ }
+ }
+#endif
+ /* Looks like everything is set to go. */
+ while (optind < argc) {
+ pid_t *pidList;
+ pid_t *pl;
+
+ /* reverse the pidlist like GNU pidof does. */
+ pidList = pidlist_reverse(find_pid_by_name(argv[optind]));
+ for (pl = pidList; *pl; pl++) {
+ SKIP_FEATURE_PIDOF_OMIT(const) unsigned omitted = 0;
+#if ENABLE_FEATURE_PIDOF_OMIT
+ if (opt & OPT_OMIT) {
+ llist_t *omits_p = omits;
+ while (omits_p) {
+ if (xatoul(omits_p->data) == *pl) {
+ omitted = 1;
+ break;
+ } else
+ omits_p = omits_p->link;
+ }
+ }
+#endif
+ if (!omitted) {
+ printf(" %u" + first, (unsigned)*pl);
+ first = 0;
+ }
+ fail = (!ENABLE_FEATURE_PIDOF_OMIT && omitted);
+
+ if (ENABLE_FEATURE_PIDOF_SINGLE && (opt & OPT_SINGLE))
+ break;
+ }
+ free(pidList);
+ optind++;
+ }
+ putchar('\n');
+
+#if ENABLE_FEATURE_PIDOF_OMIT
+ if (ENABLE_FEATURE_CLEAN_UP)
+ llist_free(omits, NULL);
+#endif
+ return fail ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/i/pc104/initrd/conf/busybox/procps/ps.c b/i/pc104/initrd/conf/busybox/procps/ps.c
new file mode 100644
index 0000000..c1cb643
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/procps/ps.c
@@ -0,0 +1,388 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini ps implementation(s) for busybox
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
+ *
+ * Licensed under the GPL version 2, see the file LICENSE in this tarball.
+ */
+
+#include "busybox.h"
+
+#if ENABLE_DESKTOP
+
+/* Print value to buf, max size+1 chars (including trailing '\0') */
+
+static void func_user(char *buf, int size, const procps_status_t *ps)
+{
+ safe_strncpy(buf, get_cached_username(ps->uid), size+1);
+}
+
+static void func_comm(char *buf, int size, const procps_status_t *ps)
+{
+ safe_strncpy(buf, ps->comm, size+1);
+}
+
+static void func_args(char *buf, int size, const procps_status_t *ps)
+{
+ buf[0] = '\0';
+ if (ps->cmd)
+ safe_strncpy(buf, ps->cmd, size+1);
+ else if (size >= 2)
+ snprintf(buf, size+1, "[%.*s]", size-2, ps->comm);
+}
+
+static void func_pid(char *buf, int size, const procps_status_t *ps)
+{
+ snprintf(buf, size+1, "%*u", size, ps->pid);
+}
+
+static void func_ppid(char *buf, int size, const procps_status_t *ps)
+{
+ snprintf(buf, size+1, "%*u", size, ps->ppid);
+}
+
+static void func_pgid(char *buf, int size, const procps_status_t *ps)
+{
+ snprintf(buf, size+1, "%*u", size, ps->pgid);
+}
+
+static void func_vsz(char *buf, int size, const procps_status_t *ps)
+{
+ char buf5[5];
+ smart_ulltoa5( ((unsigned long long)ps->vsz) << 10, buf5);
+ snprintf(buf, size+1, "%.*s", size, buf5);
+}
+
+/*
+void func_nice(char *buf, int size, const procps_status_t *ps)
+{
+ ps->???
+}
+
+void func_etime(char *buf, int size, const procps_status_t *ps)
+{
+ elapled time [[dd-]hh:]mm:ss
+}
+
+void func_time(char *buf, int size, const procps_status_t *ps)
+{
+ cumulative time [[dd-]hh:]mm:ss
+}
+
+void func_pcpu(char *buf, int size, const procps_status_t *ps)
+{
+}
+
+void func_tty(char *buf, int size, const procps_status_t *ps)
+{
+}
+*/
+
+typedef struct {
+ char name[8];
+ const char *header;
+ void (*f)(char *buf, int size, const procps_status_t *ps);
+ int ps_flags;
+ int width;
+} ps_out_t;
+
+static const ps_out_t out_spec[] = {
+// Mandated by POSIX:
+ { "user" ,"USER" ,func_user ,PSSCAN_UIDGID,8 },
+ { "comm" ,"COMMAND",func_comm ,PSSCAN_COMM ,16 },
+ { "args" ,"COMMAND",func_args ,PSSCAN_CMD|PSSCAN_COMM,256 },
+ { "pid" ,"PID" ,func_pid ,PSSCAN_PID ,5 },
+ { "ppid" ,"PPID" ,func_ppid ,PSSCAN_PPID ,5 },
+ { "pgid" ,"PGID" ,func_pgid ,PSSCAN_PGID ,5 },
+// { "etime" ,"ELAPSED",func_etime ,PSSCAN_ ,sizeof("ELAPSED")-1 },
+// { "group" ,"GROUP" ,func_group ,PSSCAN_UIDGID,sizeof("GROUP" )-1 },
+// { "nice" ,"NI" ,func_nice ,PSSCAN_ ,sizeof("NI" )-1 },
+// { "pcpu" ,"%CPU" ,func_pcpu ,PSSCAN_ ,sizeof("%CPU" )-1 },
+// { "rgroup","RGROUP" ,func_rgroup,PSSCAN_UIDGID,sizeof("RGROUP" )-1 },
+// { "ruser" ,"RUSER" ,func_ruser ,PSSCAN_UIDGID,sizeof("RUSER" )-1 },
+// { "time" ,"TIME" ,func_time ,PSSCAN_ ,sizeof("TIME" )-1 },
+// { "tty" ,"TT" ,func_tty ,PSSCAN_ ,sizeof("TT" )-1 },
+ { "vsz" ,"VSZ" ,func_vsz ,PSSCAN_VSZ ,4 },
+// Not mandated by POSIX:
+// { "rss" ,"RSS" ,func_rss ,PSSCAN_RSS ,4 },
+};
+
+#define VEC_SIZE(v) ( sizeof(v) / sizeof((v)[0]) )
+
+static ps_out_t* out;
+static int out_cnt;
+static int print_header;
+static int ps_flags;
+static char *buffer;
+static unsigned terminal_width;
+
+
+static ps_out_t* new_out_t(void)
+{
+ int i = out_cnt++;
+ out = xrealloc(out, out_cnt * sizeof(*out));
+ return &out[i];
+}
+
+static const ps_out_t* find_out_spec(const char *name)
+{
+ int i;
+ for (i = 0; i < VEC_SIZE(out_spec); i++) {
+ if (!strcmp(name, out_spec[i].name))
+ return &out_spec[i];
+ }
+ bb_error_msg_and_die("bad -o argument '%s'", name);
+}
+
+static void parse_o(char* opt)
+{
+ ps_out_t* new;
+ // POSIX: "-o is blank- or comma-separated list" (FIXME)
+ char *comma, *equal;
+ while (1) {
+ comma = strchr(opt, ',');
+ equal = strchr(opt, '=');
+ if (comma && (!equal || equal > comma)) {
+ *comma = '\0';
+ *new_out_t() = *find_out_spec(opt);
+ *comma = ',';
+ opt = comma + 1;
+ continue;
+ }
+ break;
+ }
+ new = new_out_t();
+ if (equal)
+ *equal = '\0';
+ *new = *find_out_spec(opt);
+ if (equal) {
+ *equal = '=';
+ new->header = equal + 1;
+ // POSIX: the field widths shall be ... at least as wide as
+ // the header text (default or overridden value).
+ // If the header text is null, such as -o user=,
+ // the field width shall be at least as wide as the
+ // default header text
+ if (new->header[0]) {
+ new->width = strlen(new->header);
+ print_header = 1;
+ }
+ } else
+ print_header = 1;
+}
+
+static void post_process(void)
+{
+ int i;
+ int width = 0;
+ for (i = 0; i < out_cnt; i++) {
+ ps_flags |= out[i].ps_flags;
+ if (out[i].header[0]) {
+ print_header = 1;
+ }
+ width += out[i].width + 1; /* "FIELD " */
+ }
+ buffer = xmalloc(width + 1); /* for trailing \0 */
+}
+
+static void format_header(void)
+{
+ int i;
+ ps_out_t* op;
+ char *p = buffer;
+ if (!print_header)
+ return;
+ i = 0;
+ if (out_cnt) {
+ while (1) {
+ op = &out[i];
+ if (++i == out_cnt) /* do not pad last field */
+ break;
+ p += sprintf(p, "%-*s ", op->width, op->header);
+ }
+ strcpy(p, op->header);
+ }
+ printf("%.*s\n", terminal_width, buffer);
+}
+
+static void format_process(const procps_status_t *ps)
+{
+ int i, len;
+ char *p = buffer;
+ i = 0;
+ if (out_cnt) while (1) {
+ out[i].f(p, out[i].width, ps);
+ // POSIX: Any field need not be meaningful in all
+ // implementations. In such a case a hyphen ( '-' )
+ // should be output in place of the field value.
+ if (!p[0]) {
+ p[0] = '-';
+ p[1] = '\0';
+ }
+ len = strlen(p);
+ p += len;
+ len = out[i].width - len + 1;
+ if (++i == out_cnt) /* do not pad last field */
+ break;
+ p += sprintf(p, "%*s", len, "");
+ }
+ printf("%.*s\n", terminal_width, buffer);
+}
+
+/* Cannot be const: parse_o() will choke */
+static char default_o[] = "pid,user" /* TODO: ,vsz,stat */ ",args";
+
+int ps_main(int argc, char **argv);
+int ps_main(int argc, char **argv)
+{
+ procps_status_t *p;
+ llist_t* opt_o = NULL;
+
+ // POSIX:
+ // -a Write information for all processes associated with terminals
+ // Implementations may omit session leaders from this list
+ // -A Write information for all processes
+ // -d Write information for all processes, except session leaders
+ // -e Write information for all processes (equivalent to -A.)
+ // -f Generate a full listing
+ // -l Generate a long listing
+ // -o col1,col2,col3=header
+ // Select which columns to distplay
+ /* We allow (and ignore) most of the above. FIXME */
+ opt_complementary = "o::";
+ getopt32(argc, argv, "o:aAdefl", &opt_o);
+ if (opt_o) {
+ opt_o = llist_rev(opt_o);
+ do {
+ parse_o(opt_o->data);
+ opt_o = opt_o->link;
+ } while (opt_o);
+ } else
+ parse_o(default_o);
+ post_process();
+
+ terminal_width = INT_MAX;
+ if (isatty(1)) {
+ get_terminal_width_height(1, &terminal_width, NULL);
+ terminal_width--;
+ }
+ format_header();
+
+ p = NULL;
+ while ((p = procps_scan(p, ps_flags))) {
+ format_process(p);
+ }
+
+ return EXIT_SUCCESS;
+}
+
+
+#else /* !ENABLE_DESKTOP */
+
+
+int ps_main(int argc, char **argv);
+int ps_main(int argc, char **argv)
+{
+ procps_status_t *p = NULL;
+ int i, len;
+ SKIP_SELINUX(const) int use_selinux = 0;
+ USE_SELINUX(security_context_t sid = NULL;)
+#if !ENABLE_FEATURE_PS_WIDE
+ enum { terminal_width = 79 };
+#else
+ int terminal_width;
+ int w_count = 0;
+#endif
+
+#if ENABLE_FEATURE_PS_WIDE || ENABLE_SELINUX
+#if ENABLE_FEATURE_PS_WIDE
+ opt_complementary = "-:ww";
+ USE_SELINUX(i =) getopt32(argc, argv, USE_SELINUX("Z") "w", &w_count);
+ /* if w is given once, GNU ps sets the width to 132,
+ * if w is given more than once, it is "unlimited"
+ */
+ if (w_count) {
+ terminal_width = (w_count==1) ? 132 : INT_MAX;
+ } else {
+ get_terminal_width_height(1, &terminal_width, NULL);
+ /* Go one less... */
+ terminal_width--;
+ }
+#else /* only ENABLE_SELINUX */
+ i = getopt32(argc, argv, "Z");
+#endif
+#if ENABLE_SELINUX
+ if ((i & 1) && is_selinux_enabled())
+ use_selinux = 1;
+#endif
+#endif /* ENABLE_FEATURE_PS_WIDE || ENABLE_SELINUX */
+
+ if (use_selinux)
+ puts(" PID Context Stat Command");
+ else
+ puts(" PID Uid VSZ Stat Command");
+
+ while ((p = procps_scan(p, 0
+ | PSSCAN_PID
+ | PSSCAN_UIDGID
+ | PSSCAN_STATE
+ | PSSCAN_VSZ
+ | PSSCAN_CMD
+ ))) {
+ char *namecmd = p->cmd;
+#if ENABLE_SELINUX
+ if (use_selinux) {
+ char sbuf[128];
+ len = sizeof(sbuf);
+
+ if (is_selinux_enabled()) {
+ if (getpidcon(p->pid, &sid) < 0)
+ sid = NULL;
+ }
+
+ if (sid) {
+ /* I assume sid initialized with NULL */
+ len = strlen(sid) + 1;
+ safe_strncpy(sbuf, sid, len);
+ freecon(sid);
+ sid = NULL;
+ } else {
+ safe_strncpy(sbuf, "unknown", 7);
+ }
+ len = printf("%5u %-32s %s ", p->pid, sbuf, p->state);
+ } else
+#endif
+ {
+ const char *user = get_cached_username(p->uid);
+ if (p->vsz == 0)
+ len = printf("%5u %-8s %s ",
+ p->pid, user, p->state);
+ else
+ len = printf("%5u %-8s %6ld %s ",
+ p->pid, user, p->vsz, p->state);
+ }
+
+ i = terminal_width-len;
+
+ if (namecmd && namecmd[0]) {
+ if (i < 0)
+ i = 0;
+ if (strlen(namecmd) > (size_t)i)
+ namecmd[i] = 0;
+ puts(namecmd);
+ } else {
+ namecmd = p->comm;
+ if (i < 2)
+ i = 2;
+ if (strlen(namecmd) > ((size_t)i-2))
+ namecmd[i-2] = 0;
+ printf("[%s]\n", namecmd);
+ }
+ }
+ if (ENABLE_FEATURE_CLEAN_UP)
+ clear_username_cache();
+ return EXIT_SUCCESS;
+}
+
+#endif /* ENABLE_DESKTOP */
diff --git a/i/pc104/initrd/conf/busybox/procps/ps.posix b/i/pc104/initrd/conf/busybox/procps/ps.posix
new file mode 100644
index 0000000..57f4fa8
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/procps/ps.posix
@@ -0,0 +1,175 @@
+This is what POSIX 2003 says about ps:
+
+By default, ps shall select all processes with the same effective user
+ID as the current user and the same controlling terminal as the invoker
+
+ps [-aA][-defl][-G grouplist][-o format]...[-p proclist][-t termlist]
+[-U userlist][-g grouplist][-n namelist][-u userlist]
+
+-a Write information for all processes associated with terminals.
+ Implementations may omit session leaders from this list.
+
+-A Write information for all processes.
+
+-d Write information for all processes, except session leaders.
+
+-e Write information for all processes. (Equivalent to -A.)
+
+-f Generate a full listing. (See the STDOUT section for the con-
+ tents of a full listing.)
+
+-g grouplist
+ Write information for processes whose session leaders are given
+ in grouplist. The application shall ensure that the grouplist is
+ a single argument in the form of a <blank> or comma-separated
+ list.
+
+-G grouplist
+ Write information for processes whose real group ID numbers are
+ given in grouplist. The application shall ensure that the grou-
+ plist is a single argument in the form of a <blank> or comma-
+ separated list.
+
+-l Generate a long listing. (See STDOUT for the contents of a long
+ listing.)
+
+-n namelist
+ Specify the name of an alternative system namelist file in place
+ of the default. The name of the default file and the format of a
+ namelist file are unspecified.
+
+-o format
+ Write information according to the format specification given in
+ format. Multiple -o options can be specified; the format speci-
+ fication shall be interpreted as the <space>-separated concate-
+ nation of all the format option-arguments.
+
+-p proclist
+ Write information for processes whose process ID numbers are
+ given in proclist. The application shall ensure that the pro-
+ clist is a single argument in the form of a <blank> or comma-
+ separated list.
+
+-t termlist
+ Write information for processes associated with terminals given
+ in termlist. The application shall ensure that the termlist is a
+ single argument in the form of a <blank> or comma-separated
+ list. Terminal identifiers shall be given in an implementation-
+ defined format. On XSI-conformant systems, they shall be
+ given in one of two forms: the device's filename (for example,
+ tty04) or, if the device's filename starts with tty, just the
+ identifier following the characters tty (for example, "04" ).
+
+-u userlist
+ Write information for processes whose user ID numbers or login
+ names are given in userlist. The application shall ensure that
+ the userlist is a single argument in the form of a <blank> or
+ comma-separated list. In the listing, the numerical user ID
+ shall be written unless the -f option is used, in which case the
+ login name shall be written.
+
+-U userlist
+ Write information for processes whose real user ID numbers or
+ login names are given in userlist. The application shall ensure
+ that the userlist is a single argument in the form of a <blank>
+ or comma-separated list.
+
+With the exception of -o format, all of the options shown are used to
+select processes. If any are specified, the default list shall be
+ignored and ps shall select the processes represented by the inclusive
+OR of all the selection-criteria options.
+
+The -o option allows the output format to be specified under user con-
+trol.
+
+The application shall ensure that the format specification is a list of
+names presented as a single argument, <blank> or comma-separated. Each
+variable has a default header. The default header can be overridden by
+appending an equals sign and the new text of the header. The rest of
+the characters in the argument shall be used as the header text. The
+fields specified shall be written in the order specified on the command
+line, and should be arranged in columns in the output. The field widths
+shall be selected by the system to be at least as wide as the header
+text (default or overridden value). If the header text is null, such as
+-o user=, the field width shall be at least as wide as the default
+header text. If all header text fields are null, no header line shall
+be written.
+
+ruser The real user ID of the process. This shall be the textual user
+ ID, if it can be obtained and the field width permits, or a dec-
+ imal representation otherwise.
+
+user The effective user ID of the process. This shall be the textual
+ user ID, if it can be obtained and the field width permits, or a
+ decimal representation otherwise.
+
+rgroup The real group ID of the process. This shall be the textual
+ group ID, if it can be obtained and the field width permits, or
+ a decimal representation otherwise.
+
+group The effective group ID of the process. This shall be the textual
+ group ID, if it can be obtained and the field width permits, or
+ a decimal representation otherwise.
+
+pid The decimal value of the process ID.
+
+ppid The decimal value of the parent process ID.
+
+pgid The decimal value of the process group ID.
+
+pcpu The ratio of CPU time used recently to CPU time available in the
+ same period, expressed as a percentage. The meaning of
+ "recently" in this context is unspecified. The CPU time avail-
+ able is determined in an unspecified manner.
+
+vsz The size of the process in (virtual) memory in 1024 byte units
+ as a decimal integer.
+
+nice The decimal value of the nice value of the process; see nice() .
+
+etime In the POSIX locale, the elapsed time since the process was
+ started, in the form: [[dd-]hh:]mm:ss
+
+time In the POSIX locale, the cumulative CPU time of the process in
+ the form: [dd-]hh:mm:ss
+
+tty The name of the controlling terminal of the process (if any) in
+ the same format used by the who utility.
+
+comm The name of the command being executed ( argv[0] value) as a
+ string.
+
+args The command with all its arguments as a string. The implementa-
+ tion may truncate this value to the field width; it is implemen-
+ tation-defined whether any further truncation occurs. It is
+ unspecified whether the string represented is a version of the
+ argument list as it was passed to the command when it started,
+ or is a version of the arguments as they may have been modified
+ by the application. Applications cannot depend on being able to
+ modify their argument list and having that modification be
+ reflected in the output of ps.
+
+Any field need not be meaningful in all implementations. In such a case
+a hyphen ( '-' ) should be output in place of the field value.
+
+Only comm and args shall be allowed to contain <blank>s; all others
+shall not.
+
+The following table specifies the default header to be used in the
+POSIX locale corresponding to each format specifier.
+
+ Format Specifier Default Header Format Specifier Default Header
+ args COMMAND ppid PPID
+ comm COMMAND rgroup RGROUP
+ etime ELAPSED ruser RUSER
+ group GROUP time TIME
+ nice NI tty TT
+ pcpu %CPU user USER
+ pgid PGID vsz VSZ
+ pid PID
+
+There is no special quoting mechanism for header text. The header text
+is the rest of the argument. If multiple header changes are needed,
+multiple -o options can be used, such as:
+
+ ps -o "user=User Name" -o pid=Process\ ID
diff --git a/i/pc104/initrd/conf/busybox/procps/renice.c b/i/pc104/initrd/conf/busybox/procps/renice.c
new file mode 100644
index 0000000..2964e20
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/procps/renice.c
@@ -0,0 +1,127 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * renice implementation for busybox
+ *
+ * Copyright (C) 2005 Manuel Novoa III <mjn3@codepoet.org>
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+/* Notes:
+ * Setting an absolute priority was obsoleted in SUSv2 and removed
+ * in SUSv3. However, the common linux version of renice does
+ * absolute and not relative. So we'll continue supporting absolute,
+ * although the stdout logging has been removed since both SUSv2 and
+ * SUSv3 specify that stdout isn't used.
+ *
+ * This version is lenient in that it doesn't require any IDs. The
+ * options -p, -g, and -u are treated as mode switches for the
+ * following IDs (if any). Multiple switches are allowed.
+ */
+
+#include "busybox.h"
+#include <sys/resource.h>
+
+void BUG_bad_PRIO_PROCESS(void);
+void BUG_bad_PRIO_PGRP(void);
+void BUG_bad_PRIO_USER(void);
+
+int renice_main(int argc, char **argv);
+int renice_main(int argc, char **argv)
+{
+ static const char Xetpriority_msg[] = "%cetpriority";
+
+ int retval = EXIT_SUCCESS;
+ int which = PRIO_PROCESS; /* Default 'which' value. */
+ int use_relative = 0;
+ int adjustment, new_priority;
+ unsigned who;
+ char *arg;
+
+ /* Yes, they are not #defines in glibc 2.4! #if won't work */
+ if (PRIO_PROCESS < CHAR_MIN || PRIO_PROCESS > CHAR_MAX)
+ BUG_bad_PRIO_PROCESS();
+ if (PRIO_PGRP < CHAR_MIN || PRIO_PGRP > CHAR_MAX)
+ BUG_bad_PRIO_PGRP();
+ if (PRIO_USER < CHAR_MIN || PRIO_USER > CHAR_MAX)
+ BUG_bad_PRIO_USER();
+
+ arg = *++argv;
+
+ /* Check if we are using a relative adjustment. */
+ if (arg && arg[0] == '-' && arg[1] == 'n') {
+ use_relative = 1;
+ if (!arg[2])
+ arg = *++argv;
+ else
+ arg += 2;
+ }
+
+ if (!arg) { /* No args? Then show usage. */
+ bb_show_usage();
+ }
+
+ /* Get the priority adjustment (absolute or relative). */
+ adjustment = xatoi_range(arg, INT_MIN/2, INT_MAX/2);
+
+ while ((arg = *++argv) != NULL) {
+ /* Check for a mode switch. */
+ if (arg[0] == '-' && arg[1]) {
+ static const char opts[]
+ = { 'p', 'g', 'u', 0, PRIO_PROCESS, PRIO_PGRP, PRIO_USER };
+ const char *p = strchr(opts, arg[1]);
+ if (p) {
+ which = p[4];
+ if (!arg[2])
+ continue;
+ arg += 2;
+ }
+ }
+
+ /* Process an ID arg. */
+ if (which == PRIO_USER) {
+ struct passwd *p;
+ p = getpwnam(arg);
+ if (!p) {
+ bb_error_msg("unknown user: %s", arg);
+ goto HAD_ERROR;
+ }
+ who = p->pw_uid;
+ } else {
+ who = bb_strtou(arg, NULL, 10);
+ if (errno) {
+ bb_error_msg("bad value: %s", arg);
+ goto HAD_ERROR;
+ }
+ }
+
+ /* Get priority to use, and set it. */
+ if (use_relative) {
+ int old_priority;
+
+ errno = 0; /* Needed for getpriority error detection. */
+ old_priority = getpriority(which, who);
+ if (errno) {
+ bb_perror_msg(Xetpriority_msg, 'g');
+ goto HAD_ERROR;
+ }
+
+ new_priority = old_priority + adjustment;
+ } else {
+ new_priority = adjustment;
+ }
+
+ if (setpriority(which, who, new_priority) == 0) {
+ continue;
+ }
+
+ bb_perror_msg(Xetpriority_msg, 's');
+ HAD_ERROR:
+ retval = EXIT_FAILURE;
+ }
+
+ /* No need to check for errors outputing to stderr since, if it
+ * was used, the HAD_ERROR label was reached and retval was set. */
+
+ return retval;
+}
diff --git a/i/pc104/initrd/conf/busybox/procps/sysctl.c b/i/pc104/initrd/conf/busybox/procps/sysctl.c
new file mode 100644
index 0000000..b5a0189
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/procps/sysctl.c
@@ -0,0 +1,327 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Sysctl 1.01 - A utility to read and manipulate the sysctl parameters
+ *
+ * Copyright 1999 George Staikos
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ * Changelog:
+ * v1.01:
+ * - added -p <preload> to preload values from a file
+ * v1.01.1
+ * - busybox applet aware by <solar@gentoo.org>
+ *
+ */
+
+#include "busybox.h"
+
+/*
+ * Function Prototypes
+ */
+static int sysctl_read_setting(const char *setting, int output);
+static int sysctl_write_setting(const char *setting, int output);
+static int sysctl_preload_file(const char *filename, int output);
+static int sysctl_display_all(const char *path, int output, int show_table);
+
+/*
+ * Globals...
+ */
+static const char PROC_PATH[] = "/proc/sys/";
+static const char DEFAULT_PRELOAD[] = "/etc/sysctl.conf";
+
+/* error messages */
+static const char ERR_UNKNOWN_PARAMETER[] = "error: Unknown parameter '%s'\n";
+static const char ERR_MALFORMED_SETTING[] = "error: Malformed setting '%s'\n";
+static const char ERR_NO_EQUALS[] =
+ "error: '%s' must be of the form name=value\n";
+static const char ERR_INVALID_KEY[] = "error: '%s' is an unknown key\n";
+static const char ERR_UNKNOWN_WRITING[] =
+ "error: unknown error %d setting key '%s'\n";
+static const char ERR_UNKNOWN_READING[] =
+ "error: unknown error %d reading key '%s'\n";
+static const char ERR_PERMISSION_DENIED[] =
+ "error: permission denied on key '%s'\n";
+static const char ERR_PRELOAD_FILE[] =
+ "error: cannot open preload file '%s'\n";
+static const char WARN_BAD_LINE[] =
+ "warning: %s(%d): invalid syntax, continuing...\n";
+
+
+static void dwrite_str(int fd, const char *buf)
+{
+ write(fd, buf, strlen(buf));
+}
+
+/*
+ * sysctl_main()...
+ */
+int sysctl_main(int argc, char **argv);
+int sysctl_main(int argc, char **argv)
+{
+ int retval = 0;
+ int output = 1;
+ int write_mode = 0;
+ int switches_allowed = 1;
+
+ if (argc < 2)
+ bb_show_usage();
+
+ argv++;
+
+ for (; argv && *argv && **argv; argv++) {
+ if (switches_allowed && **argv == '-') { /* we have a switch */
+ switch ((*argv)[1]) {
+ case 'n':
+ output = 0;
+ break;
+ case 'w':
+ write_mode = 1;
+ switches_allowed = 0;
+ break;
+ case 'p':
+ argv++;
+ return
+ sysctl_preload_file(((argv && *argv
+ && **argv) ? *argv :
+ DEFAULT_PRELOAD), output);
+ case 'a':
+ case 'A':
+ switches_allowed = 0;
+ return sysctl_display_all(PROC_PATH, output,
+ ((*argv)[1] == 'a') ? 0 : 1);
+ case 'h':
+ case '?':
+ bb_show_usage();
+ default:
+ bb_error_msg(ERR_UNKNOWN_PARAMETER, *argv);
+ bb_show_usage();
+ }
+ } else {
+ switches_allowed = 0;
+ if (write_mode)
+ retval = sysctl_write_setting(*argv, output);
+ else
+ sysctl_read_setting(*argv, output);
+ }
+ }
+ return retval;
+} /* end sysctl_main() */
+
+
+
+/*
+ * sysctl_preload_file
+ * preload the sysctl's from a conf file
+ * - we parse the file and then reform it (strip out whitespace)
+ */
+#define PRELOAD_BUF 256
+
+int sysctl_preload_file(const char *filename, int output)
+{
+ int lineno = 0;
+ char oneline[PRELOAD_BUF];
+ char buffer[PRELOAD_BUF];
+ char *name, *value, *ptr;
+ FILE *fp = NULL;
+
+ if (!filename || ((fp = fopen(filename, "r")) == NULL)) {
+ bb_error_msg_and_die(ERR_PRELOAD_FILE, filename);
+ }
+
+ while (fgets(oneline, sizeof(oneline) - 1, fp)) {
+ oneline[sizeof(oneline) - 1] = '\0';
+ lineno++;
+ trim(oneline);
+ ptr = (char *) oneline;
+
+ if (*ptr == '#' || *ptr == ';')
+ continue;
+
+ if (strlen(ptr) < 2)
+ continue;
+
+ name = strtok(ptr, "=");
+ if (!name || !*name) {
+ bb_error_msg(WARN_BAD_LINE, filename, lineno);
+ continue;
+ }
+
+ trim(name);
+
+ value = strtok(NULL, "\n\r");
+ if (!value || !*value) {
+ bb_error_msg(WARN_BAD_LINE, filename, lineno);
+ continue;
+ }
+
+ while ((*value == ' ' || *value == '\t') && *value != 0)
+ value++;
+ /* safe because sizeof(oneline) == sizeof(buffer) */
+ sprintf(buffer, "%s=%s", name, value);
+ sysctl_write_setting(buffer, output);
+ }
+ fclose(fp);
+ return 0;
+} /* end sysctl_preload_file() */
+
+
+/*
+ * Write a single sysctl setting
+ */
+int sysctl_write_setting(const char *setting, int output)
+{
+ int retval = 0;
+ const char *name = setting;
+ const char *value;
+ const char *equals;
+ char *tmpname, *outname, *cptr;
+ int fd = -1;
+
+ if (!name) /* probably dont' want to display this err */
+ return 0;
+
+ if (!(equals = strchr(setting, '='))) {
+ bb_error_msg(ERR_NO_EQUALS, setting);
+ return -1;
+ }
+
+ value = equals + sizeof(char); /* point to the value in name=value */
+
+ if (!*name || !*value || name == equals) {
+ bb_error_msg(ERR_MALFORMED_SETTING, setting);
+ return -2;
+ }
+
+ tmpname = xasprintf("%s%.*s", PROC_PATH, (int)(equals - name), name);
+ outname = xstrdup(tmpname + strlen(PROC_PATH));
+
+ while ((cptr = strchr(tmpname, '.')) != NULL)
+ *cptr = '/';
+
+ while ((cptr = strchr(outname, '/')) != NULL)
+ *cptr = '.';
+
+ if ((fd = open(tmpname, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) {
+ switch (errno) {
+ case ENOENT:
+ bb_error_msg(ERR_INVALID_KEY, outname);
+ break;
+ case EACCES:
+ bb_perror_msg(ERR_PERMISSION_DENIED, outname);
+ break;
+ default:
+ bb_error_msg(ERR_UNKNOWN_WRITING, errno, outname);
+ break;
+ }
+ retval = -1;
+ } else {
+ dwrite_str(fd, value);
+ close(fd);
+ if (output) {
+ dwrite_str(STDOUT_FILENO, outname);
+ dwrite_str(STDOUT_FILENO, " = ");
+ }
+ dwrite_str(STDOUT_FILENO, value);
+ dwrite_str(STDOUT_FILENO, "\n");
+ }
+
+ /* cleanup */
+ free(tmpname);
+ free(outname);
+ return retval;
+} /* end sysctl_write_setting() */
+
+
+/*
+ * Read a sysctl setting
+ *
+ */
+int sysctl_read_setting(const char *setting, int output)
+{
+ int retval = 0;
+ char *tmpname, *outname, *cptr;
+ char inbuf[1025];
+ const char *name = setting;
+ FILE *fp;
+
+ if (!setting || !*setting)
+ bb_error_msg(ERR_INVALID_KEY, setting);
+
+ tmpname = concat_path_file(PROC_PATH, name);
+ outname = xstrdup(tmpname + strlen(PROC_PATH));
+
+ while ((cptr = strchr(tmpname, '.')) != NULL)
+ *cptr = '/';
+ while ((cptr = strchr(outname, '/')) != NULL)
+ *cptr = '.';
+
+ if ((fp = fopen(tmpname, "r")) == NULL) {
+ switch (errno) {
+ case ENOENT:
+ bb_error_msg(ERR_INVALID_KEY, outname);
+ break;
+ case EACCES:
+ bb_error_msg(ERR_PERMISSION_DENIED, outname);
+ break;
+ default:
+ bb_error_msg(ERR_UNKNOWN_READING, errno, outname);
+ break;
+ }
+ retval = -1;
+ } else {
+ while (fgets(inbuf, sizeof(inbuf) - 1, fp)) {
+ if (output) {
+ dwrite_str(STDOUT_FILENO, outname);
+ dwrite_str(STDOUT_FILENO, " = ");
+ }
+ dwrite_str(STDOUT_FILENO, inbuf);
+ }
+ fclose(fp);
+ }
+
+ free(tmpname);
+ free(outname);
+ return retval;
+} /* end sysctl_read_setting() */
+
+
+
+/*
+ * Display all the sysctl settings
+ *
+ */
+int sysctl_display_all(const char *path, int output, int show_table)
+{
+ int retval = 0;
+ int retval2;
+ DIR *dp;
+ struct dirent *de;
+ char *tmpdir;
+ struct stat ts;
+
+ if (!(dp = opendir(path))) {
+ retval = -1;
+ } else {
+ while ((de = readdir(dp)) != NULL) {
+ tmpdir = concat_subpath_file(path, de->d_name);
+ if(tmpdir == NULL)
+ continue;
+ if ((retval2 = stat(tmpdir, &ts)) != 0)
+ bb_perror_msg(tmpdir);
+ else {
+ if (S_ISDIR(ts.st_mode)) {
+ sysctl_display_all(tmpdir, output, show_table);
+ } else
+ retval |=
+ sysctl_read_setting(tmpdir + strlen(PROC_PATH),
+ output);
+
+ }
+ free(tmpdir);
+ } /* end while */
+ closedir(dp);
+ }
+
+ return retval;
+} /* end sysctl_display_all() */
diff --git a/i/pc104/initrd/conf/busybox/procps/top.c b/i/pc104/initrd/conf/busybox/procps/top.c
new file mode 100644
index 0000000..ee6ee5d
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/procps/top.c
@@ -0,0 +1,570 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * A tiny 'top' utility.
+ *
+ * This is written specifically for the linux /proc/<PID>/stat(m)
+ * files format.
+
+ * This reads the PIDs of all processes and their status and shows
+ * the status of processes (first ones that fit to screen) at given
+ * intervals.
+ *
+ * NOTES:
+ * - At startup this changes to /proc, all the reads are then
+ * relative to that.
+ *
+ * (C) Eero Tamminen <oak at welho dot com>
+ *
+ * Rewritten by Vladimir Oleynik (C) 2002 <dzo@simtreas.ru>
+ */
+
+/* Original code Copyrights */
+/*
+ * Copyright (c) 1992 Branko Lankester
+ * Copyright (c) 1992 Roger Binns
+ * Copyright (C) 1994-1996 Charles L. Blake.
+ * Copyright (C) 1992-1998 Michael K. Johnson
+ * May be distributed under the conditions of the
+ * GNU Library General Public License
+ */
+
+#include "busybox.h"
+
+
+typedef struct {
+ unsigned long vsz;
+#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+ unsigned long ticks;
+ unsigned pcpu; /* delta of ticks */
+#endif
+ unsigned pid, ppid;
+ unsigned uid;
+ char state[4];
+ char comm[COMM_LEN];
+} top_status_t;
+static top_status_t *top;
+static int ntop;
+/* This structure stores some critical information from one frame to
+ the next. Used for finding deltas. */
+struct save_hist {
+ unsigned long ticks;
+ unsigned pid;
+};
+#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+static struct save_hist *prev_hist;
+static int prev_hist_count;
+/* static int hist_iterations; */
+static unsigned total_pcpu;
+/* static unsigned long total_vsz; */
+#endif
+
+#define OPT_BATCH_MODE (option_mask32 & 0x4)
+
+#if ENABLE_FEATURE_USE_TERMIOS
+static int pid_sort(top_status_t *P, top_status_t *Q)
+{
+ /* Buggy wrt pids with high bit set */
+ /* (linux pids are in [1..2^15-1]) */
+ return (Q->pid - P->pid);
+}
+#endif
+
+static int mem_sort(top_status_t *P, top_status_t *Q)
+{
+ /* We want to avoid unsigned->signed and truncation errors */
+ if (Q->vsz < P->vsz) return -1;
+ return Q->vsz != P->vsz; /* 0 if ==, 1 if > */
+}
+
+
+typedef int (*cmp_funcp)(top_status_t *P, top_status_t *Q);
+
+#if !ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+
+static cmp_funcp sort_function;
+
+#else
+
+enum { SORT_DEPTH = 3 };
+
+static cmp_funcp sort_function[SORT_DEPTH];
+
+static int pcpu_sort(top_status_t *P, top_status_t *Q)
+{
+ /* Buggy wrt ticks with high bit set */
+ /* Affects only processes for which ticks overflow */
+ return (int)Q->pcpu - (int)P->pcpu;
+}
+
+static int time_sort(top_status_t *P, top_status_t *Q)
+{
+ /* We want to avoid unsigned->signed and truncation errors */
+ if (Q->ticks < P->ticks) return -1;
+ return Q->ticks != P->ticks; /* 0 if ==, 1 if > */
+}
+
+static int mult_lvl_cmp(void* a, void* b) {
+ int i, cmp_val;
+
+ for (i = 0; i < SORT_DEPTH; i++) {
+ cmp_val = (*sort_function[i])(a, b);
+ if (cmp_val != 0)
+ return cmp_val;
+ }
+ return 0;
+}
+
+
+typedef struct {
+ unsigned long long usr,nic,sys,idle,iowait,irq,softirq,steal;
+ unsigned long long total;
+ unsigned long long busy;
+} jiffy_counts_t;
+static jiffy_counts_t jif, prev_jif;
+static void get_jiffy_counts(void)
+{
+ FILE* fp = xfopen("stat", "r");
+ prev_jif = jif;
+ if (fscanf(fp, "cpu %lld %lld %lld %lld %lld %lld %lld %lld",
+ &jif.usr,&jif.nic,&jif.sys,&jif.idle,
+ &jif.iowait,&jif.irq,&jif.softirq,&jif.steal) < 4) {
+ bb_error_msg_and_die("failed to read /proc/stat");
+ }
+ fclose(fp);
+ jif.total = jif.usr + jif.nic + jif.sys + jif.idle
+ + jif.iowait + jif.irq + jif.softirq + jif.steal;
+ /* procps 2.x does not count iowait as busy time */
+ jif.busy = jif.total - jif.idle - jif.iowait;
+}
+
+
+static void do_stats(void)
+{
+ top_status_t *cur;
+ pid_t pid;
+ int i, last_i, n;
+ struct save_hist *new_hist;
+
+ get_jiffy_counts();
+ total_pcpu = 0;
+ /* total_vsz = 0; */
+ new_hist = xmalloc(sizeof(struct save_hist)*ntop);
+ /*
+ * Make a pass through the data to get stats.
+ */
+ /* hist_iterations = 0; */
+ i = 0;
+ for (n = 0; n < ntop; n++) {
+ cur = top + n;
+
+ /*
+ * Calculate time in cur process. Time is sum of user time
+ * and system time
+ */
+ pid = cur->pid;
+ new_hist[n].ticks = cur->ticks;
+ new_hist[n].pid = pid;
+
+ /* find matching entry from previous pass */
+ cur->pcpu = 0;
+ /* do not start at index 0, continue at last used one
+ * (brought hist_iterations from ~14000 down to 172) */
+ last_i = i;
+ if (prev_hist_count) do {
+ if (prev_hist[i].pid == pid) {
+ cur->pcpu = cur->ticks - prev_hist[i].ticks;
+ total_pcpu += cur->pcpu;
+ break;
+ }
+ i = (i+1) % prev_hist_count;
+ /* hist_iterations++; */
+ } while (i != last_i);
+ /* total_vsz += cur->vsz; */
+ }
+
+ /*
+ * Save cur frame's information.
+ */
+ free(prev_hist);
+ prev_hist = new_hist;
+ prev_hist_count = ntop;
+}
+#endif /* FEATURE_TOP_CPU_USAGE_PERCENTAGE */
+
+
+/* display generic info (meminfo / loadavg) */
+static unsigned long display_generic(int scr_width)
+{
+ FILE *fp;
+ char buf[80];
+ char scrbuf[80];
+ char *end;
+ unsigned long total, used, mfree, shared, buffers, cached;
+ unsigned int needs_conversion = 1;
+
+ /* read memory info */
+ fp = xfopen("meminfo", "r");
+
+ /*
+ * Old kernels (such as 2.4.x) had a nice summary of memory info that
+ * we could parse, however this is gone entirely in 2.6. Try parsing
+ * the old way first, and if that fails, parse each field manually.
+ *
+ * First, we read in the first line. Old kernels will have bogus
+ * strings we don't care about, whereas new kernels will start right
+ * out with MemTotal:
+ * -- PFM.
+ */
+ if (fscanf(fp, "MemTotal: %lu %s\n", &total, buf) != 2) {
+ fgets(buf, sizeof(buf), fp); /* skip first line */
+
+ fscanf(fp, "Mem: %lu %lu %lu %lu %lu %lu",
+ &total, &used, &mfree, &shared, &buffers, &cached);
+ } else {
+ /*
+ * Revert to manual parsing, which incidentally already has the
+ * sizes in kilobytes. This should be safe for both 2.4 and
+ * 2.6.
+ */
+ needs_conversion = 0;
+
+ fscanf(fp, "MemFree: %lu %s\n", &mfree, buf);
+
+ /*
+ * MemShared: is no longer present in 2.6. Report this as 0,
+ * to maintain consistent behavior with normal procps.
+ */
+ if (fscanf(fp, "MemShared: %lu %s\n", &shared, buf) != 2)
+ shared = 0;
+
+ fscanf(fp, "Buffers: %lu %s\n", &buffers, buf);
+ fscanf(fp, "Cached: %lu %s\n", &cached, buf);
+
+ used = total - mfree;
+ }
+ fclose(fp);
+
+ /* read load average as a string */
+ buf[0] = '\0';
+ open_read_close("loadavg", buf, sizeof(buf));
+ end = strchr(buf, ' ');
+ if (end) end = strchr(end+1, ' ');
+ if (end) end = strchr(end+1, ' ');
+ if (end) *end = '\0';
+
+ if (needs_conversion) {
+ /* convert to kilobytes */
+ used /= 1024;
+ mfree /= 1024;
+ shared /= 1024;
+ buffers /= 1024;
+ cached /= 1024;
+ total /= 1024;
+ }
+
+ /* output memory info and load average */
+ /* clear screen & go to top */
+ if (scr_width > sizeof(scrbuf))
+ scr_width = sizeof(scrbuf);
+ snprintf(scrbuf, scr_width,
+ "Mem: %ldK used, %ldK free, %ldK shrd, %ldK buff, %ldK cached",
+ used, mfree, shared, buffers, cached);
+
+ printf(OPT_BATCH_MODE ? "%s\n" : "\e[H\e[J%s\n", scrbuf);
+
+ snprintf(scrbuf, scr_width, "Load average: %s", buf);
+ printf("%s\n", scrbuf);
+
+ return total;
+}
+
+
+/* display process statuses */
+static void display_status(int count, int scr_width)
+{
+ enum {
+ bits_per_int = sizeof(int)*8
+ };
+
+ top_status_t *s = top;
+ char vsz_str_buf[8];
+ unsigned long total_memory = display_generic(scr_width); /* or use total_vsz? */
+ unsigned pmem_shift, pmem_scale;
+
+#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+ unsigned pcpu_shift, pcpu_scale;
+ unsigned busy_jifs;
+
+ /* what info of the processes is shown */
+ printf(OPT_BATCH_MODE ? "%.*s" : "\e[7m%.*s\e[0m", scr_width,
+ " PID USER STATUS VSZ PPID %CPU %MEM COMMAND");
+#define MIN_WIDTH \
+ sizeof( " PID USER STATUS VSZ PPID %CPU %MEM C")
+#else
+ printf(OPT_BATCH_MODE ? "%.*s" : "\e[7m%.*s\e[0m", scr_width,
+ " PID USER STATUS VSZ PPID %MEM COMMAND");
+#define MIN_WIDTH \
+ sizeof( " PID USER STATUS VSZ PPID %MEM C")
+#endif
+
+ /*
+ * MEM% = s->vsz/MemTotal
+ */
+ pmem_shift = bits_per_int-11;
+ pmem_scale = 1000*(1U<<(bits_per_int-11)) / total_memory;
+ /* s->vsz is in kb. we want (s->vsz * pmem_scale) to never overflow */
+ while (pmem_scale >= 512) {
+ pmem_scale /= 4;
+ pmem_shift -= 2;
+ }
+#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+ busy_jifs = jif.busy - prev_jif.busy;
+ /* This happens if there were lots of short-lived processes
+ * between two top updates (e.g. compilation) */
+ if (total_pcpu < busy_jifs) total_pcpu = busy_jifs;
+
+ /*
+ * CPU% = s->pcpu/sum(s->pcpu) * busy_cpu_ticks/total_cpu_ticks
+ * (pcpu is delta of sys+user time between samples)
+ */
+ /* (jif.xxx - prev_jif.xxx) and s->pcpu are
+ * in 0..~64000 range (HZ*update_interval).
+ * we assume that unsigned is at least 32-bit.
+ */
+ pcpu_shift = 6;
+ pcpu_scale = (1000*64*(uint16_t)busy_jifs ? : 1);
+ while (pcpu_scale < (1U<<(bits_per_int-2))) {
+ pcpu_scale *= 4;
+ pcpu_shift += 2;
+ }
+ pcpu_scale /= ( (uint16_t)(jif.total-prev_jif.total)*total_pcpu ? : 1);
+ /* we want (s->pcpu * pcpu_scale) to never overflow */
+ while (pcpu_scale >= 1024) {
+ pcpu_scale /= 4;
+ pcpu_shift -= 2;
+ }
+ /* printf(" pmem_scale=%u pcpu_scale=%u ", pmem_scale, pcpu_scale); */
+#endif
+ while (count-- > 0) {
+ div_t pmem = div((s->vsz*pmem_scale) >> pmem_shift, 10);
+ int col = scr_width+1;
+ USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE(div_t pcpu;)
+
+ if (s->vsz >= 100*1024)
+ sprintf(vsz_str_buf, "%6ldM", s->vsz/1024);
+ else
+ sprintf(vsz_str_buf, "%7ld", s->vsz);
+ USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE(
+ pcpu = div((s->pcpu*pcpu_scale) >> pcpu_shift, 10);
+ )
+ col -= printf("\n%5u %-8s %s "
+ "%s%6u"
+ USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE("%3u.%c")
+ "%3u.%c ",
+ s->pid, get_cached_username(s->uid), s->state,
+ vsz_str_buf, s->ppid,
+ USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE(pcpu.quot, '0'+pcpu.rem,)
+ pmem.quot, '0'+pmem.rem);
+ if (col > 0)
+ printf("%.*s", col, s->comm);
+ /* printf(" %d/%d %lld/%lld", s->pcpu, total_pcpu,
+ jif.busy - prev_jif.busy, jif.total - prev_jif.total); */
+ s++;
+ }
+ /* printf(" %d", hist_iterations); */
+ putchar(OPT_BATCH_MODE ? '\n' : '\r');
+ fflush(stdout);
+}
+
+
+static void clearmems(void)
+{
+ clear_username_cache();
+ free(top);
+ top = 0;
+ ntop = 0;
+}
+
+
+#if ENABLE_FEATURE_USE_TERMIOS
+#include <termios.h>
+#include <signal.h>
+
+static struct termios initial_settings;
+
+static void reset_term(void)
+{
+ tcsetattr(0, TCSANOW, (void *) &initial_settings);
+#if ENABLE_FEATURE_CLEAN_UP
+ clearmems();
+#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+ free(prev_hist);
+#endif
+#endif /* FEATURE_CLEAN_UP */
+}
+
+static void sig_catcher(int sig ATTRIBUTE_UNUSED)
+{
+ reset_term();
+ exit(1);
+}
+#endif /* FEATURE_USE_TERMIOS */
+
+
+int top_main(int argc, char **argv);
+int top_main(int argc, char **argv)
+{
+ int count, lines, col;
+ unsigned interval = 5; /* default update rate is 5 seconds */
+ unsigned iterations = UINT_MAX; /* 2^32 iterations by default :) */
+ char *sinterval, *siterations;
+#if ENABLE_FEATURE_USE_TERMIOS
+ struct termios new_settings;
+ struct timeval tv;
+ fd_set readfds;
+ unsigned char c;
+#endif /* FEATURE_USE_TERMIOS */
+
+ /* do normal option parsing */
+ interval = 5;
+ opt_complementary = "-";
+ getopt32(argc, argv, "d:n:b", &sinterval, &siterations);
+ if (option_mask32 & 0x1) interval = xatou(sinterval); // -d
+ if (option_mask32 & 0x2) iterations = xatou(siterations); // -n
+ //if (option_mask32 & 0x4) // -b
+
+ /* change to /proc */
+ xchdir("/proc");
+#if ENABLE_FEATURE_USE_TERMIOS
+ tcgetattr(0, (void *) &initial_settings);
+ memcpy(&new_settings, &initial_settings, sizeof(struct termios));
+ /* unbuffered input, turn off echo */
+ new_settings.c_lflag &= ~(ISIG | ICANON | ECHO | ECHONL);
+
+ signal(SIGTERM, sig_catcher);
+ signal(SIGINT, sig_catcher);
+ tcsetattr(0, TCSANOW, (void *) &new_settings);
+ atexit(reset_term);
+#endif /* FEATURE_USE_TERMIOS */
+
+#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+ sort_function[0] = pcpu_sort;
+ sort_function[1] = mem_sort;
+ sort_function[2] = time_sort;
+#else
+ sort_function = mem_sort;
+#endif /* FEATURE_TOP_CPU_USAGE_PERCENTAGE */
+
+ while (1) {
+ procps_status_t *p = NULL;
+
+ /* Default to 25 lines - 5 lines for status */
+ lines = 24 - 3;
+ col = 79;
+#if ENABLE_FEATURE_USE_TERMIOS
+ get_terminal_width_height(0, &col, &lines);
+ if (lines < 5 || col < MIN_WIDTH) {
+ sleep(interval);
+ continue;
+ }
+ lines -= 3;
+#endif /* FEATURE_USE_TERMIOS */
+
+ /* read process IDs & status for all the processes */
+ while ((p = procps_scan(p, 0
+ | PSSCAN_PID
+ | PSSCAN_PPID
+ | PSSCAN_VSZ
+ | PSSCAN_STIME
+ | PSSCAN_UTIME
+ | PSSCAN_STATE
+ | PSSCAN_COMM
+ | PSSCAN_SID
+ | PSSCAN_UIDGID
+ ))) {
+ int n = ntop;
+ top = xrealloc(top, (++ntop)*sizeof(top_status_t));
+ top[n].pid = p->pid;
+ top[n].ppid = p->ppid;
+ top[n].vsz = p->vsz;
+#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+ top[n].ticks = p->stime + p->utime;
+#endif
+ top[n].uid = p->uid;
+ strcpy(top[n].state, p->state);
+ strcpy(top[n].comm, p->comm);
+ }
+ if (ntop == 0) {
+ bb_error_msg_and_die("can't find process info in /proc");
+ }
+#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+ if (!prev_hist_count) {
+ do_stats();
+ sleep(1);
+ clearmems();
+ continue;
+ }
+ do_stats();
+ qsort(top, ntop, sizeof(top_status_t), (void*)mult_lvl_cmp);
+#else
+ qsort(top, ntop, sizeof(top_status_t), (void*)sort_function);
+#endif /* FEATURE_TOP_CPU_USAGE_PERCENTAGE */
+ count = lines;
+ if (OPT_BATCH_MODE || count > ntop) {
+ count = ntop;
+ }
+ /* show status for each of the processes */
+ display_status(count, col);
+#if ENABLE_FEATURE_USE_TERMIOS
+ tv.tv_sec = interval;
+ tv.tv_usec = 0;
+ FD_ZERO(&readfds);
+ FD_SET(0, &readfds);
+ select(1, &readfds, NULL, NULL, &tv);
+ if (FD_ISSET(0, &readfds)) {
+ if (read(0, &c, 1) <= 0) { /* signal */
+ return EXIT_FAILURE;
+ }
+ if (c == 'q' || c == initial_settings.c_cc[VINTR])
+ break;
+ if (c == 'M') {
+#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+ sort_function[0] = mem_sort;
+ sort_function[1] = pcpu_sort;
+ sort_function[2] = time_sort;
+#else
+ sort_function = mem_sort;
+#endif
+ }
+#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+ if (c == 'P') {
+ sort_function[0] = pcpu_sort;
+ sort_function[1] = mem_sort;
+ sort_function[2] = time_sort;
+ }
+ if (c == 'T') {
+ sort_function[0] = time_sort;
+ sort_function[1] = mem_sort;
+ sort_function[2] = pcpu_sort;
+ }
+#endif
+ if (c == 'N') {
+#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+ sort_function[0] = pid_sort;
+#else
+ sort_function = pid_sort;
+#endif
+ }
+ }
+ if (!--iterations)
+ break;
+#else
+ sleep(interval);
+#endif /* FEATURE_USE_TERMIOS */
+ clearmems();
+ }
+ if (ENABLE_FEATURE_CLEAN_UP)
+ clearmems();
+ putchar('\n');
+ return EXIT_SUCCESS;
+}
diff --git a/i/pc104/initrd/conf/busybox/procps/uptime.c b/i/pc104/initrd/conf/busybox/procps/uptime.c
new file mode 100644
index 0000000..3573ffe
--- /dev/null
+++ b/i/pc104/initrd/conf/busybox/procps/uptime.c
@@ -0,0 +1,60 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini uptime implementation for busybox
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
+ *
+ * Licensed under the GPL version 2, see the file LICENSE in this tarball.
+ */
+
+/* This version of uptime doesn't display the number of users on the system,
+ * since busybox init doesn't mess with utmp. For folks using utmp that are
+ * just dying to have # of users reported, feel free to write it as some type
+ * of CONFIG_FEATURE_UTMP_SUPPORT #define
+ */
+
+/* getopt not needed */
+
+#include "busybox.h"
+
+#ifndef FSHIFT
+# define FSHIFT 16 /* nr of bits of precision */
+#endif
+#define FIXED_1 (1<<FSHIFT) /* 1.0 as fixed-point */
+#define LOAD_INT(x) ((x) >> FSHIFT)
+#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
+
+
+int uptime_main(int argc, char **argv);
+int uptime_main(int argc, char **argv)
+{
+ int updays, uphours, upminutes;
+ struct sysinfo info;
+ struct tm *current_time;
+ time_t current_secs;
+
+ time(&current_secs);
+ current_time = localtime(&current_secs);
+
+ sysinfo(&info);
+
+ printf(" %02d:%02d:%02d up ",
+ current_time->tm_hour, current_time->tm_min, current_time->tm_sec);
+ updays = (int) info.uptime / (60*60*24);
+ if (updays)
+ printf("%d day%s, ", updays, (updays != 1) ? "s" : "");
+ upminutes = (int) info.uptime / 60;
+ uphours = (upminutes / 60) % 24;
+ upminutes %= 60;
+ if(uphours)
+ printf("%2d:%02d, ", uphours, upminutes);
+ else
+ printf("%d min, ", upminutes);
+
+ printf("load average: %ld.%02ld, %ld.%02ld, %ld.%02ld\n",
+ LOAD_INT(info.loads[0]), LOAD_FRAC(info.loads[0]),
+ LOAD_INT(info.loads[1]), LOAD_FRAC(info.loads[1]),
+ LOAD_INT(info.loads[2]), LOAD_FRAC(info.loads[2]));
+
+ return EXIT_SUCCESS;
+}