From 5e1a84ab74d5e97582427f016f291a8c11e66f99 Mon Sep 17 00:00:00 2001 From: jutteau Date: Fri, 11 May 2007 18:10:19 +0000 Subject: Completion du script de mise à jour de la pc-104 : * Ajout des sources de busybox dans ./conf/busybox/ * Ajout d'un fichier réclamé par les script dans ./conf/busybox.links --- i/pc104/initrd/conf/busybox/procps/Config.in | 121 ++++++ i/pc104/initrd/conf/busybox/procps/Kbuild | 16 + i/pc104/initrd/conf/busybox/procps/free.c | 69 ++++ i/pc104/initrd/conf/busybox/procps/fuser.c | 368 +++++++++++++++++ i/pc104/initrd/conf/busybox/procps/kill.c | 156 ++++++++ i/pc104/initrd/conf/busybox/procps/pidof.c | 91 +++++ i/pc104/initrd/conf/busybox/procps/ps.c | 388 ++++++++++++++++++ i/pc104/initrd/conf/busybox/procps/ps.posix | 175 ++++++++ i/pc104/initrd/conf/busybox/procps/renice.c | 127 ++++++ i/pc104/initrd/conf/busybox/procps/sysctl.c | 327 +++++++++++++++ i/pc104/initrd/conf/busybox/procps/top.c | 570 +++++++++++++++++++++++++++ i/pc104/initrd/conf/busybox/procps/uptime.c | 60 +++ 12 files changed, 2468 insertions(+) create mode 100644 i/pc104/initrd/conf/busybox/procps/Config.in create mode 100644 i/pc104/initrd/conf/busybox/procps/Kbuild create mode 100644 i/pc104/initrd/conf/busybox/procps/free.c create mode 100644 i/pc104/initrd/conf/busybox/procps/fuser.c create mode 100644 i/pc104/initrd/conf/busybox/procps/kill.c create mode 100644 i/pc104/initrd/conf/busybox/procps/pidof.c create mode 100644 i/pc104/initrd/conf/busybox/procps/ps.c create mode 100644 i/pc104/initrd/conf/busybox/procps/ps.posix create mode 100644 i/pc104/initrd/conf/busybox/procps/renice.c create mode 100644 i/pc104/initrd/conf/busybox/procps/sysctl.c create mode 100644 i/pc104/initrd/conf/busybox/procps/top.c create mode 100644 i/pc104/initrd/conf/busybox/procps/uptime.c (limited to 'i/pc104/initrd/conf/busybox/procps') 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 +# +# 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 + * + * 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 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;ipid == 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 . + * Copyright (C) 1999-2004 by Erik Andersen + * + * 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 */ + 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 + * + * 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<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 + * + * 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 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 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 -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 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 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 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 + 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, 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 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 + * + * 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 + +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 to preload values from a file + * v1.01.1 + * - busybox applet aware by + * + */ + +#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//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 + * + * Rewritten by Vladimir Oleynik (C) 2002 + */ + +/* 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 +#include + +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 + * + * 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) +#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(¤t_secs); + current_time = localtime(¤t_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; +} -- cgit v1.2.3