diff --git a/.cvsignore b/.cvsignore index 71269c542..618c9fd84 100644 --- a/.cvsignore +++ b/.cvsignore @@ -2,3 +2,4 @@ busybox busybox.links _install applet_source_list +.config diff --git a/AUTHORS b/AUTHORS index 09b0b5095..4df213aa0 100644 --- a/AUTHORS +++ b/AUTHORS @@ -8,7 +8,7 @@ incorect, _please_ let me know. ----------- -Erik Andersen , +Erik Andersen , Tons of new stuff, major rewrite of most of the core apps, tons of new apps as noted in header files. diff --git a/Changelog b/Changelog index 9ed6d58ce..2a778d65d 100644 --- a/Changelog +++ b/Changelog @@ -52,8 +52,8 @@ -- Fixed msh to support underscores in variable names. -- Fixed a sed problem with unsatisfied backrefs (the problem was noted by Martin Bene). - -- Removed BB_SH define entirely. Now one simply picks the shell - or shells they want as BB_ in Config.h + -- Removed CONFIG_SH define entirely. Now one simply picks the shell + or shells they want as CONFIG_ in Config.h -- Fixed head to use ferror(3) to check for errors, not errno. * Shu-Hao Chang -- Fixed sed handling of multiple -e commands @@ -62,10 +62,10 @@ * Jaspreet Singh -- Fixed both a segfault and cosmetic bug in route * Erik Andersen - -- Made the insmod options BB_FEATURE_NEW_MODULE_INTERFACE and - BB_FEATURE_OLD_MODULE_INTERFACE mutually exclusive + -- Made the insmod options CONFIG_FEATURE_NEW_MODULE_INTERFACE and + CONFIG_FEATURE_OLD_MODULE_INTERFACE mutually exclusive -- xgetcwd.c now includes sys/param.h to ensure PATH_MAX is defined - -- Fixed a potential segfault with lash + BB_FEATURE_CLEAN_UP + -- Fixed a potential segfault with lash + CONFIG_FEATURE_CLEAN_UP -- Removed uint64_t from dos2unix, avoiding C lib compat. problems. * Glenn McGrath -- Rewrite of tftp (commands match atftp, accepts -b, can use @@ -136,7 +136,7 @@ * Matt Kraai -- Made tar read 20 512byte blocks at a time (like GNU tar) -- Allow msh.c assignments with the export and readonly commands. - -- Added BB_FEATURE_DEVFS to enable devfs device names. + -- Added CONFIG_FEATURE_DEVFS to enable devfs device names. -- Better devfs support -- Don't save/restore vi readonly flag if vi is compiled read-only. -- Reworked rdate option handling (is now smaller). @@ -317,7 +317,7 @@ * Magnus Damm -- added a tftp applet * Magnus Damm -- powerpc support for busybox insmod. * David Douthitt -- fixed a build error in df.c when - BB_FEATURE_HUMAN_READABLE was disabled + CONFIG_FEATURE_HUMAN_READABLE was disabled * John Beppu -- wrote autodocifier.pl, which will be used to auto- generate the documentation from the source code, making life much simpler for all. @@ -424,7 +424,7 @@ * Mark Whitley -- Updates to style guide * Mark Whitley -- Big cleanup in utility.c: style guide compliance, de-macro-ifying some variables and functions - * Erik Andersen -- ls now honors BB_FEATURE_AUTOWIDTH so it can find + * Erik Andersen -- ls now honors CONFIG_FEATURE_AUTOWIDTH so it can find the width and height of the console. * Erik Andersen -- insmod now ignores -L and accepts the -o option. * Erik Andersen -- updates so you can now select from the Makefile @@ -440,7 +440,7 @@ 0.48 * Glenn McGrath -- tar now supports uncompressing tar files, - define BB_FEATURE_TAR_GZIP to use the -z option. + define CONFIG_FEATURE_TAR_GZIP to use the -z option. * Matt Kraai -- fix all usage of TRUE and FALSE so all apps now return EXIT_SUCCESS or EXIT_FAILURE to the system. Now TRUE and FALSE are set to the C standard where TRUE=1. @@ -472,7 +472,7 @@ GNU-date compatible * me -- Progress meter (optional) in wget * Doolittle/me -- programs invoked by full path name take - precedence over applets unless BB_FEATURE_SH_BUILTINS_ALWAYS_WIN + precedence over applets unless CONFIG_FEATURE_SH_BUILTINS_ALWAYS_WIN * Gaute B Strokkenes -- applets found using a binary search instead of linear search. Much faster! * new applets: cmp readlink @@ -605,7 +605,7 @@ 0.45 * Now compiles vs libc5 (which can save lots of space for embedded systems). - * Added BB_FEATURE_TRIVIAL_HELP which compiles out most all of the + * Added CONFIG_FEATURE_TRIVIAL_HELP which compiles out most all of the help messages (i.e --help). Saves 17k over a full compile. * Added cut and tr from minix, since due to the license change, we can now use minix code. Minix tr saves 4k. @@ -626,7 +626,7 @@ * Replaced the telnet implementation with one written by Tomi Ollila It works great and costs 3k. * BusyBox sh (lash) now supports being used as a standalone shell. When - BB_FEATURE_SH_STANDALONE_SHELL is defined, all the busybox commands may + CONFIG_FEATURE_SH_STANDALONE_SHELL is defined, all the busybox commands may be invoked as shell internals. Best used when compiling staticly (i.e. DOSTATIC=true) * BusyBox sh (lash) internals now behave as expected wrt pipes @@ -678,7 +678,7 @@ * Fixed exit status for killall - Pavel Roskin * Fixed 'swapon -a' and 'swapoff -a', which were broken. * Fixed 'mount -a' so it works as expected. - * Implemented 'ls -R' (enabled by enabling BB_FEATURE_LS_RECURSIVE) + * Implemented 'ls -R' (enabled by enabling CONFIG_FEATURE_LS_RECURSIVE) * Implemented "ping -s", fixed error messages and argument parsing - Pavel Roskin * Syslogd will not go to background if "-n" is given. Better help @@ -716,7 +716,7 @@ saving a bunch of memory (kernel /proc support is not thin). This is done by making use of some nice kernel patches I wrote up to support the features that busybox requires and that /proc usually - provides. To enable this, turn on BB_FEATURE_USE_DEVPS_PATCH and + provides. To enable this, turn on CONFIG_FEATURE_USE_DEVPS_PATCH and patch your kernel with the devps patch in the kernel-patches/ directory. * Wrote basename, dirname, killall, and uptime. @@ -761,7 +761,7 @@ * An initial telnet implementation was added by Randolph Chung . * Fixed a bug where "sed 's/foo/bar/g'" (i.e. a script w/o a "-e") - * ps now supports BB_FEATURE_AUTOWIDTH, and can adjust its width + * ps now supports CONFIG_FEATURE_AUTOWIDTH, and can adjust its width to match the terminal (defaults to width=79 when this is off). * ps now accepts (and ignores) all options except for "--help" (which as would be expected displays help). @@ -784,7 +784,7 @@ * Fairly massive restructuring of umount.c to deal with remounting busy devices read-only. Adds a -r option to control that; it is - optionally compiled in with BB_FEATURE_REMOUNT + optionally compiled in with CONFIG_FEATURE_REMOUNT * Added a bunch of functions to mtab.c to interact with the {get,set,end}mntent interface; as it turns out, those functions do not appear to be re-entrant, and that causes a lot of problems with @@ -855,7 +855,7 @@ * Created a tiny tail implementation, removing -c, -q, -v, and making tail -f work only with a single file. This reduced tail from 6k to 2.4k. The bigger/more featured tail can still be had by disabling - BB_FEATURE_SIMPLE_TAIL in busybox.defs.h + CONFIG_FEATURE_SIMPLE_TAIL in busybox.defs.h * Ping now falls back to doing the right thing if /etc/protocols turns up missing. * Fixed mount and umount. Previously they could leak loop device @@ -907,14 +907,14 @@ devices. Support is toggled by MOUNT_LOOP feature -- Ben Collins * Several fixes from Marco Pantaleoni compile in - * fullWrite() not only if BB_TAR is defined, but also - if BB_CP or BB_MV are (fullWrite() is referenced by copyFile()) + * fullWrite() not only if CONFIG_TAR is defined, but also + if CONFIG_CP or CONFIG_MV are (fullWrite() is referenced by copyFile()) * add some compiler optimizations to further reduce executable size (as a side note, on my machines the largest code is generated by gcc 2.95.2 with -Os ! The smallest by plain gcc 2.7.2.3 with -O2 -m386 ...) * Compile now won't fail if busybox.def.h defines - BB_FEATURE_LINUXRC but not BB_INIT. (init_main used to be + CONFIG_FEATURE_INITRD but not CONFIG_INIT. (init_main used to be referenced, but not compiled) * Fixed a bug in setting TERM for serial console support. TERM now defaults to "ansi" for serial consoles. @@ -974,7 +974,7 @@ to suit my evil purposes. Costs 6k. I'll make it smaller sometime. * on reboot, init called 'umount -a -n', which caused errors - when BB_MTAB was not enabled. Changed to 'umount -a', which does + when CONFIG_MTAB was not enabled. Changed to 'umount -a', which does the right thing. * init will now try to run /sbin/getty if it is present (for easy integration with the about-to-be-released tinylogin.) @@ -1009,7 +1009,7 @@ * I've taken a first step to making busybox not need the /proc filesystem. Most apps don't need it. Those that _require_ it, will complain if you enable them when you disable - BB_FEATURE_USE_PROCFS. + CONFIG_FEATURE_USE_PROCFS. -Erik Andersen, Dec 5, 1999 @@ -1047,7 +1047,7 @@ * from Eric Delaunay). * Made createPath be quiet (again thanks to Eric Delaunay). If - * BB_CONSOLE_CMD_IF_RC_SCRIPT_EXITS is defined, then whatever + * CONFIG_CONSOLE_CMD_IF_RC_SCRIPT_EXITS is defined, then whatever command you define it as will be run if the init script exits. * Updated install.sh to make it more robust (thanks to Adam Di Carlo) * NFS support added to mount by Eric Delaunay. It costs 10k when @@ -1103,7 +1103,7 @@ to Eric Delaunay. * more started to read from stdin after the last file was finished, and options were not parsed correctly (fix thanks to Eric Delaunay). - * more will now use the terminal size if BB_FEATURE_AUTOWIDTH is on. + * more will now use the terminal size if CONFIG_FEATURE_AUTOWIDTH is on. * rm wouldn't remove a symlink unless the symlink was valid. This was a side effect of the busybox 0.32 recursiveAction() fix. Things should now work correctly. @@ -1121,7 +1121,7 @@ * Removed some debugging noise from init.c * Fixed ln so it works now (it was very broken). * Fixed df so it won't segfault when there is no /etc/fstab, - * If BB_MTAB is not defined, df and mount will whine if /etc/fstab + * If CONFIG_MTAB is not defined, df and mount will whine if /etc/fstab is not installed (since they cannot fixup "/dev/root" to state the real root device name) * merged some redundant code from mtab.c/df.c into utility.c @@ -1129,9 +1129,8 @@ -Erik Andersen, Nov 5, 1999 0.32 - * More changes -- many thanks to Lineo for paying me to work on - busybox. If you have any problems please let me know ASAP at - andersen@lineo.com or andersee@debian.org + * More changes -- If you have any problems please let me know ASAP at + andersee@debian.org * usage() now prints the BusyBox version. This will help folks realize that they are not in Kansas anymore. * Fixed mkdir -m option so that it works. kill segfaulted w/o any @@ -1142,11 +1141,11 @@ * with full regular expressions!). Fixed a stupid seg-fault in sync * Fixed mount -- mount -a failed to parse and apply mount options Fixed * umount -n (patch thanks to Matthew Grant ) - * umount -a no longer umounts /proc Added BB_MTAB, allowing (at the + * umount -a no longer umounts /proc Added CONFIG_MTAB, allowing (at the * cost of ~1.5k and the need for a rw /etc) folks to use a real /etc/mtab file instead of a symlink to /proc/mounts. mount, and umount will add/remove entries and df - will now use /etc/mtab if BB_MTAB is defined. + will now use /etc/mtab if CONFIG_MTAB is defined. * Fixed a nice bug in recursiveAction() which caused it to infinitely hunt through /proc/../fd/* creating new file descriptors if it followed the /dev/fd link over to /proc. recursiveAction() now @@ -1173,10 +1172,9 @@ -Erik Andersen, Oct 21, 1999 0.30 - Major changes -- lots of stuff rewritten. Many thanks to Lineo for - paying me to make these updates. If you have any problems with busybox, - or notice any bugs -- please let me know so I can fix it. These - changes include: + Major changes -- lots of stuff rewritten. If you have any problems + with busybox, or notice any bugs -- please let me know so I can fix + it. These changes include: Core Changes: * busybox can now invoke apps in two ways: via symlinks to the diff --git a/Config.h b/Config.h deleted file mode 100644 index 73b0f91f8..000000000 --- a/Config.h +++ /dev/null @@ -1,494 +0,0 @@ -/* vi: set sw=4 ts=4: */ -// This file defines the feature set to be compiled into busybox. -// When you turn things off here, they won't be compiled in at all. -// -//// This file is parsed by sed. You MUST use single line comments. -// i.e., //#define BB_BLAH -// -// -// BusyBox Applications -//#define BB_ADDGROUP -//#define BB_ADDUSER -//#define BB_ADJTIMEX -//#define BB_AR -//#define BB_ASH -#define BB_BASENAME -//#define BB_BUNZIP2 -#define BB_CAT -#define BB_CHGRP -#define BB_CHMOD -#define BB_CHOWN -#define BB_CHROOT -#define BB_CHVT -#define BB_CLEAR -//#define BB_CMP -#define BB_CP -//#define BB_CPIO -#define BB_CUT -#define BB_DATE -//#define BB_DC -#define BB_DD -//#define BB_DEALLOCVT -//#define BB_DELGROUP -//#define BB_DELUSER -#define BB_DF -#define BB_DIRNAME -#define BB_DMESG -//#define BB_DOS2UNIX -//#define BB_DPKG -//#define BB_DPKG_DEB -//#define BB_DUTMP -#define BB_DU -//#define BB_DUMPKMAP -#define BB_ECHO -#define BB_ENV -//#define BB_EXPR -//#define BB_FBSET -//#define BB_FDFLUSH -#define BB_FIND -#define BB_FREE -//#define BB_FREERAMDISK -//#define BB_FSCK_MINIX -//#define BB_GETOPT -//#define BB_GETTY -#define BB_GREP -#define BB_GUNZIP -#define BB_GZIP -#define BB_HALT -#define BB_HEAD -//#define BB_HOSTID -//#define BB_HOSTNAME -//#define BB_HUSH -#define BB_ID -//#define BB_IFCONFIG -#define BB_INIT -//#define BB_INSMOD -#define BB_KILL -#define BB_KILLALL -#define BB_KLOGD -//#define BB_LASH -//#define BB_LENGTH -#define BB_LN -//#define BB_LOADACM -//#define BB_LOADFONT -//#define BB_LOADKMAP -#define BB_LOGGER -//#define BB_LOGNAME -#define BB_LS -#define BB_LSMOD -//#define BB_MAKEDEVS -//#define BB_MD5SUM -#define BB_MKDIR -//#define BB_MKFIFO -//#define BB_MKFS_MINIX -#define BB_MKNOD -#define BB_MKSWAP -//#define BB_MKTEMP -#define BB_MODPROBE -#define BB_MORE -#define BB_MOUNT -#define BB_MSH -//#define BB_MT -#define BB_MV -//#define BB_NC -//#define BB_NSLOOKUP -#define BB_PIDOF -//#define BB_PING -//#define BB_PIVOT_ROOT -#define BB_POWEROFF -//#define BB_PRINTF -#define BB_PS -#define BB_PWD -//#define BB_RDATE -//#define BB_READLINK -#define BB_REBOOT -//#define BB_RENICE -#define BB_RESET -#define BB_RM -#define BB_RMDIR -//#define BB_RMMOD -//#define BB_ROUTE -//#define BB_RPM2CPIO -#define BB_SED -//#define BB_SETKEYCODES -#define BB_SLEEP -#define BB_SORT -//#define BB_STTY -//#define BB_START_STOP_DAEMON -#define BB_SWAPONOFF -#define BB_SYNC -#define BB_SYSLOGD -#define BB_TAIL -#define BB_TAR -//#define BB_TEE -//#define BB_TEST -//#define BB_TELNET -//#define BB_TFTP -#define BB_TOUCH -//#define BB_TR -//#define BB_TRACEROUTE -#define BB_TRUE_FALSE -#define BB_TTY -//#define BB_UNIX2DOS -//#define BB_UUENCODE -//#define BB_UUDECODE -#define BB_UMOUNT -#define BB_UNIQ -#define BB_UNAME -//#define BB_UPDATE -#define BB_UPTIME -//#define BB_USLEEP -//#define BB_VI -//#define BB_WATCHDOG -#define BB_WC -//#define BB_WGET -#define BB_WHICH -#define BB_WHOAMI -#define BB_XARGS -#define BB_YES -// End of Applications List -// -// -// -// --------------------------------------------------------- -// This is where feature definitions go. Generally speaking, -// turning this stuff off makes things a bit smaller (and less -// pretty/useful). -// -// -// If you enabled one or more of the shells, you may select which one -// should be run when sh is invoked: -//#define BB_FEATURE_SH_IS_ASH -//#define BB_FEATURE_SH_IS_HUSH -//#define BB_FEATURE_SH_IS_LASH -#define BB_FEATURE_SH_IS_MSH -// -// BusyBox will, by default, malloc space for its buffers. This costs code -// size for the call to xmalloc. You can use the following feature to have -// them put on the stack. For some very small machines with limited stack -// space, this can be deadly. For most folks, this works just fine... -//#define BB_FEATURE_BUFFERS_GO_ON_STACK -// The third alternative for buffer allocation is to use BSS. This works -// beautifully for computers with a real MMU (and OS support), but wastes -// runtime RAM for uCLinux. This behavior was the only one available for -// BusyBox versions 0.48 and earlier. -//#define BB_FEATURE_BUFFERS_GO_IN_BSS -// -// Turn this on to use Erik's very cool devps, and devmtab kernel drivers, -// thereby eliminating the need for the /proc filesystem and thereby saving -// lots and lots memory for more important things. NOTE: If you enable this -// feature, you _must_ have patched the kernel to include the devps patch that -// is included in the busybox/kernel-patches directory. You will also need to -// create some device special files in /dev on your embedded system: -// mknod /dev/mtab c 10 22 -// mknod /dev/ps c 10 21 -// I emailed Linus and this patch will not be going into the stock kernel. -//#define BB_FEATURE_USE_DEVPS_PATCH -// -// show verbose usage messages -//#define BB_FEATURE_VERBOSE_USAGE -// -// Use termios to manipulate the screen ('more' is prettier with this on) -//#define BB_FEATURE_USE_TERMIOS -// -// calculate terminal & column widths (for more and ls) -#define BB_FEATURE_AUTOWIDTH -// -// show username/groupnames for ls -#define BB_FEATURE_LS_USERNAME -// -// show file timestamps in ls -#define BB_FEATURE_LS_TIMESTAMPS -// -// enable ls -p and -F -#define BB_FEATURE_LS_FILETYPES -// -// sort the file names -#define BB_FEATURE_LS_SORTFILES -// -// enable ls -R -#define BB_FEATURE_LS_RECURSIVE -// -// enable ls -L -#define BB_FEATURE_LS_FOLLOWLINKS -// -// Disable for a smaller (but less functional) ping -#define BB_FEATURE_FANCY_PING -// -// Make init use a simplified /etc/inittab file (recommended). -#define BB_FEATURE_USE_INITTAB -// -//Enable init being called as /linuxrc -#define BB_FEATURE_LINUXRC -// -//Have init enable core dumping for child processes (for debugging only) -//#define BB_FEATURE_INIT_COREDUMPS -// -//Make sure nothing is printed to the console on boot -//#define BB_FEATURE_EXTRA_QUIET -// -// enable syslogd -R remotehost -#define BB_FEATURE_REMOTE_LOG -// -// enable syslogd -C -//#define BB_FEATURE_IPC_SYSLOG -// -//Disable for a simple tail implementation (2.34k vs 3k for the full one). -//Both provide 'tail -f', but this cuts out -c, -q, -s, and -v. -#define BB_FEATURE_FANCY_TAIL -// -// Enable support for loop devices in mount -#define BB_FEATURE_MOUNT_LOOP -// -// Enable support for a real /etc/mtab file instead of /proc/mounts -//#define BB_FEATURE_MTAB_SUPPORT -// -// Enable support for mounting remote NFS volumes. -// You may need to mount with "-o nolock" if you are -// not running a local portmapper daemon... -// -// If you are using uClibc, be sure that you've already compiled -// uClibc with INCLUDE_RPC=true (contained in the Config file) -//#define BB_FEATURE_NFSMOUNT -// -// Enable support forced filesystem unmounting -// (i.e., in case of an unreachable NFS system). -#define BB_FEATURE_MOUNT_FORCE -// -// Enable support for creation of tar files. -#define BB_FEATURE_TAR_CREATE -// -// Enable support for "--exclude" and "-X" for excluding files -#define BB_FEATURE_TAR_EXCLUDE -// -// Enable support for tar -z option (currently only works for inflating) -#define BB_FEATURE_TAR_GZIP -// -// Enable reverse sort -#define BB_FEATURE_SORT_REVERSE -// -// Enable uniqe sort -#define BB_FEATURE_SORT_UNIQUE -// -// Enable command line editing in the shell. -// Only relevant if a shell is enabled. On by default. -#define BB_FEATURE_COMMAND_EDITING -// -// Enable tab completion in the shell. This is now working quite nicely. -// This feature adds a bit over 4k. Only relevant if a shell is enabled. -#define BB_FEATURE_COMMAND_TAB_COMPLETION -// -// Attempts to match usernames in a ~-prefixed path -//#define BB_FEATURE_COMMAND_USERNAME_COMPLETION -// -//Allow the shell to invoke all the compiled in BusyBox applets as if they -//were shell builtins. Nice for staticly linking an emergency rescue shell, -//among other things. Off by default. -// Only relevant if a shell is enabled. -//#define BB_FEATURE_SH_STANDALONE_SHELL -// -//When this is enabled, busybox shell applets can be called using full path -//names. This causes applets (i.e., most busybox commands) to override -//real commands on the filesystem. For example, if you run run /bin/cat, it -//will use BusyBox cat even if /bin/cat exists on the filesystem and is _not_ -//busybox. Some systems want this, others do not. Choose wisely. :-) This -//only has meaning when BB_FEATURE_SH_STANDALONE_SHELL is enabled. -// Only relevant if a shell is enabled. Off by default. -//#define BB_FEATURE_SH_APPLETS_ALWAYS_WIN -// -// Uncomment this option for a fancy shell prompt that includes the -// current username and hostname. On systems that don't have usernames -// or hostnames, this can look hideous. -// Only relevant if a shell is enabled. -//#define BB_FEATURE_SH_FANCY_PROMPT -// -//Make interactive shells not print busybox messages -//#define BB_FEATURE_SH_EXTRA_QUIET -// -//Turn on extra fbset options -//#define BB_FEATURE_FBSET_FANCY -// -//Turn on fbset readmode support -//#define BB_FEATURE_FBSET_READMODE -// -// Support insmod/lsmod/rmmod for post 2.1 kernels -//#define BB_FEATURE_NEW_MODULE_INTERFACE -// -// Support insmod/lsmod/rmmod for pre 2.1 kernels -//#define BB_FEATURE_OLD_MODULE_INTERFACE -// -// Support module version checking -//#define BB_FEATURE_INSMOD_VERSION_CHECKING -// -// Support for uClinux memory usage optimization, which will load the image -// directly into the kernel memory. This divides memory requrements by three. -// If you are not running uClinux (i.e., your CPU has an MMU) leave this -// disabled... -//#define BB_FEATURE_INSMOD_LOADINKMEM -// -// Support for Minix filesystem, version 2 -//#define BB_FEATURE_MINIX2 -// -// Enable ifconfig status reporting output -- this feature adds 7k. -//#define BB_FEATURE_IFCONFIG_STATUS -// -// Enable ifconfig slip-specific options "keepalive" and "outfill" -//#define BB_FEATURE_IFCONFIG_SLIP -// -// Enable ifconfig options "mem_start", "io_addr", and "irq". -//#define BB_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ -// -// Enable ifconfig option "hw". Currently works for only with "ether". -//#define BB_FEATURE_IFCONFIG_HW -// -// Allows "broadcast +" to set broadcast automatically based on hostaddr -// and netmask, at a cost of about 100 bytes of code (i386). -//#define BB_FEATURE_IFCONFIG_BROADCAST_PLUS -// -// Enable busybox --install [-s] -// to create links (or symlinks) for all the commands that are -// compiled into the binary. (needs /proc filesystem) -//#define BB_FEATURE_INSTALLER -// -// Enable a nifty progress meter in wget (adds just under 2k) -#define BB_FEATURE_WGET_STATUSBAR -// -// Enable HTTP authentication in wget -#define BB_FEATURE_WGET_AUTHENTICATION -// -// Clean up all memory before exiting -- usually not needed -// as the OS can clean up... Don't enable this unless you -// have a really good reason for cleaning things up manually. -//#define BB_FEATURE_CLEAN_UP -// -// Support for human readable output by ls, du, etc.(example 13k, 23M, 235G) -#define BB_FEATURE_HUMAN_READABLE -// -// Support for the find -type option. -#define BB_FEATURE_FIND_TYPE -// -// Support for the find -perm option. -#define BB_FEATURE_FIND_PERM -// -// Support for the find -mtine option. -#define BB_FEATURE_FIND_MTIME -// -// Support for the -A -B and -C context flags in grep -//#define BB_FEATURE_GREP_CONTEXT -// -// Support for the EGREP applet (alias to the grep applet) -//#define BB_FEATURE_GREP_EGREP_ALIAS -// -// Tell tftp what commands that should be supported. -#define BB_FEATURE_TFTP_PUT -#define BB_FEATURE_TFTP_GET -//#define BB_FEATURE_TFTP_BLOCKSIZE -// -// features for vi -#define BB_FEATURE_VI_COLON // ":" colon commands, no "ex" mode -#define BB_FEATURE_VI_YANKMARK // Yank/Put commands and Mark cmds -#define BB_FEATURE_VI_SEARCH // search and replace cmds -#define BB_FEATURE_VI_USE_SIGNALS // catch signals -#define BB_FEATURE_VI_DOT_CMD // remember previous cmd and "." cmd -#define BB_FEATURE_VI_READONLY // vi -R and "view" mode -#define BB_FEATURE_VI_SETOPTS // set-able options, ai ic showmatch -#define BB_FEATURE_VI_SET // :set -#define BB_FEATURE_VI_WIN_RESIZE // handle window resize -// -// Enable a if you system have setuped locale -//#define BB_LOCALE_SUPPORT -// -// Support for TELNET to pass TERM type to remote host. Adds 384 bytes. -#define BB_FEATURE_TELNET_TTYPE -// -// Support for devfs. -//#define BB_FEATURE_DEVFS -// -// End of Features List -// -// -// -// -// -// -//--------------------------------------------------- -// Nothing beyond this point should ever be touched by -// mere mortals so leave this stuff alone. -// -#include -#if defined __UCLIBC__ && ! defined __UCLIBC_HAS_MMU__ - #undef BB_RPM2CPIO /* Uses gz_open(), which uses fork() */ - #undef BB_DPKG_DEB /* Uses gz_open(), which uses fork() */ - #undef BB_ASH /* Uses fork() */ - #undef BB_HUSH /* Uses fork() */ - #undef BB_LASH /* Uses fork() */ - #undef BB_INIT /* Uses fork() */ - #undef BB_FEATURE_TAR_GZIP /* Uses fork() */ - #undef BB_SYSLOGD /* Uses daemon() */ - #undef BB_KLOGD /* Uses daemon() */ - #undef BB_UPDATE /* Uses daemon() */ -#endif -#if defined BB_ASH || defined BB_HUSH || defined BB_LASH || defined BB_MSH - #if defined BB_FEATURE_COMMAND_EDITING - #define BB_CMDEDIT - #else - #undef BB_FEATURE_COMMAND_EDITING - #undef BB_FEATURE_COMMAND_TAB_COMPLETION - #undef BB_FEATURE_COMMAND_USERNAME_COMPLETION - #undef BB_FEATURE_SH_FANCY_PROMPT - #endif -#else - #undef BB_FEATURE_SH_APPLETS_ALWAYS_WIN - #undef BB_FEATURE_SH_STANDALONE_SHELL - #undef BB_FEATURE_SH_FANCY_PROMPT -#endif -// -#if (defined BB_ASH || defined BB_HUSH || defined BB_MSH) && ! defined BB_TEST - #define BB_TEST -#endif -// -#ifdef BB_KILLALL - #ifndef BB_KILL - #define BB_KILL - #endif -#endif -// -#ifndef BB_INIT - #undef BB_FEATURE_LINUXRC -#endif -// -#if defined BB_MOUNT && defined BB_FEATURE_NFSMOUNT - #define BB_NFSMOUNT -#endif -// -#if defined BB_FEATURE_AUTOWIDTH - #ifndef BB_FEATURE_USE_TERMIOS - #define BB_FEATURE_USE_TERMIOS - #endif -#endif -// -#if defined BB_INSMOD || defined BB_LSMOD - #if ! defined BB_FEATURE_NEW_MODULE_INTERFACE && ! defined BB_FEATURE_OLD_MODULE_INTERFACE - #define BB_FEATURE_NEW_MODULE_INTERFACE - #endif -#endif -// -#ifdef BB_UNIX2DOS - #define BB_DOS2UNIX -#endif -// -#ifdef BB_SYSLOGD - #if defined BB_FEATURE_IPC_SYSLOG - #define BB_LOGREAD - #endif -#endif -// -#if defined BB_ASH && defined BB_FEATURE_SH_IS_ASH -# define shell_main ash_main -#elif defined BB_HUSH && defined BB_FEATURE_SH_IS_HUSH -# define shell_main hush_main -#elif defined BB_LASH && defined BB_FEATURE_SH_IS_LASH -# define shell_main lash_main -#elif defined BB_MSH && defined BB_FEATURE_SH_IS_MSH -# define shell_main msh_main -#endif diff --git a/LICENSE b/LICENSE index 8e5a143d0..375ad2a00 100644 --- a/LICENSE +++ b/LICENSE @@ -17,15 +17,14 @@ Copyright 1998 Dave Cinege mini-gzip(gzip), mini-netcat(mnc) Copyright 1998 Charles P. Wright -Tons of new stuff as noted in header files -Copyright (C) 1999,2000,2001 by Lineo, inc. and written by -Erik Andersen , - +Tons of new stuff as noted in header files +Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen and Erik Andersen +Copyright (C) 1999,2000,2001 by Erik Andersen Please feed suggestions, bug reports, insults, and bribes back to: Erik Andersen - + diff --git a/Makefile b/Makefile index 3cabc7afa..c8337801f 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ # Makefile for busybox # -# Copyright (C) 1999,2000,2001 Erik Andersen +# Copyright (C) 1999,2000,2001 by Erik Andersen # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -20,12 +20,19 @@ PROG := busybox VERSION := 0.61.pre BUILDTIME := $(shell TZ=UTC date -u "+%Y.%m.%d-%H:%M%z") -export VERSION +TOPDIR := ${shell /bin/pwd} +HOSTCC := gcc +HOSTCFLAGS:= -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer + + +# What OS are you compiling busybox for? This allows you to include +# OS specific things, syscall overrides, etc. +TARGET_OS := linux # With a modern GNU make(1) (highly recommended, that's what all the # developers use), all of the following configuration values can be # overridden at the command line. For example: -# make CROSS=powerpc-linux- BB_SRC_DIR=$HOME/busybox PREFIX=/mnt/app +# make CROSS=powerpc-linux- CONFIG_SRC_DIR=$HOME/busybox PREFIX=/mnt/app # If you want to add some simple compiler switches (like -march=i686), # especially from the command line, use this instead of CFLAGS directly. @@ -39,18 +46,6 @@ DOSTATIC = false # Leave this set to `false' for production use. DODEBUG = false -# Setting this to `true' will cause busybox to directly use the system's -# password and group functions. Assuming you use GNU libc, when this is -# `true', you will need to install the /etc/nsswitch.conf configuration file -# and the required libnss_* libraries. This generally makes your embedded -# system quite a bit larger... If you leave this off, busybox will directly use -# the /etc/password, /etc/group files (and your system will be smaller, and I -# will get fewer emails asking about how glibc NSS works). Enabling this adds -# just 1.4k to the binary size (which is a _lot_ less then glibc NSS costs). -# Note that if you want hostname resolution to work with glibc, you still need -# the libnss_* libraries. -USE_SYSTEM_PWD_GRP = true - # This enables compiling with dmalloc ( http://dmalloc.com/ ) # which is an excellent public domain mem leak and malloc problem # detector. To enable dmalloc, before running busybox you will @@ -72,17 +67,24 @@ DOEFENCE = false # larger than 2GB! DOLFS = false -# If you have a "pristine" source directory, point BB_SRC_DIR to it. +# If you have a "pristine" source directory, point CONFIG_SRC_DIR to it. # Experimental and incomplete; tell the mailing list # if you do or don't like it so far. -BB_SRC_DIR = +CONFIG_SRC_DIR = -# If you are running a cross compiler, you may want to set this -# to something more interesting, like "powerpc-linux-". +# If you are running a cross compiler, you may want to set CROSS +# to something more interesting, like "arm-linux-". CROSS = -CC = $(CROSS)gcc -AR = $(CROSS)ar -STRIPTOOL = $(CROSS)strip +CC = $(CROSS)gcc +AR = $(CROSS)ar +AS = $(CROSS)as +LD = $(CROSS)ld +NM = $(CROSS)nm +STRIP = $(CROSS)strip +CPP = $(CC) -E +MAKEFILES = $(TOPDIR)/.config +export VERSION BUILDTIME TOPDIR HOSTCC HOSTCFLAGS CROSS CC AR AS LD NM STRIP CPP + # To compile vs uClibc, just use the compiler wrapper built by uClibc... # Everything should compile and work as expected these days... @@ -107,10 +109,11 @@ STRIPTOOL = $(CROSS)strip #GCCINCDIR = $(shell gcc -print-search-dirs | sed -ne "s/install: \(.*\)/\1include/gp") # use '-Os' optimization if available, else use -O2 -OPTIMIZATION := $(shell if $(CC) -Os -S -o /dev/null -xc /dev/null >/dev/null 2>&1; \ - then echo "-Os"; else echo "-O2" ; fi) +OPTIMIZATION := ${shell if $(CC) -Os -S -o /dev/null -xc /dev/null \ + >/dev/null 2>&1; then echo "-Os"; else echo "-O2" ; fi} WARNINGS=-Wall -Wstrict-prototypes -Wshadow +CFLAGS = -I $(TOPDIR)/include -I $(TOPDIR)/busybox ARFLAGS = -r # @@ -142,25 +145,14 @@ endif ifeq ($(strip $(DODEBUG)),true) CFLAGS += $(WARNINGS) -g -D_GNU_SOURCE LDFLAGS += -Wl,-warn-common - STRIP = + STRIPCMD = else CFLAGS += $(WARNINGS) $(OPTIMIZATION) -fomit-frame-pointer -D_GNU_SOURCE LDFLAGS += -s -Wl,-warn-common - STRIP = $(STRIPTOOL) --remove-section=.note --remove-section=.comment $(PROG) + STRIPCMD = $(STRIP) --remove-section=.note --remove-section=.comment $(PROG) endif ifeq ($(strip $(DOSTATIC)),true) LDFLAGS += --static - # - #use '-ffunction-sections -fdata-sections' and '--gc-sections' (if they - # work) to try and strip out any unused junk. Doesn't do much for me, - # but you may want to give it a shot... - # - #ifeq ($(shell $(CC) -ffunction-sections -fdata-sections -S \ - # -o /dev/null -xc /dev/null 2>/dev/null && $(LD) \ - # --gc-sections -v >/dev/null && echo 1),1) - # CFLAGS += -ffunction-sections -fdata-sections - # LDFLAGS += --gc-sections - #endif endif ifndef $(PREFIX) @@ -169,125 +161,77 @@ endif # Additional complications due to support for pristine source dir. # Include files in the build directory should take precedence over -# the copy in BB_SRC_DIR, both during the compilation phase and the +# the copy in CONFIG_SRC_DIR, both during the compilation phase and the # shell script that finds the list of object files. # Work in progress by . # -ifneq ($(strip $(BB_SRC_DIR)),) - VPATH = $(BB_SRC_DIR) +ifneq ($(strip $(CONFIG_SRC_DIR)),) + VPATH = $(CONFIG_SRC_DIR) endif -#ifneq ($(strip $(VPATH)),) -# CFLAGS += -I- -I. $(patsubst %,-I%,$(subst :, ,$(VPATH))) -#endif - -# We need to set APPLET_SOURCES to something like -# $(shell busybox.sh Config.h) -# but in a manner that works with VPATH and BB_SRC_DIR. -# Possible ways to approach this: -# -# 1. Explicitly search through .:$(VPATH) for busybox.sh and config.h, -# then $(shell $(BUSYBOX_SH) $(CONFIG_H) $(BB_SRC_DIR)) -# -# 2. Explicity search through .:$(VPATH) for slist.mk, -# then $(shell $(MAKE) -f $(SLIST_MK) VPATH=$(VPATH) BB_SRC_DIR=$(BB_SRC_DIR)) -# -# 3. Create slist.mk in this directory, with commands embedded in -# a $(shell ...) command, and $(MAKE) it immediately. -# -# 4. Use a real rule within this makefile to create a file that sets -# APPLET_SOURCE_LIST, then include that file. Has complications -# with the first trip through the makefile (before processing the -# include) trying to do too much, and a spurious warning the first -# time make is run. -# -# This is option 3: -# -#APPLET_SOURCES = $(shell \ -# echo -e 'all: busybox.sh Config.h\n\t@ $$(SHELL) $$^ $$(BB_SRC_DIR)' >slist.mk; \ -# make -f slist.mk VPATH=$(VPATH) BB_SRC_DIR=$(BB_SRC_DIR) \ -#) -# And option 4: --include applet_source_list OBJECTS = $(APPLET_SOURCES:.c=.o) busybox.o usage.o applets.o CFLAGS += $(CROSS_CFLAGS) -CFLAGS += -DBB_VER='"$(VERSION)"' -CFLAGS += -DBB_BT='"$(BUILDTIME)"' -ifdef BB_INIT_SCRIPT - CFLAGS += -DINIT_SCRIPT='"$(BB_INIT_SCRIPT)"' +ifdef CONFIG_INIT_SCRIPT + CFLAGS += -DINIT_SCRIPT='"$(CONFIG_INIT_SCRIPT)"' endif -ifneq ($(strip $(USE_SYSTEM_PWD_GRP)),true) - PWD_GRP = pwd_grp - PWD_GRP_DIR = $(BB_SRC_DIR:=/)$(PWD_GRP) - PWD_LIB = libpwd.a - PWD_CSRC=__getpwent.c pwent.c getpwnam.c getpwuid.c putpwent.c getpw.c \ - fgetpwent.c __getgrent.c grent.c getgrnam.c getgrgid.c fgetgrent.c \ - initgroups.c setgroups.c - PWD_OBJS=$(patsubst %.c,$(PWD_GRP)/%.o, $(PWD_CSRC)) -ifneq ($(strip $(BB_SRC_DIR)),) - PWD_CFLAGS = -I- -I. -endif - PWD_CFLAGS += -I$(PWD_GRP_DIR) -else - CFLAGS += -DUSE_SYSTEM_PWD_GRP -endif - -LIBBB = libbb -LIBBB_LIB = libbb.a -LIBBB_CSRC= ask_confirmation.c chomp.c concat_path_file.c copy_file.c \ -copy_file_chunk.c libc5.c device_open.c error_msg.c \ -error_msg_and_die.c fgets_str.c find_mount_point.c find_pid_by_name.c \ -find_root_device.c full_read.c full_write.c get_console.c \ -get_last_path_component.c get_line_from_file.c gz_open.c human_readable.c \ -isdirectory.c kernel_version.c loop.c mode_string.c module_syscalls.c mtab.c \ -mtab_file.c my_getgrnam.c my_getgrgid.c my_getpwnam.c my_getpwnamegid.c \ -my_getpwuid.c parse_mode.c parse_number.c perror_msg.c perror_msg_and_die.c \ -print_file.c process_escape_sequence.c read_package_field.c recursive_action.c \ -safe_read.c safe_strncpy.c syscalls.c syslog_msg_with_name.c time_string.c \ -trim.c unzip.c vdprintf.c verror_msg.c vperror_msg.c wfopen.c xfuncs.c \ -xgetcwd.c xreadlink.c xregcomp.c interface.c remove_file.c last_char_is.c \ -copyfd.c vherror_msg.c herror_msg.c herror_msg_and_die.c xgethostbyname.c \ -dirname.c make_directory.c create_icmp_socket.c u_signal_names.c arith.c \ -simplify_path.c -LIBBB_OBJS=$(patsubst %.c,$(LIBBB)/%.o, $(LIBBB_CSRC)) -ifeq ($(strip $(BB_SRC_DIR)),) - LIBBB_CFLAGS += -I$(LIBBB) -else - LIBBB_CFLAGS = -I- -I. -I./$(LIBBB) -I$(BB_SRC_DIR)/$(LIBBB) -I$(BB_SRC_DIR) -endif - -LIBBB_MSRC=libbb/messages.c -LIBBB_MESSAGES= full_version name_too_long omitting_directory not_a_directory \ -memory_exhausted invalid_date invalid_option io_error dash_dash_help \ -write_error too_few_args name_longer_than_foo unknown can_not_create_raw_socket -LIBBB_MOBJ=$(patsubst %,$(LIBBB)/%.o, $(LIBBB_MESSAGES)) - -LIBBB_ARCSRC=libbb/unarchive.c -LIBBB_ARCOBJ= archive_offset seek_sub_file extract_archive unarchive \ -get_header_ar get_header_cpio get_header_tar deb_extract -LIBBB_AROBJS=$(patsubst %,$(LIBBB)/%.o, $(LIBBB_ARCOBJ)) - - # Put user-supplied flags at the end, where they # have a chance of winning. CFLAGS += $(CFLAGS_EXTRA) .EXPORT_ALL_VARIABLES: -all: applet_source_list busybox busybox.links doc +all: do-it-all -applet_source_list: busybox.sh Config.h - (echo -n "APPLET_SOURCES := "; CC="$(CC)" BB_SRC_DIR="$(BB_SRC_DIR)" $(SHELL) $^) > $@ +# +# Make "config" the default target if there is no configuration file or +# "depend" the target if there is no top-level dependency information. +ifeq (.config,$(wildcard .config)) +include .config +ifeq (.depend,$(wildcard .depend)) +include .depend +do-it-all: busybox busybox.links doc +else +CONFIGURATION = depend +do-it-all: depend +endif +else +CONFIGURATION = menuconfig +do-it-all: menuconfig +endif +SUBDIRS =applets archival console-tools editors fileutils findutils init \ + miscutils modutils networking pwd_grp shell shellutils sysklogd \ + textutils tinylogin util-linux libbb + +bbsubdirs: $(patsubst %, _dir_%, $(SUBDIRS)) + +$(patsubst %, _dir_%, $(SUBDIRS)) : dummy include/config/MARKER + $(MAKE) CFLAGS="$(CFLAGS)" -C $(patsubst _dir_%, %, $@) + +busybox: bbsubdirs + $(CC) $(LDFLAGS) -o $@ $(shell find $(SUBDIRS) -name \*.a) $(LIBCONFIG_LIB) $(LIBRARIES) + $(STRIPCMD) + +busybox.links: applets/busybox.mkll + - $(SHELL) $^ >$@ + +install: applets/install.sh busybox busybox.links + $(SHELL) $< $(PREFIX) + +install-hardlinks: applets/install.sh busybox busybox.links + $(SHELL) $< $(PREFIX) --hardlinks + + +# Documentation Targets doc: olddoc # Old Docs... olddoc: docs/busybox.pod docs/BusyBox.txt docs/BusyBox.1 docs/BusyBox.html -docs/busybox.pod : docs/busybox_header.pod usage.h docs/busybox_footer.pod +docs/busybox.pod : docs/busybox_header.pod applets/usage.h docs/busybox_footer.pod - ( cat docs/busybox_header.pod; \ - docs/autodocifier.pl usage.h; \ + docs/autodocifier.pl applets/usage.h; \ cat docs/busybox_footer.pod ) > docs/busybox.pod docs/BusyBox.txt: docs/busybox.pod @@ -340,86 +284,89 @@ docs/busybox/busyboxdocumentation.html: docs/busybox.sgml - mkdir -p docs (cd docs/busybox.lineo.com; sgmltools -b html ../busybox.sgml) +# The nifty new buildsystem stuff +scripts/mkdep: scripts/mkdep.c + $(HOSTCC) $(HOSTCFLAGS) -o scripts/mkdep scripts/mkdep.c -busybox: $(PWD_LIB) $(LIBBB_LIB) $(OBJECTS) - $(CC) $(LDFLAGS) -o $@ $(OBJECTS) $(LIBBB_LIB) $(PWD_LIB) $(LIBRARIES) - $(STRIP) +scripts/split-include: scripts/split-include.c + $(HOSTCC) $(HOSTCFLAGS) -o scripts/split-include scripts/split-include.c -# Without VPATH, rule expands to "/bin/sh busybox.mkll Config.h applets.h" -# but with VPATH, some or all of those file names are resolved to the -# directories in which they live. -busybox.links: busybox.mkll Config.h applets.h - - $(SHELL) $^ >$@ +dep-files: scripts/mkdep #archdep + rm -f .depend .hdepend + scripts/mkdep -I $(TOPDIR)/include -- `find $(TOPDIR) -name \*.c -print` >> .depend + scripts/mkdep -I $(TOPDIR)/include -- `find $(TOPDIR) -name \*.h -print` >> .hdepend + $(MAKE) $(patsubst %,_sfdep_%,$(SUBDIRS)) _FASTDEP_ALL_SUB_DIRS="$(SUBDIRS)" + +depend dep: dep-files + @ echo -e "\n\nNow run 'make' to build BusyBox\n\n" + +CONFIG_SHELL := ${shell if [ -x "$$BASH" ]; then echo $$BASH; \ + else if [ -x /bin/bash ]; then echo /bin/bash; \ + else echo sh; fi ; fi} + +include/config/MARKER: scripts/split-include include/config.h + scripts/split-include include/config.h include/config + @ touch include/config/MARKER + +menuconfig: + $(MAKE) -C scripts/lxdialog all + $(CONFIG_SHELL) scripts/Menuconfig sysdeps/$(TARGET_OS)/config.in + +config: + $(CONFIG_SHELL) scripts/Configure sysdeps/$(TARGET_OS)/config.in + +oldconfig: + $(CONFIG_SHELL) scripts/Configure -d sysdeps/$(TARGET_OS)/config.in + + +ifdef CONFIGURATION +..$(CONFIGURATION): + @echo + @echo "You have a bad or nonexistent" .$(CONFIGURATION) ": running 'make" $(CONFIGURATION)"'" + @echo + $(MAKE) $(CONFIGURATION) + @echo + @echo "Successful. Try re-making (ignore the error that follows)" + @echo + exit 1 + +dummy: -nfsmount.o cmdedit.o: %.o: %.h -ash.o hush.o lash.o msh.o: cmdedit.h -$(OBJECTS): %.o: %.c Config.h busybox.h applets.h Makefile -ifeq ($(strip $(BB_SRC_DIR)),) - $(CC) $(CFLAGS) -I. $(patsubst %,-I%,$(subst :, ,$(BB_SRC_DIR))) -c $< -o $*.o else - $(CC) $(CFLAGS) -I- -I. $(patsubst %,-I%,$(subst :, ,$(BB_SRC_DIR))) -c $< -o $*.o + +dummy: + endif -$(PWD_OBJS): %.o: %.c Config.h busybox.h applets.h Makefile - - mkdir -p $(PWD_GRP) - $(CC) $(CFLAGS) $(PWD_CFLAGS) -c $< -o $*.o - -$(LIBBB_OBJS): %.o: %.c Config.h busybox.h applets.h Makefile libbb/libbb.h - - mkdir -p $(LIBBB) - $(CC) $(CFLAGS) $(LIBBB_CFLAGS) -c $< -o $*.o - -$(LIBBB_MOBJ): $(LIBBB_MSRC) - - mkdir -p $(LIBBB) - $(CC) $(CFLAGS) $(LIBBB_CFLAGS) -DL_$(patsubst libbb/%,%,$*) -c $< -o $*.o - -$(LIBBB_AROBJS): $(LIBBB_ARCSRC) - - mkdir -p $(LIBBB) - $(CC) $(CFLAGS) $(LIBBB_CFLAGS) -DL_$(patsubst libbb/%,%,$*) -c $< -o $*.o - -libpwd.a: $(PWD_OBJS) - $(AR) $(ARFLAGS) $@ $^ - -libbb.a: $(LIBBB_MOBJ) $(LIBBB_AROBJS) $(LIBBB_OBJS) - $(AR) $(ARFLAGS) $@ $^ - -usage.o: usage.h - -libbb/loop.o: libbb/loop.h - -libbb/loop.h: mk_loop_h.sh - @ $(SHELL) $< > $@ +include Rules.mak +# Testing... test tests: # old way of doing it #cd tests && $(MAKE) all # new way of doing it cd tests && ./tester.sh +# Cleanup clean: - - cd tests && $(MAKE) clean + - $(MAKE) -C tests clean + - $(MAKE) -C scripts/lxdialog clean - rm -f docs/BusyBox.txt docs/BusyBox.1 docs/BusyBox.html \ docs/busybox.lineo.com/BusyBox.html - rm -f docs/busybox.txt docs/busybox.dvi docs/busybox.ps \ - docs/busybox.pdf docs/busybox.lineo.com/busybox.html - - rm -f multibuild.log Config.h.orig *.gdb *.elf - - rm -rf docs/busybox _install libpwd.a libbb.a pod2htm* - - rm -f busybox.links libbb/loop.h *~ slist.mk core applet_source_list + docs/busybox.pdf docs/busybox.lineo.com/busybox.html \ + docs/busybox _install pod2htm* *.gdb *.elf *~ core + - rm -f busybox.links libbb/loop.h .config.old .hdepend + - rm -f scripts/split-include scripts/mkdep .*config.log + - rm -rf include/config include/config.h + - find -name .\*.flags -o -name .depend -exec rm -f {} \; - find -name \*.o -exec rm -f {} \; + - find -name \*.a -exec rm -f {} \; distclean: clean - - rm -f busybox applet_source_list + - rm -f busybox - cd tests && $(MAKE) distclean -install: install.sh busybox busybox.links - $(SHELL) $< $(PREFIX) - -install-hardlinks: install.sh busybox busybox.links - $(SHELL) $< $(PREFIX) --hardlinks - -debug_pristine: - @ echo VPATH=\"$(VPATH)\" - @ echo OBJECTS=\"$(OBJECTS)\" - dist release: distclean doc cd ..; \ rm -rf busybox-$(VERSION); \ @@ -437,6 +384,8 @@ dist release: distclean doc \ tar -cvzf busybox-$(VERSION).tar.gz busybox-$(VERSION)/; + + .PHONY: tags tags: ctags -R . diff --git a/README b/README index b45ef57f4..4fbc76380 100644 --- a/README +++ b/README @@ -82,7 +82,7 @@ top of ash.c as well, so check those out if you want to tweak things. Getting help: When you find you need help, you can check out the BusyBox mailing list -archives at http://opensource.lineo.com/lists/busybox/ or even join +archives at http://oss.lineo.com/lists/busybox/ or even join the mailing list if you are interested. ---------------- @@ -130,23 +130,18 @@ Source for the latest released version can always be downloaded from CVS: BusyBox now has its own publicly browsable CVS tree at: - http://opensource.lineo.com/cgi-bin/cvsweb/busybox/ + http://oss.lineo.com/cgi-bin/cvsweb/busybox/ Anonymous CVS access is available. For instructions, check out: - http://opensource.lineo.com/cvs_anon.html + http://oss.lineo.com/cvs_anon.html For those that are actively contributing there is even CVS write access: - http://opensource.lineo.com/cvs_write.html + http://oss.lineo.com/cvs_write.html ---------------- Please feed suggestions, bug reports, insults, and bribes back to: Erik Andersen - + - - - -Many thanks to go to Lineo for paying me to work on busybox. - diff --git a/addgroup.c b/addgroup.c deleted file mode 100644 index 3d932011c..000000000 --- a/addgroup.c +++ /dev/null @@ -1,178 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * addgroup - add users to /etc/passwd and /etc/shadow - * - * - * Copyright (C) 1999 by Lineo, inc. - * Written by John Beppu - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" -#include "pwd_grp/pwd.h" -#include "pwd_grp/grp.h" - -#define GROUP_FILE "/etc/group" -#define SHADOW_FILE "/etc/gshadow" - - -/* structs __________________________ */ - -/* data _____________________________ */ - -/* defaults : should this be in an external file? */ -static char *default_passwd = "x"; - - -/* make sure gr_name isn't taken, make sure gid is kosher - * return 1 on failure */ -static int group_study(const char *filename, struct group *g) -{ - FILE *etc_group; - gid_t desired; - - struct group *grp; - const int max = 65000; - - /* FIXME : make an fopen_wrapper */ - etc_group = fopen(filename, "r"); - if (!etc_group) { - perror_msg_and_die("%s", filename); - } - - /* make sure gr_name isn't taken, make sure gid is kosher */ - desired = g->gr_gid; - while ((grp = fgetgrent(etc_group))) { - if ((strcmp(grp->gr_name, g->gr_name)) == 0) { - error_msg_and_die("%s: group already in use\n", g->gr_name); - } - if ((desired) && grp->gr_gid == desired) { - error_msg_and_die("%d: gid has already been allocated\n", - desired); - } - if ((grp->gr_gid > g->gr_gid) && (grp->gr_gid < max)) { - g->gr_gid = grp->gr_gid; - } - } - fclose(etc_group); - - /* gid */ - if (desired) { - g->gr_gid = desired; - } else { - g->gr_gid++; - } - /* return 1; */ - return 0; -} - -/* append a new user to the passwd file */ -static int addgroup(const char *filename, char *group, gid_t gid) -{ - FILE *etc_group; - FILE *etc_gshadow; - char *gshadow = SHADOW_FILE; - - struct group gr; - - /* group:passwd:gid:userlist */ - const char *entryfmt = "%s:%s:%d:%s\n"; - - /* make sure gid and group haven't already been allocated */ - gr.gr_gid = gid; - gr.gr_name = group; - if (group_study(filename, &gr)) - return 1; - - /* add entry to group */ - etc_group = fopen(filename, "a"); - if (!etc_group) { - perror_msg_and_die("%s", filename); - } - fprintf(etc_group, entryfmt, group, default_passwd, gr.gr_gid, ""); - fclose(etc_group); - - /* add entry to gshadow if necessary */ - if (access(gshadow, F_OK|W_OK) == 0) { - etc_gshadow = xfopen(gshadow, "a"); - fprintf(etc_gshadow, "%s:!::\n", group); - fclose(etc_gshadow); - } - - /* return 1; */ - return 0; -} - -/* - * addgroup will take a login_name as its first parameter. - * - * gid - * - * can be customized via command-line parameters. - * ________________________________________________________________________ */ -int addgroup_main(int argc, char **argv) -{ - int i; - char opt; - char *group; - gid_t gid = 0; - - /* get remaining args */ - for (i = 1; i < argc; i++) { - if (argv[i][0] == '-') { - opt = argv[i][1]; - switch (opt) { - case 'h': - show_usage(); - break; - case 'g': - gid = strtol(argv[++i], NULL, 10); - break; - default: - error_msg_and_die("addgroup: invalid option -- %c\n", opt); - } - } else { - break; - } - } - - if (i >= argc) { - show_usage(); - } else { - group = argv[i]; - } - - if (geteuid() != 0) { - error_msg_and_die - ("addgroup: Only root may add a group to the system.\n"); - } - - /* werk */ - return addgroup(GROUP_FILE, group, gid); -} - -/* $Id: addgroup.c,v 1.1 2001/08/21 16:18:59 andersen Exp $ */ diff --git a/adduser.c b/adduser.c deleted file mode 100644 index 6bd2c253e..000000000 --- a/adduser.c +++ /dev/null @@ -1,366 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * adduser - add users to /etc/passwd and /etc/shadow - * - * - * Copyright (C) 1999 by Lineo, inc. - * Written by John Beppu - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" -#include "pwd_grp/pwd.h" -#include "pwd_grp/grp.h" - -#define PASSWD_FILE "/etc/passwd" -#define SHADOW_FILE "/etc/gshadow" - -#if 0 -# define PASSWD_FILE "passwd" -# define SHADOW_FILE "shadow" -#endif - -/* structs __________________________ */ - -typedef struct { - uid_t u; - gid_t g; -} Id; - -/* data _____________________________ */ - -/* defaults : should this be in an external file? */ -static char *default_passwd = "x"; -static char *default_gecos = "Embedix User,,,"; -static char *default_home_prefix = "/home"; -static char *default_shell = "/bin/sh"; - -/* shadow in use? */ -static int shadow_enabled = 0; - -/* I was doing this all over the place */ -static FILE *fopen_wrapper(const char *filename, const char *mode) -{ - FILE *f; - - f = fopen(filename, mode); - if (f == NULL) { - fprintf(stderr, "adduser: %s: %s\n", filename, strerror(errno)); - } - return f; -} - -/* remix */ -/* EDR recoded such that the uid may be passed in *p */ -static int passwd_study(const char *filename, struct passwd *p) -{ - struct passwd *pw; - FILE *passwd; - - const int min = 500; - const int max = 65000; - - passwd = fopen_wrapper(filename, "r"); - if (!passwd) - return 4; - - /* EDR if uid is out of bounds, set to min */ - if ((p->pw_uid > max) || (p->pw_uid < min)) - p->pw_uid = min; - - /* stuff to do: - * make sure login isn't taken; - * find free uid and gid; - */ - while ((pw = fgetpwent(passwd))) { - if (strcmp(pw->pw_name, p->pw_name) == 0) { - /* return 0; */ - return 1; - } - if ((pw->pw_uid >= p->pw_uid) && (pw->pw_uid < max) - && (pw->pw_uid >= min)) { - p->pw_uid = pw->pw_uid + 1; - } - } - - /* EDR check for an already existing gid */ - while (getgrgid(p->pw_uid) != NULL) - p->pw_uid++; - - /* EDR also check for an existing group definition */ - if (getgrnam(p->pw_name) != NULL) - return 3; - - /* EDR bounds check */ - if ((p->pw_uid > max) || (p->pw_uid < min)) - return 2; - - /* EDR create new gid always = uid */ - p->pw_gid = p->pw_uid; - - /* return 1; */ - return 0; -} - -static void addgroup_wrapper(const char *login, gid_t gid) -{ - int argc = 4; - char *argv[] = { "addgroup", "-g", NULL, NULL }; - char group_id[8]; - char group_name[32]; - - strncpy(group_name, login, 32); - argv[3] = group_name; - sprintf(group_id, "%d", gid); - argv[2] = group_id; - addgroup_main(argc, argv); -} - -static void passwd_wrapper(const char *login) -{ - char *prog = "passwd"; - execlp(prog, prog, login, NULL); - error_msg_and_die("Failed to execute 'passwd', you must set the password for '%s' manually\n", login); -} - -/* - * pwd_to_spwd - create entries for new spwd structure - * - * pwd_to_spwd() creates a new (struct spwd) containing the - * information in the pointed-to (struct passwd). - */ -#define DAY (24L*3600L) -#define WEEK (7*DAY) -#define SCALE DAY -static struct spwd *pwd_to_spwd(const struct passwd *pw) -{ - static struct spwd sp; - - /* - * Nice, easy parts first. The name and passwd map directly - * from the old password structure to the new one. - */ - sp.sp_namp = pw->pw_name; - sp.sp_pwdp = pw->pw_passwd; - - /* - * Defaults used if there is no pw_age information. - */ - sp.sp_min = 0; - sp.sp_max = (10000L * DAY) / SCALE; - sp.sp_lstchg = time((time_t *) 0) / SCALE; - - /* - * These fields have no corresponding information in the password - * file. They are set to uninitialized values. - */ - sp.sp_warn = -1; - sp.sp_expire = -1; - sp.sp_inact = -1; - sp.sp_flag = -1; - - return &sp; -} - -/* putpwent(3) remix */ -static int adduser(const char *filename, struct passwd *p) -{ - FILE *passwd; - int r; - FILE *shadow; - struct spwd *sp; - - /* make sure everything is kosher and setup uid && gid */ - passwd = fopen_wrapper(filename, "a"); - if (passwd == NULL) { - /* return -1; */ - return 1; - } - fseek(passwd, 0, SEEK_END); - - /* if (passwd_study(filename, p) == 0) { */ - r = passwd_study(filename, p); - if (r) { - if (r == 1) - error_msg("%s: login already in use\n", p->pw_name); - else if (r == 2) - error_msg("illegal uid or no uids left\n"); - else if (r == 3) - error_msg("group name %s already in use\n", p->pw_name); - else - error_msg("generic error.\n"); - /* return -1; */ - return 1; - } - - /* add to passwd */ - if (putpwent(p, passwd) == -1) { - /* return -1; */ - return 1; - } - fclose(passwd); - - /* add to shadow if necessary */ - if (shadow_enabled) { - shadow = fopen_wrapper(SHADOW_FILE, "a"); - if (shadow == NULL) { - /* return -1; */ - return 1; - } - fseek(shadow, 0, SEEK_END); - sp = pwd_to_spwd(p); - sp->sp_max = 99999; /* debianish */ - sp->sp_warn = 7; - fprintf(shadow, "%s:!:%ld:%ld:%ld:%ld:::\n", - sp->sp_namp, sp->sp_lstchg, sp->sp_min, sp->sp_max, - sp->sp_warn); - fclose(shadow); - } - - /* add to group */ - /* addgroup should be responsible for dealing w/ gshadow */ - addgroup_wrapper(p->pw_name, p->pw_gid); - - /* Clear the umask for this process so it doesn't - * * screw up the permissions on the mkdir and chown. */ - umask(0); - - /* mkdir */ - if (mkdir(p->pw_dir, 0755)) { - perror_msg("%s", p->pw_dir); - } - /* Set the owner and group so it is owned by the new user. */ - if (chown(p->pw_dir, p->pw_uid, p->pw_gid)) { - perror_msg("%s", p->pw_dir); - } - /* Now fix up the permissions to 2755. Can't do it before now - * since chown will clear the setgid bit */ - if (chmod(p->pw_dir, 02755)) { - perror_msg("%s", p->pw_dir); - } - /* interactively set passwd */ - passwd_wrapper(p->pw_name); - - return 0; -} - - -/* return current uid (root is always uid == 0, right?) */ -static uid_t i_am_not_root() -{ - return geteuid(); -} - -/* - * adduser will take a login_name as its first parameter. - * - * home - * shell - * gecos - * - * can be customized via command-line parameters. - * ________________________________________________________________________ */ -int adduser_main(int argc, char **argv) -{ - int i; - char opt; - char *login; - char *gecos; - char *home = NULL; - char *shell; - char path[MAXPATHLEN]; - - struct passwd pw; - - /* init */ - if (argc < 2) { - show_usage(); - } - gecos = default_gecos; - shell = default_shell; - - /* get args */ - for (i = 1; i < argc; i++) { - if (argv[i][0] == '-') { - opt = argv[i][1]; - switch (opt) { - case 'h': - home = argv[++i]; - break; - case 'g': - gecos = argv[++i]; - break; - case 's': - shell = argv[++i]; - break; - default: - error_msg("invalid option -- %c\n", opt); - break; - } - } else { - break; - } - } - - /* got root? */ - if (i_am_not_root()) { - error_msg_and_die( "Only root may add a user or group to the system.\n"); - } - - /* get login */ - if (i >= argc) { - error_msg_and_die( "adduser: no user specified\n"); - } - login = argv[i]; - - /* create string for $HOME if not specified already */ - if (!home) { - snprintf(path, MAXPATHLEN, "%s/%s", default_home_prefix, login); - path[MAXPATHLEN - 1] = 0; - home = path; - } - /* is /etc/shadow in use? */ - shadow_enabled = (0 == access(SHADOW_FILE, F_OK)); - - /* create a passwd struct */ - pw.pw_name = login; - pw.pw_passwd = default_passwd; - pw.pw_uid = 0; - pw.pw_gid = 0; - pw.pw_gecos = gecos; - pw.pw_dir = home; - pw.pw_shell = shell; - - /* grand finale */ - i = adduser(PASSWD_FILE, &pw); - - return (i); -} - -/* $Id: adduser.c,v 1.1 2001/08/21 16:18:59 andersen Exp $ */ diff --git a/adjtimex.c b/adjtimex.c deleted file mode 100644 index e3c160d87..000000000 --- a/adjtimex.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * adjtimex.c - read, and possibly modify, the Linux kernel `timex' variables. - * - * Originally written: October 1997 - * Last hack: March 2001 - * Copyright 1997, 2000, 2001 Larry Doolittle - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License (Version 2, - * June 1991) as published by the Free Software Foundation. At the - * time of writing, that license was published by the FSF with the URL - * http://www.gnu.org/copyleft/gpl.html, and is incorporated herein by - * reference. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * This adjtimex(1) is very similar in intent to adjtimex(8) by Steven - * Dick and Jim Van Zandt - * (see http://metalab.unc.edu/pub/Linux/system/admin/time/adjtimex*). - * That version predates this one, and is _much_ bigger and more - * featureful. My independently written version was very similar to - * Steven's from the start, because they both follow the kernel timex - * structure. I further tweaked this version to be equivalent to Steven's - * where possible, but I don't like getopt_long, so the actual usage - * syntax is incompatible. - * - * Amazingly enough, my Red Hat 5.2 sys/timex (and sub-includes) - * don't actually give a prototype for adjtimex(2), so building - * this code (with -Wall) gives a warning. Later versions of - * glibc fix this issue. - * - * This program is too simple for a Makefile, just build with: - * gcc -Wall -O adjtimex.c -o adjtimex - * - * busyboxed 20 March 2001, Larry Doolittle - * It will autosense if it is built in a busybox environment, based - * on the BB_VER preprocessor macro. - */ - -#include -#include -#include -#include - -#if __GNU_LIBRARY__ < 5 -#include -extern int adjtimex(struct timex *buf); -#else -#include -#endif - -#ifdef BB_VER -#include "busybox.h" -#endif - -static struct {int bit; char *name;} statlist[] = { - { STA_PLL, "PLL" }, - { STA_PPSFREQ, "PPSFREQ" }, - { STA_PPSTIME, "PPSTIME" }, - { STA_FLL, "FFL" }, - { STA_INS, "INS" }, - { STA_DEL, "DEL" }, - { STA_UNSYNC, "UNSYNC" }, - { STA_FREQHOLD, "FREQHOLD" }, - { STA_PPSSIGNAL, "PPSSIGNAL" }, - { STA_PPSJITTER, "PPSJITTER" }, - { STA_PPSWANDER, "PPSWANDER" }, - { STA_PPSERROR, "PPSERROR" }, - { STA_CLOCKERR, "CLOCKERR" }, - { 0, NULL } }; - -static char *ret_code_descript[] = { - "clock synchronized", - "insert leap second", - "delete leap second", - "leap second in progress", - "leap second has occurred", - "clock not synchronized" }; - -#ifdef BB_VER -#define main adjtimex_main -#else -void usage(char *prog) -{ - fprintf(stderr, - "Usage: %s [ -q ] [ -o offset ] [ -f frequency ] [ -p timeconstant ] [ -t tick ]\n", - prog); -} -#define show_usage() usage(argv[0]) -#endif - -int main(int argc, char ** argv) -{ - struct timex txc; - int quiet=0; - int c, i, ret, sep; - char *descript; - txc.modes=0; - for (;;) { - c = getopt( argc, argv, "qo:f:p:t:"); - if (c == EOF) break; - switch (c) { - case 'q': - quiet=1; - break; - case 'o': - txc.offset = atoi(optarg); - txc.modes |= ADJ_OFFSET_SINGLESHOT; - break; - case 'f': - txc.freq = atoi(optarg); - txc.modes |= ADJ_FREQUENCY; - break; - case 'p': - txc.constant = atoi(optarg); - txc.modes |= ADJ_TIMECONST; - break; - case 't': - txc.tick = atoi(optarg); - txc.modes |= ADJ_TICK; - break; - default: - show_usage(); - exit(1); - } - } - if (argc != optind) { /* no valid non-option parameters */ - show_usage(); - exit(1); - } - - ret = adjtimex(&txc); - - if (ret < 0) perror("adjtimex"); - - if (!quiet && ret>=0) { - printf( - " mode: %d\n" - "-o offset: %ld\n" - "-f frequency: %ld\n" - " maxerror: %ld\n" - " esterror: %ld\n" - " status: %d ( ", - txc.modes, txc.offset, txc.freq, txc.maxerror, - txc.esterror, txc.status); - - /* representative output of next code fragment: - "PLL | PPSTIME" */ - sep=0; - for (i=0; statlist[i].name; i++) { - if (txc.status & statlist[i].bit) { - if (sep) fputs(" | ",stdout); - fputs(statlist[i].name,stdout); - sep=1; - } - } - - descript = "error"; - if (ret >= 0 && ret <= 5) descript = ret_code_descript[ret]; - printf(" )\n" - "-p timeconstant: %ld\n" - " precision: %ld\n" - " tolerance: %ld\n" - "-t tick: %ld\n" - " time.tv_sec: %ld\n" - " time.tv_usec: %ld\n" - " return value: %d (%s)\n", - txc.constant, - txc.precision, txc.tolerance, txc.tick, - (long)txc.time.tv_sec, (long)txc.time.tv_usec, ret, descript); - } - return (ret<0); -} diff --git a/applets.c b/applets.c deleted file mode 100644 index f3e56a9f3..000000000 --- a/applets.c +++ /dev/null @@ -1,116 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Utility routines. - * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * - */ - -#include -#include -#include -#include "busybox.h" - -#undef APPLET -#undef APPLET_NOUSAGE -#undef PROTOTYPES -#include "applets.h" - -struct BB_applet *applet_using; - -/* The -1 arises because of the {0,NULL,0,-1} entry above. */ -const size_t NUM_APPLETS = (sizeof (applets) / sizeof (struct BB_applet) - 1); - -extern void show_usage(void) -{ - const char *format_string; - const char *usage_string = usage_messages; - int i; - - for (i = applet_using - applets; i > 0; ) { - if (!*usage_string++) { - --i; - } - } - format_string = "%s\n\nUsage: %s %s\n\n"; - if(*usage_string == 0) - format_string = "%s\n\nNo help available.\n\n"; - fprintf(stderr, format_string, - full_version, applet_using->name, usage_string); - exit(EXIT_FAILURE); -} - -static int applet_name_compare(const void *x, const void *y) -{ - const char *name = x; - const struct BB_applet *applet = y; - - return strcmp(name, applet->name); -} - -extern const size_t NUM_APPLETS; - -struct BB_applet *find_applet_by_name(const char *name) -{ - return bsearch(name, applets, NUM_APPLETS, sizeof(struct BB_applet), - applet_name_compare); -} - -void run_applet_by_name(const char *name, int argc, char **argv) -{ - static int recurse_level = 0; - extern int been_there_done_that; /* From busybox.c */ - - recurse_level++; - /* Do a binary search to find the applet entry given the name. */ - if ((applet_using = find_applet_by_name(name)) != NULL) { - applet_name = applet_using->name; - if (argv[1] && strcmp(argv[1], "--help") == 0) { - if (strcmp(applet_using->name, "busybox")==0) { - if(argv[2]) - applet_using = find_applet_by_name(argv[2]); - else - applet_using = NULL; - } - if(applet_using) - show_usage(); - been_there_done_that=1; - busybox_main(0, NULL); - } - exit((*(applet_using->main)) (argc, argv)); - } - /* Just in case they have renamed busybox - Check argv[1] */ - if (recurse_level == 1) { - run_applet_by_name("busybox", argc, argv); - } - recurse_level--; -} - - -/* END CODE */ -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ diff --git a/applets.h b/applets.h deleted file mode 100644 index 5ecfe3cba..000000000 --- a/applets.h +++ /dev/null @@ -1,500 +0,0 @@ -/* - * applets.h - a listing of all busybox applets. - * - * If you write a new applet, you need to add an entry to this list to make - * busybox aware of it. - * - * It is CRUCIAL that this listing be kept in ascii order, otherwise the binary - * search lookup contributed by Gaute B Strokkenes stops working. If you value - * your kneecaps, you'll be sure to *make sure* that any changes made to this - * file result in the listing remaining in ascii order. You have been warned. - */ - -#undef APPLET -#undef APPLET_ODDNAME -#undef APPLET_NOUSAGE - - -#if defined(PROTOTYPES) - #define APPLET(a,b,c) extern int b(int argc, char **argv); - #define APPLET_NOUSAGE(a,b,c) extern int b(int argc, char **argv); - #define APPLET_ODDNAME(a,b,c,d) extern int b(int argc, char **argv); - extern const char usage_messages[]; -#elif defined(MAKE_USAGE) - #ifdef BB_FEATURE_VERBOSE_USAGE - #define APPLET(a,b,c) a##_trivial_usage "\n\n" a##_full_usage "\0" - #define APPLET_NOUSAGE(a,b,c) "\0" - #define APPLET_ODDNAME(a,b,c,d) d##_trivial_usage "\n\n" d##_full_usage "\0" - #else - #define APPLET(a,b,c) a##_trivial_usage "\0" - #define APPLET_NOUSAGE(a,b,c) "\0" - #define APPLET_ODDNAME(a,b,c,d) d##_trivial_usage "\0" - #endif -#elif defined(MAKE_LINKS) -# define APPLET(a,b,c) LINK c a -# define APPLET_NOUSAGE(a,b,c) LINK c a -# define APPLET_ODDNAME(a,b,c,d) LINK c a -#else - const struct BB_applet applets[] = { - #define APPLET(a,b,c) {#a,b,c}, - #define APPLET_NOUSAGE(a,b,c) {a,b,c}, - #define APPLET_ODDNAME(a,b,c,d) {a,b,c}, -#endif - - - -#ifdef BB_TEST - APPLET_NOUSAGE("[", test_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_ADDGROUP - APPLET(addgroup, addgroup_main, _BB_DIR_BIN) -#endif -#ifdef BB_ADDUSER - APPLET(adduser, adduser_main, _BB_DIR_BIN) -#endif -#ifdef BB_ADJTIMEX - APPLET(adjtimex, adjtimex_main, _BB_DIR_SBIN) -#endif -#ifdef BB_AR - APPLET(ar, ar_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_ASH - APPLET_NOUSAGE("ash", ash_main, _BB_DIR_BIN) -#endif -#ifdef BB_BASENAME - APPLET(basename, basename_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_BUNZIP2 - APPLET(bunzip2, bunzip2_main, _BB_DIR_USR_BIN) -#endif - APPLET_NOUSAGE("busybox", busybox_main, _BB_DIR_BIN) -#ifdef BB_CAT - APPLET(cat, cat_main, _BB_DIR_BIN) -#endif -#ifdef BB_CHGRP - APPLET(chgrp, chgrp_main, _BB_DIR_BIN) -#endif -#ifdef BB_CHMOD - APPLET(chmod, chmod_main, _BB_DIR_BIN) -#endif -#ifdef BB_CHOWN - APPLET(chown, chown_main, _BB_DIR_BIN) -#endif -#ifdef BB_CHROOT - APPLET(chroot, chroot_main, _BB_DIR_USR_SBIN) -#endif -#ifdef BB_CHVT - APPLET(chvt, chvt_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_CLEAR - APPLET(clear, clear_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_CMP - APPLET(cmp, cmp_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_CP - APPLET(cp, cp_main, _BB_DIR_BIN) -#endif -#ifdef BB_CPIO - APPLET(cpio, cpio_main, _BB_DIR_BIN) -#endif -#ifdef BB_CUT - APPLET(cut, cut_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_DATE - APPLET(date, date_main, _BB_DIR_BIN) -#endif -#ifdef BB_DC - APPLET(dc, dc_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_DD - APPLET(dd, dd_main, _BB_DIR_BIN) -#endif -#ifdef BB_DEALLOCVT - APPLET(deallocvt, deallocvt_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_DELGROUP - APPLET(delgroup, delgroup_main, _BB_DIR_BIN) -#endif -#ifdef BB_DELUSER - APPLET(deluser, deluser_main, _BB_DIR_BIN) -#endif -#ifdef BB_DF - APPLET(df, df_main, _BB_DIR_BIN) -#endif -#ifdef BB_DIRNAME - APPLET(dirname, dirname_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_DMESG - APPLET(dmesg, dmesg_main, _BB_DIR_BIN) -#endif -#ifdef BB_DOS2UNIX - APPLET(dos2unix, dos2unix_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_DPKG - APPLET(dpkg, dpkg_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_DPKG_DEB - APPLET_ODDNAME("dpkg-deb", dpkg_deb_main, _BB_DIR_USR_BIN, dpkg_deb) -#endif -#ifdef BB_DU - APPLET(du, du_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_DUMPKMAP - APPLET(dumpkmap, dumpkmap_main, _BB_DIR_BIN) -#endif -#ifdef BB_DUTMP - APPLET(dutmp, dutmp_main, _BB_DIR_USR_SBIN) -#endif -#ifdef BB_ECHO - APPLET(echo, echo_main, _BB_DIR_BIN) -#endif -#if defined(BB_FEATURE_GREP_EGREP_ALIAS) && defined(BB_GREP) - APPLET_NOUSAGE("egrep", grep_main, _BB_DIR_BIN) -#endif -#ifdef BB_ENV - APPLET(env, env_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_EXPR - APPLET(expr, expr_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_TRUE_FALSE - APPLET(false, false_main, _BB_DIR_BIN) -#endif -#ifdef BB_FBSET - APPLET(fbset, fbset_main, _BB_DIR_USR_SBIN) -#endif -#ifdef BB_FDFLUSH - APPLET(fdflush, fdflush_main, _BB_DIR_BIN) -#endif -#ifdef BB_FIND - APPLET(find, find_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_FREE - APPLET(free, free_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_FREERAMDISK - APPLET(freeramdisk, freeramdisk_main, _BB_DIR_SBIN) -#endif -#ifdef BB_FSCK_MINIX - APPLET_ODDNAME("fsck.minix", fsck_minix_main, _BB_DIR_SBIN, fsck_minix) -#endif -#ifdef BB_GETOPT - APPLET(getopt, getopt_main, _BB_DIR_BIN) -#endif -#ifdef BB_GETTY - APPLET(getty, getty_main, _BB_DIR_SBIN) -#endif -#ifdef BB_GREP - APPLET(grep, grep_main, _BB_DIR_BIN) -#endif -#ifdef BB_GUNZIP - APPLET(gunzip, gunzip_main, _BB_DIR_BIN) -#endif -#ifdef BB_GZIP - APPLET(gzip, gzip_main, _BB_DIR_BIN) -#endif -#ifdef BB_HALT - APPLET(halt, halt_main, _BB_DIR_SBIN) -#endif -#ifdef BB_HEAD - APPLET(head, head_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_HOSTID - APPLET(hostid, hostid_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_HOSTNAME - APPLET(hostname, hostname_main, _BB_DIR_BIN) -#endif -#ifdef BB_HUSH - APPLET_NOUSAGE("hush", hush_main, _BB_DIR_BIN) -#endif -#ifdef BB_ID - APPLET(id, id_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_IFCONFIG - APPLET(ifconfig, ifconfig_main, _BB_DIR_SBIN) -#endif -#ifdef BB_INIT - APPLET(init, init_main, _BB_DIR_SBIN) -#endif -#ifdef BB_INSMOD - APPLET(insmod, insmod_main, _BB_DIR_SBIN) -#endif -#ifdef BB_KILL - APPLET(kill, kill_main, _BB_DIR_BIN) -#endif -#ifdef BB_KILLALL - APPLET(killall, kill_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_KLOGD - APPLET(klogd, klogd_main, _BB_DIR_SBIN) -#endif -#ifdef BB_LASH - APPLET(lash, lash_main, _BB_DIR_BIN) -#endif -#ifdef BB_LENGTH - APPLET(length, length_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_FEATURE_LINUXRC - APPLET_NOUSAGE("linuxrc", init_main, _BB_DIR_ROOT) -#endif -#ifdef BB_LN - APPLET(ln, ln_main, _BB_DIR_BIN) -#endif -#ifdef BB_LOADACM - APPLET(loadacm, loadacm_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_LOADFONT - APPLET(loadfont, loadfont_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_LOADKMAP - APPLET(loadkmap, loadkmap_main, _BB_DIR_SBIN) -#endif -#ifdef BB_LOGGER - APPLET(logger, logger_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_LOGNAME - APPLET(logname, logname_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_LOGREAD - APPLET(logread, logread_main, _BB_DIR_SBIN) -#endif -#ifdef BB_LS - APPLET(ls, ls_main, _BB_DIR_BIN) -#endif -#ifdef BB_LSMOD - APPLET(lsmod, lsmod_main, _BB_DIR_SBIN) -#endif -#ifdef BB_MAKEDEVS - APPLET(makedevs, makedevs_main, _BB_DIR_SBIN) -#endif -#ifdef BB_MD5SUM - APPLET(md5sum, md5sum_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_MKDIR - APPLET(mkdir, mkdir_main, _BB_DIR_BIN) -#endif -#ifdef BB_MKFIFO - APPLET(mkfifo, mkfifo_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_MKFS_MINIX - APPLET_ODDNAME("mkfs.minix", mkfs_minix_main, _BB_DIR_SBIN, mkfs_minix) -#endif -#ifdef BB_MKNOD - APPLET(mknod, mknod_main, _BB_DIR_BIN) -#endif -#ifdef BB_MKSWAP - APPLET(mkswap, mkswap_main, _BB_DIR_SBIN) -#endif -#ifdef BB_MKTEMP - APPLET(mktemp, mktemp_main, _BB_DIR_BIN) -#endif -#ifdef BB_MODPROBE - APPLET(modprobe, modprobe_main, _BB_DIR_SBIN) -#endif -#ifdef BB_MORE - APPLET(more, more_main, _BB_DIR_BIN) -#endif -#ifdef BB_MOUNT - APPLET(mount, mount_main, _BB_DIR_BIN) -#endif -#ifdef BB_MSH - APPLET_NOUSAGE("msh", msh_main, _BB_DIR_BIN) -#endif -#ifdef BB_MT - APPLET(mt, mt_main, _BB_DIR_BIN) -#endif -#ifdef BB_MV - APPLET(mv, mv_main, _BB_DIR_BIN) -#endif -#ifdef BB_NC - APPLET(nc, nc_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_NSLOOKUP - APPLET(nslookup, nslookup_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_PIDOF - APPLET(pidof, pidof_main, _BB_DIR_BIN) -#endif -#ifdef BB_PING - APPLET(ping, ping_main, _BB_DIR_BIN) -#endif -#ifdef BB_PIVOT_ROOT - APPLET(pivot_root, pivot_root_main, _BB_DIR_SBIN) -#endif -#ifdef BB_POWEROFF - APPLET(poweroff, poweroff_main, _BB_DIR_SBIN) -#endif -#ifdef BB_PRINTF - APPLET(printf, printf_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_PS - APPLET(ps, ps_main, _BB_DIR_BIN) -#endif -#ifdef BB_PWD - APPLET(pwd, pwd_main, _BB_DIR_BIN) -#endif -#ifdef BB_RDATE - APPLET(rdate, rdate_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_READLINK - APPLET(readlink, readlink_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_REBOOT - APPLET(reboot, reboot_main, _BB_DIR_SBIN) -#endif -#ifdef BB_RENICE - APPLET(renice, renice_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_RESET - APPLET(reset, reset_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_RM - APPLET(rm, rm_main, _BB_DIR_BIN) -#endif -#ifdef BB_RMDIR - APPLET(rmdir, rmdir_main, _BB_DIR_BIN) -#endif -#ifdef BB_RMMOD - APPLET(rmmod, rmmod_main, _BB_DIR_SBIN) -#endif -#ifdef BB_ROUTE - APPLET(route, route_main, _BB_DIR_SBIN) -#endif -#ifdef BB_RPM2CPIO - APPLET(rpm2cpio, rpm2cpio_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_SED - APPLET(sed, sed_main, _BB_DIR_BIN) -#endif -#ifdef BB_SETKEYCODES - APPLET(setkeycodes, setkeycodes_main, _BB_DIR_USR_BIN) -#endif -#if defined(BB_FEATURE_SH_IS_ASH) && defined(BB_ASH) - APPLET_NOUSAGE("sh", ash_main, _BB_DIR_BIN) -#elif defined(BB_FEATURE_SH_IS_HUSH) && defined(BB_HUSH) - APPLET_NOUSAGE("sh", hush_main, _BB_DIR_BIN) -#elif defined(BB_FEATURE_SH_IS_LASH) && defined(BB_LASH) - APPLET_NOUSAGE("sh", lash_main, _BB_DIR_BIN) -#elif defined(BB_FEATURE_SH_IS_MSH) && defined(BB_MSH) - APPLET_NOUSAGE("sh", msh_main, _BB_DIR_BIN) -#endif -#ifdef BB_SLEEP - APPLET(sleep, sleep_main, _BB_DIR_BIN) -#endif -#ifdef BB_SORT - APPLET(sort, sort_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_START_STOP_DAEMON - APPLET_ODDNAME("start-stop-daemon", start_stop_daemon_main, _BB_DIR_SBIN, start_stop_daemon) -#endif -#ifdef BB_STTY - APPLET(stty, stty_main, _BB_DIR_BIN) -#endif -#ifdef BB_SWAPONOFF - APPLET(swapoff, swap_on_off_main, _BB_DIR_SBIN) -#endif -#ifdef BB_SWAPONOFF - APPLET(swapon, swap_on_off_main, _BB_DIR_SBIN) -#endif -#ifdef BB_SYNC - APPLET(sync, sync_main, _BB_DIR_BIN) -#endif -#ifdef BB_SYSLOGD - APPLET(syslogd, syslogd_main, _BB_DIR_SBIN) -#endif -#ifdef BB_TAIL - APPLET(tail, tail_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_TAR - APPLET(tar, tar_main, _BB_DIR_BIN) -#endif -#ifdef BB_TEE - APPLET(tee, tee_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_TELNET - APPLET(telnet, telnet_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_TEST - APPLET(test, test_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_TFTP - APPLET(tftp, tftp_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_TOUCH - APPLET(touch, touch_main, _BB_DIR_BIN) -#endif -#ifdef BB_TR - APPLET(tr, tr_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_TRACEROUTE - APPLET(traceroute, traceroute_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_TRUE_FALSE - APPLET(true, true_main, _BB_DIR_BIN) -#endif -#ifdef BB_TTY - APPLET(tty, tty_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_UMOUNT - APPLET(umount, umount_main, _BB_DIR_BIN) -#endif -#ifdef BB_UNAME - APPLET(uname, uname_main, _BB_DIR_BIN) -#endif -#ifdef BB_UNIQ - APPLET(uniq, uniq_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_UNIX2DOS - APPLET(unix2dos, dos2unix_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_UPDATE - APPLET(update, update_main, _BB_DIR_SBIN) -#endif -#ifdef BB_UPTIME - APPLET(uptime, uptime_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_USLEEP - APPLET(usleep, usleep_main, _BB_DIR_BIN) -#endif -#ifdef BB_UUDECODE - APPLET(uudecode, uudecode_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_UUENCODE - APPLET(uuencode, uuencode_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_VI - APPLET(vi, vi_main, _BB_DIR_BIN) -#endif -#ifdef BB_WATCHDOG - APPLET(watchdog, watchdog_main, _BB_DIR_SBIN) -#endif -#ifdef BB_WC - APPLET(wc, wc_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_WGET - APPLET(wget, wget_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_WHICH - APPLET(which, which_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_WHOAMI - APPLET(whoami, whoami_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_XARGS - APPLET(xargs, xargs_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_YES - APPLET(yes, yes_main, _BB_DIR_USR_BIN) -#endif -#ifdef BB_GUNZIP - APPLET(zcat, gunzip_main, _BB_DIR_BIN) -#endif - -#if !defined(PROTOTYPES) && !defined(MAKE_USAGE) - { 0,NULL,0 } -}; - -#endif - diff --git a/applets/busybox.c b/applets/busybox.c index 33efb5d84..e6e5eca2d 100644 --- a/applets/busybox.c +++ b/applets/busybox.c @@ -5,14 +5,14 @@ #include #include #include "busybox.h" -#ifdef BB_LOCALE_SUPPORT +#ifdef CONFIG_LOCALE_SUPPORT #include #endif int been_there_done_that = 0; /* Also used in applets.c */ const char *applet_name; -#ifdef BB_FEATURE_INSTALLER +#ifdef CONFIG_FEATURE_INSTALLER /* * directory table * this should be consistent w/ the enum, busybox.h::Location, @@ -63,7 +63,7 @@ static void install_links(const char *busybox, int use_symbolic_links) } } -#endif /* BB_FEATURE_INSTALLER */ +#endif /* CONFIG_FEATURE_INSTALLER */ int main(int argc, char **argv) { @@ -79,8 +79,8 @@ int main(int argc, char **argv) applet_name = s; } -#ifdef BB_LOCALE_SUPPORT -#ifdef BB_INIT +#ifdef CONFIG_LOCALE_SUPPORT +#ifdef CONFIG_INIT if(getpid()!=1) /* Do not set locale for `init' */ #endif { @@ -97,7 +97,7 @@ int busybox_main(int argc, char **argv) { int col = 0, len, i; -#ifdef BB_FEATURE_INSTALLER +#ifdef CONFIG_FEATURE_INSTALLER /* * This style of argument parsing doesn't scale well * in the event that busybox starts wanting more --options. @@ -125,7 +125,7 @@ int busybox_main(int argc, char **argv) } return rc; } -#endif /* BB_FEATURE_INSTALLER */ +#endif /* CONFIG_FEATURE_INSTALLER */ argc--; diff --git a/applets/busybox.sh b/applets/busybox.sh index 9ab0f4bdb..6ac4e8043 100755 --- a/applets/busybox.sh +++ b/applets/busybox.sh @@ -5,11 +5,11 @@ export LC_CTYPE=POSIX RAW=` \ $CC -E -dM ${1:-Config.h} | \ - sed -n -e '/^.*BB_FEATURE.*$/d;s/^#define.*\/\1.c/gp;' \ + sed -n -e '/^.*CONFIG_FEATURE.*$/d;s/^#define.*\/\1.c/gp;' \ | tr A-Z a-z | sort ` test "${RAW}" != "" || exit -if [ -d "$BB_SRC_DIR" ]; then cd $BB_SRC_DIR; fi +if [ -d "$CONFIG_SRC_DIR" ]; then cd $CONFIG_SRC_DIR; fi # By running $RAW through "ls", we avoid listing # source files that don't exist. ls $RAW 2>/dev/null | tr '\n' ' ' diff --git a/applets/usage.h b/applets/usage.h index 5e514274a..1de29666e 100644 --- a/applets/usage.h +++ b/applets/usage.h @@ -247,7 +247,7 @@ #define deluser_full_usage \ "Deletes user USER from the system" -#ifdef BB_FEATURE_HUMAN_READABLE +#ifdef CONFIG_FEATURE_HUMAN_READABLE #define USAGE_HUMAN_READABLE(a) a #define USAGE_NOT_HUMAN_READABLE(a) #else @@ -464,17 +464,17 @@ #define fdflush_full_usage \ "Forces floppy disk drive to detect disk change" -#ifdef BB_FEATURE_FIND_TYPE +#ifdef CONFIG_FEATURE_FIND_TYPE #define USAGE_FIND_TYPE(a) a #else #define USAGE_FIND_TYPE(a) #endif -#ifdef BB_FEATURE_FIND_PERM +#ifdef CONFIG_FEATURE_FIND_PERM #define USAGE_FIND_PERM(a) a #else #define USAGE_FIND_PERM(a) #endif -#ifdef BB_FEATURE_FIND_MTIME +#ifdef CONFIG_FEATURE_FIND_MTIME #define USAGE_FIND_MTIME(a) a #else #define USAGE_FIND_MTIME(a) @@ -678,22 +678,22 @@ "$ id\n" \ "uid=1000(andersen) gid=1000(andersen)\n" -#ifdef BB_FEATURE_IFCONFIG_SLIP +#ifdef CONFIG_FEATURE_IFCONFIG_SLIP #define USAGE_SIOCSKEEPALIVE(a) a #else #define USAGE_SIOCSKEEPALIVE(a) #endif -#ifdef BB_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ +#ifdef CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ #define USAGE_IFCONFIG_MII(a) a #else #define USAGE_IFCONFIG_MII(a) #endif -#ifdef BB_FEATURE_IFCONFIG_HW +#ifdef CONFIG_FEATURE_IFCONFIG_HW #define USAGE_IFCONFIG_HW(a) a #else #define USAGE_IFCONFIG_HW(a) #endif -#ifdef BB_FEATURE_IFCONFIG_STATUS +#ifdef CONFIG_FEATURE_IFCONFIG_STATUS #define USAGE_IFCONFIG_OPT_A(a) a #else #define USAGE_IFCONFIG_OPT_A(a) @@ -950,32 +950,32 @@ #define logread_full_usage \ "Shows the messages from syslogd (using circular buffer)." -#ifdef BB_FEATURE_LS_TIMESTAMPS +#ifdef CONFIG_FEATURE_LS_TIMESTAMPS #define USAGE_LS_TIMESTAMPS(a) a #else #define USAGE_LS_TIMESTAMPS(a) #endif -#ifdef BB_FEATURE_LS_FILETYPES +#ifdef CONFIG_FEATURE_LS_FILETYPES #define USAGE_LS_FILETYPES(a) a #else #define USAGE_LS_FILETYPES(a) #endif -#ifdef BB_FEATURE_LS_FOLLOWLINKS +#ifdef CONFIG_FEATURE_LS_FOLLOWLINKS #define USAGE_LS_FOLLOWLINKS(a) a #else #define USAGE_LS_FOLLOWLINKS(a) #endif -#ifdef BB_FEATURE_LS_RECURSIVE +#ifdef CONFIG_FEATURE_LS_RECURSIVE #define USAGE_LS_RECURSIVE(a) a #else #define USAGE_LS_RECURSIVE(a) #endif -#ifdef BB_FEATURE_LS_SORTFILES +#ifdef CONFIG_FEATURE_LS_SORTFILES #define USAGE_LS_SORTFILES(a) a #else #define USAGE_LS_SORTFILES(a) #endif -#ifdef BB_FEATURE_AUTOWIDTH +#ifdef CONFIG_FEATURE_AUTOWIDTH #define USAGE_AUTOWIDTH(a) a #else #define USAGE_AUTOWIDTH(a) @@ -1145,12 +1145,12 @@ #define more_example_usage \ "$ dmesg | more\n" -#ifdef BB_FEATURE_MOUNT_LOOP +#ifdef CONFIG_FEATURE_MOUNT_LOOP #define USAGE_MOUNT_LOOP(a) a #else #define USAGE_MOUNT_LOOP(a) #endif -#ifdef BB_FEATURE_MTAB_SUPPORT +#ifdef CONFIG_FEATURE_MTAB_SUPPORT #define USAGE_MTAB(a) a #else #define USAGE_MTAB(a) @@ -1245,7 +1245,7 @@ "$ pidof init\n" \ "1\n" -#ifndef BB_FEATURE_FANCY_PING +#ifndef CONFIG_FEATURE_FANCY_PING #define ping_trivial_usage "host" #define ping_full_usage "Send ICMP ECHO_REQUEST packets to network hosts" #else @@ -1431,12 +1431,12 @@ "[2 second delay results]\n" -#ifdef BB_FEATURE_SORT_UNIQUE +#ifdef CONFIG_FEATURE_SORT_UNIQUE #define USAGE_SORT_UNIQUE(a) a #else #define USAGE_SORT_UNIQUE(a) #endif -#ifdef BB_FEATURE_SORT_REVERSE +#ifdef CONFIG_FEATURE_SORT_REVERSE #define USAGE_SORT_REVERSE(a) a #else #define USAGE_SORT_REVERSE(a) @@ -1503,7 +1503,7 @@ "Write all buffered filesystem blocks to disk." -#ifdef BB_FEATURE_REMOTE_LOG +#ifdef CONFIG_FEATURE_REMOTE_LOG #define USAGE_REMOTE_LOG(a) a #else #define USAGE_REMOTE_LOG(a) @@ -1525,7 +1525,7 @@ "$ syslogd -R 192.168.1.1:601\n" -#ifndef BB_FEATURE_FANCY_TAIL +#ifndef CONFIG_FEATURE_FANCY_TAIL #define USAGE_UNSIMPLE_TAIL(a) #else #define USAGE_UNSIMPLE_TAIL(a) a @@ -1550,12 +1550,12 @@ "$ tail -n 1 /etc/resolv.conf\n" \ "nameserver 10.0.0.1\n" -#ifdef BB_FEATURE_TAR_CREATE +#ifdef CONFIG_FEATURE_TAR_CREATE #define USAGE_TAR_CREATE(a) a #else #define USAGE_TAR_CREATE(a) #endif -#ifdef BB_FEATURE_TAR_EXCLUDE +#ifdef CONFIG_FEATURE_TAR_EXCLUDE #define USAGE_TAR_EXCLUDE(a) a #else #define USAGE_TAR_EXCLUDE(a) @@ -1619,17 +1619,17 @@ "$ echo $?\n" \ "1\n" -#ifdef BB_FEATURE_TFTP_GET +#ifdef CONFIG_FEATURE_TFTP_GET #define USAGE_TFTP_GET(a) a #else #define USAGE_TFTP_GET(a) #endif -#ifdef BB_FEATURE_TFTP_PUT +#ifdef CONFIG_FEATURE_TFTP_PUT #define USAGE_TFTP_PUT(a) a #else #define USAGE_TFTP_PUT(a) #endif -#ifdef BB_FEATURE_TFTP_BLOCKSIZE +#ifdef CONFIG_FEATURE_TFTP_BLOCKSIZE #define USAGE_TFTP_BS(a) a #else #define USAGE_TFTP_BS(a) @@ -1719,7 +1719,7 @@ "$ tty\n" \ "/dev/tty2\n" -#ifdef BB_FEATURE_MOUNT_FORCE +#ifdef CONFIG_FEATURE_MOUNT_FORCE #define USAGE_MOUNT_FORCE(a) a #else #define USAGE_MOUNT_FORCE(a) diff --git a/ar.c b/ar.c deleted file mode 100644 index e02b2651e..000000000 --- a/ar.c +++ /dev/null @@ -1,89 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini ar implementation for busybox - * - * Copyright (C) 2000 by Glenn McGrath - * Written by Glenn McGrath 1 June 2000 - * - * Based in part on BusyBox tar, Debian dpkg-deb and GNU ar. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -#include -#include -#include -#include -#include -#include "busybox.h" - -extern int ar_main(int argc, char **argv) -{ - FILE *src_stream = NULL; - char **extract_names = NULL; - char ar_magic[8]; - int extract_function = extract_unconditional; - int opt; - int num_of_entries = 0; - extern off_t archive_offset; - - while ((opt = getopt(argc, argv, "ovtpx")) != -1) { - switch (opt) { - case 'o': - extract_function |= extract_preserve_date; - break; - case 'v': - extract_function |= extract_verbose_list; - break; - case 't': - extract_function |= extract_list; - break; - case 'p': - extract_function |= extract_to_stdout; - break; - case 'x': - extract_function |= extract_all_to_fs; - break; - default: - show_usage(); - } - } - - /* check the src filename was specified */ - if (optind == argc) { - show_usage(); - } - - src_stream = xfopen(argv[optind++], "r"); - - /* check ar magic */ - fread(ar_magic, 1, 8, src_stream); - archive_offset = 8; - if (strncmp(ar_magic,"!",7) != 0) { - error_msg_and_die("invalid magic"); - } - - /* Create a list of files to extract */ - while (optind < argc) { - extract_names = xrealloc(extract_names, sizeof(char *) * (num_of_entries + 2)); - extract_names[num_of_entries] = xstrdup(argv[optind]); - num_of_entries++; - extract_names[num_of_entries] = NULL; - optind++; - } - - unarchive(src_stream, stdout, &get_header_ar, extract_function, "./", extract_names, NULL); - return EXIT_SUCCESS; -} diff --git a/archival/Makefile b/archival/Makefile new file mode 100644 index 000000000..66c2d0b6b --- /dev/null +++ b/archival/Makefile @@ -0,0 +1,43 @@ +# Makefile for busybox +# +# Copyright (C) 1999,2000,2001 by Erik Andersen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +TOPDIR :=.. +L_TARGET := archival.a + +obj-y := +obj-n := +obj- := + +obj-$(CONFIG_AR) += ar.o +obj-$(CONFIG_BUNZIP2) += bunzip2.o +obj-$(CONFIG_CPIO) += cpio.o +obj-$(CONFIG_DPKG) += dpkg.o +obj-$(CONFIG_DPKG_DEB) += dpkg_deb.o +obj-$(CONFIG_GUNZIP) += gunzip.o +obj-$(CONFIG_GZIP) += gzip.o +obj-$(CONFIG_RPMUNPACK) += rpm2cpio.o +obj-$(CONFIG_TAR) += tar.o + + +# Hand off to toplevel Rules.mak +include $(TOPDIR)/Rules.mak + +clean: + rm -f $(L_TARGET) *.o core + diff --git a/archival/config.in b/archival/config.in new file mode 100644 index 000000000..c195f24a1 --- /dev/null +++ b/archival/config.in @@ -0,0 +1,19 @@ +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +mainmenu_option next_comment +comment 'Archival Utilities' + +bool 'ar' CONFIG_AR +bool 'bunzip2' CONFIG_BUNZIP2 +bool 'cpio' CONFIG_CPIO +bool 'dpkg' CONFIG_DPKG +bool 'dpkg_deb' CONFIG_DPKG_DEB +bool 'gunzip' CONFIG_GUNZIP +bool 'gzip' CONFIG_GZIP +bool 'rpm2cpio' CONFIG_RPM2CPIO +bool 'tar' CONFIG_TAR +endmenu + diff --git a/archival/gzip.c b/archival/gzip.c index 5c86c1070..df665c121 100644 --- a/archival/gzip.c +++ b/archival/gzip.c @@ -1231,7 +1231,7 @@ int gzip_main(int argc, char **argv) break; case 'q': break; -#ifdef BB_GUNZIP +#ifdef CONFIG_GUNZIP case 'd': optind = 1; return gunzip_main(argc, argv); diff --git a/archival/tar.c b/archival/tar.c index f7a3da66f..9e38eea75 100644 --- a/archival/tar.c +++ b/archival/tar.c @@ -9,8 +9,8 @@ * ground up. It still has remnents of the old code lying about, but it is * very different now (i.e., cleaner, less global variables, etc.) * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , + * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen * * Based in part in the tar implementation in sash * Copyright (c) 1999 by David I. Bell @@ -49,7 +49,7 @@ #include #include "busybox.h" -#ifdef BB_FEATURE_TAR_CREATE +#ifdef CONFIG_FEATURE_TAR_CREATE /* Tar file constants */ # define TAR_MAGIC "ustar" /* ustar and a null */ @@ -395,11 +395,11 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf, void* if (header_name[0] == '\0') return TRUE; -# if defined BB_FEATURE_TAR_EXCLUDE +# if defined CONFIG_FEATURE_TAR_EXCLUDE if (exclude_file(tbInfo->excludeList, header_name)) { return SKIP; } -# endif //BB_FEATURE_TAR_EXCLUDE +# endif //CONFIG_FEATURE_TAR_EXCLUDE if (writeTarHeader(tbInfo, header_name, fileName, statbuf)==FALSE) { return( FALSE); @@ -527,7 +527,7 @@ void append_file_list_to_list(char *filename, char ***name_list, int *num_of_ent fclose(src_stream); } -#ifdef BB_FEATURE_TAR_EXCLUDE +#ifdef CONFIG_FEATURE_TAR_EXCLUDE /* * Create a list of names that are in the include list AND NOT in the exclude lists */ @@ -626,7 +626,7 @@ int tar_main(int argc, char **argv) /* These are optional */ /* Exclude or Include files listed in */ -#ifdef BB_FEATURE_TAR_EXCLUDE +#ifdef CONFIG_FEATURE_TAR_EXCLUDE case 'X': append_file_list_to_list(optarg, &exclude_list, &exclude_list_count); break; @@ -660,7 +660,7 @@ int tar_main(int argc, char **argv) } extract_function |= extract_list; break; -#ifdef BB_FEATURE_TAR_GZIP +#ifdef CONFIG_FEATURE_TAR_GZIP case 'z': untar_funct |= untar_unzip; break; @@ -698,43 +698,43 @@ int tar_main(int argc, char **argv) } else { src_stream = stdin; } -#ifdef BB_FEATURE_TAR_GZIP +#ifdef CONFIG_FEATURE_TAR_GZIP /* Get a binary tree of all the tar file headers */ if (untar_funct & untar_unzip) { uncompressed_stream = gz_open(src_stream, &gunzip_pid); } else -#endif // BB_FEATURE_TAR_GZIP +#endif // CONFIG_FEATURE_TAR_GZIP uncompressed_stream = src_stream; /* extract or list archive */ unarchive(uncompressed_stream, stdout, &get_header_tar, extract_function, dst_prefix, include_list, exclude_list); fclose(uncompressed_stream); } -#ifdef BB_FEATURE_TAR_CREATE +#ifdef CONFIG_FEATURE_TAR_CREATE /* create an archive */ else if (untar_funct & untar_create) { int verboseFlag = FALSE; -#ifdef BB_FEATURE_TAR_GZIP +#ifdef CONFIG_FEATURE_TAR_GZIP if (untar_funct && untar_unzip) { error_msg_and_die("Creation of compressed tarfile not internally support by tar, pipe to busybox gunzip"); } -#endif // BB_FEATURE_TAR_GZIP +#endif // CONFIG_FEATURE_TAR_GZIP if (extract_function & extract_verbose_list) { verboseFlag = TRUE; } writeTarFile(src_filename, verboseFlag, &argv[argc - 1], include_list); } -#endif // BB_FEATURE_TAR_CREATE +#endif // CONFIG_FEATURE_TAR_CREATE /* Cleanups */ -#ifdef BB_FEATURE_TAR_GZIP +#ifdef CONFIG_FEATURE_TAR_GZIP if (untar_funct & untar_unzip) { fclose(src_stream); close(gz_fd); gz_close(gunzip_pid); } -#endif // BB_FEATURE_TAR_GZIP +#endif // CONFIG_FEATURE_TAR_GZIP if (src_filename) { free(src_filename); } diff --git a/ash.c b/ash.c deleted file mode 100644 index 486386a25..000000000 --- a/ash.c +++ /dev/null @@ -1,12825 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * ash shell port for busybox - * - * Copyright (c) 1989, 1991, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * This version of ash is adapted from the source in Debian's ash 0.3.8-5 - * package. - * - * Modified by Erik Andersen and - * Vladimir Oleynik to be used in busybox - * - * - * Original copyright notice is retained at the end of this file. - */ - - -/* These defines allow you to adjust the feature set to be compiled - * into the ash shell. As a rule, enabling these options will make - * ash get bigger... With all of these options off, ash adds about - * 60k to busybox on an x86 system.*/ - - -/* Enable job control. This allows you to run jobs in the background, - * which is great when ash is being used as an interactive shell, but - * it completely useless for is all you are doing is running scripts. - * This adds about 2.5k on an x86 system. */ -#undef JOBS - -/* This enables alias support in ash. If you want to support things - * like "alias ls='ls -l'" with ash, enable this. This is only useful - * when ash is used as an intractive shell. This adds about 1.5k */ -#define ASH_ALIAS - -/* If you need ash to act as a full Posix shell, with full math - * support, enable this. This adds a bit over 2k an x86 system. */ -//#undef ASH_MATH_SUPPORT -#define ASH_MATH_SUPPORT - -/* Getopts is used by shell procedures to parse positional parameters. - * You probably want to leave this disabled, and use the busybox getopt - * applet if you want to do this sort of thing. There are some scripts - * out there that use it, so it you need it, enable. Most people will - * leave this disabled. This adds 1k on an x86 system. */ -#undef ASH_GETOPTS - -/* This allows you to override shell builtins and use whatever is on - * the filesystem. This is most useful when ash is acting as a - * standalone shell. Adds about 272 bytes. */ -#undef ASH_CMDCMD - - -/* Optimize size vs speed as size */ -#define ASH_OPTIMIZE_FOR_SIZE - -/* Enable this to compile in extra debugging noise. When debugging is - * on, debugging info will be written to $HOME/trace and a quit signal - * will generate a core dump. */ -#undef DEBUG - -/* These are here to work with glibc -- Don't change these... */ -#undef FNMATCH_BROKEN -#undef GLOB_BROKEN -#define IFS_BROKEN - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#if !defined(FNMATCH_BROKEN) -#include -#endif -#if !defined(GLOB_BROKEN) -#include -#endif - -#ifdef JOBS -#include -#endif - -#include "busybox.h" -#include "cmdedit.h" - -/* - * This file was generated by the mksyntax program. - */ - -/* Syntax classes */ -#define CWORD 0 /* character is nothing special */ -#define CNL 1 /* newline character */ -#define CBACK 2 /* a backslash character */ -#define CSQUOTE 3 /* single quote */ -#define CDQUOTE 4 /* double quote */ -#define CENDQUOTE 5 /* a terminating quote */ -#define CBQUOTE 6 /* backwards single quote */ -#define CVAR 7 /* a dollar sign */ -#define CENDVAR 8 /* a '}' character */ -#define CLP 9 /* a left paren in arithmetic */ -#define CRP 10 /* a right paren in arithmetic */ -#define CENDFILE 11 /* end of file */ -#define CCTL 12 /* like CWORD, except it must be escaped */ -#define CSPCL 13 /* these terminate a word */ -#define CIGN 14 /* character should be ignored */ - -#define SYNBASE 130 -#define PEOF -130 - -#define PEOA -129 - -#define TEOF 0 -#define TNL 1 -#define TREDIR 2 -#define TWORD 3 -#define TASSIGN 4 -#define TSEMI 5 -#define TBACKGND 6 -#define TAND 7 -#define TOR 8 -#define TPIPE 9 -#define TLP 10 -#define TRP 11 -#define TENDCASE 12 -#define TENDBQUOTE 13 -#define TNOT 14 -#define TCASE 15 -#define TDO 16 -#define TDONE 17 -#define TELIF 18 -#define TELSE 19 -#define TESAC 20 -#define TFI 21 -#define TFOR 22 -#define TIF 23 -#define TIN 24 -#define TTHEN 25 -#define TUNTIL 26 -#define TWHILE 27 -#define TBEGIN 28 -#define TEND 29 - - - -/* control characters in argument strings */ -#define CTLESC '\201' -#define CTLVAR '\202' -#define CTLENDVAR '\203' -#define CTLBACKQ '\204' -#define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */ -/* CTLBACKQ | CTLQUOTE == '\205' */ -#define CTLARI '\206' -#define CTLENDARI '\207' -#define CTLQUOTEMARK '\210' - - -#define is_digit(c) ((c)>='0' && (c)<='9') -#define is_name(c) (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalpha((unsigned char) (c)))) -#define is_in_name(c) (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalnum((unsigned char) (c)))) - -/* - * is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise - * (assuming ascii char codes, as the original implementation did) - */ -#define is_special(c) \ - ( (((unsigned int)c) - 33 < 32) \ - && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1)) - -#define digit_val(c) ((c) - '0') - - -#define _DIAGASSERT(x) - - - -#define S_DFL 1 /* default signal handling (SIG_DFL) */ -#define S_CATCH 2 /* signal is caught */ -#define S_IGN 3 /* signal is ignored (SIG_IGN) */ -#define S_HARD_IGN 4 /* signal is ignored permenantly */ -#define S_RESET 5 /* temporary - to reset a hard ignored sig */ - - -/* variable substitution byte (follows CTLVAR) */ -#define VSTYPE 0x0f /* type of variable substitution */ -#define VSNUL 0x10 /* colon--treat the empty string as unset */ -#define VSQUOTE 0x80 /* inside double quotes--suppress splitting */ - -/* values of VSTYPE field */ -#define VSNORMAL 0x1 /* normal variable: $var or ${var} */ -#define VSMINUS 0x2 /* ${var-text} */ -#define VSPLUS 0x3 /* ${var+text} */ -#define VSQUESTION 0x4 /* ${var?message} */ -#define VSASSIGN 0x5 /* ${var=text} */ -#define VSTRIMLEFT 0x6 /* ${var#pattern} */ -#define VSTRIMLEFTMAX 0x7 /* ${var##pattern} */ -#define VSTRIMRIGHT 0x8 /* ${var%pattern} */ -#define VSTRIMRIGHTMAX 0x9 /* ${var%%pattern} */ -#define VSLENGTH 0xa /* ${#var} */ - -/* flags passed to redirect */ -#define REDIR_PUSH 01 /* save previous values of file descriptors */ -#define REDIR_BACKQ 02 /* save the command output to pipe */ - -/* - * BSD setjmp saves the signal mask, which violates ANSI C and takes time, - * so we use _setjmp instead. - */ - -#if defined(BSD) -#define setjmp(jmploc) _setjmp(jmploc) -#define longjmp(jmploc, val) _longjmp(jmploc, val) -#endif - -/* - * Most machines require the value returned from malloc to be aligned - * in some way. The following macro will get this right on many machines. - */ - -#ifndef ALIGN -union align { - int i; - char *cp; -}; - -#define ALIGN(nbytes) (((nbytes) + sizeof(union align) - 1) & ~(sizeof(union align) - 1)) -#endif - -#ifdef BB_LOCALE_SUPPORT -#include -static void change_lc_all(const char *value); -static void change_lc_ctype(const char *value); -#endif - -/* - * These macros allow the user to suspend the handling of interrupt signals - * over a period of time. This is similar to SIGHOLD to or sigblock, but - * much more efficient and portable. (But hacking the kernel is so much - * more fun than worrying about efficiency and portability. :-)) - */ - -static void onint (void); -static volatile int suppressint; -static volatile int intpending; - -#define INTOFF suppressint++ -#ifndef ASH_OPTIMIZE_FOR_SIZE -#define INTON { if (--suppressint == 0 && intpending) onint(); } -#define FORCEINTON {suppressint = 0; if (intpending) onint();} -#else -static void __inton (void); -static void forceinton (void); -#define INTON __inton() -#define FORCEINTON forceinton() -#endif - -#define CLEAR_PENDING_INT intpending = 0 -#define int_pending() intpending - - -typedef void *pointer; -#ifndef NULL -#define NULL (void *)0 -#endif - -static inline pointer ckmalloc (int sz) { return xmalloc(sz); } -static inline pointer ckrealloc(void *p, int sz) { return xrealloc(p, sz); } -static inline char * savestr (const char *s) { return xstrdup(s); } - -static pointer stalloc (int); -static void stunalloc (pointer); -static void ungrabstackstr (char *, char *); -static char * growstackstr(void); -static char * makestrspace(size_t newlen); -static char *sstrdup (const char *); - -/* - * Parse trees for commands are allocated in lifo order, so we use a stack - * to make this more efficient, and also to avoid all sorts of exception - * handling code to handle interrupts in the middle of a parse. - * - * The size 504 was chosen because the Ultrix malloc handles that size - * well. - */ - -#define MINSIZE 504 /* minimum size of a block */ - - -struct stack_block { - struct stack_block *prev; - char space[MINSIZE]; -}; - -static struct stack_block stackbase; -static struct stack_block *stackp = &stackbase; -static struct stackmark *markp; -static char *stacknxt = stackbase.space; -static int stacknleft = MINSIZE; - - -#define equal(s1, s2) (strcmp(s1, s2) == 0) - -#define stackblock() stacknxt -#define stackblocksize() stacknleft -#define STARTSTACKSTR(p) p = stackblock(), sstrnleft = stackblocksize() - -#define STPUTC(c, p) (--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), *p++ = (c))) -#define CHECKSTRSPACE(n, p) { if (sstrnleft < n) p = makestrspace(n); } -#define STACKSTRNUL(p) (sstrnleft == 0? (p = growstackstr(), *p = '\0') : (*p = '\0')) - - -#define USTPUTC(c, p) (--sstrnleft, *p++ = (c)) -#define STUNPUTC(p) (++sstrnleft, --p) -#define STTOPC(p) p[-1] -#define STADJUST(amount, p) (p += (amount), sstrnleft -= (amount)) -#define grabstackstr(p) stalloc(stackblocksize() - sstrnleft) - -#define ckfree(p) free((pointer)(p)) - - -#ifdef DEBUG -#define TRACE(param) trace param -static void trace (const char *, ...); -static void trargs (char **); -static void showtree (union node *); -static void trputc (int); -static void trputs (const char *); -static void opentrace (void); -#else -#define TRACE(param) -#endif - -#define NSEMI 0 -#define NCMD 1 -#define NPIPE 2 -#define NREDIR 3 -#define NBACKGND 4 -#define NSUBSHELL 5 -#define NAND 6 -#define NOR 7 -#define NIF 8 -#define NWHILE 9 -#define NUNTIL 10 -#define NFOR 11 -#define NCASE 12 -#define NCLIST 13 -#define NDEFUN 14 -#define NARG 15 -#define NTO 16 -#define NFROM 17 -#define NFROMTO 18 -#define NAPPEND 19 -#define NTOOV 20 -#define NTOFD 21 -#define NFROMFD 22 -#define NHERE 23 -#define NXHERE 24 -#define NNOT 25 - -/* - * expandarg() flags - */ -#define EXP_FULL 0x1 /* perform word splitting & file globbing */ -#define EXP_TILDE 0x2 /* do normal tilde expansion */ -#define EXP_VARTILDE 0x4 /* expand tildes in an assignment */ -#define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */ -#define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */ -#define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */ - - -#define NOPTS 16 - -static char optet_vals[NOPTS]; - -static const char * const optlist[NOPTS] = { - "e" "errexit", - "f" "noglob", - "I" "ignoreeof", - "i" "interactive", - "m" "monitor", - "n" "noexec", - "s" "stdin", - "x" "xtrace", - "v" "verbose", - "V" "vi", - "E" "emacs", - "C" "noclobber", - "a" "allexport", - "b" "notify", - "u" "nounset", - "q" "quietprofile" -}; - -#define optent_name(optent) (optent+1) -#define optent_letter(optent) optent[0] -#define optent_val(optent) optet_vals[optent] - -#define eflag optent_val(0) -#define fflag optent_val(1) -#define Iflag optent_val(2) -#define iflag optent_val(3) -#define mflag optent_val(4) -#define nflag optent_val(5) -#define sflag optent_val(6) -#define xflag optent_val(7) -#define vflag optent_val(8) -#define Vflag optent_val(9) -#define Eflag optent_val(10) -#define Cflag optent_val(11) -#define aflag optent_val(12) -#define bflag optent_val(13) -#define uflag optent_val(14) -#define qflag optent_val(15) - - -/* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */ -#define FORK_FG 0 -#define FORK_BG 1 -#define FORK_NOJOB 2 - - -struct nbinary { - int type; - union node *ch1; - union node *ch2; -}; - - -struct ncmd { - int type; - int backgnd; - union node *assign; - union node *args; - union node *redirect; -}; - - -struct npipe { - int type; - int backgnd; - struct nodelist *cmdlist; -}; - - -struct nredir { - int type; - union node *n; - union node *redirect; -}; - - -struct nif { - int type; - union node *test; - union node *ifpart; - union node *elsepart; -}; - - -struct nfor { - int type; - union node *args; - union node *body; - char *var; -}; - - -struct ncase { - int type; - union node *expr; - union node *cases; -}; - - -struct nclist { - int type; - union node *next; - union node *pattern; - union node *body; -}; - - -struct narg { - int type; - union node *next; - char *text; - struct nodelist *backquote; -}; - - -struct nfile { - int type; - union node *next; - int fd; - union node *fname; - char *expfname; -}; - - -struct ndup { - int type; - union node *next; - int fd; - int dupfd; - union node *vname; -}; - - -struct nhere { - int type; - union node *next; - int fd; - union node *doc; -}; - - -struct nnot { - int type; - union node *com; -}; - - -union node { - int type; - struct nbinary nbinary; - struct ncmd ncmd; - struct npipe npipe; - struct nredir nredir; - struct nif nif; - struct nfor nfor; - struct ncase ncase; - struct nclist nclist; - struct narg narg; - struct nfile nfile; - struct ndup ndup; - struct nhere nhere; - struct nnot nnot; -}; - - -struct nodelist { - struct nodelist *next; - union node *n; -}; - -struct backcmd { /* result of evalbackcmd */ - int fd; /* file descriptor to read from */ - char *buf; /* buffer */ - int nleft; /* number of chars in buffer */ - struct job *jp; /* job structure for command */ -}; - -struct cmdentry { - int cmdtype; - union param { - int index; - union node *func; - const struct builtincmd *cmd; - } u; -}; - -struct strlist { - struct strlist *next; - char *text; -}; - - -struct arglist { - struct strlist *list; - struct strlist **lastp; -}; - -struct strpush { - struct strpush *prev; /* preceding string on stack */ - char *prevstring; - int prevnleft; -#ifdef ASH_ALIAS - struct alias *ap; /* if push was associated with an alias */ -#endif - char *string; /* remember the string since it may change */ -}; - -struct parsefile { - struct parsefile *prev; /* preceding file on stack */ - int linno; /* current line */ - int fd; /* file descriptor (or -1 if string) */ - int nleft; /* number of chars left in this line */ - int lleft; /* number of chars left in this buffer */ - char *nextc; /* next char in buffer */ - char *buf; /* input buffer */ - struct strpush *strpush; /* for pushing strings at this level */ - struct strpush basestrpush; /* so pushing one is fast */ -}; - -struct stackmark { - struct stack_block *stackp; - char *stacknxt; - int stacknleft; - struct stackmark *marknext; -}; - -struct shparam { - int nparam; /* # of positional parameters (without $0) */ - unsigned char malloc; /* if parameter list dynamically allocated */ - char **p; /* parameter list */ - int optind; /* next parameter to be processed by getopts */ - int optoff; /* used by getopts */ -}; - -/* - * When commands are first encountered, they are entered in a hash table. - * This ensures that a full path search will not have to be done for them - * on each invocation. - * - * We should investigate converting to a linear search, even though that - * would make the command name "hash" a misnomer. - */ -#define CMDTABLESIZE 31 /* should be prime */ -#define ARB 1 /* actual size determined at run time */ - - - -struct tblentry { - struct tblentry *next; /* next entry in hash chain */ - union param param; /* definition of builtin function */ - short cmdtype; /* index identifying command */ - char rehash; /* if set, cd done since entry created */ - char cmdname[ARB]; /* name of command */ -}; - - -static struct tblentry *cmdtable[CMDTABLESIZE]; -static int builtinloc = -1; /* index in path of %builtin, or -1 */ -static int exerrno = 0; /* Last exec error */ - - -static void tryexec (char *, char **, char **); -static void printentry (struct tblentry *, int); -static void clearcmdentry (int); -static struct tblentry *cmdlookup (const char *, int); -static void delete_cmd_entry (void); -static int path_change (const char *, int *); - - -static void flushall (void); -static void out2fmt (const char *, ...) - __attribute__((__format__(__printf__,1,2))); -static int xwrite (int, const char *, int); - -static inline void outstr (const char *p, FILE *file) { fputs(p, file); } -static void out1str(const char *p) { outstr(p, stdout); } -static void out2str(const char *p) { outstr(p, stderr); } - -#ifndef ASH_OPTIMIZE_FOR_SIZE -#define out2c(c) putc((c), stderr) -#else -static void out2c(int c) { putc(c, stderr); } -#endif - - -#ifdef ASH_OPTIMIZE_FOR_SIZE -#define USE_SIT_FUNCTION -#endif - -/* number syntax index */ -#define BASESYNTAX 0 /* not in quotes */ -#define DQSYNTAX 1 /* in double quotes */ -#define SQSYNTAX 2 /* in single quotes */ -#define ARISYNTAX 3 /* in arithmetic */ - -static const char S_I_T[][4] = { - /* 0 */ { CSPCL, CIGN, CIGN, CIGN }, /* PEOA */ - /* 1 */ { CSPCL, CWORD, CWORD, CWORD }, /* ' ' */ - /* 2 */ { CNL, CNL, CNL, CNL }, /* \n */ - /* 3 */ { CWORD, CCTL, CCTL, CWORD }, /* !*-/:=?[]~ */ - /* 4 */ { CDQUOTE, CENDQUOTE, CWORD, CDQUOTE }, /* '"' */ - /* 5 */ { CVAR, CVAR, CWORD, CVAR }, /* $ */ - /* 6 */ { CSQUOTE, CWORD, CENDQUOTE, CSQUOTE }, /* "'" */ - /* 7 */ { CSPCL, CWORD, CWORD, CLP }, /* ( */ - /* 8 */ { CSPCL, CWORD, CWORD, CRP }, /* ) */ - /* 9 */ { CBACK, CBACK, CCTL, CBACK }, /* \ */ - /* 10 */ { CBQUOTE, CBQUOTE, CWORD, CBQUOTE }, /* ` */ - /* 11 */ { CENDVAR, CENDVAR, CWORD, CENDVAR }, /* } */ -#ifndef USE_SIT_FUNCTION - /* 12 */ { CENDFILE, CENDFILE, CENDFILE, CENDFILE }, /* PEOF */ - /* 13 */ { CWORD, CWORD, CWORD, CWORD }, /* 0-9A-Za-z */ - /* 14 */ { CCTL, CCTL, CCTL, CCTL } /* CTLESC ... */ -#endif -}; - -#ifdef USE_SIT_FUNCTION - -#define U_C(c) ((unsigned char)(c)) - -static int SIT(int c, int syntax) -{ - static const char spec_symbls[]="\t\n !\"$&'()*-/:;<=>?[\\]`|}~"; - static const char syntax_index_table [] = { - 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */ - 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */ - 3, 1, 3, 3, 9, 3,10, 1, /* "=>?[\\]`|" */ - 11,3 }; /* "}~" */ - const char *s; - int indx; - - if(c==PEOF) /* 2^8+2 */ - return CENDFILE; - if(c==PEOA) /* 2^8+1 */ - indx = 0; - else if(U_C(c)>=U_C(CTLESC) && U_C(c)<=U_C(CTLQUOTEMARK)) - return CCTL; - else { - s = strchr(spec_symbls, c); - if(s==0) - return CWORD; - indx = syntax_index_table[(s-spec_symbls)]; - } - return S_I_T[indx][syntax]; -} - -#else /* USE_SIT_FUNCTION */ - -#define SIT(c, syntax) S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax] - -#define CSPCL_CIGN_CIGN_CIGN 0 -#define CSPCL_CWORD_CWORD_CWORD 1 -#define CNL_CNL_CNL_CNL 2 -#define CWORD_CCTL_CCTL_CWORD 3 -#define CDQUOTE_CENDQUOTE_CWORD_CDQUOTE 4 -#define CVAR_CVAR_CWORD_CVAR 5 -#define CSQUOTE_CWORD_CENDQUOTE_CSQUOTE 6 -#define CSPCL_CWORD_CWORD_CLP 7 -#define CSPCL_CWORD_CWORD_CRP 8 -#define CBACK_CBACK_CCTL_CBACK 9 -#define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 10 -#define CENDVAR_CENDVAR_CWORD_CENDVAR 11 -#define CENDFILE_CENDFILE_CENDFILE_CENDFILE 12 -#define CWORD_CWORD_CWORD_CWORD 13 -#define CCTL_CCTL_CCTL_CCTL 14 - -static const char syntax_index_table[258] = { - /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */ - /* 0 -130 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE, - /* 1 -129 PEOA */ CSPCL_CIGN_CIGN_CIGN, - /* 2 -128 0xff */ CWORD_CWORD_CWORD_CWORD, - /* 3 -127 */ CCTL_CCTL_CCTL_CCTL, /* CTLQUOTEMARK */ - /* 4 -126 */ CCTL_CCTL_CCTL_CCTL, - /* 5 -125 */ CCTL_CCTL_CCTL_CCTL, - /* 6 -124 */ CCTL_CCTL_CCTL_CCTL, - /* 7 -123 */ CCTL_CCTL_CCTL_CCTL, - /* 8 -122 */ CCTL_CCTL_CCTL_CCTL, - /* 9 -121 */ CCTL_CCTL_CCTL_CCTL, - /* 10 -120 */ CCTL_CCTL_CCTL_CCTL, /* CTLESC */ - /* 11 -119 */ CWORD_CWORD_CWORD_CWORD, - /* 12 -118 */ CWORD_CWORD_CWORD_CWORD, - /* 13 -117 */ CWORD_CWORD_CWORD_CWORD, - /* 14 -116 */ CWORD_CWORD_CWORD_CWORD, - /* 15 -115 */ CWORD_CWORD_CWORD_CWORD, - /* 16 -114 */ CWORD_CWORD_CWORD_CWORD, - /* 17 -113 */ CWORD_CWORD_CWORD_CWORD, - /* 18 -112 */ CWORD_CWORD_CWORD_CWORD, - /* 19 -111 */ CWORD_CWORD_CWORD_CWORD, - /* 20 -110 */ CWORD_CWORD_CWORD_CWORD, - /* 21 -109 */ CWORD_CWORD_CWORD_CWORD, - /* 22 -108 */ CWORD_CWORD_CWORD_CWORD, - /* 23 -107 */ CWORD_CWORD_CWORD_CWORD, - /* 24 -106 */ CWORD_CWORD_CWORD_CWORD, - /* 25 -105 */ CWORD_CWORD_CWORD_CWORD, - /* 26 -104 */ CWORD_CWORD_CWORD_CWORD, - /* 27 -103 */ CWORD_CWORD_CWORD_CWORD, - /* 28 -102 */ CWORD_CWORD_CWORD_CWORD, - /* 29 -101 */ CWORD_CWORD_CWORD_CWORD, - /* 30 -100 */ CWORD_CWORD_CWORD_CWORD, - /* 31 -99 */ CWORD_CWORD_CWORD_CWORD, - /* 32 -98 */ CWORD_CWORD_CWORD_CWORD, - /* 33 -97 */ CWORD_CWORD_CWORD_CWORD, - /* 34 -96 */ CWORD_CWORD_CWORD_CWORD, - /* 35 -95 */ CWORD_CWORD_CWORD_CWORD, - /* 36 -94 */ CWORD_CWORD_CWORD_CWORD, - /* 37 -93 */ CWORD_CWORD_CWORD_CWORD, - /* 38 -92 */ CWORD_CWORD_CWORD_CWORD, - /* 39 -91 */ CWORD_CWORD_CWORD_CWORD, - /* 40 -90 */ CWORD_CWORD_CWORD_CWORD, - /* 41 -89 */ CWORD_CWORD_CWORD_CWORD, - /* 42 -88 */ CWORD_CWORD_CWORD_CWORD, - /* 43 -87 */ CWORD_CWORD_CWORD_CWORD, - /* 44 -86 */ CWORD_CWORD_CWORD_CWORD, - /* 45 -85 */ CWORD_CWORD_CWORD_CWORD, - /* 46 -84 */ CWORD_CWORD_CWORD_CWORD, - /* 47 -83 */ CWORD_CWORD_CWORD_CWORD, - /* 48 -82 */ CWORD_CWORD_CWORD_CWORD, - /* 49 -81 */ CWORD_CWORD_CWORD_CWORD, - /* 50 -80 */ CWORD_CWORD_CWORD_CWORD, - /* 51 -79 */ CWORD_CWORD_CWORD_CWORD, - /* 52 -78 */ CWORD_CWORD_CWORD_CWORD, - /* 53 -77 */ CWORD_CWORD_CWORD_CWORD, - /* 54 -76 */ CWORD_CWORD_CWORD_CWORD, - /* 55 -75 */ CWORD_CWORD_CWORD_CWORD, - /* 56 -74 */ CWORD_CWORD_CWORD_CWORD, - /* 57 -73 */ CWORD_CWORD_CWORD_CWORD, - /* 58 -72 */ CWORD_CWORD_CWORD_CWORD, - /* 59 -71 */ CWORD_CWORD_CWORD_CWORD, - /* 60 -70 */ CWORD_CWORD_CWORD_CWORD, - /* 61 -69 */ CWORD_CWORD_CWORD_CWORD, - /* 62 -68 */ CWORD_CWORD_CWORD_CWORD, - /* 63 -67 */ CWORD_CWORD_CWORD_CWORD, - /* 64 -66 */ CWORD_CWORD_CWORD_CWORD, - /* 65 -65 */ CWORD_CWORD_CWORD_CWORD, - /* 66 -64 */ CWORD_CWORD_CWORD_CWORD, - /* 67 -63 */ CWORD_CWORD_CWORD_CWORD, - /* 68 -62 */ CWORD_CWORD_CWORD_CWORD, - /* 69 -61 */ CWORD_CWORD_CWORD_CWORD, - /* 70 -60 */ CWORD_CWORD_CWORD_CWORD, - /* 71 -59 */ CWORD_CWORD_CWORD_CWORD, - /* 72 -58 */ CWORD_CWORD_CWORD_CWORD, - /* 73 -57 */ CWORD_CWORD_CWORD_CWORD, - /* 74 -56 */ CWORD_CWORD_CWORD_CWORD, - /* 75 -55 */ CWORD_CWORD_CWORD_CWORD, - /* 76 -54 */ CWORD_CWORD_CWORD_CWORD, - /* 77 -53 */ CWORD_CWORD_CWORD_CWORD, - /* 78 -52 */ CWORD_CWORD_CWORD_CWORD, - /* 79 -51 */ CWORD_CWORD_CWORD_CWORD, - /* 80 -50 */ CWORD_CWORD_CWORD_CWORD, - /* 81 -49 */ CWORD_CWORD_CWORD_CWORD, - /* 82 -48 */ CWORD_CWORD_CWORD_CWORD, - /* 83 -47 */ CWORD_CWORD_CWORD_CWORD, - /* 84 -46 */ CWORD_CWORD_CWORD_CWORD, - /* 85 -45 */ CWORD_CWORD_CWORD_CWORD, - /* 86 -44 */ CWORD_CWORD_CWORD_CWORD, - /* 87 -43 */ CWORD_CWORD_CWORD_CWORD, - /* 88 -42 */ CWORD_CWORD_CWORD_CWORD, - /* 89 -41 */ CWORD_CWORD_CWORD_CWORD, - /* 90 -40 */ CWORD_CWORD_CWORD_CWORD, - /* 91 -39 */ CWORD_CWORD_CWORD_CWORD, - /* 92 -38 */ CWORD_CWORD_CWORD_CWORD, - /* 93 -37 */ CWORD_CWORD_CWORD_CWORD, - /* 94 -36 */ CWORD_CWORD_CWORD_CWORD, - /* 95 -35 */ CWORD_CWORD_CWORD_CWORD, - /* 96 -34 */ CWORD_CWORD_CWORD_CWORD, - /* 97 -33 */ CWORD_CWORD_CWORD_CWORD, - /* 98 -32 */ CWORD_CWORD_CWORD_CWORD, - /* 99 -31 */ CWORD_CWORD_CWORD_CWORD, - /* 100 -30 */ CWORD_CWORD_CWORD_CWORD, - /* 101 -29 */ CWORD_CWORD_CWORD_CWORD, - /* 102 -28 */ CWORD_CWORD_CWORD_CWORD, - /* 103 -27 */ CWORD_CWORD_CWORD_CWORD, - /* 104 -26 */ CWORD_CWORD_CWORD_CWORD, - /* 105 -25 */ CWORD_CWORD_CWORD_CWORD, - /* 106 -24 */ CWORD_CWORD_CWORD_CWORD, - /* 107 -23 */ CWORD_CWORD_CWORD_CWORD, - /* 108 -22 */ CWORD_CWORD_CWORD_CWORD, - /* 109 -21 */ CWORD_CWORD_CWORD_CWORD, - /* 110 -20 */ CWORD_CWORD_CWORD_CWORD, - /* 111 -19 */ CWORD_CWORD_CWORD_CWORD, - /* 112 -18 */ CWORD_CWORD_CWORD_CWORD, - /* 113 -17 */ CWORD_CWORD_CWORD_CWORD, - /* 114 -16 */ CWORD_CWORD_CWORD_CWORD, - /* 115 -15 */ CWORD_CWORD_CWORD_CWORD, - /* 116 -14 */ CWORD_CWORD_CWORD_CWORD, - /* 117 -13 */ CWORD_CWORD_CWORD_CWORD, - /* 118 -12 */ CWORD_CWORD_CWORD_CWORD, - /* 119 -11 */ CWORD_CWORD_CWORD_CWORD, - /* 120 -10 */ CWORD_CWORD_CWORD_CWORD, - /* 121 -9 */ CWORD_CWORD_CWORD_CWORD, - /* 122 -8 */ CWORD_CWORD_CWORD_CWORD, - /* 123 -7 */ CWORD_CWORD_CWORD_CWORD, - /* 124 -6 */ CWORD_CWORD_CWORD_CWORD, - /* 125 -5 */ CWORD_CWORD_CWORD_CWORD, - /* 126 -4 */ CWORD_CWORD_CWORD_CWORD, - /* 127 -3 */ CWORD_CWORD_CWORD_CWORD, - /* 128 -2 */ CWORD_CWORD_CWORD_CWORD, - /* 129 -1 */ CWORD_CWORD_CWORD_CWORD, - /* 130 0 */ CWORD_CWORD_CWORD_CWORD, - /* 131 1 */ CWORD_CWORD_CWORD_CWORD, - /* 132 2 */ CWORD_CWORD_CWORD_CWORD, - /* 133 3 */ CWORD_CWORD_CWORD_CWORD, - /* 134 4 */ CWORD_CWORD_CWORD_CWORD, - /* 135 5 */ CWORD_CWORD_CWORD_CWORD, - /* 136 6 */ CWORD_CWORD_CWORD_CWORD, - /* 137 7 */ CWORD_CWORD_CWORD_CWORD, - /* 138 8 */ CWORD_CWORD_CWORD_CWORD, - /* 139 9 "\t" */ CSPCL_CWORD_CWORD_CWORD, - /* 140 10 "\n" */ CNL_CNL_CNL_CNL, - /* 141 11 */ CWORD_CWORD_CWORD_CWORD, - /* 142 12 */ CWORD_CWORD_CWORD_CWORD, - /* 143 13 */ CWORD_CWORD_CWORD_CWORD, - /* 144 14 */ CWORD_CWORD_CWORD_CWORD, - /* 145 15 */ CWORD_CWORD_CWORD_CWORD, - /* 146 16 */ CWORD_CWORD_CWORD_CWORD, - /* 147 17 */ CWORD_CWORD_CWORD_CWORD, - /* 148 18 */ CWORD_CWORD_CWORD_CWORD, - /* 149 19 */ CWORD_CWORD_CWORD_CWORD, - /* 150 20 */ CWORD_CWORD_CWORD_CWORD, - /* 151 21 */ CWORD_CWORD_CWORD_CWORD, - /* 152 22 */ CWORD_CWORD_CWORD_CWORD, - /* 153 23 */ CWORD_CWORD_CWORD_CWORD, - /* 154 24 */ CWORD_CWORD_CWORD_CWORD, - /* 155 25 */ CWORD_CWORD_CWORD_CWORD, - /* 156 26 */ CWORD_CWORD_CWORD_CWORD, - /* 157 27 */ CWORD_CWORD_CWORD_CWORD, - /* 158 28 */ CWORD_CWORD_CWORD_CWORD, - /* 159 29 */ CWORD_CWORD_CWORD_CWORD, - /* 160 30 */ CWORD_CWORD_CWORD_CWORD, - /* 161 31 */ CWORD_CWORD_CWORD_CWORD, - /* 162 32 " " */ CSPCL_CWORD_CWORD_CWORD, - /* 163 33 "!" */ CWORD_CCTL_CCTL_CWORD, - /* 164 34 """ */ CDQUOTE_CENDQUOTE_CWORD_CDQUOTE, - /* 165 35 "#" */ CWORD_CWORD_CWORD_CWORD, - /* 166 36 "$" */ CVAR_CVAR_CWORD_CVAR, - /* 167 37 "%" */ CWORD_CWORD_CWORD_CWORD, - /* 168 38 "&" */ CSPCL_CWORD_CWORD_CWORD, - /* 169 39 "'" */ CSQUOTE_CWORD_CENDQUOTE_CSQUOTE, - /* 170 40 "(" */ CSPCL_CWORD_CWORD_CLP, - /* 171 41 ")" */ CSPCL_CWORD_CWORD_CRP, - /* 172 42 "*" */ CWORD_CCTL_CCTL_CWORD, - /* 173 43 "+" */ CWORD_CWORD_CWORD_CWORD, - /* 174 44 "," */ CWORD_CWORD_CWORD_CWORD, - /* 175 45 "-" */ CWORD_CCTL_CCTL_CWORD, - /* 176 46 "." */ CWORD_CWORD_CWORD_CWORD, - /* 177 47 "/" */ CWORD_CCTL_CCTL_CWORD, - /* 178 48 "0" */ CWORD_CWORD_CWORD_CWORD, - /* 179 49 "1" */ CWORD_CWORD_CWORD_CWORD, - /* 180 50 "2" */ CWORD_CWORD_CWORD_CWORD, - /* 181 51 "3" */ CWORD_CWORD_CWORD_CWORD, - /* 182 52 "4" */ CWORD_CWORD_CWORD_CWORD, - /* 183 53 "5" */ CWORD_CWORD_CWORD_CWORD, - /* 184 54 "6" */ CWORD_CWORD_CWORD_CWORD, - /* 185 55 "7" */ CWORD_CWORD_CWORD_CWORD, - /* 186 56 "8" */ CWORD_CWORD_CWORD_CWORD, - /* 187 57 "9" */ CWORD_CWORD_CWORD_CWORD, - /* 188 58 ":" */ CWORD_CCTL_CCTL_CWORD, - /* 189 59 ";" */ CSPCL_CWORD_CWORD_CWORD, - /* 190 60 "<" */ CSPCL_CWORD_CWORD_CWORD, - /* 191 61 "=" */ CWORD_CCTL_CCTL_CWORD, - /* 192 62 ">" */ CSPCL_CWORD_CWORD_CWORD, - /* 193 63 "?" */ CWORD_CCTL_CCTL_CWORD, - /* 194 64 "@" */ CWORD_CWORD_CWORD_CWORD, - /* 195 65 "A" */ CWORD_CWORD_CWORD_CWORD, - /* 196 66 "B" */ CWORD_CWORD_CWORD_CWORD, - /* 197 67 "C" */ CWORD_CWORD_CWORD_CWORD, - /* 198 68 "D" */ CWORD_CWORD_CWORD_CWORD, - /* 199 69 "E" */ CWORD_CWORD_CWORD_CWORD, - /* 200 70 "F" */ CWORD_CWORD_CWORD_CWORD, - /* 201 71 "G" */ CWORD_CWORD_CWORD_CWORD, - /* 202 72 "H" */ CWORD_CWORD_CWORD_CWORD, - /* 203 73 "I" */ CWORD_CWORD_CWORD_CWORD, - /* 204 74 "J" */ CWORD_CWORD_CWORD_CWORD, - /* 205 75 "K" */ CWORD_CWORD_CWORD_CWORD, - /* 206 76 "L" */ CWORD_CWORD_CWORD_CWORD, - /* 207 77 "M" */ CWORD_CWORD_CWORD_CWORD, - /* 208 78 "N" */ CWORD_CWORD_CWORD_CWORD, - /* 209 79 "O" */ CWORD_CWORD_CWORD_CWORD, - /* 210 80 "P" */ CWORD_CWORD_CWORD_CWORD, - /* 211 81 "Q" */ CWORD_CWORD_CWORD_CWORD, - /* 212 82 "R" */ CWORD_CWORD_CWORD_CWORD, - /* 213 83 "S" */ CWORD_CWORD_CWORD_CWORD, - /* 214 84 "T" */ CWORD_CWORD_CWORD_CWORD, - /* 215 85 "U" */ CWORD_CWORD_CWORD_CWORD, - /* 216 86 "V" */ CWORD_CWORD_CWORD_CWORD, - /* 217 87 "W" */ CWORD_CWORD_CWORD_CWORD, - /* 218 88 "X" */ CWORD_CWORD_CWORD_CWORD, - /* 219 89 "Y" */ CWORD_CWORD_CWORD_CWORD, - /* 220 90 "Z" */ CWORD_CWORD_CWORD_CWORD, - /* 221 91 "[" */ CWORD_CCTL_CCTL_CWORD, - /* 222 92 "\" */ CBACK_CBACK_CCTL_CBACK, - /* 223 93 "]" */ CWORD_CCTL_CCTL_CWORD, - /* 224 94 "^" */ CWORD_CWORD_CWORD_CWORD, - /* 225 95 "_" */ CWORD_CWORD_CWORD_CWORD, - /* 226 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE, - /* 227 97 "a" */ CWORD_CWORD_CWORD_CWORD, - /* 228 98 "b" */ CWORD_CWORD_CWORD_CWORD, - /* 229 99 "c" */ CWORD_CWORD_CWORD_CWORD, - /* 230 100 "d" */ CWORD_CWORD_CWORD_CWORD, - /* 231 101 "e" */ CWORD_CWORD_CWORD_CWORD, - /* 232 102 "f" */ CWORD_CWORD_CWORD_CWORD, - /* 233 103 "g" */ CWORD_CWORD_CWORD_CWORD, - /* 234 104 "h" */ CWORD_CWORD_CWORD_CWORD, - /* 235 105 "i" */ CWORD_CWORD_CWORD_CWORD, - /* 236 106 "j" */ CWORD_CWORD_CWORD_CWORD, - /* 237 107 "k" */ CWORD_CWORD_CWORD_CWORD, - /* 238 108 "l" */ CWORD_CWORD_CWORD_CWORD, - /* 239 109 "m" */ CWORD_CWORD_CWORD_CWORD, - /* 240 110 "n" */ CWORD_CWORD_CWORD_CWORD, - /* 241 111 "o" */ CWORD_CWORD_CWORD_CWORD, - /* 242 112 "p" */ CWORD_CWORD_CWORD_CWORD, - /* 243 113 "q" */ CWORD_CWORD_CWORD_CWORD, - /* 244 114 "r" */ CWORD_CWORD_CWORD_CWORD, - /* 245 115 "s" */ CWORD_CWORD_CWORD_CWORD, - /* 246 116 "t" */ CWORD_CWORD_CWORD_CWORD, - /* 247 117 "u" */ CWORD_CWORD_CWORD_CWORD, - /* 248 118 "v" */ CWORD_CWORD_CWORD_CWORD, - /* 249 119 "w" */ CWORD_CWORD_CWORD_CWORD, - /* 250 120 "x" */ CWORD_CWORD_CWORD_CWORD, - /* 251 121 "y" */ CWORD_CWORD_CWORD_CWORD, - /* 252 122 "z" */ CWORD_CWORD_CWORD_CWORD, - /* 253 123 "{" */ CWORD_CWORD_CWORD_CWORD, - /* 254 124 "|" */ CSPCL_CWORD_CWORD_CWORD, - /* 255 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR, - /* 256 126 "~" */ CWORD_CCTL_CCTL_CWORD, - /* 257 127 */ CWORD_CWORD_CWORD_CWORD, -}; - -#endif /* USE_SIT_FUNCTION */ - - -/* first char is indicating which tokens mark the end of a list */ -static const char *const tokname_array[] = { - "\1end of file", - "\0newline", - "\0redirection", - "\0word", - "\0assignment", - "\0;", - "\0&", - "\0&&", - "\0||", - "\0|", - "\0(", - "\1)", - "\1;;", - "\1`", -#define KWDOFFSET 14 - /* the following are keywords */ - "\0!", - "\0case", - "\1do", - "\1done", - "\1elif", - "\1else", - "\1esac", - "\1fi", - "\0for", - "\0if", - "\0in", - "\1then", - "\0until", - "\0while", - "\0{", - "\1}", -}; - -static const char *tokname(int tok) -{ - static char buf[16]; - - if(tok>=TSEMI) - buf[0] = '"'; - sprintf(buf+(tok>=TSEMI), "%s%c", - tokname_array[tok]+1, (tok>=TSEMI ? '"' : 0)); - return buf; -} - -static int plinno = 1; /* input line number */ - -static int parselleft; /* copy of parsefile->lleft */ - -static struct parsefile basepf; /* top level input file */ -static char basebuf[BUFSIZ]; /* buffer for top level input file */ -static struct parsefile *parsefile = &basepf; /* current input file */ - -/* - * NEOF is returned by parsecmd when it encounters an end of file. It - * must be distinct from NULL, so we use the address of a variable that - * happens to be handy. - */ - -static int tokpushback; /* last token pushed back */ -#define NEOF ((union node *)&tokpushback) -static int checkkwd; /* 1 == check for kwds, 2 == also eat newlines */ - - -static void error (const char *, ...) __attribute__((__noreturn__)); -static void exerror (int, const char *, ...) __attribute__((__noreturn__)); -static void shellexec (char **, char **, const char *, int) - __attribute__((noreturn)); -static void exitshell (int) __attribute__((noreturn)); - -static int goodname(const char *); -static void ignoresig (int); -static void onsig (int); -static void dotrap (void); -static int decode_signal (const char *, int); - -static void shprocvar(void); -static void deletefuncs(void); -static void setparam (char **); -static void freeparam (volatile struct shparam *); - -/* reasons for skipping commands (see comment on breakcmd routine) */ -#define SKIPBREAK 1 -#define SKIPCONT 2 -#define SKIPFUNC 3 -#define SKIPFILE 4 - -/* values of cmdtype */ -#define CMDUNKNOWN -1 /* no entry in table for command */ -#define CMDNORMAL 0 /* command is an executable program */ -#define CMDBUILTIN 1 /* command is a shell builtin */ -#define CMDFUNCTION 2 /* command is a shell function */ - -#define DO_ERR 1 /* find_command prints errors */ -#define DO_ABS 2 /* find_command checks absolute paths */ -#define DO_NOFUN 4 /* find_command ignores functions */ -#define DO_BRUTE 8 /* find_command ignores hash table */ - -/* - * Shell variables. - */ - -/* flags */ -#define VEXPORT 0x01 /* variable is exported */ -#define VREADONLY 0x02 /* variable cannot be modified */ -#define VSTRFIXED 0x04 /* variable struct is staticly allocated */ -#define VTEXTFIXED 0x08 /* text is staticly allocated */ -#define VSTACK 0x10 /* text is allocated on the stack */ -#define VUNSET 0x20 /* the variable is not set */ -#define VNOFUNC 0x40 /* don't call the callback function */ - - -struct var { - struct var *next; /* next entry in hash list */ - int flags; /* flags are defined above */ - char *text; /* name=value */ - void (*func) (const char *); - /* function to be called when */ - /* the variable gets set/unset */ -}; - -struct localvar { - struct localvar *next; /* next local variable in list */ - struct var *vp; /* the variable that was made local */ - int flags; /* saved flags */ - char *text; /* saved text */ -}; - - -#if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) -#define rmescapes(p) _rmescapes((p), 0) -static char *_rmescapes (char *, int); -#else -static void rmescapes (char *); -#endif - -static int casematch (union node *, const char *); -static void clearredir(void); -static void popstring(void); -static void readcmdfile (const char *); - -static int number (const char *); -static int is_number (const char *, int *num); -static char *single_quote (const char *); -static int nextopt (const char *); - -static void redirect (union node *, int); -static void popredir (void); -static int dup_as_newfd (int, int); - -static void changepath(const char *newval); -static void getoptsreset(const char *value); - - -static int parsenleft; /* copy of parsefile->nleft */ -static char *parsenextc; /* copy of parsefile->nextc */ -static int rootpid; /* pid of main shell */ -static int rootshell; /* true if we aren't a child of the main shell */ - -static const char spcstr[] = " "; -static const char snlfmt[] = "%s\n"; - -static int sstrnleft; -static int herefd = -1; - -static struct localvar *localvars; - -static struct var vifs; -static struct var vmail; -static struct var vmpath; -static struct var vpath; -static struct var vps1; -static struct var vps2; -static struct var voptind; -#ifdef BB_LOCALE_SUPPORT -static struct var vlc_all; -static struct var vlc_ctype; -#endif - -struct varinit { - struct var *var; - int flags; - const char *text; - void (*func) (const char *); -}; - -static const char defpathvar[] = - "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"; -#define defpath (defpathvar + 5) - -#ifdef IFS_BROKEN -static const char defifsvar[] = "IFS= \t\n"; -#define defifs (defifsvar + 4) -#else -static const char defifs[] = " \t\n"; -#endif - -static const struct varinit varinit[] = { -#ifdef IFS_BROKEN - { &vifs, VSTRFIXED|VTEXTFIXED, defifsvar, -#else - { &vifs, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS=", -#endif - NULL }, - { &vmail, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL=", - NULL }, - { &vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH=", - NULL }, - { &vpath, VSTRFIXED|VTEXTFIXED, defpathvar, - changepath }, - /* - * vps1 depends on uid - */ - { &vps2, VSTRFIXED|VTEXTFIXED, "PS2=> ", - NULL }, - { &voptind, VSTRFIXED|VTEXTFIXED, "OPTIND=1", - getoptsreset }, -#ifdef BB_LOCALE_SUPPORT - { &vlc_all, VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL=", - change_lc_all }, - { &vlc_ctype, VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE=", - change_lc_ctype }, -#endif - { NULL, 0, NULL, - NULL } -}; - -#define VTABSIZE 39 - -static struct var *vartab[VTABSIZE]; - -/* - * The following macros access the values of the above variables. - * They have to skip over the name. They return the null string - * for unset variables. - */ - -#define ifsval() (vifs.text + 4) -#define ifsset() ((vifs.flags & VUNSET) == 0) -#define mailval() (vmail.text + 5) -#define mpathval() (vmpath.text + 9) -#define pathval() (vpath.text + 5) -#define ps1val() (vps1.text + 4) -#define ps2val() (vps2.text + 4) -#define optindval() (voptind.text + 7) - -#define mpathset() ((vmpath.flags & VUNSET) == 0) - -static void initvar (void); -static void setvar (const char *, const char *, int); -static void setvareq (char *, int); -static void listsetvar (struct strlist *); -static const char *lookupvar (const char *); -static const char *bltinlookup (const char *); -static char **environment (void); -static int showvarscmd (int, char **); -static void mklocal (char *); -static void poplocalvars (void); -static int unsetvar (const char *); -static int varequal (const char *, const char *); - - -static char *arg0; /* value of $0 */ -static struct shparam shellparam; /* current positional parameters */ -static char **argptr; /* argument list for builtin commands */ -static char *optionarg; /* set by nextopt (like getopt) */ -static char *optptr; /* used by nextopt */ -static char *minusc; /* argument to -c option */ - - -#ifdef ASH_ALIAS - -#define ALIASINUSE 1 -#define ALIASDEAD 2 - -#define ATABSIZE 39 - -struct alias { - struct alias *next; - char *name; - char *val; - int flag; -}; - -static struct alias *atab[ATABSIZE]; - -static void setalias (char *, char *); -static struct alias **hashalias (const char *); -static struct alias *freealias (struct alias *); -static struct alias **__lookupalias (const char *); - -static void -setalias(name, val) - char *name, *val; -{ - struct alias *ap, **app; - - app = __lookupalias(name); - ap = *app; - INTOFF; - if (ap) { - if (!(ap->flag & ALIASINUSE)) { - ckfree(ap->val); - } - ap->val = savestr(val); - ap->flag &= ~ALIASDEAD; - } else { - /* not found */ - ap = ckmalloc(sizeof (struct alias)); - ap->name = savestr(name); - ap->val = savestr(val); - ap->flag = 0; - ap->next = 0; - *app = ap; - } - INTON; -} - -static int -unalias(char *name) -{ - struct alias **app; - - app = __lookupalias(name); - - if (*app) { - INTOFF; - *app = freealias(*app); - INTON; - return (0); - } - - return (1); -} - -static void -rmaliases(void) -{ - struct alias *ap, **app; - int i; - - INTOFF; - for (i = 0; i < ATABSIZE; i++) { - app = &atab[i]; - for (ap = *app; ap; ap = *app) { - *app = freealias(*app); - if (ap == *app) { - app = &ap->next; - } - } - } - INTON; -} - -static struct alias * -lookupalias(const char *name, int check) -{ - struct alias *ap = *__lookupalias(name); - - if (check && ap && (ap->flag & ALIASINUSE)) - return (NULL); - return (ap); -} - -static void -printalias(const struct alias *ap) { - char *p; - - p = single_quote(ap->val); - printf("alias %s=%s\n", ap->name, p); - stunalloc(p); -} - - -/* - * TODO - sort output - */ -static int -aliascmd(int argc, char **argv) -{ - char *n, *v; - int ret = 0; - struct alias *ap; - - if (argc == 1) { - int i; - - for (i = 0; i < ATABSIZE; i++) - for (ap = atab[i]; ap; ap = ap->next) { - printalias(ap); - } - return (0); - } - while ((n = *++argv) != NULL) { - if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */ - if ((ap = *__lookupalias(n)) == NULL) { - out2fmt("%s: %s not found\n", "alias", n); - ret = 1; - } else - printalias(ap); - } - else { - *v++ = '\0'; - setalias(n, v); - } - } - - return (ret); -} - -static int -unaliascmd(int argc, char **argv) -{ - int i; - - while ((i = nextopt("a")) != '\0') { - if (i == 'a') { - rmaliases(); - return (0); - } - } - for (i = 0; *argptr; argptr++) { - if (unalias(*argptr)) { - out2fmt("%s: %s not found\n", "unalias", *argptr); - i = 1; - } - } - - return (i); -} - -static struct alias ** -hashalias(p) - const char *p; - { - unsigned int hashval; - - hashval = *p << 4; - while (*p) - hashval+= *p++; - return &atab[hashval % ATABSIZE]; -} - -static struct alias * -freealias(struct alias *ap) { - struct alias *next; - - if (ap->flag & ALIASINUSE) { - ap->flag |= ALIASDEAD; - return ap; - } - - next = ap->next; - ckfree(ap->name); - ckfree(ap->val); - ckfree(ap); - return next; -} - - -static struct alias ** -__lookupalias(const char *name) { - struct alias **app = hashalias(name); - - for (; *app; app = &(*app)->next) { - if (equal(name, (*app)->name)) { - break; - } - } - - return app; -} -#endif - -#ifdef ASH_MATH_SUPPORT -/* The generated file arith.c has been replaced with a custom hand - * written implementation written by Aaron Lehmann . - * This is now part of libbb, so that it can be used by all the shells - * in busybox. */ -static void expari (int); -#endif - -static char *trap[NSIG]; /* trap handler commands */ -static char sigmode[NSIG - 1]; /* current value of signal */ -static char gotsig[NSIG - 1]; /* indicates specified signal received */ -static int pendingsigs; /* indicates some signal received */ - -/* - * This file was generated by the mkbuiltins program. - */ - -#ifdef JOBS -static int bgcmd (int, char **); -static int fgcmd (int, char **); -static int killcmd (int, char **); -#endif -static int bltincmd (int, char **); -static int cdcmd (int, char **); -static int breakcmd (int, char **); -#ifdef ASH_CMDCMD -static int commandcmd (int, char **); -#endif -static int dotcmd (int, char **); -static int evalcmd (int, char **); -static int execcmd (int, char **); -static int exitcmd (int, char **); -static int exportcmd (int, char **); -static int histcmd (int, char **); -static int hashcmd (int, char **); -static int helpcmd (int, char **); -static int jobscmd (int, char **); -static int localcmd (int, char **); -#ifndef BB_PWD -static int pwdcmd (int, char **); -#endif -static int readcmd (int, char **); -static int returncmd (int, char **); -static int setcmd (int, char **); -static int setvarcmd (int, char **); -static int shiftcmd (int, char **); -static int trapcmd (int, char **); -static int umaskcmd (int, char **); -#ifdef ASH_ALIAS -static int aliascmd (int, char **); -static int unaliascmd (int, char **); -#endif -static int unsetcmd (int, char **); -static int waitcmd (int, char **); -static int ulimitcmd (int, char **); -static int timescmd (int, char **); -#ifdef ASH_MATH_SUPPORT -static int letcmd (int, char **); -#endif -static int typecmd (int, char **); -#ifdef ASH_GETOPTS -static int getoptscmd (int, char **); -#endif - -#ifndef BB_TRUE_FALSE -static int true_main (int, char **); -static int false_main (int, char **); -#endif - -static void setpwd (const char *, int); - - -#define BUILTIN_NOSPEC "0" -#define BUILTIN_SPECIAL "1" -#define BUILTIN_REGULAR "2" -#define BUILTIN_ASSIGN "4" -#define BUILTIN_SPEC_ASSG "5" -#define BUILTIN_REG_ASSG "6" - -#define IS_BUILTIN_SPECIAL(builtincmd) ((builtincmd)->name[0] & 1) -#define IS_BUILTIN_REGULAR(builtincmd) ((builtincmd)->name[0] & 2) -#define IS_BUILTIN_ASSIGN(builtincmd) ((builtincmd)->name[0] & 4) - -struct builtincmd { - const char *name; - int (*const builtinfunc) (int, char **); - //unsigned flags; -}; - - -/* It is CRUCIAL that this listing be kept in ascii order, otherwise - * the binary search in find_builtin() will stop working. If you value - * your kneecaps, you'll be sure to *make sure* that any changes made - * to this array result in the listing remaining in ascii order. You - * have been warned. - */ -static const struct builtincmd builtincmds[] = { - { BUILTIN_SPECIAL ".", dotcmd }, /* first, see declare DOTCMD */ - { BUILTIN_SPECIAL ":", true_main }, -#ifdef ASH_ALIAS - { BUILTIN_REG_ASSG "alias", aliascmd }, -#endif -#ifdef JOBS - { BUILTIN_REGULAR "bg", bgcmd }, -#endif - { BUILTIN_SPECIAL "break", breakcmd }, - { BUILTIN_SPECIAL "builtin", bltincmd }, - { BUILTIN_REGULAR "cd", cdcmd }, - { BUILTIN_NOSPEC "chdir", cdcmd }, -#ifdef ASH_CMDCMD - { BUILTIN_REGULAR "command", commandcmd }, -#endif - { BUILTIN_SPECIAL "continue", breakcmd }, - { BUILTIN_SPECIAL "eval", evalcmd }, - { BUILTIN_SPECIAL "exec", execcmd }, - { BUILTIN_SPECIAL "exit", exitcmd }, - { BUILTIN_SPEC_ASSG "export", exportcmd }, - { BUILTIN_REGULAR "false", false_main }, - { BUILTIN_REGULAR "fc", histcmd }, -#ifdef JOBS - { BUILTIN_REGULAR "fg", fgcmd }, -#endif -#ifdef ASH_GETOPTS - { BUILTIN_REGULAR "getopts", getoptscmd }, -#endif - { BUILTIN_NOSPEC "hash", hashcmd }, - { BUILTIN_NOSPEC "help", helpcmd }, - { BUILTIN_REGULAR "jobs", jobscmd }, -#ifdef JOBS - { BUILTIN_REGULAR "kill", killcmd }, -#endif -#ifdef ASH_MATH_SUPPORT - { BUILTIN_REGULAR "let", letcmd }, -#endif - { BUILTIN_ASSIGN "local", localcmd }, -#ifndef BB_PWD - { BUILTIN_NOSPEC "pwd", pwdcmd }, -#endif - { BUILTIN_REGULAR "read", readcmd }, - { BUILTIN_SPEC_ASSG "readonly", exportcmd }, - { BUILTIN_SPECIAL "return", returncmd }, - { BUILTIN_SPECIAL "set", setcmd }, - { BUILTIN_NOSPEC "setvar", setvarcmd }, - { BUILTIN_SPECIAL "shift", shiftcmd }, - { BUILTIN_SPECIAL "times", timescmd }, - { BUILTIN_SPECIAL "trap", trapcmd }, - { BUILTIN_REGULAR "true", true_main }, - { BUILTIN_NOSPEC "type", typecmd }, - { BUILTIN_NOSPEC "ulimit", ulimitcmd }, - { BUILTIN_REGULAR "umask", umaskcmd }, -#ifdef ASH_ALIAS - { BUILTIN_REGULAR "unalias", unaliascmd }, -#endif - { BUILTIN_SPECIAL "unset", unsetcmd }, - { BUILTIN_REGULAR "wait", waitcmd }, -}; -#define NUMBUILTINS (sizeof (builtincmds) / sizeof (struct builtincmd) ) - -#define DOTCMD &builtincmds[0] -static struct builtincmd *BLTINCMD; -static struct builtincmd *EXECCMD; -static struct builtincmd *EVALCMD; - -/* states */ -#define JOBSTOPPED 1 /* all procs are stopped */ -#define JOBDONE 2 /* all procs are completed */ - -/* - * A job structure contains information about a job. A job is either a - * single process or a set of processes contained in a pipeline. In the - * latter case, pidlist will be non-NULL, and will point to a -1 terminated - * array of pids. - */ - -struct procstat { - pid_t pid; /* process id */ - int status; /* status flags (defined above) */ - char *cmd; /* text of command being run */ -}; - - -static int job_warning; /* user was warned about stopped jobs */ - -#ifdef JOBS -static void setjobctl(int enable); -#else -#define setjobctl(on) /* do nothing */ -#endif - - -struct job { - struct procstat ps0; /* status of process */ - struct procstat *ps; /* status or processes when more than one */ - short nprocs; /* number of processes */ - short pgrp; /* process group of this job */ - char state; /* true if job is finished */ - char used; /* true if this entry is in used */ - char changed; /* true if status has changed */ -#ifdef JOBS - char jobctl; /* job running under job control */ -#endif -}; - -static struct job *jobtab; /* array of jobs */ -static int njobs; /* size of array */ -static int backgndpid = -1; /* pid of last background process */ -#ifdef JOBS -static int initialpgrp; /* pgrp of shell on invocation */ -static int curjob; /* current job */ -static int jobctl; -#endif -static int intreceived; - -static struct job *makejob (const union node *, int); -static int forkshell (struct job *, const union node *, int); -static int waitforjob (struct job *); - -static int docd (char *, int); -static char *getcomponent (void); -static void updatepwd (const char *); -static void getpwd (void); - -static char *padvance (const char **, const char *); - -static char nullstr[1]; /* zero length string */ -static char *curdir = nullstr; /* current working directory */ -static char *cdcomppath; - -static int -cdcmd(argc, argv) - int argc; - char **argv; -{ - const char *dest; - const char *path; - char *p; - struct stat statb; - int print = 0; - - nextopt(nullstr); - if ((dest = *argptr) == NULL && (dest = bltinlookup("HOME")) == NULL) - error("HOME not set"); - if (*dest == '\0') - dest = "."; - if (dest[0] == '-' && dest[1] == '\0') { - dest = bltinlookup("OLDPWD"); - if (!dest || !*dest) { - dest = curdir; - } - print = 1; - if (dest) - print = 1; - else - dest = "."; - } - if (*dest == '/' || (path = bltinlookup("CDPATH")) == NULL) - path = nullstr; - while ((p = padvance(&path, dest)) != NULL) { - if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) { - if (!print) { - /* - * XXX - rethink - */ - if (p[0] == '.' && p[1] == '/' && p[2] != '\0') - p += 2; - print = strcmp(p, dest); - } - if (docd(p, print) >= 0) - return 0; - - } - } - error("can't cd to %s", dest); - /* NOTREACHED */ -} - - -/* - * Actually do the chdir. In an interactive shell, print the - * directory name if "print" is nonzero. - */ - -static int -docd(dest, print) - char *dest; - int print; -{ - char *p; - char *q; - char *component; - struct stat statb; - int first; - int badstat; - - TRACE(("docd(\"%s\", %d) called\n", dest, print)); - - /* - * Check each component of the path. If we find a symlink or - * something we can't stat, clear curdir to force a getcwd() - * next time we get the value of the current directory. - */ - badstat = 0; - cdcomppath = sstrdup(dest); - STARTSTACKSTR(p); - if (*dest == '/') { - STPUTC('/', p); - cdcomppath++; - } - first = 1; - while ((q = getcomponent()) != NULL) { - if (q[0] == '\0' || (q[0] == '.' && q[1] == '\0')) - continue; - if (! first) - STPUTC('/', p); - first = 0; - component = q; - while (*q) - STPUTC(*q++, p); - if (equal(component, "..")) - continue; - STACKSTRNUL(p); - if ((lstat(stackblock(), &statb) < 0) - || (S_ISLNK(statb.st_mode))) { - /* print = 1; */ - badstat = 1; - break; - } - } - - INTOFF; - if (chdir(dest) < 0) { - INTON; - return -1; - } - updatepwd(badstat ? NULL : dest); - INTON; - if (print && iflag) - printf(snlfmt, curdir); - return 0; -} - - -/* - * Get the next component of the path name pointed to by cdcomppath. - * This routine overwrites the string pointed to by cdcomppath. - */ - -static char * -getcomponent() { - char *p; - char *start; - - if ((p = cdcomppath) == NULL) - return NULL; - start = cdcomppath; - while (*p != '/' && *p != '\0') - p++; - if (*p == '\0') { - cdcomppath = NULL; - } else { - *p++ = '\0'; - cdcomppath = p; - } - return start; -} - - - -/* - * Update curdir (the name of the current directory) in response to a - * cd command. We also call hashcd to let the routines in exec.c know - * that the current directory has changed. - */ - -static void hashcd (void); - -static void -updatepwd(const char *dir) -{ - char *new; - char *p; - size_t len; - - hashcd(); /* update command hash table */ - - /* - * If our argument is NULL, we don't know the current directory - * any more because we traversed a symbolic link or something - * we couldn't stat(). - */ - if (dir == NULL || curdir == nullstr) { - setpwd(0, 1); - return; - } - len = strlen(dir); - cdcomppath = sstrdup(dir); - STARTSTACKSTR(new); - if (*dir != '/') { - p = curdir; - while (*p) - STPUTC(*p++, new); - if (p[-1] == '/') - STUNPUTC(new); - } - while ((p = getcomponent()) != NULL) { - if (equal(p, "..")) { - while (new > stackblock() && (STUNPUTC(new), *new) != '/'); - } else if (*p != '\0' && ! equal(p, ".")) { - STPUTC('/', new); - while (*p) - STPUTC(*p++, new); - } - } - if (new == stackblock()) - STPUTC('/', new); - STACKSTRNUL(new); - setpwd(stackblock(), 1); -} - - -#ifndef BB_PWD -static int -pwdcmd(argc, argv) - int argc; - char **argv; -{ - printf(snlfmt, curdir); - return 0; -} -#endif - -/* - * Find out what the current directory is. If we already know the current - * directory, this routine returns immediately. - */ -static void -getpwd(void) -{ - curdir = xgetcwd(0); - if(curdir==0) - curdir = nullstr; -} - -static void -setpwd(const char *val, int setold) -{ - if (setold) { - setvar("OLDPWD", curdir, VEXPORT); - } - INTOFF; - if (curdir != nullstr) { - free(curdir); - curdir = nullstr; - } - if (!val) { - getpwd(); - } else { - curdir = savestr(val); - } - INTON; - setvar("PWD", curdir, VEXPORT); -} - -/* - * Errors and exceptions. - */ - -/* - * Code to handle exceptions in C. - */ - -/* - * We enclose jmp_buf in a structure so that we can declare pointers to - * jump locations. The global variable handler contains the location to - * jump to when an exception occurs, and the global variable exception - * contains a code identifying the exeception. To implement nested - * exception handlers, the user should save the value of handler on entry - * to an inner scope, set handler to point to a jmploc structure for the - * inner scope, and restore handler on exit from the scope. - */ - -struct jmploc { - jmp_buf loc; -}; - -/* exceptions */ -#define EXINT 0 /* SIGINT received */ -#define EXERROR 1 /* a generic error */ -#define EXSHELLPROC 2 /* execute a shell procedure */ -#define EXEXEC 3 /* command execution failed */ - -static struct jmploc *handler; -static int exception; - -static void exverror (int, const char *, va_list) - __attribute__((__noreturn__)); - -/* - * Called to raise an exception. Since C doesn't include exceptions, we - * just do a longjmp to the exception handler. The type of exception is - * stored in the global variable "exception". - */ - -static void exraise (int) __attribute__((__noreturn__)); - -static void -exraise(int e) -{ -#ifdef DEBUG - if (handler == NULL) - abort(); -#endif - flushall(); - exception = e; - longjmp(handler->loc, 1); -} - - -/* - * Called from trap.c when a SIGINT is received. (If the user specifies - * that SIGINT is to be trapped or ignored using the trap builtin, then - * this routine is not called.) Suppressint is nonzero when interrupts - * are held using the INTOFF macro. The call to _exit is necessary because - * there is a short period after a fork before the signal handlers are - * set to the appropriate value for the child. (The test for iflag is - * just defensive programming.) - */ - -static void -onint(void) { - sigset_t mysigset; - - if (suppressint) { - intpending++; - return; - } - intpending = 0; - sigemptyset(&mysigset); - sigprocmask(SIG_SETMASK, &mysigset, NULL); - if (rootshell && iflag) - exraise(EXINT); - else { - signal(SIGINT, SIG_DFL); - raise(SIGINT); - } - /* NOTREACHED */ -} - - -static char *commandname; /* currently executing command */ - -/* - * Exverror is called to raise the error exception. If the first argument - * is not NULL then error prints an error message using printf style - * formatting. It then raises the error exception. - */ -static void -exverror(int cond, const char *msg, va_list ap) -{ - CLEAR_PENDING_INT; - INTOFF; - -#ifdef DEBUG - if (msg) - TRACE(("exverror(%d, \"%s\") pid=%d\n", cond, msg, getpid())); - else - TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid())); -#endif - if (msg) { - if (commandname) - out2fmt("%s: ", commandname); - vfprintf(stderr, msg, ap); - out2c('\n'); - } - exraise(cond); - /* NOTREACHED */ -} - - -static void -error(const char *msg, ...) -{ - va_list ap; - va_start(ap, msg); - exverror(EXERROR, msg, ap); - /* NOTREACHED */ - va_end(ap); -} - - -static void -exerror(int cond, const char *msg, ...) -{ - va_list ap; - va_start(ap, msg); - exverror(cond, msg, ap); - /* NOTREACHED */ - va_end(ap); -} - - - -/* - * Table of error messages. - */ - -struct errname { - short errcode; /* error number */ - char action; /* operation which encountered the error */ -}; - -/* - * Types of operations (passed to the errmsg routine). - */ - -#define E_OPEN 01 /* opening a file */ -#define E_CREAT 02 /* creating a file */ -#define E_EXEC 04 /* executing a program */ - -#define ALL (E_OPEN|E_CREAT|E_EXEC) - -static const struct errname errormsg[] = { - { EINTR, ALL }, - { EACCES, ALL }, - { EIO, ALL }, - { ENOENT, E_OPEN }, - { ENOENT, E_CREAT }, - { ENOENT, E_EXEC }, - { ENOTDIR, E_OPEN }, - { ENOTDIR, E_CREAT }, - { ENOTDIR, E_EXEC }, - { EISDIR, ALL }, - { EEXIST, E_CREAT }, -#ifdef EMFILE - { EMFILE, ALL }, -#endif - { ENFILE, ALL }, - { ENOSPC, ALL }, -#ifdef EDQUOT - { EDQUOT, ALL }, -#endif -#ifdef ENOSR - { ENOSR, ALL }, -#endif - { ENXIO, ALL }, - { EROFS, ALL }, - { ETXTBSY, ALL }, -#ifdef EAGAIN - { EAGAIN, E_EXEC }, -#endif - { ENOMEM, ALL }, -#ifdef ENOLINK - { ENOLINK, ALL }, -#endif -#ifdef EMULTIHOP - { EMULTIHOP, ALL }, -#endif -#ifdef ECOMM - { ECOMM, ALL }, -#endif -#ifdef ESTALE - { ESTALE, ALL }, -#endif -#ifdef ETIMEDOUT - { ETIMEDOUT, ALL }, -#endif -#ifdef ELOOP - { ELOOP, ALL }, -#endif - { E2BIG, E_EXEC }, -#ifdef ELIBACC - { ELIBACC, E_EXEC }, -#endif -}; - -#define ERRNAME_SIZE (sizeof(errormsg)/sizeof(struct errname)) - -/* - * Return a string describing an error. The returned string may be a - * pointer to a static buffer that will be overwritten on the next call. - * Action describes the operation that got the error. - */ - -static const char * -errmsg(int e, int action) -{ - struct errname const *ep; - static char buf[12]; - - for (ep = errormsg ; ep < errormsg+ERRNAME_SIZE; ep++) { - if (ep->errcode == e && (ep->action & action) != 0) - return strerror(e); - } - - snprintf(buf, sizeof buf, "error %d", e); - return buf; -} - - -#ifdef ASH_OPTIMIZE_FOR_SIZE -static void -__inton() { - if (--suppressint == 0 && intpending) { - onint(); - } -} -static void forceinton (void) { - suppressint = 0; - if (intpending) - onint(); -} -#endif - -/* flags in argument to evaltree */ -#define EV_EXIT 01 /* exit after evaluating tree */ -#define EV_TESTED 02 /* exit status is checked; ignore -e flag */ -#define EV_BACKCMD 04 /* command executing within back quotes */ - -static int evalskip; /* set if we are skipping commands */ -static int skipcount; /* number of levels to skip */ -static int loopnest; /* current loop nesting level */ -static int funcnest; /* depth of function calls */ - - -static struct strlist *cmdenviron; /* environment for builtin command */ -static int exitstatus; /* exit status of last command */ -static int oexitstatus; /* saved exit status */ - -static void evalsubshell (const union node *, int); -static void expredir (union node *); -static void prehash (union node *); -static void eprintlist (struct strlist *); - -static union node *parsecmd(int); -/* - * Called to reset things after an exception. - */ - -/* - * The eval commmand. - */ -static void evalstring (char *, int); - -static int -evalcmd(argc, argv) - int argc; - char **argv; -{ - char *p; - char *concat; - char **ap; - - if (argc > 1) { - p = argv[1]; - if (argc > 2) { - STARTSTACKSTR(concat); - ap = argv + 2; - for (;;) { - while (*p) - STPUTC(*p++, concat); - if ((p = *ap++) == NULL) - break; - STPUTC(' ', concat); - } - STPUTC('\0', concat); - p = grabstackstr(concat); - } - evalstring(p, EV_TESTED); - } - return exitstatus; -} - -/* - * Execute a command or commands contained in a string. - */ - -static void evaltree (union node *, int); -static void setinputstring (char *); -static void popfile (void); -static void setstackmark(struct stackmark *mark); -static void popstackmark(struct stackmark *mark); - - -static void -evalstring(char *s, int flag) -{ - union node *n; - struct stackmark smark; - - setstackmark(&smark); - setinputstring(s); - while ((n = parsecmd(0)) != NEOF) { - evaltree(n, flag); - popstackmark(&smark); - } - popfile(); - popstackmark(&smark); -} - -static struct builtincmd *find_builtin (const char *); -static void expandarg (union node *, struct arglist *, int); -static void calcsize (const union node *); -static union node *copynode (const union node *); - -/* - * Make a copy of a parse tree. - */ - -static int funcblocksize; /* size of structures in function */ -static int funcstringsize; /* size of strings in node */ -static pointer funcblock; /* block to allocate function from */ -static char *funcstring; /* block to allocate strings from */ - - -static inline union node * -copyfunc(union node *n) -{ - if (n == NULL) - return NULL; - funcblocksize = 0; - funcstringsize = 0; - calcsize(n); - funcblock = ckmalloc(funcblocksize + funcstringsize); - funcstring = (char *) funcblock + funcblocksize; - return copynode(n); -} - -/* - * Free a parse tree. - */ - -static void -freefunc(union node *n) -{ - if (n) - ckfree(n); -} - - -/* - * Add a new command entry, replacing any existing command entry for - * the same name. - */ - -static inline void -addcmdentry(char *name, struct cmdentry *entry) -{ - struct tblentry *cmdp; - - INTOFF; - cmdp = cmdlookup(name, 1); - if (cmdp->cmdtype == CMDFUNCTION) { - freefunc(cmdp->param.func); - } - cmdp->cmdtype = entry->cmdtype; - cmdp->param = entry->u; - INTON; -} - -static inline void -evalloop(const union node *n, int flags) -{ - int status; - - loopnest++; - status = 0; - for (;;) { - evaltree(n->nbinary.ch1, EV_TESTED); - if (evalskip) { -skipping: if (evalskip == SKIPCONT && --skipcount <= 0) { - evalskip = 0; - continue; - } - if (evalskip == SKIPBREAK && --skipcount <= 0) - evalskip = 0; - break; - } - if (n->type == NWHILE) { - if (exitstatus != 0) - break; - } else { - if (exitstatus == 0) - break; - } - evaltree(n->nbinary.ch2, flags & EV_TESTED); - status = exitstatus; - if (evalskip) - goto skipping; - } - loopnest--; - exitstatus = status; -} - -static void -evalfor(const union node *n, int flags) -{ - struct arglist arglist; - union node *argp; - struct strlist *sp; - struct stackmark smark; - - setstackmark(&smark); - arglist.lastp = &arglist.list; - for (argp = n->nfor.args ; argp ; argp = argp->narg.next) { - oexitstatus = exitstatus; - expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD); - if (evalskip) - goto out; - } - *arglist.lastp = NULL; - - exitstatus = 0; - loopnest++; - for (sp = arglist.list ; sp ; sp = sp->next) { - setvar(n->nfor.var, sp->text, 0); - evaltree(n->nfor.body, flags & EV_TESTED); - if (evalskip) { - if (evalskip == SKIPCONT && --skipcount <= 0) { - evalskip = 0; - continue; - } - if (evalskip == SKIPBREAK && --skipcount <= 0) - evalskip = 0; - break; - } - } - loopnest--; -out: - popstackmark(&smark); -} - -static inline void -evalcase(const union node *n, int flags) -{ - union node *cp; - union node *patp; - struct arglist arglist; - struct stackmark smark; - - setstackmark(&smark); - arglist.lastp = &arglist.list; - oexitstatus = exitstatus; - expandarg(n->ncase.expr, &arglist, EXP_TILDE); - for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) { - for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) { - if (casematch(patp, arglist.list->text)) { - if (evalskip == 0) { - evaltree(cp->nclist.body, flags); - } - goto out; - } - } - } -out: - popstackmark(&smark); -} - -/* - * Evaluate a pipeline. All the processes in the pipeline are children - * of the process creating the pipeline. (This differs from some versions - * of the shell, which make the last process in a pipeline the parent - * of all the rest.) - */ - -static inline void evalpipe(union node *n) -{ - struct job *jp; - struct nodelist *lp; - int pipelen; - int prevfd; - int pip[2]; - - TRACE(("evalpipe(0x%lx) called\n", (long)n)); - pipelen = 0; - for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) - pipelen++; - INTOFF; - jp = makejob(n, pipelen); - prevfd = -1; - for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { - prehash(lp->n); - pip[1] = -1; - if (lp->next) { - if (pipe(pip) < 0) { - close(prevfd); - error("Pipe call failed"); - } - } - if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) { - INTON; - if (prevfd > 0) { - close(0); - dup_as_newfd(prevfd, 0); - close(prevfd); - if (pip[0] == 0) { - pip[0] = -1; - } - } - if (pip[1] >= 0) { - if (pip[0] >= 0) { - close(pip[0]); - } - if (pip[1] != 1) { - close(1); - dup_as_newfd(pip[1], 1); - close(pip[1]); - } - } - evaltree(lp->n, EV_EXIT); - } - if (prevfd >= 0) - close(prevfd); - prevfd = pip[0]; - close(pip[1]); - } - INTON; - if (n->npipe.backgnd == 0) { - INTOFF; - exitstatus = waitforjob(jp); - TRACE(("evalpipe: job done exit status %d\n", exitstatus)); - INTON; - } -} - -static void find_command (const char *, struct cmdentry *, int, const char *); - -static int -isassignment(const char *word) { - if (!is_name(*word)) { - return 0; - } - do { - word++; - } while (is_in_name(*word)); - return *word == '='; -} - - -static void -evalcommand(union node *cmd, int flags) -{ - struct stackmark smark; - union node *argp; - struct arglist arglist; - struct arglist varlist; - char **argv; - int argc; - char **envp; - struct strlist *sp; - int mode; - struct cmdentry cmdentry; - struct job *jp; - char *volatile savecmdname; - volatile struct shparam saveparam; - struct localvar *volatile savelocalvars; - volatile int e; - char *lastarg; - const char *path; - const struct builtincmd *firstbltin; - struct jmploc *volatile savehandler; - struct jmploc jmploc; -#if __GNUC__ - /* Avoid longjmp clobbering */ - (void) &argv; - (void) &argc; - (void) &lastarg; - (void) &flags; -#endif - - /* First expand the arguments. */ - TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags)); - setstackmark(&smark); - arglist.lastp = &arglist.list; - varlist.lastp = &varlist.list; - arglist.list = 0; - oexitstatus = exitstatus; - exitstatus = 0; - path = pathval(); - for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) { - expandarg(argp, &varlist, EXP_VARTILDE); - } - for ( - argp = cmd->ncmd.args; argp && !arglist.list; - argp = argp->narg.next - ) { - expandarg(argp, &arglist, EXP_FULL | EXP_TILDE); - } - if (argp) { - struct builtincmd *bcmd; - int pseudovarflag; - bcmd = find_builtin(arglist.list->text); - pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd); - for (; argp; argp = argp->narg.next) { - if (pseudovarflag && isassignment(argp->narg.text)) { - expandarg(argp, &arglist, EXP_VARTILDE); - continue; - } - expandarg(argp, &arglist, EXP_FULL | EXP_TILDE); - } - } - *arglist.lastp = NULL; - *varlist.lastp = NULL; - expredir(cmd->ncmd.redirect); - argc = 0; - for (sp = arglist.list ; sp ; sp = sp->next) - argc++; - argv = stalloc(sizeof (char *) * (argc + 1)); - - for (sp = arglist.list ; sp ; sp = sp->next) { - TRACE(("evalcommand arg: %s\n", sp->text)); - *argv++ = sp->text; - } - *argv = NULL; - lastarg = NULL; - if (iflag && funcnest == 0 && argc > 0) - lastarg = argv[-1]; - argv -= argc; - - /* Print the command if xflag is set. */ - if (xflag) { - out2c('+'); - eprintlist(varlist.list); - eprintlist(arglist.list); - out2c('\n'); - } - - /* Now locate the command. */ - if (argc == 0) { - cmdentry.cmdtype = CMDBUILTIN; - firstbltin = cmdentry.u.cmd = BLTINCMD; - } else { - const char *oldpath; - int findflag = DO_ERR; - int oldfindflag; - - /* - * Modify the command lookup path, if a PATH= assignment - * is present - */ - for (sp = varlist.list ; sp ; sp = sp->next) - if (varequal(sp->text, defpathvar)) { - path = sp->text + 5; - findflag |= DO_BRUTE; - } - oldpath = path; - oldfindflag = findflag; - firstbltin = 0; - for(;;) { - find_command(argv[0], &cmdentry, findflag, path); - if (cmdentry.cmdtype == CMDUNKNOWN) { /* command not found */ - exitstatus = 127; - goto out; - } - /* implement bltin and command here */ - if (cmdentry.cmdtype != CMDBUILTIN) { - break; - } - if (!firstbltin) { - firstbltin = cmdentry.u.cmd; - } - if (cmdentry.u.cmd == BLTINCMD) { - for(;;) { - struct builtincmd *bcmd; - - argv++; - if (--argc == 0) - goto found; - if (!(bcmd = find_builtin(*argv))) { - out2fmt("%s: not found\n", *argv); - exitstatus = 127; - goto out; - } - cmdentry.u.cmd = bcmd; - if (bcmd != BLTINCMD) - break; - } - } - if (cmdentry.u.cmd == find_builtin("command")) { - argv++; - if (--argc == 0) { - goto found; - } - if (*argv[0] == '-') { - if (!equal(argv[0], "-p")) { - argv--; - argc++; - break; - } - argv++; - if (--argc == 0) { - goto found; - } - path = defpath; - findflag |= DO_BRUTE; - } else { - path = oldpath; - findflag = oldfindflag; - } - findflag |= DO_NOFUN; - continue; - } -found: - break; - } - } - - /* Fork off a child process if necessary. */ - if (cmd->ncmd.backgnd - || (cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0) - ) { - jp = makejob(cmd, 1); - mode = cmd->ncmd.backgnd; - if (forkshell(jp, cmd, mode) != 0) - goto parent; /* at end of routine */ - flags |= EV_EXIT; - } - - /* This is the child process if a fork occurred. */ - /* Execute the command. */ - if (cmdentry.cmdtype == CMDFUNCTION) { -#ifdef DEBUG - trputs("Shell function: "); trargs(argv); -#endif - exitstatus = oexitstatus; - redirect(cmd->ncmd.redirect, REDIR_PUSH); - saveparam = shellparam; - shellparam.malloc = 0; - shellparam.nparam = argc - 1; - shellparam.p = argv + 1; - INTOFF; - savelocalvars = localvars; - localvars = NULL; - INTON; - if (setjmp(jmploc.loc)) { - if (exception == EXSHELLPROC) { - freeparam((volatile struct shparam *) - &saveparam); - } else { - saveparam.optind = shellparam.optind; - saveparam.optoff = shellparam.optoff; - freeparam(&shellparam); - shellparam = saveparam; - } - poplocalvars(); - localvars = savelocalvars; - handler = savehandler; - longjmp(handler->loc, 1); - } - savehandler = handler; - handler = &jmploc; - for (sp = varlist.list ; sp ; sp = sp->next) - mklocal(sp->text); - funcnest++; - evaltree(cmdentry.u.func, flags & EV_TESTED); - funcnest--; - INTOFF; - poplocalvars(); - localvars = savelocalvars; - saveparam.optind = shellparam.optind; - saveparam.optoff = shellparam.optoff; - freeparam(&shellparam); - shellparam = saveparam; - handler = savehandler; - popredir(); - INTON; - if (evalskip == SKIPFUNC) { - evalskip = 0; - skipcount = 0; - } - if (flags & EV_EXIT) - exitshell(exitstatus); - } else if (cmdentry.cmdtype == CMDBUILTIN) { -#ifdef DEBUG - trputs("builtin command: "); trargs(argv); -#endif - mode = (cmdentry.u.cmd == EXECCMD)? 0 : REDIR_PUSH; - redirect(cmd->ncmd.redirect, mode); - savecmdname = commandname; - if (IS_BUILTIN_SPECIAL(firstbltin)) { - listsetvar(varlist.list); - } else { - cmdenviron = varlist.list; - } - e = -1; - if (setjmp(jmploc.loc)) { - e = exception; - exitstatus = (e == EXINT)? SIGINT+128 : 2; - goto cmddone; - } - savehandler = handler; - handler = &jmploc; - commandname = argv[0]; - argptr = argv + 1; - optptr = NULL; /* initialize nextopt */ - exitstatus = (*cmdentry.u.cmd->builtinfunc)(argc, argv); - flushall(); -cmddone: - cmdenviron = NULL; - if (e != EXSHELLPROC) { - commandname = savecmdname; - if (flags & EV_EXIT) - exitshell(exitstatus); - } - handler = savehandler; - if (e != -1) { - if ((e != EXERROR && e != EXEXEC) - || cmdentry.u.cmd == BLTINCMD - || cmdentry.u.cmd == DOTCMD - || cmdentry.u.cmd == EVALCMD - || cmdentry.u.cmd == EXECCMD) - exraise(e); - FORCEINTON; - } - if (cmdentry.u.cmd != EXECCMD) - popredir(); - } else { -#ifdef DEBUG - trputs("normal command: "); trargs(argv); -#endif - redirect(cmd->ncmd.redirect, 0); - clearredir(); - for (sp = varlist.list ; sp ; sp = sp->next) - setvareq(sp->text, VEXPORT|VSTACK); - envp = environment(); - shellexec(argv, envp, path, cmdentry.u.index); - } - goto out; - -parent: /* parent process gets here (if we forked) */ - if (mode == 0) { /* argument to fork */ - INTOFF; - exitstatus = waitforjob(jp); - INTON; - } - -out: - if (lastarg) - setvar("_", lastarg, 0); - popstackmark(&smark); -} - -/* - * Evaluate a parse tree. The value is left in the global variable - * exitstatus. - */ -static void -evaltree(n, flags) - union node *n; - int flags; -{ - int checkexit = 0; - if (n == NULL) { - TRACE(("evaltree(NULL) called\n")); - goto out; - } - TRACE(("evaltree(0x%lx: %d) called\n", (long)n, n->type)); - switch (n->type) { - case NSEMI: - evaltree(n->nbinary.ch1, flags & EV_TESTED); - if (evalskip) - goto out; - evaltree(n->nbinary.ch2, flags); - break; - case NAND: - evaltree(n->nbinary.ch1, EV_TESTED); - if (evalskip || exitstatus != 0) - goto out; - evaltree(n->nbinary.ch2, flags); - break; - case NOR: - evaltree(n->nbinary.ch1, EV_TESTED); - if (evalskip || exitstatus == 0) - goto out; - evaltree(n->nbinary.ch2, flags); - break; - case NREDIR: - expredir(n->nredir.redirect); - redirect(n->nredir.redirect, REDIR_PUSH); - evaltree(n->nredir.n, flags); - popredir(); - break; - case NSUBSHELL: - evalsubshell(n, flags); - break; - case NBACKGND: - evalsubshell(n, flags); - break; - case NIF: { - evaltree(n->nif.test, EV_TESTED); - if (evalskip) - goto out; - if (exitstatus == 0) - evaltree(n->nif.ifpart, flags); - else if (n->nif.elsepart) - evaltree(n->nif.elsepart, flags); - else - exitstatus = 0; - break; - } - case NWHILE: - case NUNTIL: - evalloop(n, flags); - break; - case NFOR: - evalfor(n, flags); - break; - case NCASE: - evalcase(n, flags); - break; - case NDEFUN: { - struct builtincmd *bcmd; - struct cmdentry entry; - if ( - (bcmd = find_builtin(n->narg.text)) && - IS_BUILTIN_SPECIAL(bcmd) - ) { - out2fmt("%s is a special built-in\n", n->narg.text); - exitstatus = 1; - break; - } - entry.cmdtype = CMDFUNCTION; - entry.u.func = copyfunc(n->narg.next); - addcmdentry(n->narg.text, &entry); - exitstatus = 0; - break; - } - case NNOT: - evaltree(n->nnot.com, EV_TESTED); - exitstatus = !exitstatus; - break; - - case NPIPE: - evalpipe(n); - checkexit = 1; - break; - case NCMD: - evalcommand(n, flags); - checkexit = 1; - break; -#ifdef DEBUG - default: - printf("Node type = %d\n", n->type); - break; -#endif - } -out: - if (pendingsigs) - dotrap(); - if ( - flags & EV_EXIT || - (checkexit && eflag && exitstatus && !(flags & EV_TESTED)) - ) - exitshell(exitstatus); -} - -/* - * Kick off a subshell to evaluate a tree. - */ - -static void -evalsubshell(const union node *n, int flags) -{ - struct job *jp; - int backgnd = (n->type == NBACKGND); - - expredir(n->nredir.redirect); - jp = makejob(n, 1); - if (forkshell(jp, n, backgnd) == 0) { - if (backgnd) - flags &=~ EV_TESTED; - redirect(n->nredir.redirect, 0); - evaltree(n->nredir.n, flags | EV_EXIT); /* never returns */ - } - if (! backgnd) { - INTOFF; - exitstatus = waitforjob(jp); - INTON; - } -} - -/* - * Compute the names of the files in a redirection list. - */ - -static void fixredir(union node *n, const char *text, int err); - -static void -expredir(union node *n) -{ - union node *redir; - - for (redir = n ; redir ; redir = redir->nfile.next) { - struct arglist fn; - fn.lastp = &fn.list; - oexitstatus = exitstatus; - switch (redir->type) { - case NFROMTO: - case NFROM: - case NTO: - case NAPPEND: - case NTOOV: - expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR); - redir->nfile.expfname = fn.list->text; - break; - case NFROMFD: - case NTOFD: - if (redir->ndup.vname) { - expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE); - fixredir(redir, fn.list->text, 1); - } - break; - } - } -} - - -/* - * Execute a command inside back quotes. If it's a builtin command, we - * want to save its output in a block obtained from malloc. Otherwise - * we fork off a subprocess and get the output of the command via a pipe. - * Should be called with interrupts off. - */ - -static void -evalbackcmd(union node *n, struct backcmd *result) -{ - int pip[2]; - struct job *jp; - struct stackmark smark; /* unnecessary */ - - setstackmark(&smark); - result->fd = -1; - result->buf = NULL; - result->nleft = 0; - result->jp = NULL; - if (n == NULL) { - exitstatus = 0; - goto out; - } - exitstatus = 0; - if (pipe(pip) < 0) - error("Pipe call failed"); - jp = makejob(n, 1); - if (forkshell(jp, n, FORK_NOJOB) == 0) { - FORCEINTON; - close(pip[0]); - if (pip[1] != 1) { - close(1); - dup_as_newfd(pip[1], 1); - close(pip[1]); - } - eflag = 0; - evaltree(n, EV_EXIT); - } - close(pip[1]); - result->fd = pip[0]; - result->jp = jp; -out: - popstackmark(&smark); - TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n", - result->fd, result->buf, result->nleft, result->jp)); -} - - -/* - * Execute a simple command. - */ - -/* - * Search for a command. This is called before we fork so that the - * location of the command will be available in the parent as well as - * the child. The check for "goodname" is an overly conservative - * check that the name will not be subject to expansion. - */ - -static void -prehash(n) - union node *n; -{ - struct cmdentry entry; - - if (n->type == NCMD && n->ncmd.args) - if (goodname(n->ncmd.args->narg.text)) - find_command(n->ncmd.args->narg.text, &entry, 0, - pathval()); -} - - -/* - * Builtin commands. Builtin commands whose functions are closely - * tied to evaluation are implemented here. - */ - -/* - * No command given, or a bltin command with no arguments. Set the - * specified variables. - */ - -int -bltincmd(argc, argv) - int argc; - char **argv; -{ - /* - * Preserve exitstatus of a previous possible redirection - * as POSIX mandates - */ - return exitstatus; -} - - -/* - * Handle break and continue commands. Break, continue, and return are - * all handled by setting the evalskip flag. The evaluation routines - * above all check this flag, and if it is set they start skipping - * commands rather than executing them. The variable skipcount is - * the number of loops to break/continue, or the number of function - * levels to return. (The latter is always 1.) It should probably - * be an error to break out of more loops than exist, but it isn't - * in the standard shell so we don't make it one here. - */ - -static int -breakcmd(argc, argv) - int argc; - char **argv; -{ - int n = argc > 1 ? number(argv[1]) : 1; - - if (n > loopnest) - n = loopnest; - if (n > 0) { - evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK; - skipcount = n; - } - return 0; -} - - -/* - * The return command. - */ - -static int -returncmd(argc, argv) - int argc; - char **argv; -{ - int ret = argc > 1 ? number(argv[1]) : oexitstatus; - - if (funcnest) { - evalskip = SKIPFUNC; - skipcount = 1; - return ret; - } - else { - /* Do what ksh does; skip the rest of the file */ - evalskip = SKIPFILE; - skipcount = 1; - return ret; - } -} - - -#ifndef BB_TRUE_FALSE -static int -false_main(argc, argv) - int argc; - char **argv; -{ - return 1; -} - - -static int -true_main(argc, argv) - int argc; - char **argv; -{ - return 0; -} -#endif - -/* - * Controls whether the shell is interactive or not. - */ - -static void setsignal(int signo); -static void chkmail(int silent); - - -static void -setinteractive(int on) -{ - static int is_interactive; - static int do_banner=0; - - if (on == is_interactive) - return; - setsignal(SIGINT); - setsignal(SIGQUIT); - setsignal(SIGTERM); - chkmail(1); - is_interactive = on; - if (do_banner==0 && is_interactive) { - /* Looks like they want an interactive shell */ -#ifndef BB_FEATURE_SH_EXTRA_QUIET - printf( "\n\n" BB_BANNER " Built-in shell (ash)\n"); - printf( "Enter 'help' for a list of built-in commands.\n\n"); -#endif - do_banner=1; - } -} - -static void -optschanged(void) -{ - setinteractive(iflag); - setjobctl(mflag); -} - - -static int -execcmd(argc, argv) - int argc; - char **argv; -{ - if (argc > 1) { - struct strlist *sp; - - iflag = 0; /* exit on error */ - mflag = 0; - optschanged(); - for (sp = cmdenviron; sp ; sp = sp->next) - setvareq(sp->text, VEXPORT|VSTACK); - shellexec(argv + 1, environment(), pathval(), 0); - } - return 0; -} - -static void -eprintlist(struct strlist *sp) -{ - for (; sp; sp = sp->next) { - out2fmt(" %s",sp->text); - } -} - -/* - * Exec a program. Never returns. If you change this routine, you may - * have to change the find_command routine as well. - */ - -static const char *pathopt; /* set by padvance */ - -static void -shellexec(argv, envp, path, idx) - char **argv, **envp; - const char *path; - int idx; -{ - char *cmdname; - int e; - - if (strchr(argv[0], '/') != NULL) { - tryexec(argv[0], argv, envp); - e = errno; - } else { - e = ENOENT; - while ((cmdname = padvance(&path, argv[0])) != NULL) { - if (--idx < 0 && pathopt == NULL) { - tryexec(cmdname, argv, envp); - if (errno != ENOENT && errno != ENOTDIR) - e = errno; - } - stunalloc(cmdname); - } - } - - /* Map to POSIX errors */ - switch (e) { - case EACCES: - exerrno = 126; - break; - case ENOENT: - exerrno = 127; - break; - default: - exerrno = 2; - break; - } - exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC)); - /* NOTREACHED */ -} - -/* - * Clear traps on a fork. - */ -static void -clear_traps(void) { - char **tp; - - for (tp = trap ; tp < &trap[NSIG] ; tp++) { - if (*tp && **tp) { /* trap not NULL or SIG_IGN */ - INTOFF; - ckfree(*tp); - *tp = NULL; - if (tp != &trap[0]) - setsignal(tp - trap); - INTON; - } - } -} - - -static void -initshellproc(void) { - -#ifdef ASH_ALIAS - /* from alias.c: */ - { - rmaliases(); - } -#endif - /* from eval.c: */ - { - exitstatus = 0; - } - - /* from exec.c: */ - { - deletefuncs(); - } - - /* from jobs.c: */ - { - backgndpid = -1; -#ifdef JOBS - jobctl = 0; -#endif - } - - /* from options.c: */ - { - int i; - - for (i = 0; i < NOPTS; i++) - optent_val(i) = 0; - optschanged(); - - } - - /* from redir.c: */ - { - clearredir(); - } - - /* from trap.c: */ - { - char *sm; - - clear_traps(); - for (sm = sigmode ; sm < sigmode + NSIG - 1; sm++) { - if (*sm == S_IGN) - *sm = S_HARD_IGN; - } - } - - /* from var.c: */ - { - shprocvar(); - } -} - -static int preadbuffer(void); -static void pushfile (void); - -/* - * Read a character from the script, returning PEOF on end of file. - * Nul characters in the input are silently discarded. - */ - -#ifndef ASH_OPTIMIZE_FOR_SIZE -#define pgetc_macro() (--parsenleft >= 0? *parsenextc++ : preadbuffer()) -static int -pgetc(void) -{ - return pgetc_macro(); -} -#else -static int -pgetc_macro(void) -{ - return --parsenleft >= 0? *parsenextc++ : preadbuffer(); -} - -static inline int -pgetc(void) -{ - return pgetc_macro(); -} -#endif - - -/* - * Undo the last call to pgetc. Only one character may be pushed back. - * PEOF may be pushed back. - */ - -static void pungetc(void) -{ - parsenleft++; - parsenextc--; -} - - -static void -popfile(void) { - struct parsefile *pf = parsefile; - - INTOFF; - if (pf->fd >= 0) - close(pf->fd); - if (pf->buf) - ckfree(pf->buf); - while (pf->strpush) - popstring(); - parsefile = pf->prev; - ckfree(pf); - parsenleft = parsefile->nleft; - parselleft = parsefile->lleft; - parsenextc = parsefile->nextc; - plinno = parsefile->linno; - INTON; -} - - -/* - * Return to top level. - */ - -static void -popallfiles(void) { - while (parsefile != &basepf) - popfile(); -} - -/* - * Close the file(s) that the shell is reading commands from. Called - * after a fork is done. - */ - -static void closescript(void) -{ - popallfiles(); - if (parsefile->fd > 0) { - close(parsefile->fd); - parsefile->fd = 0; - } -} - - -/* - * Like setinputfile, but takes an open file descriptor. Call this with - * interrupts off. - */ - -static void setinputfd(int fd, int push) -{ - (void) fcntl(fd, F_SETFD, FD_CLOEXEC); - if (push) { - pushfile(); - parsefile->buf = 0; - } else { - closescript(); - while (parsefile->strpush) - popstring(); - } - parsefile->fd = fd; - if (parsefile->buf == NULL) - parsefile->buf = ckmalloc(BUFSIZ); - parselleft = parsenleft = 0; - plinno = 1; -} - - -/* - * Set the input to take input from a file. If push is set, push the - * old input onto the stack first. - */ - -static void -setinputfile(const char *fname, int push) -{ - int fd; - int myfileno2; - - INTOFF; - if ((fd = open(fname, O_RDONLY)) < 0) - error("Can't open %s", fname); - if (fd < 10) { - myfileno2 = dup_as_newfd(fd, 10); - close(fd); - if (myfileno2 < 0) - error("Out of file descriptors"); - fd = myfileno2; - } - setinputfd(fd, push); - INTON; -} - - -static void -tryexec(char *cmd, char **argv, char **envp) -{ - int e; - -#ifdef BB_FEATURE_SH_STANDALONE_SHELL - char *name = cmd; - char** argv_l=argv; - int argc_l; -#ifdef BB_FEATURE_SH_APPLETS_ALWAYS_WIN - name = get_last_path_component(name); -#endif - argv_l=envp; - for(argc_l=0;*argv_l!=NULL; argv_l++, argc_l++) - putenv(*argv_l); - argv_l=argv; - for(argc_l=0;*argv_l!=NULL; argv_l++, argc_l++) - optind = 1; - run_applet_by_name(name, argc_l, argv); -#endif - execve(cmd, argv, envp); - e = errno; - if (e == ENOEXEC) { - INTOFF; - initshellproc(); - setinputfile(cmd, 0); - commandname = arg0 = savestr(argv[0]); - setparam(argv + 1); - exraise(EXSHELLPROC); - } - errno = e; -} - -static char *commandtext (const union node *); - -/* - * Do a path search. The variable path (passed by reference) should be - * set to the start of the path before the first call; padvance will update - * this value as it proceeds. Successive calls to padvance will return - * the possible path expansions in sequence. If an option (indicated by - * a percent sign) appears in the path entry then the global variable - * pathopt will be set to point to it; otherwise pathopt will be set to - * NULL. - */ - -static const char *pathopt; - -static void growstackblock(void); - - -static char * -padvance(const char **path, const char *name) -{ - const char *p; - char *q; - const char *start; - int len; - - if (*path == NULL) - return NULL; - start = *path; - for (p = start ; *p && *p != ':' && *p != '%' ; p++); - len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */ - while (stackblocksize() < len) - growstackblock(); - q = stackblock(); - if (p != start) { - memcpy(q, start, p - start); - q += p - start; - *q++ = '/'; - } - strcpy(q, name); - pathopt = NULL; - if (*p == '%') { - pathopt = ++p; - while (*p && *p != ':') p++; - } - if (*p == ':') - *path = p + 1; - else - *path = NULL; - return stalloc(len); -} - -/* - * Wrapper around strcmp for qsort/bsearch/... - */ -static int -pstrcmp(const void *a, const void *b) -{ - return strcmp((const char *) a, (*(const char *const *) b) + 1); -} - -/* - * Find a keyword is in a sorted array. - */ - -static const char *const * -findkwd(const char *s) -{ - return bsearch(s, tokname_array + KWDOFFSET, - (sizeof(tokname_array)/sizeof(const char *)) - KWDOFFSET, - sizeof(const char *), pstrcmp); -} - - -/*** Command hashing code ***/ - - -static int -hashcmd(argc, argv) - int argc; - char **argv; -{ - struct tblentry **pp; - struct tblentry *cmdp; - int c; - int verbose; - struct cmdentry entry; - char *name; -#ifdef ASH_ALIAS - const struct alias *ap; -#endif - - verbose = 0; - while ((c = nextopt("rvV")) != '\0') { - if (c == 'r') { - clearcmdentry(0); - return 0; - } else if (c == 'v' || c == 'V') { - verbose = c; - } - } - if (*argptr == NULL) { - for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) { - for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) { - if (cmdp->cmdtype != CMDBUILTIN) { - printentry(cmdp, verbose); - } - } - } - return 0; - } - c = 0; - while ((name = *argptr++) != NULL) { - if ((cmdp = cmdlookup(name, 0)) != NULL - && (cmdp->cmdtype == CMDNORMAL - || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))) - delete_cmd_entry(); -#ifdef ASH_ALIAS - /* Then look at the aliases */ - if ((ap = lookupalias(name, 0)) != NULL) { - if (verbose=='v') - printf("%s is an alias for %s\n", name, ap->val); - else - printalias(ap); - continue; - } -#endif - /* First look at the keywords */ - if (findkwd(name)!=0) { - if (verbose=='v') - printf("%s is a shell keyword\n", name); - else - printf(snlfmt, name); - continue; - } - - find_command(name, &entry, DO_ERR, pathval()); - if (entry.cmdtype == CMDUNKNOWN) c = 1; - else if (verbose) { - cmdp = cmdlookup(name, 0); - if (cmdp) printentry(cmdp, verbose=='v'); - flushall(); - } - } - return c; -} - -static void -printentry(cmdp, verbose) - struct tblentry *cmdp; - int verbose; - { - int idx; - const char *path; - char *name; - - printf("%s%s", cmdp->cmdname, (verbose ? " is " : "")); - if (cmdp->cmdtype == CMDNORMAL) { - idx = cmdp->param.index; - path = pathval(); - do { - name = padvance(&path, cmdp->cmdname); - stunalloc(name); - } while (--idx >= 0); - if(verbose) - out1str(name); - } else if (cmdp->cmdtype == CMDBUILTIN) { - if(verbose) - out1str("a shell builtin"); - } else if (cmdp->cmdtype == CMDFUNCTION) { - if (verbose) { - INTOFF; - out1str("a function\n"); - name = commandtext(cmdp->param.func); - printf("%s() {\n %s\n}", cmdp->cmdname, name); - ckfree(name); - INTON; - } -#ifdef DEBUG - } else { - error("internal error: cmdtype %d", cmdp->cmdtype); -#endif - } - printf(snlfmt, cmdp->rehash ? "*" : nullstr); -} - - - -/*** List the available builtins ***/ - - -static int helpcmd(int argc, char** argv) -{ - int col, i; - - printf("\nBuilt-in commands:\n-------------------\n"); - for (col=0, i=0; i < NUMBUILTINS; i++) { - col += printf("%c%s", ((col == 0) ? '\t' : ' '), - builtincmds[i].name+1); - if (col > 60) { - printf("\n"); - col = 0; - } - } -#ifdef BB_FEATURE_SH_STANDALONE_SHELL - { - extern const struct BB_applet applets[]; - extern const size_t NUM_APPLETS; - - for (i=0; i < NUM_APPLETS; i++) { - - col += printf("%c%s", ((col == 0) ? '\t' : ' '), - applets[i].name); - if (col > 60) { - printf("\n"); - col = 0; - } - } - } -#endif - printf("\n\n"); - return EXIT_SUCCESS; -} - -/* - * Resolve a command name. If you change this routine, you may have to - * change the shellexec routine as well. - */ - -static int prefix (const char *, const char *); - -static void -find_command(const char *name, struct cmdentry *entry, int act, const char *path) -{ - struct tblentry *cmdp; - int idx; - int prev; - char *fullname; - struct stat statb; - int e; - int bltin; - int firstchange; - int updatetbl; - int regular; - struct builtincmd *bcmd; - - /* If name contains a slash, don't use the hash table */ - if (strchr(name, '/') != NULL) { - if (act & DO_ABS) { - while (stat(name, &statb) < 0) { - if (errno != ENOENT && errno != ENOTDIR) - e = errno; - entry->cmdtype = CMDUNKNOWN; - entry->u.index = -1; - return; - } - entry->cmdtype = CMDNORMAL; - entry->u.index = -1; - return; - } - entry->cmdtype = CMDNORMAL; - entry->u.index = 0; - return; - } - - updatetbl = 1; - if (act & DO_BRUTE) { - firstchange = path_change(path, &bltin); - } else { - bltin = builtinloc; - firstchange = 9999; - } - - /* If name is in the table, and not invalidated by cd, we're done */ - if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->rehash == 0) { - if (cmdp->cmdtype == CMDFUNCTION) { - if (act & DO_NOFUN) { - updatetbl = 0; - } else { - goto success; - } - } else if (act & DO_BRUTE) { - if ((cmdp->cmdtype == CMDNORMAL && - cmdp->param.index >= firstchange) || - (cmdp->cmdtype == CMDBUILTIN && - ((builtinloc < 0 && bltin >= 0) ? - bltin : builtinloc) >= firstchange)) { - /* need to recompute the entry */ - } else { - goto success; - } - } else { - goto success; - } - } - - bcmd = find_builtin(name); - regular = bcmd && IS_BUILTIN_REGULAR(bcmd); - - if (regular) { - if (cmdp && (cmdp->cmdtype == CMDBUILTIN)) { - goto success; - } - } else if (act & DO_BRUTE) { - if (firstchange == 0) { - updatetbl = 0; - } - } - - /* If %builtin not in path, check for builtin next */ - if (regular || (bltin < 0 && bcmd)) { -builtin: - if (!updatetbl) { - entry->cmdtype = CMDBUILTIN; - entry->u.cmd = bcmd; - return; - } - INTOFF; - cmdp = cmdlookup(name, 1); - cmdp->cmdtype = CMDBUILTIN; - cmdp->param.cmd = bcmd; - INTON; - goto success; - } - - /* We have to search path. */ - prev = -1; /* where to start */ - if (cmdp && cmdp->rehash) { /* doing a rehash */ - if (cmdp->cmdtype == CMDBUILTIN) - prev = builtinloc; - else - prev = cmdp->param.index; - } - - e = ENOENT; - idx = -1; -loop: - while ((fullname = padvance(&path, name)) != NULL) { - stunalloc(fullname); - idx++; - if (idx >= firstchange) { - updatetbl = 0; - } - if (pathopt) { - if (prefix("builtin", pathopt)) { - if ((bcmd = find_builtin(name))) { - goto builtin; - } - continue; - } else if (!(act & DO_NOFUN) && - prefix("func", pathopt)) { - /* handled below */ - } else { - continue; /* ignore unimplemented options */ - } - } - /* if rehash, don't redo absolute path names */ - if (fullname[0] == '/' && idx <= prev && - idx < firstchange) { - if (idx < prev) - continue; - TRACE(("searchexec \"%s\": no change\n", name)); - goto success; - } - while (stat(fullname, &statb) < 0) { - if (errno != ENOENT && errno != ENOTDIR) - e = errno; - goto loop; - } - e = EACCES; /* if we fail, this will be the error */ - if (!S_ISREG(statb.st_mode)) - continue; - if (pathopt) { /* this is a %func directory */ - stalloc(strlen(fullname) + 1); - readcmdfile(fullname); - if ((cmdp = cmdlookup(name, 0)) == NULL || cmdp->cmdtype != CMDFUNCTION) - error("%s not defined in %s", name, fullname); - stunalloc(fullname); - goto success; - } - TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname)); - /* If we aren't called with DO_BRUTE and cmdp is set, it must - be a function and we're being called with DO_NOFUN */ - if (!updatetbl) { - entry->cmdtype = CMDNORMAL; - entry->u.index = idx; - return; - } - INTOFF; - cmdp = cmdlookup(name, 1); - cmdp->cmdtype = CMDNORMAL; - cmdp->param.index = idx; - INTON; - goto success; - } - - /* We failed. If there was an entry for this command, delete it */ - if (cmdp && updatetbl) - delete_cmd_entry(); - if (act & DO_ERR) - out2fmt("%s: %s\n", name, errmsg(e, E_EXEC)); - entry->cmdtype = CMDUNKNOWN; - return; - -success: - cmdp->rehash = 0; - entry->cmdtype = cmdp->cmdtype; - entry->u = cmdp->param; -} - - - -/* - * Search the table of builtin commands. - */ - -static int -bstrcmp(const void *name, const void *b) -{ - return strcmp((const char *)name, (*(const char *const *) b)+1); -} - -static struct builtincmd * -find_builtin(const char *name) -{ - struct builtincmd *bp; - - bp = bsearch(name, builtincmds, NUMBUILTINS, sizeof(struct builtincmd), - bstrcmp - ); - return bp; -} - - -/* - * Called when a cd is done. Marks all commands so the next time they - * are executed they will be rehashed. - */ - -static void -hashcd(void) { - struct tblentry **pp; - struct tblentry *cmdp; - - for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) { - for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) { - if (cmdp->cmdtype == CMDNORMAL - || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)) - cmdp->rehash = 1; - } - } -} - - - -/* - * Called before PATH is changed. The argument is the new value of PATH; - * pathval() still returns the old value at this point. Called with - * interrupts off. - */ - -static void -changepath(const char *newval) -{ - int firstchange; - int bltin; - - firstchange = path_change(newval, &bltin); - if (builtinloc < 0 && bltin >= 0) - builtinloc = bltin; /* zap builtins */ - clearcmdentry(firstchange); - builtinloc = bltin; -} - - -/* - * Clear out command entries. The argument specifies the first entry in - * PATH which has changed. - */ - -static void -clearcmdentry(firstchange) - int firstchange; -{ - struct tblentry **tblp; - struct tblentry **pp; - struct tblentry *cmdp; - - INTOFF; - for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) { - pp = tblp; - while ((cmdp = *pp) != NULL) { - if ((cmdp->cmdtype == CMDNORMAL && - cmdp->param.index >= firstchange) - || (cmdp->cmdtype == CMDBUILTIN && - builtinloc >= firstchange)) { - *pp = cmdp->next; - ckfree(cmdp); - } else { - pp = &cmdp->next; - } - } - } - INTON; -} - - -/* - * Delete all functions. - */ - -static void -deletefuncs(void) { - struct tblentry **tblp; - struct tblentry **pp; - struct tblentry *cmdp; - - INTOFF; - for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) { - pp = tblp; - while ((cmdp = *pp) != NULL) { - if (cmdp->cmdtype == CMDFUNCTION) { - *pp = cmdp->next; - freefunc(cmdp->param.func); - ckfree(cmdp); - } else { - pp = &cmdp->next; - } - } - } - INTON; -} - - - -/* - * Locate a command in the command hash table. If "add" is nonzero, - * add the command to the table if it is not already present. The - * variable "lastcmdentry" is set to point to the address of the link - * pointing to the entry, so that delete_cmd_entry can delete the - * entry. - */ - -static struct tblentry **lastcmdentry; - -static struct tblentry * -cmdlookup(const char *name, int add) -{ - int hashval; - const char *p; - struct tblentry *cmdp; - struct tblentry **pp; - - p = name; - hashval = *p << 4; - while (*p) - hashval += *p++; - hashval &= 0x7FFF; - pp = &cmdtable[hashval % CMDTABLESIZE]; - for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) { - if (equal(cmdp->cmdname, name)) - break; - pp = &cmdp->next; - } - if (add && cmdp == NULL) { - INTOFF; - cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB - + strlen(name) + 1); - cmdp->next = NULL; - cmdp->cmdtype = CMDUNKNOWN; - cmdp->rehash = 0; - strcpy(cmdp->cmdname, name); - INTON; - } - lastcmdentry = pp; - return cmdp; -} - -/* - * Delete the command entry returned on the last lookup. - */ - -static void -delete_cmd_entry() { - struct tblentry *cmdp; - - INTOFF; - cmdp = *lastcmdentry; - *lastcmdentry = cmdp->next; - ckfree(cmdp); - INTON; -} - - - - - -static const unsigned char nodesize[26] = { - ALIGN(sizeof (struct nbinary)), - ALIGN(sizeof (struct ncmd)), - ALIGN(sizeof (struct npipe)), - ALIGN(sizeof (struct nredir)), - ALIGN(sizeof (struct nredir)), - ALIGN(sizeof (struct nredir)), - ALIGN(sizeof (struct nbinary)), - ALIGN(sizeof (struct nbinary)), - ALIGN(sizeof (struct nif)), - ALIGN(sizeof (struct nbinary)), - ALIGN(sizeof (struct nbinary)), - ALIGN(sizeof (struct nfor)), - ALIGN(sizeof (struct ncase)), - ALIGN(sizeof (struct nclist)), - ALIGN(sizeof (struct narg)), - ALIGN(sizeof (struct narg)), - ALIGN(sizeof (struct nfile)), - ALIGN(sizeof (struct nfile)), - ALIGN(sizeof (struct nfile)), - ALIGN(sizeof (struct nfile)), - ALIGN(sizeof (struct nfile)), - ALIGN(sizeof (struct ndup)), - ALIGN(sizeof (struct ndup)), - ALIGN(sizeof (struct nhere)), - ALIGN(sizeof (struct nhere)), - ALIGN(sizeof (struct nnot)), -}; - - - -/* - * Delete a function if it exists. - */ - -static void -unsetfunc(char *name) -{ - struct tblentry *cmdp; - - if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) { - freefunc(cmdp->param.func); - delete_cmd_entry(); - } -} - - -/* - * Locate and print what a word is... - */ - -static int -typecmd(int argc, char **argv) -{ - int i; - int err = 0; - char *argv_a[2]; - - argv_a[1] = 0; - - for (i = 1; i < argc; i++) { - argv_a[0] = argv[i]; - argptr = argv_a; - optptr = "v"; - err |= hashcmd(argc, argv); - } - return err; -} - -#ifdef ASH_CMDCMD -static int -commandcmd(argc, argv) - int argc; - char **argv; -{ - int c; - int default_path = 0; - int verify_only = 0; - int verbose_verify_only = 0; - - while ((c = nextopt("pvV")) != '\0') - switch (c) { - case 'p': - default_path = 1; - break; - case 'v': - verify_only = 1; - break; - case 'V': - verbose_verify_only = 1; - break; - } - - if (default_path + verify_only + verbose_verify_only > 1 || - !*argptr) { - out2str( - "command [-p] command [arg ...]\n" - "command {-v|-V} command\n"); - return EX_USAGE; - } - - if (verify_only || verbose_verify_only) { - char *argv_a[2]; - - argv_a[1] = 0; - argv_a[0] = *argptr; - argptr = argv_a; - optptr = verbose_verify_only ? "v" : "V"; /* reverse special */ - return hashcmd(argc, argv); - } - - return 0; -} -#endif - -static int -path_change(newval, bltin) - const char *newval; - int *bltin; -{ - const char *old, *new; - int idx; - int firstchange; - - old = pathval(); - new = newval; - firstchange = 9999; /* assume no change */ - idx = 0; - *bltin = -1; - for (;;) { - if (*old != *new) { - firstchange = idx; - if ((*old == '\0' && *new == ':') - || (*old == ':' && *new == '\0')) - firstchange++; - old = new; /* ignore subsequent differences */ - } - if (*new == '\0') - break; - if (*new == '%' && *bltin < 0 && prefix("builtin", new + 1)) - *bltin = idx; - if (*new == ':') { - idx++; - } - new++, old++; - } - if (builtinloc >= 0 && *bltin < 0) - firstchange = 0; - return firstchange; -} -/* - * Routines to expand arguments to commands. We have to deal with - * backquotes, shell variables, and file metacharacters. - */ -/* - * _rmescape() flags - */ -#define RMESCAPE_ALLOC 0x1 /* Allocate a new string */ -#define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */ - -/* - * Structure specifying which parts of the string should be searched - * for IFS characters. - */ - -struct ifsregion { - struct ifsregion *next; /* next region in list */ - int begoff; /* offset of start of region */ - int endoff; /* offset of end of region */ - int nulonly; /* search for nul bytes only */ -}; - - -static char *expdest; /* output of current string */ -static struct nodelist *argbackq; /* list of back quote expressions */ -static struct ifsregion ifsfirst; /* first struct in list of ifs regions */ -static struct ifsregion *ifslastp; /* last struct in list */ -static struct arglist exparg; /* holds expanded arg list */ - -static void argstr (char *, int); -static char *exptilde (char *, int); -static void expbackq (union node *, int, int); -static int subevalvar (char *, char *, int, int, int, int, int); -static int varisset (char *, int); -static void strtodest (const char *, int, int); -static void varvalue (char *, int, int); -static void recordregion (int, int, int); -static void removerecordregions (int); -static void ifsbreakup (char *, struct arglist *); -static void ifsfree (void); -static void expandmeta (struct strlist *, int); -#if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) -#define preglob(p) _rmescapes((p), RMESCAPE_ALLOC | RMESCAPE_GLOB) -#if !defined(GLOB_BROKEN) -static void addglob (const glob_t *); -#endif -#endif -#if !(defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN)) -static void expmeta (char *, char *); -#endif -#if !(defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN)) -static struct strlist *expsort (struct strlist *); -static struct strlist *msort (struct strlist *, int); -#endif -static int patmatch (char *, char *, int); -#if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) -static int patmatch2 (char *, char *, int); -#else -static int pmatch (char *, char *, int); -#define patmatch2 patmatch -#endif -static char *cvtnum (int, char *); - -/* - * Expand shell variables and backquotes inside a here document. - */ - -/* arg: the document, fd: where to write the expanded version */ -static inline void -expandhere(union node *arg, int fd) -{ - herefd = fd; - expandarg(arg, (struct arglist *)NULL, 0); - xwrite(fd, stackblock(), expdest - stackblock()); -} - - -/* - * Perform variable substitution and command substitution on an argument, - * placing the resulting list of arguments in arglist. If EXP_FULL is true, - * perform splitting and file name expansion. When arglist is NULL, perform - * here document expansion. - */ - -static void -expandarg(arg, arglist, flag) - union node *arg; - struct arglist *arglist; - int flag; -{ - struct strlist *sp; - char *p; - - argbackq = arg->narg.backquote; - STARTSTACKSTR(expdest); - ifsfirst.next = NULL; - ifslastp = NULL; - argstr(arg->narg.text, flag); - if (arglist == NULL) { - return; /* here document expanded */ - } - STPUTC('\0', expdest); - p = grabstackstr(expdest); - exparg.lastp = &exparg.list; - /* - * TODO - EXP_REDIR - */ - if (flag & EXP_FULL) { - ifsbreakup(p, &exparg); - *exparg.lastp = NULL; - exparg.lastp = &exparg.list; - expandmeta(exparg.list, flag); - } else { - if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */ - rmescapes(p); - sp = (struct strlist *)stalloc(sizeof (struct strlist)); - sp->text = p; - *exparg.lastp = sp; - exparg.lastp = &sp->next; - } - ifsfree(); - *exparg.lastp = NULL; - if (exparg.list) { - *arglist->lastp = exparg.list; - arglist->lastp = exparg.lastp; - } -} - - -/* - * Expand a variable, and return a pointer to the next character in the - * input string. - */ - -static inline char * evalvar(char *p, int flag) -{ - int subtype; - int varflags; - char *var; - const char *val; - int patloc; - int c; - int set; - int special; - int startloc; - int varlen; - int easy; - int quotes = flag & (EXP_FULL | EXP_CASE); - - varflags = *p++; - subtype = varflags & VSTYPE; - var = p; - special = 0; - if (! is_name(*p)) - special = 1; - p = strchr(p, '=') + 1; -again: /* jump here after setting a variable with ${var=text} */ - if (special) { - set = varisset(var, varflags & VSNUL); - val = NULL; - } else { - val = lookupvar(var); - if (val == NULL || ((varflags & VSNUL) && val[0] == '\0')) { - val = NULL; - set = 0; - } else - set = 1; - } - varlen = 0; - startloc = expdest - stackblock(); - if (set && subtype != VSPLUS) { - /* insert the value of the variable */ - if (special) { - varvalue(var, varflags & VSQUOTE, flag); - if (subtype == VSLENGTH) { - varlen = expdest - stackblock() - startloc; - STADJUST(-varlen, expdest); - } - } else { - if (subtype == VSLENGTH) { - varlen = strlen(val); - } else { - strtodest( - val, - varflags & VSQUOTE ? - DQSYNTAX : BASESYNTAX, - quotes - ); - } - } - } - - if (subtype == VSPLUS) - set = ! set; - - easy = ((varflags & VSQUOTE) == 0 || - (*var == '@' && shellparam.nparam != 1)); - - - switch (subtype) { - case VSLENGTH: - expdest = cvtnum(varlen, expdest); - goto record; - - case VSNORMAL: - if (!easy) - break; -record: - recordregion(startloc, expdest - stackblock(), - varflags & VSQUOTE); - break; - - case VSPLUS: - case VSMINUS: - if (!set) { - argstr(p, flag); - break; - } - if (easy) - goto record; - break; - - case VSTRIMLEFT: - case VSTRIMLEFTMAX: - case VSTRIMRIGHT: - case VSTRIMRIGHTMAX: - if (!set) - break; - /* - * Terminate the string and start recording the pattern - * right after it - */ - STPUTC('\0', expdest); - patloc = expdest - stackblock(); - if (subevalvar(p, NULL, patloc, subtype, - startloc, varflags, quotes) == 0) { - int amount = (expdest - stackblock() - patloc) + 1; - STADJUST(-amount, expdest); - } - /* Remove any recorded regions beyond start of variable */ - removerecordregions(startloc); - goto record; - - case VSASSIGN: - case VSQUESTION: - if (!set) { - if (subevalvar(p, var, 0, subtype, startloc, - varflags, quotes)) { - varflags &= ~VSNUL; - /* - * Remove any recorded regions beyond - * start of variable - */ - removerecordregions(startloc); - goto again; - } - break; - } - if (easy) - goto record; - break; - -#ifdef DEBUG - default: - abort(); -#endif - } - - if (subtype != VSNORMAL) { /* skip to end of alternative */ - int nesting = 1; - for (;;) { - if ((c = *p++) == CTLESC) - p++; - else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) { - if (set) - argbackq = argbackq->next; - } else if (c == CTLVAR) { - if ((*p++ & VSTYPE) != VSNORMAL) - nesting++; - } else if (c == CTLENDVAR) { - if (--nesting == 0) - break; - } - } - } - return p; -} - - -/* - * Perform variable and command substitution. If EXP_FULL is set, output CTLESC - * characters to allow for further processing. Otherwise treat - * $@ like $* since no splitting will be performed. - */ - -static void -argstr(p, flag) - char *p; - int flag; -{ - char c; - int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */ - int firsteq = 1; - - if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE))) - p = exptilde(p, flag); - for (;;) { - switch (c = *p++) { - case '\0': - case CTLENDVAR: /* ??? */ - goto breakloop; - case CTLQUOTEMARK: - /* "$@" syntax adherence hack */ - if (p[0] == CTLVAR && p[2] == '@' && p[3] == '=') - break; - if ((flag & EXP_FULL) != 0) - STPUTC(c, expdest); - break; - case CTLESC: - if (quotes) - STPUTC(c, expdest); - c = *p++; - STPUTC(c, expdest); - break; - case CTLVAR: - p = evalvar(p, flag); - break; - case CTLBACKQ: - case CTLBACKQ|CTLQUOTE: - expbackq(argbackq->n, c & CTLQUOTE, flag); - argbackq = argbackq->next; - break; -#ifdef ASH_MATH_SUPPORT - case CTLENDARI: - expari(flag); - break; -#endif - case ':': - case '=': - /* - * sort of a hack - expand tildes in variable - * assignments (after the first '=' and after ':'s). - */ - STPUTC(c, expdest); - if (flag & EXP_VARTILDE && *p == '~') { - if (c == '=') { - if (firsteq) - firsteq = 0; - else - break; - } - p = exptilde(p, flag); - } - break; - default: - STPUTC(c, expdest); - } - } -breakloop:; - return; -} - -static char * -exptilde(p, flag) - char *p; - int flag; -{ - char c, *startp = p; - struct passwd *pw; - const char *home; - int quotes = flag & (EXP_FULL | EXP_CASE); - - while ((c = *p) != '\0') { - switch(c) { - case CTLESC: - return (startp); - case CTLQUOTEMARK: - return (startp); - case ':': - if (flag & EXP_VARTILDE) - goto done; - break; - case '/': - goto done; - } - p++; - } -done: - *p = '\0'; - if (*(startp+1) == '\0') { - if ((home = lookupvar("HOME")) == NULL) - goto lose; - } else { - if ((pw = getpwnam(startp+1)) == NULL) - goto lose; - home = pw->pw_dir; - } - if (*home == '\0') - goto lose; - *p = c; - strtodest(home, SQSYNTAX, quotes); - return (p); -lose: - *p = c; - return (startp); -} - - -static void -removerecordregions(int endoff) -{ - if (ifslastp == NULL) - return; - - if (ifsfirst.endoff > endoff) { - while (ifsfirst.next != NULL) { - struct ifsregion *ifsp; - INTOFF; - ifsp = ifsfirst.next->next; - ckfree(ifsfirst.next); - ifsfirst.next = ifsp; - INTON; - } - if (ifsfirst.begoff > endoff) - ifslastp = NULL; - else { - ifslastp = &ifsfirst; - ifsfirst.endoff = endoff; - } - return; - } - - ifslastp = &ifsfirst; - while (ifslastp->next && ifslastp->next->begoff < endoff) - ifslastp=ifslastp->next; - while (ifslastp->next != NULL) { - struct ifsregion *ifsp; - INTOFF; - ifsp = ifslastp->next->next; - ckfree(ifslastp->next); - ifslastp->next = ifsp; - INTON; - } - if (ifslastp->endoff > endoff) - ifslastp->endoff = endoff; -} - - -#ifdef ASH_MATH_SUPPORT -/* - * Expand arithmetic expression. Backup to start of expression, - * evaluate, place result in (backed up) result, adjust string position. - */ -static void -expari(int flag) -{ - char *p, *start; - int errcode; - int result; - int begoff; - int quotes = flag & (EXP_FULL | EXP_CASE); - int quoted; - - /* ifsfree(); */ - - /* - * This routine is slightly over-complicated for - * efficiency. First we make sure there is - * enough space for the result, which may be bigger - * than the expression if we add exponentation. Next we - * scan backwards looking for the start of arithmetic. If the - * next previous character is a CTLESC character, then we - * have to rescan starting from the beginning since CTLESC - * characters have to be processed left to right. - */ - CHECKSTRSPACE(10, expdest); - USTPUTC('\0', expdest); - start = stackblock(); - p = expdest - 1; - while (*p != CTLARI && p >= start) - --p; - if (*p != CTLARI) - error("missing CTLARI (shouldn't happen)"); - if (p > start && *(p-1) == CTLESC) - for (p = start; *p != CTLARI; p++) - if (*p == CTLESC) - p++; - - if (p[1] == '"') - quoted=1; - else - quoted=0; - begoff = p - start; - removerecordregions(begoff); - if (quotes) - rmescapes(p+2); - result = arith(p+2, &errcode); - if (errcode < 0) { - if(errcode == -2) - error("divide by zero"); - else - error("syntax error: \"%s\"\n", p+2); - } - snprintf(p, 12, "%d", result); - - while (*p++) - ; - - if (quoted == 0) - recordregion(begoff, p - 1 - start, 0); - result = expdest - p + 1; - STADJUST(-result, expdest); -} -#endif - -/* - * Expand stuff in backwards quotes. - */ - -static void -expbackq(cmd, quoted, flag) - union node *cmd; - int quoted; - int flag; -{ - volatile struct backcmd in; - int i; - char buf[128]; - char *p; - char *dest = expdest; - volatile struct ifsregion saveifs; - struct ifsregion *volatile savelastp; - struct nodelist *volatile saveargbackq; - char lastc; - int startloc = dest - stackblock(); - int syntax = quoted ? DQSYNTAX : BASESYNTAX; - volatile int saveherefd; - int quotes = flag & (EXP_FULL | EXP_CASE); - struct jmploc jmploc; - struct jmploc *volatile savehandler; - int ex; - -#if __GNUC__ - /* Avoid longjmp clobbering */ - (void) &dest; - (void) &syntax; -#endif - - in.fd = -1; - in.buf = 0; - in.jp = 0; - - INTOFF; - saveifs = ifsfirst; - savelastp = ifslastp; - saveargbackq = argbackq; - saveherefd = herefd; - herefd = -1; - if ((ex = setjmp(jmploc.loc))) { - goto err1; - } - savehandler = handler; - handler = &jmploc; - INTON; - p = grabstackstr(dest); - evalbackcmd(cmd, (struct backcmd *) &in); - ungrabstackstr(p, dest); -err1: - INTOFF; - ifsfirst = saveifs; - ifslastp = savelastp; - argbackq = saveargbackq; - herefd = saveherefd; - if (ex) { - goto err2; - } - - p = in.buf; - lastc = '\0'; - for (;;) { - if (--in.nleft < 0) { - if (in.fd < 0) - break; - i = safe_read(in.fd, buf, sizeof buf); - TRACE(("expbackq: read returns %d\n", i)); - if (i <= 0) - break; - p = buf; - in.nleft = i - 1; - } - lastc = *p++; - if (lastc != '\0') { - if (quotes && SIT(lastc, syntax) == CCTL) - STPUTC(CTLESC, dest); - STPUTC(lastc, dest); - } - } - - /* Eat all trailing newlines */ - for (; dest > stackblock() && dest[-1] == '\n';) - STUNPUTC(dest); - -err2: - if (in.fd >= 0) - close(in.fd); - if (in.buf) - ckfree(in.buf); - if (in.jp) - exitstatus = waitforjob(in.jp); - handler = savehandler; - if (ex) { - longjmp(handler->loc, 1); - } - if (quoted == 0) - recordregion(startloc, dest - stackblock(), 0); - TRACE(("evalbackq: size=%d: \"%.*s\"\n", - (dest - stackblock()) - startloc, - (dest - stackblock()) - startloc, - stackblock() + startloc)); - expdest = dest; - INTON; -} - -static int -subevalvar(p, str, strloc, subtype, startloc, varflags, quotes) - char *p; - char *str; - int strloc; - int subtype; - int startloc; - int varflags; - int quotes; -{ - char *startp; - char *loc = NULL; - char *q; - int c = 0; - int saveherefd = herefd; - struct nodelist *saveargbackq = argbackq; - int amount; - - herefd = -1; - argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0); - STACKSTRNUL(expdest); - herefd = saveherefd; - argbackq = saveargbackq; - startp = stackblock() + startloc; - if (str == NULL) - str = stackblock() + strloc; - - switch (subtype) { - case VSASSIGN: - setvar(str, startp, 0); - amount = startp - expdest; - STADJUST(amount, expdest); - varflags &= ~VSNUL; - if (c != 0) - *loc = c; - return 1; - - case VSQUESTION: - if (*p != CTLENDVAR) { - out2fmt(snlfmt, startp); - error((char *)NULL); - } - error("%.*s: parameter %snot set", p - str - 1, - str, (varflags & VSNUL) ? "null or " - : nullstr); - /* NOTREACHED */ - - case VSTRIMLEFT: - for (loc = startp; loc < str; loc++) { - c = *loc; - *loc = '\0'; - if (patmatch2(str, startp, quotes)) - goto recordleft; - *loc = c; - if (quotes && *loc == CTLESC) - loc++; - } - return 0; - - case VSTRIMLEFTMAX: - for (loc = str - 1; loc >= startp;) { - c = *loc; - *loc = '\0'; - if (patmatch2(str, startp, quotes)) - goto recordleft; - *loc = c; - loc--; - if (quotes && loc > startp && *(loc - 1) == CTLESC) { - for (q = startp; q < loc; q++) - if (*q == CTLESC) - q++; - if (q > loc) - loc--; - } - } - return 0; - - case VSTRIMRIGHT: - for (loc = str - 1; loc >= startp;) { - if (patmatch2(str, loc, quotes)) - goto recordright; - loc--; - if (quotes && loc > startp && *(loc - 1) == CTLESC) { - for (q = startp; q < loc; q++) - if (*q == CTLESC) - q++; - if (q > loc) - loc--; - } - } - return 0; - - case VSTRIMRIGHTMAX: - for (loc = startp; loc < str - 1; loc++) { - if (patmatch2(str, loc, quotes)) - goto recordright; - if (quotes && *loc == CTLESC) - loc++; - } - return 0; - -#ifdef DEBUG - default: - abort(); -#endif - } - -recordleft: - *loc = c; - amount = ((str - 1) - (loc - startp)) - expdest; - STADJUST(amount, expdest); - while (loc != str - 1) - *startp++ = *loc++; - return 1; - -recordright: - amount = loc - expdest; - STADJUST(amount, expdest); - STPUTC('\0', expdest); - STADJUST(-1, expdest); - return 1; -} - - -/* - * Test whether a specialized variable is set. - */ - -static int -varisset(name, nulok) - char *name; - int nulok; -{ - if (*name == '!') - return backgndpid != -1; - else if (*name == '@' || *name == '*') { - if (*shellparam.p == NULL) - return 0; - - if (nulok) { - char **av; - - for (av = shellparam.p; *av; av++) - if (**av != '\0') - return 1; - return 0; - } - } else if (is_digit(*name)) { - char *ap; - int num = atoi(name); - - if (num > shellparam.nparam) - return 0; - - if (num == 0) - ap = arg0; - else - ap = shellparam.p[num - 1]; - - if (nulok && (ap == NULL || *ap == '\0')) - return 0; - } - return 1; -} - -/* - * Put a string on the stack. - */ - -static void -strtodest(const char *p, int syntax, int quotes) -{ - while (*p) { - if (quotes && SIT(*p,syntax) == CCTL) - STPUTC(CTLESC, expdest); - STPUTC(*p++, expdest); - } -} - -/* - * Add the value of a specialized variable to the stack string. - */ - -static void -varvalue(char *name, int quoted, int flags) -{ - int num; - char *p; - int i; - int sep; - int sepq = 0; - char **ap; - int syntax; - int allow_split = flags & EXP_FULL; - int quotes = flags & (EXP_FULL | EXP_CASE); - - syntax = quoted ? DQSYNTAX : BASESYNTAX; - switch (*name) { - case '$': - num = rootpid; - goto numvar; - case '?': - num = oexitstatus; - goto numvar; - case '#': - num = shellparam.nparam; - goto numvar; - case '!': - num = backgndpid; -numvar: - expdest = cvtnum(num, expdest); - break; - case '-': - for (i = 0 ; i < NOPTS ; i++) { - if (optent_val(i)) - STPUTC(optent_letter(optlist[i]), expdest); - } - break; - case '@': - if (allow_split && quoted) { - sep = 1 << CHAR_BIT; - goto param; - } - /* fall through */ - case '*': - sep = ifsset() ? ifsval()[0] : ' '; - if (quotes) { - sepq = SIT(sep,syntax) == CCTL; - } -param: - for (ap = shellparam.p ; (p = *ap++) != NULL ; ) { - strtodest(p, syntax, quotes); - if (*ap && sep) { - if (sepq) - STPUTC(CTLESC, expdest); - STPUTC(sep, expdest); - } - } - break; - case '0': - strtodest(arg0, syntax, quotes); - break; - default: - num = atoi(name); - if (num > 0 && num <= shellparam.nparam) { - strtodest(shellparam.p[num - 1], syntax, quotes); - } - break; - } -} - - -/* - * Record the fact that we have to scan this region of the - * string for IFS characters. - */ - -static void -recordregion(start, end, nulonly) - int start; - int end; - int nulonly; -{ - struct ifsregion *ifsp; - - if (ifslastp == NULL) { - ifsp = &ifsfirst; - } else { - INTOFF; - ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion)); - ifsp->next = NULL; - ifslastp->next = ifsp; - INTON; - } - ifslastp = ifsp; - ifslastp->begoff = start; - ifslastp->endoff = end; - ifslastp->nulonly = nulonly; -} - - - -/* - * Break the argument string into pieces based upon IFS and add the - * strings to the argument list. The regions of the string to be - * searched for IFS characters have been stored by recordregion. - */ -static void -ifsbreakup(string, arglist) - char *string; - struct arglist *arglist; - { - struct ifsregion *ifsp; - struct strlist *sp; - char *start; - char *p; - char *q; - const char *ifs, *realifs; - int ifsspc; - int nulonly; - - - start = string; - ifsspc = 0; - nulonly = 0; - realifs = ifsset() ? ifsval() : defifs; - if (ifslastp != NULL) { - ifsp = &ifsfirst; - do { - p = string + ifsp->begoff; - nulonly = ifsp->nulonly; - ifs = nulonly ? nullstr : realifs; - ifsspc = 0; - while (p < string + ifsp->endoff) { - q = p; - if (*p == CTLESC) - p++; - if (strchr(ifs, *p)) { - if (!nulonly) - ifsspc = (strchr(defifs, *p) != NULL); - /* Ignore IFS whitespace at start */ - if (q == start && ifsspc) { - p++; - start = p; - continue; - } - *q = '\0'; - sp = (struct strlist *)stalloc(sizeof *sp); - sp->text = start; - *arglist->lastp = sp; - arglist->lastp = &sp->next; - p++; - if (!nulonly) { - for (;;) { - if (p >= string + ifsp->endoff) { - break; - } - q = p; - if (*p == CTLESC) - p++; - if (strchr(ifs, *p) == NULL ) { - p = q; - break; - } else if (strchr(defifs, *p) == NULL) { - if (ifsspc) { - p++; - ifsspc = 0; - } else { - p = q; - break; - } - } else - p++; - } - } - start = p; - } else - p++; - } - } while ((ifsp = ifsp->next) != NULL); - if (!(*start || (!ifsspc && start > string && nulonly))) { - return; - } - } - - sp = (struct strlist *)stalloc(sizeof *sp); - sp->text = start; - *arglist->lastp = sp; - arglist->lastp = &sp->next; -} - -static void -ifsfree() -{ - while (ifsfirst.next != NULL) { - struct ifsregion *ifsp; - INTOFF; - ifsp = ifsfirst.next->next; - ckfree(ifsfirst.next); - ifsfirst.next = ifsp; - INTON; - } - ifslastp = NULL; - ifsfirst.next = NULL; -} - -/* - * Add a file name to the list. - */ - -static void -addfname(const char *name) -{ - char *p; - struct strlist *sp; - - p = sstrdup(name); - sp = (struct strlist *)stalloc(sizeof *sp); - sp->text = p; - *exparg.lastp = sp; - exparg.lastp = &sp->next; -} - -/* - * Expand shell metacharacters. At this point, the only control characters - * should be escapes. The results are stored in the list exparg. - */ - -#if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) -static void -expandmeta(str, flag) - struct strlist *str; - int flag; -{ - const char *p; - glob_t pglob; - /* TODO - EXP_REDIR */ - - while (str) { - if (fflag) - goto nometa; - p = preglob(str->text); - INTOFF; - switch (glob(p, 0, 0, &pglob)) { - case 0: - if(pglob.gl_pathv[1]==0 && !strcmp(p, pglob.gl_pathv[0])) - goto nometa2; - addglob(&pglob); - globfree(&pglob); - INTON; - break; - case GLOB_NOMATCH: -nometa2: - globfree(&pglob); - INTON; -nometa: - *exparg.lastp = str; - rmescapes(str->text); - exparg.lastp = &str->next; - break; - default: /* GLOB_NOSPACE */ - error("Out of space"); - } - str = str->next; - } -} - - -/* - * Add the result of glob(3) to the list. - */ - -static void -addglob(pglob) - const glob_t *pglob; -{ - char **p = pglob->gl_pathv; - - do { - addfname(*p); - } while (*++p); -} - - -#else /* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */ -static char *expdir; - - -static void -expandmeta(str, flag) - struct strlist *str; - int flag; -{ - char *p; - struct strlist **savelastp; - struct strlist *sp; - char c; - /* TODO - EXP_REDIR */ - - while (str) { - if (fflag) - goto nometa; - p = str->text; - for (;;) { /* fast check for meta chars */ - if ((c = *p++) == '\0') - goto nometa; - if (c == '*' || c == '?' || c == '[' || c == '!') - break; - } - savelastp = exparg.lastp; - INTOFF; - if (expdir == NULL) { - int i = strlen(str->text); - expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */ - } - - expmeta(expdir, str->text); - ckfree(expdir); - expdir = NULL; - INTON; - if (exparg.lastp == savelastp) { - /* - * no matches - */ -nometa: - *exparg.lastp = str; - rmescapes(str->text); - exparg.lastp = &str->next; - } else { - *exparg.lastp = NULL; - *savelastp = sp = expsort(*savelastp); - while (sp->next != NULL) - sp = sp->next; - exparg.lastp = &sp->next; - } - str = str->next; - } -} - - -/* - * Do metacharacter (i.e. *, ?, [...]) expansion. - */ - -static void -expmeta(enddir, name) - char *enddir; - char *name; - { - char *p; - const char *cp; - char *q; - char *start; - char *endname; - int metaflag; - struct stat statb; - DIR *dirp; - struct dirent *dp; - int atend; - int matchdot; - - metaflag = 0; - start = name; - for (p = name ; ; p++) { - if (*p == '*' || *p == '?') - metaflag = 1; - else if (*p == '[') { - q = p + 1; - if (*q == '!') - q++; - for (;;) { - while (*q == CTLQUOTEMARK) - q++; - if (*q == CTLESC) - q++; - if (*q == '/' || *q == '\0') - break; - if (*++q == ']') { - metaflag = 1; - break; - } - } - } else if (*p == '!' && p[1] == '!' && (p == name || p[-1] == '/')) { - metaflag = 1; - } else if (*p == '\0') - break; - else if (*p == CTLQUOTEMARK) - continue; - else if (*p == CTLESC) - p++; - if (*p == '/') { - if (metaflag) - break; - start = p + 1; - } - } - if (metaflag == 0) { /* we've reached the end of the file name */ - if (enddir != expdir) - metaflag++; - for (p = name ; ; p++) { - if (*p == CTLQUOTEMARK) - continue; - if (*p == CTLESC) - p++; - *enddir++ = *p; - if (*p == '\0') - break; - } - if (metaflag == 0 || lstat(expdir, &statb) >= 0) - addfname(expdir); - return; - } - endname = p; - if (start != name) { - p = name; - while (p < start) { - while (*p == CTLQUOTEMARK) - p++; - if (*p == CTLESC) - p++; - *enddir++ = *p++; - } - } - if (enddir == expdir) { - cp = "."; - } else if (enddir == expdir + 1 && *expdir == '/') { - cp = "/"; - } else { - cp = expdir; - enddir[-1] = '\0'; - } - if ((dirp = opendir(cp)) == NULL) - return; - if (enddir != expdir) - enddir[-1] = '/'; - if (*endname == 0) { - atend = 1; - } else { - atend = 0; - *endname++ = '\0'; - } - matchdot = 0; - p = start; - while (*p == CTLQUOTEMARK) - p++; - if (*p == CTLESC) - p++; - if (*p == '.') - matchdot++; - while (! int_pending() && (dp = readdir(dirp)) != NULL) { - if (dp->d_name[0] == '.' && ! matchdot) - continue; - if (patmatch(start, dp->d_name, 0)) { - if (atend) { - strcpy(enddir, dp->d_name); - addfname(expdir); - } else { - for (p = enddir, cp = dp->d_name; - (*p++ = *cp++) != '\0';) - continue; - p[-1] = '/'; - expmeta(p, endname); - } - } - } - closedir(dirp); - if (! atend) - endname[-1] = '/'; -} -#endif /* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */ - - - -#if !(defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN)) -/* - * Sort the results of file name expansion. It calculates the number of - * strings to sort and then calls msort (short for merge sort) to do the - * work. - */ - -static struct strlist * -expsort(str) - struct strlist *str; - { - int len; - struct strlist *sp; - - len = 0; - for (sp = str ; sp ; sp = sp->next) - len++; - return msort(str, len); -} - - -static struct strlist * -msort(list, len) - struct strlist *list; - int len; -{ - struct strlist *p, *q = NULL; - struct strlist **lpp; - int half; - int n; - - if (len <= 1) - return list; - half = len >> 1; - p = list; - for (n = half ; --n >= 0 ; ) { - q = p; - p = p->next; - } - q->next = NULL; /* terminate first half of list */ - q = msort(list, half); /* sort first half of list */ - p = msort(p, len - half); /* sort second half */ - lpp = &list; - for (;;) { - if (strcmp(p->text, q->text) < 0) { - *lpp = p; - lpp = &p->next; - if ((p = *lpp) == NULL) { - *lpp = q; - break; - } - } else { - *lpp = q; - lpp = &q->next; - if ((q = *lpp) == NULL) { - *lpp = p; - break; - } - } - } - return list; -} -#endif - - - -/* - * Returns true if the pattern matches the string. - */ - -#if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) -/* squoted: string might have quote chars */ -static int -patmatch(char *pattern, char *string, int squoted) -{ - const char *p; - char *q; - - p = preglob(pattern); - q = squoted ? _rmescapes(string, RMESCAPE_ALLOC) : string; - - return !fnmatch(p, q, 0); -} - - -static int -patmatch2(char *pattern, char *string, int squoted) -{ - char *p; - int res; - - sstrnleft--; - p = grabstackstr(expdest); - res = patmatch(pattern, string, squoted); - ungrabstackstr(p, expdest); - return res; -} -#else -static int -patmatch(char *pattern, char *string, int squoted) { - return pmatch(pattern, string, squoted); -} - - -static int -pmatch(char *pattern, char *string, int squoted) -{ - char *p, *q; - char c; - - p = pattern; - q = string; - for (;;) { - switch (c = *p++) { - case '\0': - goto breakloop; - case CTLESC: - if (squoted && *q == CTLESC) - q++; - if (*q++ != *p++) - return 0; - break; - case CTLQUOTEMARK: - continue; - case '?': - if (squoted && *q == CTLESC) - q++; - if (*q++ == '\0') - return 0; - break; - case '*': - c = *p; - while (c == CTLQUOTEMARK || c == '*') - c = *++p; - if (c != CTLESC && c != CTLQUOTEMARK && - c != '?' && c != '*' && c != '[') { - while (*q != c) { - if (squoted && *q == CTLESC && - q[1] == c) - break; - if (*q == '\0') - return 0; - if (squoted && *q == CTLESC) - q++; - q++; - } - } - do { - if (pmatch(p, q, squoted)) - return 1; - if (squoted && *q == CTLESC) - q++; - } while (*q++ != '\0'); - return 0; - case '[': { - char *endp; - int invert, found; - char chr; - - endp = p; - if (*endp == '!') - endp++; - for (;;) { - while (*endp == CTLQUOTEMARK) - endp++; - if (*endp == '\0') - goto dft; /* no matching ] */ - if (*endp == CTLESC) - endp++; - if (*++endp == ']') - break; - } - invert = 0; - if (*p == '!') { - invert++; - p++; - } - found = 0; - chr = *q++; - if (squoted && chr == CTLESC) - chr = *q++; - if (chr == '\0') - return 0; - c = *p++; - do { - if (c == CTLQUOTEMARK) - continue; - if (c == CTLESC) - c = *p++; - if (*p == '-' && p[1] != ']') { - p++; - while (*p == CTLQUOTEMARK) - p++; - if (*p == CTLESC) - p++; - if (chr >= c && chr <= *p) - found = 1; - p++; - } else { - if (chr == c) - found = 1; - } - } while ((c = *p++) != ']'); - if (found == invert) - return 0; - break; - } -dft: default: - if (squoted && *q == CTLESC) - q++; - if (*q++ != c) - return 0; - break; - } - } -breakloop: - if (*q != '\0') - return 0; - return 1; -} -#endif - - - -/* - * Remove any CTLESC characters from a string. - */ - -#if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) -static char * -_rmescapes(char *str, int flag) -{ - char *p, *q, *r; - static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 }; - - p = strpbrk(str, qchars); - if (!p) { - return str; - } - q = p; - r = str; - if (flag & RMESCAPE_ALLOC) { - size_t len = p - str; - q = r = stalloc(strlen(p) + len + 1); - if (len > 0) { - memcpy(q, str, len); - q += len; - } - } - while (*p) { - if (*p == CTLQUOTEMARK) { - p++; - continue; - } - if (*p == CTLESC) { - p++; - if (flag & RMESCAPE_GLOB && *p != '/') { - *q++ = '\\'; - } - } - *q++ = *p++; - } - *q = '\0'; - return r; -} -#else -static void -rmescapes(str) - char *str; -{ - char *p, *q; - - p = str; - while (*p != CTLESC && *p != CTLQUOTEMARK) { - if (*p++ == '\0') - return; - } - q = p; - while (*p) { - if (*p == CTLQUOTEMARK) { - p++; - continue; - } - if (*p == CTLESC) - p++; - *q++ = *p++; - } - *q = '\0'; -} -#endif - - - -/* - * See if a pattern matches in a case statement. - */ - -static int -casematch(union node *pattern, const char *val) -{ - struct stackmark smark; - int result; - char *p; - - setstackmark(&smark); - argbackq = pattern->narg.backquote; - STARTSTACKSTR(expdest); - ifslastp = NULL; - argstr(pattern->narg.text, EXP_TILDE | EXP_CASE); - STPUTC('\0', expdest); - p = grabstackstr(expdest); - result = patmatch(p, (char *)val, 0); - popstackmark(&smark); - return result; -} - -/* - * Our own itoa(). - */ - -static char * -cvtnum(num, buf) - int num; - char *buf; - { - int len; - - CHECKSTRSPACE(32, buf); - len = sprintf(buf, "%d", num); - STADJUST(len, buf); - return buf; -} -/* - * Editline and history functions (and glue). - */ -static int histcmd(argc, argv) - int argc; - char **argv; -{ - error("not compiled with history support"); - /* NOTREACHED */ -} - - -struct redirtab { - struct redirtab *next; - short renamed[10]; /* Current ash support only 0-9 descriptors */ - /* char on arm (and others) can't be negative */ -}; - -static struct redirtab *redirlist; - -extern char **environ; - - - -/* - * Initialization code. - */ - -static void -init(void) { - - /* from cd.c: */ - { - setpwd(0, 0); - } - - /* from input.c: */ - { - basepf.nextc = basepf.buf = basebuf; - } - - /* from var.c: */ - { - char **envp; - char ppid[32]; - - initvar(); - for (envp = environ ; *envp ; envp++) { - if (strchr(*envp, '=')) { - setvareq(*envp, VEXPORT|VTEXTFIXED); - } - } - - snprintf(ppid, sizeof(ppid), "%d", (int) getppid()); - setvar("PPID", ppid, 0); - } -} - - - -/* - * This routine is called when an error or an interrupt occurs in an - * interactive shell and control is returned to the main command loop. - */ - -/* 1 == check for aliases, 2 == also check for assignments */ -static int checkalias; /* also used in no alias mode for check assignments */ - -static void -reset(void) { - - /* from eval.c: */ - { - evalskip = 0; - loopnest = 0; - funcnest = 0; - } - - /* from input.c: */ - { - if (exception != EXSHELLPROC) - parselleft = parsenleft = 0; /* clear input buffer */ - popallfiles(); - } - - /* from parser.c: */ - { - tokpushback = 0; - checkkwd = 0; - checkalias = 0; - } - - /* from redir.c: */ - { - while (redirlist) - popredir(); - } - -} - - - -/* - * This file implements the input routines used by the parser. - */ - -#ifdef BB_FEATURE_COMMAND_EDITING -static const char * cmdedit_prompt; -static inline void putprompt(const char *s) { - cmdedit_prompt = s; -} -#else -static inline void putprompt(const char *s) { - out2str(s); -} -#endif - -#define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */ - - - -/* - * Same as pgetc(), but ignores PEOA. - */ - -#ifdef ASH_ALIAS -static int -pgetc2(void) -{ - int c; - do { - c = pgetc_macro(); - } while (c == PEOA); - return c; -} -#else -static inline int pgetc2() { return pgetc_macro(); } -#endif - -/* - * Read a line from the script. - */ - -static inline char * -pfgets(char *line, int len) -{ - char *p = line; - int nleft = len; - int c; - - while (--nleft > 0) { - c = pgetc2(); - if (c == PEOF) { - if (p == line) - return NULL; - break; - } - *p++ = c; - if (c == '\n') - break; - } - *p = '\0'; - return line; -} - -static inline int -preadfd(void) -{ - int nr; - char *buf = parsefile->buf; - parsenextc = buf; - -retry: -#ifdef BB_FEATURE_COMMAND_EDITING - { - if (!iflag || parsefile->fd) - nr = safe_read(parsefile->fd, buf, BUFSIZ - 1); - else { - nr = cmdedit_read_input((char*)cmdedit_prompt, buf); - } - } -#else - nr = safe_read(parsefile->fd, buf, BUFSIZ - 1); -#endif - - if (nr < 0) { - if (parsefile->fd == 0 && errno == EWOULDBLOCK) { - int flags = fcntl(0, F_GETFL, 0); - if (flags >= 0 && flags & O_NONBLOCK) { - flags &=~ O_NONBLOCK; - if (fcntl(0, F_SETFL, flags) >= 0) { - out2str("sh: turning off NDELAY mode\n"); - goto retry; - } - } - } - } - return nr; -} - -static void -popstring(void) -{ - struct strpush *sp = parsefile->strpush; - - INTOFF; -#ifdef ASH_ALIAS - if (sp->ap) { - if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') { - if (!checkalias) { - checkalias = 1; - } - } - if (sp->string != sp->ap->val) { - ckfree(sp->string); - } - - sp->ap->flag &= ~ALIASINUSE; - if (sp->ap->flag & ALIASDEAD) { - unalias(sp->ap->name); - } - } -#endif - parsenextc = sp->prevstring; - parsenleft = sp->prevnleft; -/*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/ - parsefile->strpush = sp->prev; - if (sp != &(parsefile->basestrpush)) - ckfree(sp); - INTON; -} - - -/* - * Refill the input buffer and return the next input character: - * - * 1) If a string was pushed back on the input, pop it; - * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading - * from a string so we can't refill the buffer, return EOF. - * 3) If the is more stuff in this buffer, use it else call read to fill it. - * 4) Process input up to the next newline, deleting nul characters. - */ - -static int -preadbuffer(void) -{ - char *p, *q; - int more; - char savec; - - while (parsefile->strpush) { -#ifdef ASH_ALIAS - if (parsenleft == -1 && parsefile->strpush->ap && - parsenextc[-1] != ' ' && parsenextc[-1] != '\t') { - return PEOA; - } -#endif - popstring(); - if (--parsenleft >= 0) - return (*parsenextc++); - } - if (parsenleft == EOF_NLEFT || parsefile->buf == NULL) - return PEOF; - flushall(); - -again: - if (parselleft <= 0) { - if ((parselleft = preadfd()) <= 0) { - parselleft = parsenleft = EOF_NLEFT; - return PEOF; - } - } - - q = p = parsenextc; - - /* delete nul characters */ - for (more = 1; more;) { - switch (*p) { - case '\0': - p++; /* Skip nul */ - goto check; - - - case '\n': - parsenleft = q - parsenextc; - more = 0; /* Stop processing here */ - break; - } - - *q++ = *p++; -check: - if (--parselleft <= 0 && more) { - parsenleft = q - parsenextc - 1; - if (parsenleft < 0) - goto again; - more = 0; - } - } - - savec = *q; - *q = '\0'; - - if (vflag) { - out2str(parsenextc); - } - - *q = savec; - - return *parsenextc++; -} - - -/* - * Push a string back onto the input at this current parsefile level. - * We handle aliases this way. - */ -static void -pushstring(char *s, int len, void *ap) -{ - struct strpush *sp; - - INTOFF; -/*dprintf("*** calling pushstring: %s, %d\n", s, len);*/ - if (parsefile->strpush) { - sp = ckmalloc(sizeof (struct strpush)); - sp->prev = parsefile->strpush; - parsefile->strpush = sp; - } else - sp = parsefile->strpush = &(parsefile->basestrpush); - sp->prevstring = parsenextc; - sp->prevnleft = parsenleft; -#ifdef ASH_ALIAS - sp->ap = (struct alias *)ap; - if (ap) { - ((struct alias *)ap)->flag |= ALIASINUSE; - sp->string = s; - } -#endif - parsenextc = s; - parsenleft = len; - INTON; -} - - -/* - * Like setinputfile, but takes input from a string. - */ - -static void -setinputstring(char *string) -{ - INTOFF; - pushfile(); - parsenextc = string; - parsenleft = strlen(string); - parsefile->buf = NULL; - plinno = 1; - INTON; -} - - - -/* - * To handle the "." command, a stack of input files is used. Pushfile - * adds a new entry to the stack and popfile restores the previous level. - */ - -static void -pushfile(void) { - struct parsefile *pf; - - parsefile->nleft = parsenleft; - parsefile->lleft = parselleft; - parsefile->nextc = parsenextc; - parsefile->linno = plinno; - pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile)); - pf->prev = parsefile; - pf->fd = -1; - pf->strpush = NULL; - pf->basestrpush.prev = NULL; - parsefile = pf; -} - -#ifdef JOBS -static void restartjob (struct job *); -#endif -static void freejob (struct job *); -static struct job *getjob (const char *); -static int dowait (int, struct job *); -static void waitonint(int); - - -/* - * We keep track of whether or not fd0 has been redirected. This is for - * background commands, where we want to redirect fd0 to /dev/null only - * if it hasn't already been redirected. -*/ -static int fd0_redirected = 0; - -/* Return true if fd 0 has already been redirected at least once. */ -static inline int -fd0_redirected_p (void) -{ - return fd0_redirected != 0; -} - -static void dupredirect (const union node *, int, int fd1dup); - -#ifdef JOBS -/* - * Turn job control on and off. - * - * Note: This code assumes that the third arg to ioctl is a character - * pointer, which is true on Berkeley systems but not System V. Since - * System V doesn't have job control yet, this isn't a problem now. - */ - - - -static void setjobctl(int enable) -{ -#ifdef OLD_TTY_DRIVER - int ldisc; -#endif - - if (enable == jobctl || rootshell == 0) - return; - if (enable) { - do { /* while we are in the background */ -#ifdef OLD_TTY_DRIVER - if (ioctl(2, TIOCGPGRP, (char *)&initialpgrp) < 0) { -#else - initialpgrp = tcgetpgrp(2); - if (initialpgrp < 0) { -#endif - out2str("sh: can't access tty; job control turned off\n"); - mflag = 0; - return; - } - if (initialpgrp == -1) - initialpgrp = getpgrp(); - else if (initialpgrp != getpgrp()) { - killpg(initialpgrp, SIGTTIN); - continue; - } - } while (0); -#ifdef OLD_TTY_DRIVER - if (ioctl(2, TIOCGETD, (char *)&ldisc) < 0 || ldisc != NTTYDISC) { - out2str("sh: need new tty driver to run job control; job control turned off\n"); - mflag = 0; - return; - } -#endif - setsignal(SIGTSTP); - setsignal(SIGTTOU); - setsignal(SIGTTIN); - setpgid(0, rootpid); -#ifdef OLD_TTY_DRIVER - ioctl(2, TIOCSPGRP, (char *)&rootpid); -#else - tcsetpgrp(2, rootpid); -#endif - } else { /* turning job control off */ - setpgid(0, initialpgrp); -#ifdef OLD_TTY_DRIVER - ioctl(2, TIOCSPGRP, (char *)&initialpgrp); -#else - tcsetpgrp(2, initialpgrp); -#endif - setsignal(SIGTSTP); - setsignal(SIGTTOU); - setsignal(SIGTTIN); - } - jobctl = enable; -} -#endif - - -#ifdef JOBS -static int -killcmd(argc, argv) - int argc; - char **argv; -{ - int signo = -1; - int list = 0; - int i; - pid_t pid; - struct job *jp; - - if (argc <= 1) { -usage: - error( -"Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n" -"kill -l [exitstatus]" - ); - } - - if (*argv[1] == '-') { - signo = decode_signal(argv[1] + 1, 1); - if (signo < 0) { - int c; - - while ((c = nextopt("ls:")) != '\0') - switch (c) { - case 'l': - list = 1; - break; - case 's': - signo = decode_signal(optionarg, 1); - if (signo < 0) { - error( - "invalid signal number or name: %s", - optionarg - ); - } - break; -#ifdef DEBUG - default: - error( - "nextopt returned character code 0%o", c); -#endif - } - } else - argptr++; - } - - if (!list && signo < 0) - signo = SIGTERM; - - if ((signo < 0 || !*argptr) ^ list) { - goto usage; - } - - if (list) { - const char *name; - - if (!*argptr) { - out1str("0\n"); - for (i = 1; i < NSIG; i++) { - name = u_signal_names(0, &i, 1); - if(name) - printf(snlfmt, name); - } - return 0; - } - name = u_signal_names(*argptr, &signo, -1); - if (name) - printf(snlfmt, name); - else - error("invalid signal number or exit status: %s", - *argptr); - return 0; - } - - do { - if (**argptr == '%') { - jp = getjob(*argptr); - if (jp->jobctl == 0) - error("job %s not created under job control", - *argptr); - pid = -jp->ps[0].pid; - } else - pid = atoi(*argptr); - if (kill(pid, signo) != 0) - error("%s: %m", *argptr); - } while (*++argptr); - - return 0; -} - -static int -fgcmd(argc, argv) - int argc; - char **argv; -{ - struct job *jp; - int pgrp; - int status; - - jp = getjob(argv[1]); - if (jp->jobctl == 0) - error("job not created under job control"); - pgrp = jp->ps[0].pid; -#ifdef OLD_TTY_DRIVER - ioctl(2, TIOCSPGRP, (char *)&pgrp); -#else - tcsetpgrp(2, pgrp); -#endif - restartjob(jp); - INTOFF; - status = waitforjob(jp); - INTON; - return status; -} - - -static int -bgcmd(argc, argv) - int argc; - char **argv; -{ - struct job *jp; - - do { - jp = getjob(*++argv); - if (jp->jobctl == 0) - error("job not created under job control"); - restartjob(jp); - } while (--argc > 1); - return 0; -} - - -static void -restartjob(jp) - struct job *jp; -{ - struct procstat *ps; - int i; - - if (jp->state == JOBDONE) - return; - INTOFF; - killpg(jp->ps[0].pid, SIGCONT); - for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) { - if (WIFSTOPPED(ps->status)) { - ps->status = -1; - jp->state = 0; - } - } - INTON; -} -#endif - -static void showjobs(int change); - - -static int -jobscmd(argc, argv) - int argc; - char **argv; -{ - showjobs(0); - return 0; -} - - -/* - * Print a list of jobs. If "change" is nonzero, only print jobs whose - * statuses have changed since the last call to showjobs. - * - * If the shell is interrupted in the process of creating a job, the - * result may be a job structure containing zero processes. Such structures - * will be freed here. - */ - -static void -showjobs(change) - int change; -{ - int jobno; - int procno; - int i; - struct job *jp; - struct procstat *ps; - int col; - char s[64]; - - TRACE(("showjobs(%d) called\n", change)); - while (dowait(0, (struct job *)NULL) > 0); - for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) { - if (! jp->used) - continue; - if (jp->nprocs == 0) { - freejob(jp); - continue; - } - if (change && ! jp->changed) - continue; - procno = jp->nprocs; - for (ps = jp->ps ; ; ps++) { /* for each process */ - if (ps == jp->ps) - snprintf(s, 64, "[%d] %ld ", jobno, - (long)ps->pid); - else - snprintf(s, 64, " %ld ", - (long)ps->pid); - out1str(s); - col = strlen(s); - s[0] = '\0'; - if (ps->status == -1) { - /* don't print anything */ - } else if (WIFEXITED(ps->status)) { - snprintf(s, 64, "Exit %d", - WEXITSTATUS(ps->status)); - } else { -#ifdef JOBS - if (WIFSTOPPED(ps->status)) - i = WSTOPSIG(ps->status); - else /* WIFSIGNALED(ps->status) */ -#endif - i = WTERMSIG(ps->status); - if ((i & 0x7F) < NSIG && sys_siglist[i & 0x7F]) - strcpy(s, sys_siglist[i & 0x7F]); - else - snprintf(s, 64, "Signal %d", i & 0x7F); - if (WCOREDUMP(ps->status)) - strcat(s, " (core dumped)"); - } - out1str(s); - col += strlen(s); - printf( - "%*c%s\n", 30 - col >= 0 ? 30 - col : 0, ' ', - ps->cmd - ); - if (--procno <= 0) - break; - } - jp->changed = 0; - if (jp->state == JOBDONE) { - freejob(jp); - } - } -} - - -/* - * Mark a job structure as unused. - */ - -static void -freejob(struct job *jp) -{ - const struct procstat *ps; - int i; - - INTOFF; - for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) { - if (ps->cmd != nullstr) - ckfree(ps->cmd); - } - if (jp->ps != &jp->ps0) - ckfree(jp->ps); - jp->used = 0; -#ifdef JOBS - if (curjob == jp - jobtab + 1) - curjob = 0; -#endif - INTON; -} - - - -static int -waitcmd(argc, argv) - int argc; - char **argv; -{ - struct job *job; - int status, retval; - struct job *jp; - - if (--argc > 0) { -start: - job = getjob(*++argv); - } else { - job = NULL; - } - for (;;) { /* loop until process terminated or stopped */ - if (job != NULL) { - if (job->state) { - status = job->ps[job->nprocs - 1].status; - if (! iflag) - freejob(job); - if (--argc) { - goto start; - } - if (WIFEXITED(status)) - retval = WEXITSTATUS(status); -#ifdef JOBS - else if (WIFSTOPPED(status)) - retval = WSTOPSIG(status) + 128; -#endif - else { - /* XXX: limits number of signals */ - retval = WTERMSIG(status) + 128; - } - return retval; - } - } else { - for (jp = jobtab ; ; jp++) { - if (jp >= jobtab + njobs) { /* no running procs */ - return 0; - } - if (jp->used && jp->state == 0) - break; - } - } - if (dowait(2, 0) < 0 && errno == EINTR) { - return 129; - } - } -} - - - -/* - * Convert a job name to a job structure. - */ - -static struct job * -getjob(const char *name) -{ - int jobno; - struct job *jp; - int pid; - int i; - - if (name == NULL) { -#ifdef JOBS -currentjob: - if ((jobno = curjob) == 0 || jobtab[jobno - 1].used == 0) - error("No current job"); - return &jobtab[jobno - 1]; -#else - error("No current job"); -#endif - } else if (name[0] == '%') { - if (is_digit(name[1])) { - jobno = number(name + 1); - if (jobno > 0 && jobno <= njobs - && jobtab[jobno - 1].used != 0) - return &jobtab[jobno - 1]; -#ifdef JOBS - } else if (name[1] == '%' && name[2] == '\0') { - goto currentjob; -#endif - } else { - struct job *found = NULL; - for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) { - if (jp->used && jp->nprocs > 0 - && prefix(name + 1, jp->ps[0].cmd)) { - if (found) - error("%s: ambiguous", name); - found = jp; - } - } - if (found) - return found; - } - } else if (is_number(name, &pid)) { - for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) { - if (jp->used && jp->nprocs > 0 - && jp->ps[jp->nprocs - 1].pid == pid) - return jp; - } - } - error("No such job: %s", name); - /* NOTREACHED */ -} - - - -/* - * Return a new job structure, - */ - -static struct job * -makejob(const union node *node, int nprocs) -{ - int i; - struct job *jp; - - for (i = njobs, jp = jobtab ; ; jp++) { - if (--i < 0) { - INTOFF; - if (njobs == 0) { - jobtab = ckmalloc(4 * sizeof jobtab[0]); - } else { - jp = ckmalloc((njobs + 4) * sizeof jobtab[0]); - memcpy(jp, jobtab, njobs * sizeof jp[0]); - /* Relocate `ps' pointers */ - for (i = 0; i < njobs; i++) - if (jp[i].ps == &jobtab[i].ps0) - jp[i].ps = &jp[i].ps0; - ckfree(jobtab); - jobtab = jp; - } - jp = jobtab + njobs; - for (i = 4 ; --i >= 0 ; jobtab[njobs++].used = 0); - INTON; - break; - } - if (jp->used == 0) - break; - } - INTOFF; - jp->state = 0; - jp->used = 1; - jp->changed = 0; - jp->nprocs = 0; -#ifdef JOBS - jp->jobctl = jobctl; -#endif - if (nprocs > 1) { - jp->ps = ckmalloc(nprocs * sizeof (struct procstat)); - } else { - jp->ps = &jp->ps0; - } - INTON; - TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs, - jp - jobtab + 1)); - return jp; -} - - -/* - * Fork of a subshell. If we are doing job control, give the subshell its - * own process group. Jp is a job structure that the job is to be added to. - * N is the command that will be evaluated by the child. Both jp and n may - * be NULL. The mode parameter can be one of the following: - * FORK_FG - Fork off a foreground process. - * FORK_BG - Fork off a background process. - * FORK_NOJOB - Like FORK_FG, but don't give the process its own - * process group even if job control is on. - * - * When job control is turned off, background processes have their standard - * input redirected to /dev/null (except for the second and later processes - * in a pipeline). - */ - - - -static int -forkshell(struct job *jp, const union node *n, int mode) -{ - int pid; -#ifdef JOBS - int pgrp; -#endif - const char *devnull = _PATH_DEVNULL; - const char *nullerr = "Can't open %s"; - - TRACE(("forkshell(%%%d, 0x%lx, %d) called\n", jp - jobtab, (long)n, - mode)); - INTOFF; - pid = fork(); - if (pid == -1) { - TRACE(("Fork failed, errno=%d\n", errno)); - INTON; - error("Cannot fork"); - } - if (pid == 0) { - struct job *p; - int wasroot; - int i; - - TRACE(("Child shell %d\n", getpid())); - wasroot = rootshell; - rootshell = 0; - closescript(); - INTON; - clear_traps(); -#ifdef JOBS - jobctl = 0; /* do job control only in root shell */ - if (wasroot && mode != FORK_NOJOB && mflag) { - if (jp == NULL || jp->nprocs == 0) - pgrp = getpid(); - else - pgrp = jp->ps[0].pid; - setpgid(0, pgrp); - if (mode == FORK_FG) { - /*** this causes superfluous TIOCSPGRPS ***/ -#ifdef OLD_TTY_DRIVER - if (ioctl(2, TIOCSPGRP, (char *)&pgrp) < 0) - error("TIOCSPGRP failed, errno=%d", errno); -#else - if (tcsetpgrp(2, pgrp) < 0) - error("tcsetpgrp failed, errno=%d", errno); -#endif - } - setsignal(SIGTSTP); - setsignal(SIGTTOU); - } else if (mode == FORK_BG) { - ignoresig(SIGINT); - ignoresig(SIGQUIT); - if ((jp == NULL || jp->nprocs == 0) && - ! fd0_redirected_p ()) { - close(0); - if (open(devnull, O_RDONLY) != 0) - error(nullerr, devnull); - } - } -#else - if (mode == FORK_BG) { - ignoresig(SIGINT); - ignoresig(SIGQUIT); - if ((jp == NULL || jp->nprocs == 0) && - ! fd0_redirected_p ()) { - close(0); - if (open(devnull, O_RDONLY) != 0) - error(nullerr, devnull); - } - } -#endif - for (i = njobs, p = jobtab ; --i >= 0 ; p++) - if (p->used) - freejob(p); - if (wasroot && iflag) { - setsignal(SIGINT); - setsignal(SIGQUIT); - setsignal(SIGTERM); - } - return pid; - } -#ifdef JOBS - if (rootshell && mode != FORK_NOJOB && mflag) { - if (jp == NULL || jp->nprocs == 0) - pgrp = pid; - else - pgrp = jp->ps[0].pid; - setpgid(pid, pgrp); - } -#endif - if (mode == FORK_BG) - backgndpid = pid; /* set $! */ - if (jp) { - struct procstat *ps = &jp->ps[jp->nprocs++]; - ps->pid = pid; - ps->status = -1; - ps->cmd = nullstr; - if (iflag && rootshell && n) - ps->cmd = commandtext(n); - } - INTON; - TRACE(("In parent shell: child = %d\n", pid)); - return pid; -} - - - -/* - * Wait for job to finish. - * - * Under job control we have the problem that while a child process is - * running interrupts generated by the user are sent to the child but not - * to the shell. This means that an infinite loop started by an inter- - * active user may be hard to kill. With job control turned off, an - * interactive user may place an interactive program inside a loop. If - * the interactive program catches interrupts, the user doesn't want - * these interrupts to also abort the loop. The approach we take here - * is to have the shell ignore interrupt signals while waiting for a - * forground process to terminate, and then send itself an interrupt - * signal if the child process was terminated by an interrupt signal. - * Unfortunately, some programs want to do a bit of cleanup and then - * exit on interrupt; unless these processes terminate themselves by - * sending a signal to themselves (instead of calling exit) they will - * confuse this approach. - */ - -static int -waitforjob(struct job *jp) -{ -#ifdef JOBS - int mypgrp = getpgrp(); -#endif - int status; - int st; - struct sigaction act, oact; - - INTOFF; - intreceived = 0; -#ifdef JOBS - if (!jobctl) { -#else - if (!iflag) { -#endif - sigaction(SIGINT, 0, &act); - act.sa_handler = waitonint; - sigaction(SIGINT, &act, &oact); - } - TRACE(("waitforjob(%%%d) called\n", jp - jobtab + 1)); - while (jp->state == 0) { - dowait(1, jp); - } -#ifdef JOBS - if (!jobctl) { -#else - if (!iflag) { -#endif - sigaction(SIGINT, &oact, 0); - if (intreceived && trap[SIGINT]) kill(getpid(), SIGINT); - } -#ifdef JOBS - if (jp->jobctl) { -#ifdef OLD_TTY_DRIVER - if (ioctl(2, TIOCSPGRP, (char *)&mypgrp) < 0) - error("TIOCSPGRP failed, errno=%d\n", errno); -#else - if (tcsetpgrp(2, mypgrp) < 0) - error("tcsetpgrp failed, errno=%d\n", errno); -#endif - } - if (jp->state == JOBSTOPPED) - curjob = jp - jobtab + 1; -#endif - status = jp->ps[jp->nprocs - 1].status; - /* convert to 8 bits */ - if (WIFEXITED(status)) - st = WEXITSTATUS(status); -#ifdef JOBS - else if (WIFSTOPPED(status)) - st = WSTOPSIG(status) + 128; -#endif - else - st = WTERMSIG(status) + 128; -#ifdef JOBS - if (jp->jobctl) { - /* - * This is truly gross. - * If we're doing job control, then we did a TIOCSPGRP which - * caused us (the shell) to no longer be in the controlling - * session -- so we wouldn't have seen any ^C/SIGINT. So, we - * intuit from the subprocess exit status whether a SIGINT - * occured, and if so interrupt ourselves. Yuck. - mycroft - */ - if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT) - raise(SIGINT); - } - if (jp->state == JOBDONE) - -#endif - freejob(jp); - INTON; - return st; -} - - - -/* - * Wait for a process to terminate. - */ - -/* - * Do a wait system call. If job control is compiled in, we accept - * stopped processes. If block is zero, we return a value of zero - * rather than blocking. - * - * System V doesn't have a non-blocking wait system call. It does - * have a SIGCLD signal that is sent to a process when one of it's - * children dies. The obvious way to use SIGCLD would be to install - * a handler for SIGCLD which simply bumped a counter when a SIGCLD - * was received, and have waitproc bump another counter when it got - * the status of a process. Waitproc would then know that a wait - * system call would not block if the two counters were different. - * This approach doesn't work because if a process has children that - * have not been waited for, System V will send it a SIGCLD when it - * installs a signal handler for SIGCLD. What this means is that when - * a child exits, the shell will be sent SIGCLD signals continuously - * until is runs out of stack space, unless it does a wait call before - * restoring the signal handler. The code below takes advantage of - * this (mis)feature by installing a signal handler for SIGCLD and - * then checking to see whether it was called. If there are any - * children to be waited for, it will be. - * - */ - -static inline int -waitproc(int block, int *status) -{ - int flags; - - flags = 0; -#ifdef JOBS - if (jobctl) - flags |= WUNTRACED; -#endif - if (block == 0) - flags |= WNOHANG; - return wait3(status, flags, (struct rusage *)NULL); -} - -static int -dowait(int block, struct job *job) -{ - int pid; - int status; - struct procstat *sp; - struct job *jp; - struct job *thisjob; - int done; - int stopped; - int core; - int sig; - - TRACE(("dowait(%d) called\n", block)); - do { - pid = waitproc(block, &status); - TRACE(("wait returns %d, status=%d\n", pid, status)); - } while (!(block & 2) && pid == -1 && errno == EINTR); - if (pid <= 0) - return pid; - INTOFF; - thisjob = NULL; - for (jp = jobtab ; jp < jobtab + njobs ; jp++) { - if (jp->used) { - done = 1; - stopped = 1; - for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) { - if (sp->pid == -1) - continue; - if (sp->pid == pid) { - TRACE(("Changing status of proc %d from 0x%x to 0x%x\n", pid, sp->status, status)); - sp->status = status; - thisjob = jp; - } - if (sp->status == -1) - stopped = 0; - else if (WIFSTOPPED(sp->status)) - done = 0; - } - if (stopped) { /* stopped or done */ - int state = done? JOBDONE : JOBSTOPPED; - if (jp->state != state) { - TRACE(("Job %d: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state)); - jp->state = state; -#ifdef JOBS - if (done && curjob == jp - jobtab + 1) - curjob = 0; /* no current job */ -#endif - } - } - } - } - INTON; - if (! rootshell || ! iflag || (job && thisjob == job)) { - core = WCOREDUMP(status); -#ifdef JOBS - if (WIFSTOPPED(status)) sig = WSTOPSIG(status); - else -#endif - if (WIFEXITED(status)) sig = 0; - else sig = WTERMSIG(status); - - if (sig != 0 && sig != SIGINT && sig != SIGPIPE) { - if (thisjob != job) - out2fmt("%d: ", pid); -#ifdef JOBS - if (sig == SIGTSTP && rootshell && iflag) - out2fmt("%%%ld ", - (long)(job - jobtab + 1)); -#endif - if (sig < NSIG && sys_siglist[sig]) - out2str(sys_siglist[sig]); - else - out2fmt("Signal %d", sig); - if (core) - out2str(" - core dumped"); - out2c('\n'); - } else { - TRACE(("Not printing status: status=%d, sig=%d\n", - status, sig)); - } - } else { - TRACE(("Not printing status, rootshell=%d, job=0x%x\n", rootshell, job)); - if (thisjob) - thisjob->changed = 1; - } - return pid; -} - - - - -/* - * return 1 if there are stopped jobs, otherwise 0 - */ -static int -stoppedjobs(void) -{ - int jobno; - struct job *jp; - - if (job_warning) - return (0); - for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) { - if (jp->used == 0) - continue; - if (jp->state == JOBSTOPPED) { - out2str("You have stopped jobs.\n"); - job_warning = 2; - return (1); - } - } - - return (0); -} - -/* - * Return a string identifying a command (to be printed by the - * jobs command. - */ - -static char *cmdnextc; -static int cmdnleft; -#define MAXCMDTEXT 200 - -static void -cmdputs(const char *s) -{ - const char *p; - char *q; - char c; - int subtype = 0; - - if (cmdnleft <= 0) - return; - p = s; - q = cmdnextc; - while ((c = *p++) != '\0') { - if (c == CTLESC) - *q++ = *p++; - else if (c == CTLVAR) { - *q++ = '$'; - if (--cmdnleft > 0) - *q++ = '{'; - subtype = *p++; - } else if (c == '=' && subtype != 0) { - *q++ = "}-+?="[(subtype & VSTYPE) - VSNORMAL]; - subtype = 0; - } else if (c == CTLENDVAR) { - *q++ = '}'; - } else if (c == CTLBACKQ || c == CTLBACKQ+CTLQUOTE) - cmdnleft++; /* ignore it */ - else - *q++ = c; - if (--cmdnleft <= 0) { - *q++ = '.'; - *q++ = '.'; - *q++ = '.'; - break; - } - } - cmdnextc = q; -} - -#define CMDTXT_TABLE -#ifdef CMDTXT_TABLE -/* - * To collect a lot of redundant code in cmdtxt() case statements, we - * implement a mini language here. Each type of node struct has an - * associated instruction sequence that operates on its members via - * their offsets. The instruction are pack in unsigned chars with - * format IIDDDDDE where the bits are - * I : part of the instruction opcode, which are - * 00 : member is a pointer to another node -- process it recursively - * 40 : member is a pointer to a char string -- output it - * 80 : output the string whose index is stored in the data field - * CC : flag signaling that this case needs external processing - * D : data - either the (shifted) index of a fixed string to output or - * the actual offset of the member to operate on in the struct - * (since we assume bit 0 is set, the offset is not shifted) - * E : flag signaling end of instruction sequence - * - * WARNING: In order to handle larger offsets for 64bit archs, this code - * assumes that no offset can be an odd number and stores the - * end-of-instructions flag in bit 0. - */ - -#define CMDTXT_NOMORE 0x01 /* NOTE: no offset should be odd */ -#define CMDTXT_CHARPTR 0x40 -#define CMDTXT_STRING 0x80 -#define CMDTXT_SPECIAL 0xC0 -#define CMDTXT_OFFSETMASK 0x3E - -static const char * const cmdtxt_strings[] = { - /* 0 1 2 3 4 5 6 7 */ - "; ", "(", ")", " && ", " || ", "if ", "; then ", "...", - /* 8 9 10 11 12 13 */ - "while ", "; do ", "; done", "until ", "for ", " in ...", - /* 14 15 16 17 */ - "case ", "???", "() ...", "<<..." -}; - -static const char * const redir_strings[] = { - ">", "<", "<>", ">>", ">|", ">&", "<&" -}; - -static const unsigned char cmdtxt_ops[] = { -#define CMDTXT_NSEMI 0 - offsetof(union node, nbinary.ch1), - 0|CMDTXT_STRING, - offsetof(union node, nbinary.ch2)|CMDTXT_NOMORE, -#define CMDTXT_NCMD (CMDTXT_NSEMI + 3) -#define CMDTXT_NPIPE (CMDTXT_NCMD) -#define CMDTXT_NCASE (CMDTXT_NCMD) -#define CMDTXT_NTO (CMDTXT_NCMD) -#define CMDTXT_NFROM (CMDTXT_NCMD) -#define CMDTXT_NFROMTO (CMDTXT_NCMD) -#define CMDTXT_NAPPEND (CMDTXT_NCMD) -#define CMDTXT_NTOOV (CMDTXT_NCMD) -#define CMDTXT_NTOFD (CMDTXT_NCMD) -#define CMDTXT_NFROMFD (CMDTXT_NCMD) - CMDTXT_SPECIAL, -#define CMDTXT_NREDIR (CMDTXT_NPIPE + 1) -#define CMDTXT_NBACKGND (CMDTXT_NREDIR) - offsetof(union node, nredir.n)|CMDTXT_NOMORE, -#define CMDTXT_NSUBSHELL (CMDTXT_NBACKGND + 1) - (1*2)|CMDTXT_STRING, - offsetof(union node, nredir.n), - (2*2)|CMDTXT_STRING|CMDTXT_NOMORE, -#define CMDTXT_NAND (CMDTXT_NSUBSHELL + 3) - offsetof(union node, nbinary.ch1), - (3*2)|CMDTXT_STRING, - offsetof(union node, nbinary.ch2)|CMDTXT_NOMORE, -#define CMDTXT_NOR (CMDTXT_NAND + 3) - offsetof(union node, nbinary.ch1), - (4*2)|CMDTXT_STRING, - offsetof(union node, nbinary.ch2)|CMDTXT_NOMORE, -#define CMDTXT_NIF (CMDTXT_NOR + 3) - (5*2)|CMDTXT_STRING, - offsetof(union node, nif.test), - (6*2)|CMDTXT_STRING, - offsetof(union node, nif.ifpart), - (7*2)|CMDTXT_STRING|CMDTXT_NOMORE, -#define CMDTXT_NWHILE (CMDTXT_NIF + 5) - (8*2)|CMDTXT_STRING, - offsetof(union node, nbinary.ch1), - (9*2)|CMDTXT_STRING, - offsetof(union node, nbinary.ch2), - (10*2)|CMDTXT_STRING|CMDTXT_NOMORE, -#define CMDTXT_NUNTIL (CMDTXT_NWHILE + 5) - (11*2)|CMDTXT_STRING, - offsetof(union node, nbinary.ch1), - (9*2)|CMDTXT_STRING, - offsetof(union node, nbinary.ch2), - (10*2)|CMDTXT_STRING|CMDTXT_NOMORE, -#define CMDTXT_NFOR (CMDTXT_NUNTIL + 5) - (12*2)|CMDTXT_STRING, - offsetof(union node, nfor.var)|CMDTXT_CHARPTR, - (13*2)|CMDTXT_STRING|CMDTXT_NOMORE, -#define CMDTXT_NCLIST (CMDTXT_NFOR + 3) /* TODO: IS THIS CORRECT??? */ -#define CMDTXT_NNOT (CMDTXT_NCLIST) /* TODO: IS THIS CORRECT??? */ - (15*2)|CMDTXT_STRING|CMDTXT_NOMORE, -#define CMDTXT_NDEFUN (CMDTXT_NCLIST + 1) - offsetof(union node, narg.text)|CMDTXT_CHARPTR, - (16*2)|CMDTXT_STRING|CMDTXT_NOMORE, -#define CMDTXT_NARG (CMDTXT_NDEFUN + 2) - offsetof(union node, narg.text)|CMDTXT_CHARPTR|CMDTXT_NOMORE, -#define CMDTXT_NHERE (CMDTXT_NARG + 1) -#define CMDTXT_NXHERE (CMDTXT_NHERE) - (17*2)|CMDTXT_STRING|CMDTXT_NOMORE, -}; - -#if CMDTXT_NXHERE != 36 -#error CMDTXT_NXHERE -#endif - -static const unsigned char cmdtxt_ops_index[26] = { - CMDTXT_NSEMI, - CMDTXT_NCMD, - CMDTXT_NPIPE, - CMDTXT_NREDIR, - CMDTXT_NBACKGND, - CMDTXT_NSUBSHELL, - CMDTXT_NAND, - CMDTXT_NOR, - CMDTXT_NIF, - CMDTXT_NWHILE, - CMDTXT_NUNTIL, - CMDTXT_NFOR, - CMDTXT_NCASE, - CMDTXT_NCLIST, - CMDTXT_NDEFUN, - CMDTXT_NARG, - CMDTXT_NTO, - CMDTXT_NFROM, - CMDTXT_NFROMTO, - CMDTXT_NAPPEND, - CMDTXT_NTOOV, - CMDTXT_NTOFD, - CMDTXT_NFROMFD, - CMDTXT_NHERE, - CMDTXT_NXHERE, - CMDTXT_NNOT, -}; - -static void -cmdtxt(const union node *n) -{ - const char *p; - - if (n == NULL) - return; - - p = cmdtxt_ops + (int) cmdtxt_ops_index[n->type]; - if ((*p & CMDTXT_SPECIAL) != CMDTXT_SPECIAL) { /* normal case */ - do { - if (*p & CMDTXT_STRING) { /* output fixed string */ - cmdputs(cmdtxt_strings[((int)(*p & CMDTXT_OFFSETMASK) >> 1)]); - } else { - const char *pf = ((const char *) n) - + ((int)(*p & CMDTXT_OFFSETMASK)); - if (*p & CMDTXT_CHARPTR) { /* output dynamic string */ - cmdputs(*((const char **) pf)); - } else { /* output field */ - cmdtxt(*((const union node **) pf)); - } - } - } while (!(*p++ & CMDTXT_NOMORE)); - } else if (n->type == NCMD) { - union node *np; - for (np = n->ncmd.args ; np ; np = np->narg.next) { - cmdtxt(np); - if (np->narg.next) - cmdputs(spcstr); - } - for (np = n->ncmd.redirect ; np ; np = np->nfile.next) { - cmdputs(spcstr); - cmdtxt(np); - } - } else if (n->type == NPIPE) { - struct nodelist *lp; - for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { - cmdtxt(lp->n); - if (lp->next) - cmdputs(" | "); - } - } else if (n->type == NCASE) { - cmdputs(cmdtxt_strings[14]); - cmdputs(n->ncase.expr->narg.text); - cmdputs(cmdtxt_strings[13]); - } else { -#if (NTO != 16) || (NFROM != 17) || (NFROMTO != 18) || (NAPPEND != 19) || (NTOOV != 20) || (NTOFD != 21) || (NFROMFD != 22) -#error Assumption violated regarding range and ordering of NTO ... NFROMFD! -#endif - char s[2]; - -#ifdef DEBUG - assert((n->type >= NTO) && (n->type <= NFROMFD)); -#endif - - p = redir_strings[n->type - NTO]; - if (n->nfile.fd != ('>' == *p)) { - s[0] = n->nfile.fd + '0'; - s[1] = '\0'; - cmdputs(s); - } - cmdputs(p); - if (n->type >= NTOFD) { - s[0] = n->ndup.dupfd + '0'; - s[1] = '\0'; - cmdputs(s); - } else { - cmdtxt(n->nfile.fname); - } - } -} -#else /* CMDTXT_TABLE */ -static void -cmdtxt(const union node *n) -{ - union node *np; - struct nodelist *lp; - const char *p; - int i; - char s[2]; - - if (n == NULL) - return; - switch (n->type) { - case NSEMI: - cmdtxt(n->nbinary.ch1); - cmdputs("; "); - cmdtxt(n->nbinary.ch2); - break; - case NAND: - cmdtxt(n->nbinary.ch1); - cmdputs(" && "); - cmdtxt(n->nbinary.ch2); - break; - case NOR: - cmdtxt(n->nbinary.ch1); - cmdputs(" || "); - cmdtxt(n->nbinary.ch2); - break; - case NPIPE: - for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { - cmdtxt(lp->n); - if (lp->next) - cmdputs(" | "); - } - break; - case NSUBSHELL: - cmdputs("("); - cmdtxt(n->nredir.n); - cmdputs(")"); - break; - case NREDIR: - case NBACKGND: - cmdtxt(n->nredir.n); - break; - case NIF: - cmdputs("if "); - cmdtxt(n->nif.test); - cmdputs("; then "); - cmdtxt(n->nif.ifpart); - cmdputs("..."); - break; - case NWHILE: - cmdputs("while "); - goto until; - case NUNTIL: - cmdputs("until "); -until: - cmdtxt(n->nbinary.ch1); - cmdputs("; do "); - cmdtxt(n->nbinary.ch2); - cmdputs("; done"); - break; - case NFOR: - cmdputs("for "); - cmdputs(n->nfor.var); - cmdputs(" in ..."); - break; - case NCASE: - cmdputs("case "); - cmdputs(n->ncase.expr->narg.text); - cmdputs(" in ..."); - break; - case NDEFUN: - cmdputs(n->narg.text); - cmdputs("() ..."); - break; - case NCMD: - for (np = n->ncmd.args ; np ; np = np->narg.next) { - cmdtxt(np); - if (np->narg.next) - cmdputs(spcstr); - } - for (np = n->ncmd.redirect ; np ; np = np->nfile.next) { - cmdputs(spcstr); - cmdtxt(np); - } - break; - case NARG: - cmdputs(n->narg.text); - break; - case NTO: - p = ">"; i = 1; goto redir; - case NAPPEND: - p = ">>"; i = 1; goto redir; - case NTOFD: - p = ">&"; i = 1; goto redir; - case NTOOV: - p = ">|"; i = 1; goto redir; - case NFROM: - p = "<"; i = 0; goto redir; - case NFROMFD: - p = "<&"; i = 0; goto redir; - case NFROMTO: - p = "<>"; i = 0; goto redir; -redir: - if (n->nfile.fd != i) { - s[0] = n->nfile.fd + '0'; - s[1] = '\0'; - cmdputs(s); - } - cmdputs(p); - if (n->type == NTOFD || n->type == NFROMFD) { - s[0] = n->ndup.dupfd + '0'; - s[1] = '\0'; - cmdputs(s); - } else { - cmdtxt(n->nfile.fname); - } - break; - case NHERE: - case NXHERE: - cmdputs("<<..."); - break; - default: - cmdputs("???"); - break; - } -} -#endif /* CMDTXT_TABLE */ - -static char * -commandtext(const union node *n) -{ - char *name; - - cmdnextc = name = ckmalloc(MAXCMDTEXT); - cmdnleft = MAXCMDTEXT - 4; - cmdtxt(n); - *cmdnextc = '\0'; - return name; -} - - -static void waitonint(int sig) { - intreceived = 1; - return; -} -/* - * Routines to check for mail. (Perhaps make part of main.c?) - */ - - -#define MAXMBOXES 10 - - -static int nmboxes; /* number of mailboxes */ -static time_t mailtime[MAXMBOXES]; /* times of mailboxes */ - - - -/* - * Print appropriate message(s) if mail has arrived. If the argument is - * nozero, then the value of MAIL has changed, so we just update the - * values. - */ - -static void -chkmail(int silent) -{ - int i; - const char *mpath; - char *p; - char *q; - struct stackmark smark; - struct stat statb; - - if (silent) - nmboxes = 10; - if (nmboxes == 0) - return; - setstackmark(&smark); - mpath = mpathset()? mpathval() : mailval(); - for (i = 0 ; i < nmboxes ; i++) { - p = padvance(&mpath, nullstr); - if (p == NULL) - break; - if (*p == '\0') - continue; - for (q = p ; *q ; q++); -#ifdef DEBUG - if (q[-1] != '/') - abort(); -#endif - q[-1] = '\0'; /* delete trailing '/' */ - if (stat(p, &statb) < 0) - statb.st_size = 0; - if (statb.st_size > mailtime[i] && ! silent) { - out2fmt(snlfmt, - pathopt? pathopt : "you have mail"); - } - mailtime[i] = statb.st_size; - } - nmboxes = i; - popstackmark(&smark); -} - -#define PROFILE 0 - -#if PROFILE -static short profile_buf[16384]; -extern int etext(); -#endif - -static void read_profile (const char *); -static void cmdloop (int); -static void options (int); -static void setoption (int, int); -static void procargs (int, char **); - - -/* - * Main routine. We initialize things, parse the arguments, execute - * profiles if we're a login shell, and then call cmdloop to execute - * commands. The setjmp call sets up the location to jump to when an - * exception occurs. When an exception occurs the variable "state" - * is used to figure out how far we had gotten. - */ - -int -ash_main(argc, argv) - int argc; - char **argv; -{ - struct jmploc jmploc; - struct stackmark smark; - volatile int state; - const char *shinit; - - BLTINCMD = find_builtin("builtin"); - EXECCMD = find_builtin("exec"); - EVALCMD = find_builtin("eval"); - -#ifndef BB_FEATURE_SH_FANCY_PROMPT - unsetenv("PS1"); - unsetenv("PS2"); -#endif - -#if PROFILE - monitor(4, etext, profile_buf, sizeof profile_buf, 50); -#endif -#if defined(linux) || defined(__GNU__) - signal(SIGCHLD, SIG_DFL); -#endif - state = 0; - if (setjmp(jmploc.loc)) { - INTOFF; - /* - * When a shell procedure is executed, we raise the - * exception EXSHELLPROC to clean up before executing - * the shell procedure. - */ - if (exception == EXSHELLPROC) { - rootpid = getpid(); - rootshell = 1; - minusc = NULL; - state = 3; - } else { - if (exception == EXEXEC) { - exitstatus = exerrno; - } else if (exception == EXERROR) { - exitstatus = 2; - } - if (state == 0 || iflag == 0 || ! rootshell) - exitshell(exitstatus); - } - reset(); - if (exception == EXINT) { - out2c('\n'); - } - popstackmark(&smark); - FORCEINTON; /* enable interrupts */ - if (state == 1) - goto state1; - else if (state == 2) - goto state2; - else if (state == 3) - goto state3; - else - goto state4; - } - handler = &jmploc; -#ifdef DEBUG - opentrace(); - trputs("Shell args: "); trargs(argv); -#endif - rootpid = getpid(); - rootshell = 1; - init(); - setstackmark(&smark); - procargs(argc, argv); - if (argv[0] && argv[0][0] == '-') { - state = 1; - read_profile("/etc/profile"); -state1: - state = 2; - read_profile(".profile"); - } -state2: - state = 3; -#ifndef linux - if (getuid() == geteuid() && getgid() == getegid()) { -#endif - if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') { - state = 3; - read_profile(shinit); - } -#ifndef linux - } -#endif -state3: - state = 4; - if (sflag == 0 || minusc) { - static const char sigs[] = { - SIGINT, SIGQUIT, SIGHUP, -#ifdef SIGTSTP - SIGTSTP, -#endif - SIGPIPE - }; -#define SIGSSIZE ((sizeof(sigs)/sizeof(sigs[0])) - 1) /* trailing nul */ - int i; - - for (i = 0; i < SIGSSIZE; i++) - setsignal(sigs[i]); - } - - if (minusc) - evalstring(minusc, 0); - - if (sflag || minusc == NULL) { -state4: /* XXX ??? - why isn't this before the "if" statement */ - cmdloop(1); - } -#if PROFILE - monitor(0); -#endif - exitshell(exitstatus); - /* NOTREACHED */ -} - - -/* - * Read and execute commands. "Top" is nonzero for the top level command - * loop; it turns on prompting if the shell is interactive. - */ - -static void -cmdloop(int top) -{ - union node *n; - struct stackmark smark; - int inter; - int numeof = 0; - - TRACE(("cmdloop(%d) called\n", top)); - setstackmark(&smark); - for (;;) { - if (pendingsigs) - dotrap(); - inter = 0; - if (iflag && top) { - inter++; - showjobs(1); - chkmail(0); - flushall(); - } - n = parsecmd(inter); - /* showtree(n); DEBUG */ - if (n == NEOF) { - if (!top || numeof >= 50) - break; - if (!stoppedjobs()) { - if (!Iflag) - break; - out2str("\nUse \"exit\" to leave shell.\n"); - } - numeof++; - } else if (n != NULL && nflag == 0) { - job_warning = (job_warning == 2) ? 1 : 0; - numeof = 0; - evaltree(n, 0); - } - popstackmark(&smark); - setstackmark(&smark); - if (evalskip == SKIPFILE) { - evalskip = 0; - break; - } - } - popstackmark(&smark); -} - - - -/* - * Read /etc/profile or .profile. Return on error. - */ - -static void -read_profile(name) - const char *name; -{ - int fd; - int xflag_save; - int vflag_save; - - INTOFF; - if ((fd = open(name, O_RDONLY)) >= 0) - setinputfd(fd, 1); - INTON; - if (fd < 0) - return; - /* -q turns off -x and -v just when executing init files */ - /* Note: Might do a little redundant work, but reduces code size. */ - xflag_save = xflag; - vflag_save = vflag; - if (qflag) { - vflag = xflag = 0; - } - cmdloop(0); - xflag = xflag_save; - vflag = vflag_save; - popfile(); -} - - - -/* - * Read a file containing shell functions. - */ - -static void -readcmdfile(const char *name) -{ - int fd; - - INTOFF; - if ((fd = open(name, O_RDONLY)) >= 0) - setinputfd(fd, 1); - else - error("Can't open %s", name); - INTON; - cmdloop(0); - popfile(); -} - - - -/* - * Take commands from a file. To be compatable we should do a path - * search for the file, which is necessary to find sub-commands. - */ - - -static inline char * -find_dot_file(char *mybasename) -{ - char *fullname; - const char *path = pathval(); - struct stat statb; - - /* don't try this for absolute or relative paths */ - if (strchr(mybasename, '/')) - return mybasename; - - while ((fullname = padvance(&path, mybasename)) != NULL) { - if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) { - /* - * Don't bother freeing here, since it will - * be freed by the caller. - */ - return fullname; - } - stunalloc(fullname); - } - - /* not found in the PATH */ - error("%s: not found", mybasename); - /* NOTREACHED */ -} - -static int -dotcmd(argc, argv) - int argc; - char **argv; -{ - struct strlist *sp; - exitstatus = 0; - - for (sp = cmdenviron; sp ; sp = sp->next) - setvareq(savestr(sp->text), VSTRFIXED|VTEXTFIXED); - - if (argc >= 2) { /* That's what SVR2 does */ - char *fullname; - struct stackmark smark; - - setstackmark(&smark); - fullname = find_dot_file(argv[1]); - setinputfile(fullname, 1); - commandname = fullname; - cmdloop(0); - popfile(); - popstackmark(&smark); - } - return exitstatus; -} - - -static int -exitcmd(argc, argv) - int argc; - char **argv; -{ - if (stoppedjobs()) - return 0; - if (argc > 1) - exitstatus = number(argv[1]); - else - exitstatus = oexitstatus; - exitshell(exitstatus); - /* NOTREACHED */ -} - -static pointer -stalloc(int nbytes) -{ - char *p; - - nbytes = ALIGN(nbytes); - if (nbytes > stacknleft) { - int blocksize; - struct stack_block *sp; - - blocksize = nbytes; - if (blocksize < MINSIZE) - blocksize = MINSIZE; - INTOFF; - sp = ckmalloc(sizeof(struct stack_block) - MINSIZE + blocksize); - sp->prev = stackp; - stacknxt = sp->space; - stacknleft = blocksize; - stackp = sp; - INTON; - } - p = stacknxt; - stacknxt += nbytes; - stacknleft -= nbytes; - return p; -} - - -static void -stunalloc(pointer p) -{ -#ifdef DEBUG - if (p == NULL) { /*DEBUG */ - write(2, "stunalloc\n", 10); - abort(); - } -#endif - if (!(stacknxt >= (char *)p && (char *)p >= stackp->space)) { - p = stackp->space; - } - stacknleft += stacknxt - (char *)p; - stacknxt = p; -} - - -static void -setstackmark(struct stackmark *mark) -{ - mark->stackp = stackp; - mark->stacknxt = stacknxt; - mark->stacknleft = stacknleft; - mark->marknext = markp; - markp = mark; -} - - -static void -popstackmark(struct stackmark *mark) -{ - struct stack_block *sp; - - INTOFF; - markp = mark->marknext; - while (stackp != mark->stackp) { - sp = stackp; - stackp = sp->prev; - ckfree(sp); - } - stacknxt = mark->stacknxt; - stacknleft = mark->stacknleft; - INTON; -} - - -/* - * When the parser reads in a string, it wants to stick the string on the - * stack and only adjust the stack pointer when it knows how big the - * string is. Stackblock (defined in stack.h) returns a pointer to a block - * of space on top of the stack and stackblocklen returns the length of - * this block. Growstackblock will grow this space by at least one byte, - * possibly moving it (like realloc). Grabstackblock actually allocates the - * part of the block that has been used. - */ - -static void -growstackblock(void) { - char *p; - int newlen = ALIGN(stacknleft * 2 + 100); - char *oldspace = stacknxt; - int oldlen = stacknleft; - struct stack_block *sp; - struct stack_block *oldstackp; - - if (stacknxt == stackp->space && stackp != &stackbase) { - INTOFF; - oldstackp = stackp; - sp = stackp; - stackp = sp->prev; - sp = ckrealloc((pointer)sp, sizeof(struct stack_block) - MINSIZE + newlen); - sp->prev = stackp; - stackp = sp; - stacknxt = sp->space; - stacknleft = newlen; - { - /* Stack marks pointing to the start of the old block - * must be relocated to point to the new block - */ - struct stackmark *xmark; - xmark = markp; - while (xmark != NULL && xmark->stackp == oldstackp) { - xmark->stackp = stackp; - xmark->stacknxt = stacknxt; - xmark->stacknleft = stacknleft; - xmark = xmark->marknext; - } - } - INTON; - } else { - p = stalloc(newlen); - memcpy(p, oldspace, oldlen); - stacknxt = p; /* free the space */ - stacknleft += newlen; /* we just allocated */ - } -} - - - -static inline void -grabstackblock(int len) -{ - len = ALIGN(len); - stacknxt += len; - stacknleft -= len; -} - - - -/* - * The following routines are somewhat easier to use that the above. - * The user declares a variable of type STACKSTR, which may be declared - * to be a register. The macro STARTSTACKSTR initializes things. Then - * the user uses the macro STPUTC to add characters to the string. In - * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is - * grown as necessary. When the user is done, she can just leave the - * string there and refer to it using stackblock(). Or she can allocate - * the space for it using grabstackstr(). If it is necessary to allow - * someone else to use the stack temporarily and then continue to grow - * the string, the user should use grabstack to allocate the space, and - * then call ungrabstr(p) to return to the previous mode of operation. - * - * USTPUTC is like STPUTC except that it doesn't check for overflow. - * CHECKSTACKSPACE can be called before USTPUTC to ensure that there - * is space for at least one character. - */ - - -static char * -growstackstr(void) { - int len = stackblocksize(); - if (herefd >= 0 && len >= 1024) { - xwrite(herefd, stackblock(), len); - sstrnleft = len - 1; - return stackblock(); - } - growstackblock(); - sstrnleft = stackblocksize() - len - 1; - return stackblock() + len; -} - - -/* - * Called from CHECKSTRSPACE. - */ - -static char * -makestrspace(size_t newlen) { - int len = stackblocksize() - sstrnleft; - do { - growstackblock(); - sstrnleft = stackblocksize() - len; - } while (sstrnleft < newlen); - return stackblock() + len; -} - - - -static void -ungrabstackstr(char *s, char *p) -{ - stacknleft += stacknxt - s; - stacknxt = s; - sstrnleft = stacknleft - (p - s); -} -/* - * Miscelaneous builtins. - */ - - -#undef rflag - -#if !defined(__GLIBC__) || __GLIBC__ == 2 && __GLIBC_MINOR__ < 1 -typedef long rlim_t; -#endif - - - -/* - * The read builtin. The -e option causes backslashes to escape the - * following character. - * - * This uses unbuffered input, which may be avoidable in some cases. - */ - -static int -readcmd(int argc, char **argv) -{ - char **ap; - int backslash; - char c; - int rflag; - char *prompt; - const char *ifs; - char *p; - int startword; - int status; - int i; - - rflag = 0; - prompt = NULL; - while ((i = nextopt("p:r")) != '\0') { - if (i == 'p') - prompt = optionarg; - else - rflag = 1; - } - if (prompt && isatty(0)) { - out2str(prompt); /* read without cmdedit */ - flushall(); - } - if (*(ap = argptr) == NULL) - error("arg count"); - if ((ifs = bltinlookup("IFS")) == NULL) - ifs = defifs; - status = 0; - startword = 1; - backslash = 0; - STARTSTACKSTR(p); - for (;;) { - if (read(0, &c, 1) != 1) { - status = 1; - break; - } - if (c == '\0') - continue; - if (backslash) { - backslash = 0; - if (c != '\n') - STPUTC(c, p); - continue; - } - if (!rflag && c == '\\') { - backslash++; - continue; - } - if (c == '\n') - break; - if (startword && *ifs == ' ' && strchr(ifs, c)) { - continue; - } - startword = 0; - if (backslash && c == '\\') { - if (read(0, &c, 1) != 1) { - status = 1; - break; - } - STPUTC(c, p); - } else if (ap[1] != NULL && strchr(ifs, c) != NULL) { - STACKSTRNUL(p); - setvar(*ap, stackblock(), 0); - ap++; - startword = 1; - STARTSTACKSTR(p); - } else { - STPUTC(c, p); - } - } - STACKSTRNUL(p); - /* Remove trailing blanks */ - while (stackblock() <= --p && strchr(ifs, *p) != NULL) - *p = '\0'; - setvar(*ap, stackblock(), 0); - while (*++ap != NULL) - setvar(*ap, nullstr, 0); - return status; -} - - - -static int -umaskcmd(argc, argv) - int argc; - char **argv; -{ - static const char permuser[3] = "ugo"; - static const char permmode[3] = "rwx"; - static const short int permmask[] = { - S_IRUSR, S_IWUSR, S_IXUSR, - S_IRGRP, S_IWGRP, S_IXGRP, - S_IROTH, S_IWOTH, S_IXOTH - }; - - char *ap; - mode_t mask; - int i; - int symbolic_mode = 0; - - while (nextopt("S") != '\0') { - symbolic_mode = 1; - } - - INTOFF; - mask = umask(0); - umask(mask); - INTON; - - if ((ap = *argptr) == NULL) { - if (symbolic_mode) { - char buf[18]; - char *p = buf; - for (i=0 ; i<3 ; i++) { - int j; - *p++ = permuser[i]; - *p++ = '='; - for (j=0 ; j<3 ; j++) { - if ((mask & permmask[3*i+j]) == 0) { - *p++ = permmode[j]; - } - } - *p++ = ','; - } - *--p = 0; - puts(buf); - } else { - printf("%.4o\n", mask); - } - } else { - if (is_digit((unsigned char)*ap)) { - mask = 0; - do { - if (*ap >= '8' || *ap < '0') - error("Illegal number: %s", argv[1]); - mask = (mask << 3) + (*ap - '0'); - } while (*++ap != '\0'); - umask(mask); - } else { - mask = ~mask & 0777; - if (parse_mode(ap, &mask) == FALSE) { - error("Illegal mode: %s", ap); - } - umask(~mask & 0777); - } - } - return 0; -} - -/* - * ulimit builtin - * - * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and - * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with - * ash by J.T. Conklin. - * - * Public domain. - */ - -struct limits { - const char *name; - short cmd; - short factor; /* multiply by to get rlim_{cur,max} values */ -}; - -static const struct limits limits[] = { -#ifdef RLIMIT_CPU - { "time(seconds)", RLIMIT_CPU, 1 }, -#endif -#ifdef RLIMIT_FSIZE - { "file(blocks)", RLIMIT_FSIZE, 512 }, -#endif -#ifdef RLIMIT_DATA - { "data(kbytes)", RLIMIT_DATA, 1024 }, -#endif -#ifdef RLIMIT_STACK - { "stack(kbytes)", RLIMIT_STACK, 1024 }, -#endif -#ifdef RLIMIT_CORE - { "coredump(blocks)", RLIMIT_CORE, 512 }, -#endif -#ifdef RLIMIT_RSS - { "memory(kbytes)", RLIMIT_RSS, 1024 }, -#endif -#ifdef RLIMIT_MEMLOCK - { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024 }, -#endif -#ifdef RLIMIT_NPROC - { "process(processes)", RLIMIT_NPROC, 1 }, -#endif -#ifdef RLIMIT_NOFILE - { "nofiles(descriptors)", RLIMIT_NOFILE, 1 }, -#endif -#ifdef RLIMIT_VMEM - { "vmemory(kbytes)", RLIMIT_VMEM, 1024 }, -#endif -#ifdef RLIMIT_SWAP - { "swap(kbytes)", RLIMIT_SWAP, 1024 }, -#endif - { NULL, 0, 0 } -}; - -static int -ulimitcmd(argc, argv) - int argc; - char **argv; -{ - static const char unlimited_string[] = "unlimited"; - int c; - rlim_t val = 0; - enum { SOFT = 0x1, HARD = 0x2 } - how = SOFT | HARD; - const struct limits *l; - int set, all = 0; - int optc, what; - struct rlimit limit; - - what = 'f'; - - while ((optc = nextopt("HSa" -#ifdef RLIMIT_CPU - "t" -#endif -#ifdef RLIMIT_FSIZE - "f" -#endif -#ifdef RLIMIT_DATA - "d" -#endif -#ifdef RLIMIT_STACK - "s" -#endif -#ifdef RLIMIT_CORE - "c" -#endif -#ifdef RLIMIT_RSS - "m" -#endif -#ifdef RLIMIT_MEMLOCK - "l" -#endif -#ifdef RLIMIT_NPROC - "p" -#endif -#ifdef RLIMIT_NOFILE - "n" -#endif -#ifdef RLIMIT_VMEM - "v" -#endif -#ifdef RLIMIT_SWAP - "w" -#endif - )) != '\0') { - if (optc == 'H') { - how = HARD; - } else if (optc == 'S') { - how = SOFT; - } else if (optc == 'a') { - all = 1; - } else { - what = optc; - } - } - - for (l = limits; l->name; l++) { - if(l->name[0] == what) - break; - if(l->name[1]=='w' && what=='w') - break; - } - - set = *argptr ? 1 : 0; - if (set) { - char *p = *argptr; - - if (all || argptr[1]) - error("too many arguments"); - if (strcmp(p, unlimited_string) == 0) - val = RLIM_INFINITY; - else { - val = (rlim_t) 0; - - while ((c = *p++) >= '0' && c <= '9') - { - val = (val * 10) + (long)(c - '0'); - if (val < (rlim_t) 0) - break; - } - if (c) - error("bad number"); - val *= l->factor; - } - } - - if (all) { - for (l = limits; l->name; l++) { - printf("%-20s ", l->name); - getrlimit(l->cmd, &limit); - OUTPUT_LIMIT: - if (how & SOFT) - val = limit.rlim_cur; - else if (how & HARD) - val = limit.rlim_max; - - if (val == RLIM_INFINITY) - puts(unlimited_string); - else - { - val /= l->factor; - printf("%lld\n", (long long) val); - } - if (!all) { - break; - } - } - return 0; - } - - if (!set) { - goto OUTPUT_LIMIT; - } - - getrlimit(l->cmd, &limit); - if (how & HARD) - limit.rlim_max = val; - if (how & SOFT) - limit.rlim_cur = val; - if (setrlimit(l->cmd, &limit) < 0) - error("error setting limit (%m)"); - return 0; -} -/* - * prefix -- see if pfx is a prefix of string. - */ - -static int -prefix(char const *pfx, char const *string) -{ - while (*pfx) { - if (*pfx++ != *string++) - return 0; - } - return 1; -} - -/* - * Return true if s is a string of digits, and save munber in intptr - * nagative is bad - */ - -static int -is_number(const char *p, int *intptr) -{ - int ret = 0; - - do { - if (! is_digit(*p)) - return 0; - ret *= 10; - ret += digit_val(*p); - p++; - } while (*p != '\0'); - - *intptr = ret; - return 1; -} - -/* - * Convert a string of digits to an integer, printing an error message on - * failure. - */ - -static int -number(const char *s) -{ - int i; - if (! is_number(s, &i)) - error("Illegal number: %s", s); - return i; -} - -/* - * Produce a possibly single quoted string suitable as input to the shell. - * The return string is allocated on the stack. - */ - -static char * -single_quote(const char *s) { - char *p; - - STARTSTACKSTR(p); - - do { - char *q = p; - size_t len1, len1p, len2, len2p; - - len1 = strcspn(s, "'"); - len2 = strspn(s + len1, "'"); - - len1p = len1 ? len1 + 2 : len1; - len2p = len2 + ((len2 < 2) ? len2 : 2); - - CHECKSTRSPACE(len1p + len2p + 1, p); - - if (len1) { - *p = '\''; - q = p + 1 + len1; - memcpy(p + 1, s, len1); - *q++ = '\''; - s += len1; - } - - if (len2 > 1) { - *q = '"'; - q += 1 + len2; - memcpy(q + 1, s, len2); - *q = '"'; - s += len2; - } else if (len2 == 1) { - *q++ = '\\'; - *q = '\''; - s++; - } - - STADJUST(len1p + len2p, p); - } while (*s); - - USTPUTC(0, p); - - return grabstackstr(p); -} - -/* - * Like strdup but works with the ash stack. - */ - -static char * -sstrdup(const char *p) -{ - size_t len = strlen(p) + 1; - return memcpy(stalloc(len), p, len); -} - - -/* - * Routine for dealing with parsed shell commands. - */ - - -static void sizenodelist (const struct nodelist *); -static struct nodelist *copynodelist (const struct nodelist *); -static char *nodesavestr (const char *); - -#define CALCSIZE_TABLE -#define COPYNODE_TABLE -#if defined(CALCSIZE_TABLE) || defined(COPYNODE_TABLE) -/* - * To collect a lot of redundant code in case statements for copynode() - * and calcsize(), we implement a mini language here. Each type of node - * struct has an associated instruction sequence that operates on its - * members via their offsets. The instruction are pack in unsigned chars - * with format IIDDDDDE where the bits are - * I : part of the instruction opcode, which are - * 00 : member is a pointer to another node - * 40 : member is an integer - * 80 : member is a pointer to a nodelist - * CC : member is a pointer to a char string - * D : data - the actual offset of the member to operate on in the struct - * (since we assume bit 0 is set, it is not shifted) - * E : flag signaling end of instruction sequence - * - * WARNING: In order to handle larger offsets for 64bit archs, this code - * assumes that no offset can be an odd number and stores the - * end-of-instructions flag in bit 0. - */ - -#define NODE_INTEGER 0x40 -#define NODE_NODELIST 0x80 -#define NODE_CHARPTR 0xC0 -#define NODE_NOMORE 0x01 /* Note: no offset should be odd (aligned)*/ -#define NODE_MBRMASK 0xC0 -#define NODE_OFFSETMASK 0x3E - -static const unsigned char copynode_ops[35] = { -#define COPYNODE_OPS0 0 - offsetof(union node, nbinary.ch2), - offsetof(union node, nbinary.ch1)|NODE_NOMORE, -#define COPYNODE_OPS1 (COPYNODE_OPS0 + 2) - offsetof(union node, ncmd.redirect), - offsetof(union node, ncmd.args), - offsetof(union node, ncmd.assign), - offsetof(union node, ncmd.backgnd)|NODE_INTEGER|NODE_NOMORE, -#define COPYNODE_OPS2 (COPYNODE_OPS1 + 4) - offsetof(union node, npipe.cmdlist)|NODE_NODELIST, - offsetof(union node, npipe.backgnd)|NODE_INTEGER|NODE_NOMORE, -#define COPYNODE_OPS3 (COPYNODE_OPS2 + 2) - offsetof(union node, nredir.redirect), - offsetof(union node, nredir.n)|NODE_NOMORE, -#define COPYNODE_OPS4 (COPYNODE_OPS3 + 2) - offsetof(union node, nif.elsepart), - offsetof(union node, nif.ifpart), - offsetof(union node, nif.test)|NODE_NOMORE, -#define COPYNODE_OPS5 (COPYNODE_OPS4 + 3) - offsetof(union node, nfor.var)|NODE_CHARPTR, - offsetof(union node, nfor.body), - offsetof(union node, nfor.args)|NODE_NOMORE, -#define COPYNODE_OPS6 (COPYNODE_OPS5 + 3) - offsetof(union node, ncase.cases), - offsetof(union node, ncase.expr)|NODE_NOMORE, -#define COPYNODE_OPS7 (COPYNODE_OPS6 + 2) - offsetof(union node, nclist.body), - offsetof(union node, nclist.pattern), - offsetof(union node, nclist.next)|NODE_NOMORE, -#define COPYNODE_OPS8 (COPYNODE_OPS7 + 3) - offsetof(union node, narg.backquote)|NODE_NODELIST, - offsetof(union node, narg.text)|NODE_CHARPTR, - offsetof(union node, narg.next)|NODE_NOMORE, -#define COPYNODE_OPS9 (COPYNODE_OPS8 + 3) - offsetof(union node, nfile.fname), - offsetof(union node, nfile.fd)|NODE_INTEGER, - offsetof(union node, nfile.next)|NODE_NOMORE, -#define COPYNODE_OPS10 (COPYNODE_OPS9 + 3) - offsetof(union node, ndup.vname), - offsetof(union node, ndup.dupfd)|NODE_INTEGER, - offsetof(union node, ndup.fd)|NODE_INTEGER, - offsetof(union node, ndup.next)|NODE_NOMORE, -#define COPYNODE_OPS11 (COPYNODE_OPS10 + 4) - offsetof(union node, nhere.doc), - offsetof(union node, nhere.fd)|NODE_INTEGER, - offsetof(union node, nhere.next)|NODE_NOMORE, -#define COPYNODE_OPS12 (COPYNODE_OPS11 + 3) - offsetof(union node, nnot.com)|NODE_NOMORE, -}; - -#if COPYNODE_OPS12 != 34 -#error COPYNODE_OPS12 is incorrect -#endif - -static const unsigned char copynode_ops_index[26] = { - COPYNODE_OPS0, /* NSEMI */ - COPYNODE_OPS1, /* NCMD */ - COPYNODE_OPS2, /* NPIPE */ - COPYNODE_OPS3, /* NREDIR */ - COPYNODE_OPS3, /* NBACKGND */ - COPYNODE_OPS3, /* NSUBSHELL */ - COPYNODE_OPS0, /* NAND */ - COPYNODE_OPS0, /* NOR */ - COPYNODE_OPS4, /* NIF */ - COPYNODE_OPS0, /* NWHILE */ - COPYNODE_OPS0, /* NUNTIL */ - COPYNODE_OPS5, /* NFOR */ - COPYNODE_OPS6, /* NCASE */ - COPYNODE_OPS7, /* NCLIST */ - COPYNODE_OPS8, /* NDEFUN */ - COPYNODE_OPS8, /* NARG */ - COPYNODE_OPS9, /* NTO */ - COPYNODE_OPS9, /* NFROM */ - COPYNODE_OPS9, /* NFROMTO */ - COPYNODE_OPS9, /* NAPPEND */ - COPYNODE_OPS9, /* NTOOV */ - COPYNODE_OPS10, /* NTOFD */ - COPYNODE_OPS10, /* NFROMFD */ - COPYNODE_OPS11, /* NHERE */ - COPYNODE_OPS11, /* NXHERE */ - COPYNODE_OPS12, /* NNOT */ -}; - -#if NODE_CHARPTR != NODE_MBRMASK -#error NODE_CHARPTR != NODE_MBRMASK!!! -#endif -#endif /* defined(CALCSIZE_TABLE) || defined(COPYNODE_TABLE) */ - -#ifdef COPYNODE_TABLE -static union node * -copynode(const union node *n) -{ - union node *new; - const unsigned char *p; - - if (n == NULL) { - return NULL; - } - new = funcblock; - new->type = n->type; - funcblock = (char *) funcblock + (int) nodesize[n->type]; - p = copynode_ops + (int) copynode_ops_index[n->type]; - do { - char *nn = ((char *) new) + ((int)(*p & NODE_OFFSETMASK)); - const char *no = ((const char *) n) + ((int)(*p & NODE_OFFSETMASK)); - - if (!(*p & NODE_MBRMASK)) { /* standard node */ - *((union node **)nn) = copynode(*((const union node **) no)); - } else if ((*p & NODE_MBRMASK) == NODE_CHARPTR) { /* string */ - *((const char **)nn) = nodesavestr(*((const char **)no)); - } else if (*p & NODE_NODELIST) { /* nodelist */ - *((struct nodelist **)nn) - = copynodelist(*((const struct nodelist **) no)); - } else { /* integer */ - *((int *) nn) = *((int *) no); - } - } while (!(*p++ & NODE_NOMORE)); - return new; -} -#else /* COPYNODE_TABLE */ -static union node * -copynode(const union node *n) -{ - union node *new; - - if (n == NULL) - return NULL; - new = funcblock; - funcblock = (char *) funcblock + nodesize[n->type]; - switch (n->type) { - case NSEMI: - case NAND: - case NOR: - case NWHILE: - case NUNTIL: - new->nbinary.ch2 = copynode(n->nbinary.ch2); - new->nbinary.ch1 = copynode(n->nbinary.ch1); - break; - case NCMD: - new->ncmd.redirect = copynode(n->ncmd.redirect); - new->ncmd.args = copynode(n->ncmd.args); - new->ncmd.assign = copynode(n->ncmd.assign); - new->ncmd.backgnd = n->ncmd.backgnd; - break; - case NPIPE: - new->npipe.cmdlist = copynodelist(n->npipe.cmdlist); - new->npipe.backgnd = n->npipe.backgnd; - break; - case NREDIR: - case NBACKGND: - case NSUBSHELL: - new->nredir.redirect = copynode(n->nredir.redirect); - new->nredir.n = copynode(n->nredir.n); - break; - case NIF: - new->nif.elsepart = copynode(n->nif.elsepart); - new->nif.ifpart = copynode(n->nif.ifpart); - new->nif.test = copynode(n->nif.test); - break; - case NFOR: - new->nfor.var = nodesavestr(n->nfor.var); - new->nfor.body = copynode(n->nfor.body); - new->nfor.args = copynode(n->nfor.args); - break; - case NCASE: - new->ncase.cases = copynode(n->ncase.cases); - new->ncase.expr = copynode(n->ncase.expr); - break; - case NCLIST: - new->nclist.body = copynode(n->nclist.body); - new->nclist.pattern = copynode(n->nclist.pattern); - new->nclist.next = copynode(n->nclist.next); - break; - case NDEFUN: - case NARG: - new->narg.backquote = copynodelist(n->narg.backquote); - new->narg.text = nodesavestr(n->narg.text); - new->narg.next = copynode(n->narg.next); - break; - case NTO: - case NFROM: - case NFROMTO: - case NAPPEND: - case NTOOV: - new->nfile.fname = copynode(n->nfile.fname); - new->nfile.fd = n->nfile.fd; - new->nfile.next = copynode(n->nfile.next); - break; - case NTOFD: - case NFROMFD: - new->ndup.vname = copynode(n->ndup.vname); - new->ndup.dupfd = n->ndup.dupfd; - new->ndup.fd = n->ndup.fd; - new->ndup.next = copynode(n->ndup.next); - break; - case NHERE: - case NXHERE: - new->nhere.doc = copynode(n->nhere.doc); - new->nhere.fd = n->nhere.fd; - new->nhere.next = copynode(n->nhere.next); - break; - case NNOT: - new->nnot.com = copynode(n->nnot.com); - break; - }; - new->type = n->type; - return new; -} -#endif /* COPYNODE_TABLE */ - -#ifdef CALCSIZE_TABLE -static void -calcsize(const union node *n) -{ - const unsigned char *p; - - if (n == NULL) - return; - funcblocksize += (int) nodesize[n->type]; - - p = copynode_ops + (int) copynode_ops_index[n->type]; - do { - const char *no = ((const char *) n) + ((int)(*p & NODE_OFFSETMASK)); - - if (!(*p & NODE_MBRMASK)) { /* standard node */ - calcsize(*((const union node **) no)); - } else if ((*p & NODE_MBRMASK) == NODE_CHARPTR) { /* string */ - funcstringsize += strlen(*((const char **)no)) + 1; - } else if (*p & NODE_NODELIST) { /* nodelist */ - sizenodelist(*((const struct nodelist **) no)); - } /* else integer -- ignore */ - } while (!(*p++ & NODE_NOMORE)); -} -#else /* CALCSIZE_TABLE */ -static void -calcsize(const union node *n) -{ - if (n == NULL) - return; - funcblocksize += nodesize[n->type]; - switch (n->type) { - case NSEMI: - case NAND: - case NOR: - case NWHILE: - case NUNTIL: - calcsize(n->nbinary.ch2); - calcsize(n->nbinary.ch1); - break; - case NCMD: - calcsize(n->ncmd.redirect); - calcsize(n->ncmd.args); - calcsize(n->ncmd.assign); - break; - case NPIPE: - sizenodelist(n->npipe.cmdlist); - break; - case NREDIR: - case NBACKGND: - case NSUBSHELL: - calcsize(n->nredir.redirect); - calcsize(n->nredir.n); - break; - case NIF: - calcsize(n->nif.elsepart); - calcsize(n->nif.ifpart); - calcsize(n->nif.test); - break; - case NFOR: - funcstringsize += strlen(n->nfor.var) + 1; - calcsize(n->nfor.body); - calcsize(n->nfor.args); - break; - case NCASE: - calcsize(n->ncase.cases); - calcsize(n->ncase.expr); - break; - case NCLIST: - calcsize(n->nclist.body); - calcsize(n->nclist.pattern); - calcsize(n->nclist.next); - break; - case NDEFUN: - case NARG: - sizenodelist(n->narg.backquote); - funcstringsize += strlen(n->narg.text) + 1; - calcsize(n->narg.next); - break; - case NTO: - case NFROM: - case NFROMTO: - case NAPPEND: - case NTOOV: - calcsize(n->nfile.fname); - calcsize(n->nfile.next); - break; - case NTOFD: - case NFROMFD: - calcsize(n->ndup.vname); - calcsize(n->ndup.next); - break; - case NHERE: - case NXHERE: - calcsize(n->nhere.doc); - calcsize(n->nhere.next); - break; - case NNOT: - calcsize(n->nnot.com); - break; - }; -} -#endif /* CALCSIZE_TABLE */ - -static void -sizenodelist(const struct nodelist *lp) -{ - while (lp) { - funcblocksize += ALIGN(sizeof(struct nodelist)); - calcsize(lp->n); - lp = lp->next; - } -} - - -static struct nodelist * -copynodelist(const struct nodelist *lp) -{ - struct nodelist *start; - struct nodelist **lpp; - - lpp = &start; - while (lp) { - *lpp = funcblock; - funcblock = (char *) funcblock + ALIGN(sizeof(struct nodelist)); - (*lpp)->n = copynode(lp->n); - lp = lp->next; - lpp = &(*lpp)->next; - } - *lpp = NULL; - return start; -} - - -static char * -nodesavestr(const char *s) -{ - const char *p = s; - char *q = funcstring; - char *rtn = funcstring; - - while ((*q++ = *p++) != '\0') - continue; - funcstring = q; - return rtn; -} - -#ifdef ASH_GETOPTS -static int getopts (char *, char *, char **, int *, int *); -#endif - - -/* - * Process the shell command line arguments. - */ - -static void -procargs(argc, argv) - int argc; - char **argv; -{ - int i; - - argptr = argv; - if (argc > 0) - argptr++; - for (i = 0; i < NOPTS; i++) - optent_val(i) = 2; - options(1); - if (*argptr == NULL && minusc == NULL) - sflag = 1; - if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1)) - iflag = 1; - if (mflag == 2) - mflag = iflag; - for (i = 0; i < NOPTS; i++) - if (optent_val(i) == 2) - optent_val(i) = 0; - arg0 = argv[0]; - if (sflag == 0 && minusc == NULL) { - commandname = argv[0]; - arg0 = *argptr++; - setinputfile(arg0, 0); - commandname = arg0; - } - /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */ - if (argptr && minusc && *argptr) - arg0 = *argptr++; - - shellparam.p = argptr; - shellparam.optind = 1; - shellparam.optoff = -1; - /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */ - while (*argptr) { - shellparam.nparam++; - argptr++; - } - optschanged(); -} - - - -/* - * Process shell options. The global variable argptr contains a pointer - * to the argument list; we advance it past the options. - */ - -static inline void -minus_o(const char *name, int val) -{ - int i; - - if (name == NULL) { - out1str("Current option settings\n"); - for (i = 0; i < NOPTS; i++) - printf("%-16s%s\n", optent_name(optlist[i]), - optent_val(i) ? "on" : "off"); - } else { - for (i = 0; i < NOPTS; i++) - if (equal(name, optent_name(optlist[i]))) { - setoption(optent_letter(optlist[i]), val); - return; - } - error("Illegal option -o %s", name); - } -} - - -static void -options(int cmdline) -{ - char *p; - int val; - int c; - - if (cmdline) - minusc = NULL; - while ((p = *argptr) != NULL) { - argptr++; - if ((c = *p++) == '-') { - val = 1; - if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) { - if (!cmdline) { - /* "-" means turn off -x and -v */ - if (p[0] == '\0') - xflag = vflag = 0; - /* "--" means reset params */ - else if (*argptr == NULL) - setparam(argptr); - } - break; /* "-" or "--" terminates options */ - } - } else if (c == '+') { - val = 0; - } else { - argptr--; - break; - } - while ((c = *p++) != '\0') { - if (c == 'c' && cmdline) { - char *q; -#ifdef NOHACK /* removing this code allows sh -ce 'foo' for compat */ - if (*p == '\0') -#endif - q = *argptr++; - if (q == NULL || minusc != NULL) - error("Bad -c option"); - minusc = q; -#ifdef NOHACK - break; -#endif - } else if (c == 'o') { - minus_o(*argptr, val); - if (*argptr) - argptr++; - } else { - setoption(c, val); - } - } - } -} - - -static void -setoption(int flag, int val) -{ - int i; - - for (i = 0; i < NOPTS; i++) - if (optent_letter(optlist[i]) == flag) { - optent_val(i) = val; - if (val) { - /* #%$ hack for ksh semantics */ - if (flag == 'V') - Eflag = 0; - else if (flag == 'E') - Vflag = 0; - } - return; - } - error("Illegal option -%c", flag); - /* NOTREACHED */ -} - - - -/* - * Set the shell parameters. - */ - -static void -setparam(char **argv) -{ - char **newparam; - char **ap; - int nparam; - - for (nparam = 0 ; argv[nparam] ; nparam++); - ap = newparam = ckmalloc((nparam + 1) * sizeof *ap); - while (*argv) { - *ap++ = savestr(*argv++); - } - *ap = NULL; - freeparam(&shellparam); - shellparam.malloc = 1; - shellparam.nparam = nparam; - shellparam.p = newparam; - shellparam.optind = 1; - shellparam.optoff = -1; -} - - -/* - * Free the list of positional parameters. - */ - -static void -freeparam(volatile struct shparam *param) -{ - char **ap; - - if (param->malloc) { - for (ap = param->p ; *ap ; ap++) - ckfree(*ap); - ckfree(param->p); - } -} - - - -/* - * The shift builtin command. - */ - -static int -shiftcmd(argc, argv) - int argc; - char **argv; -{ - int n; - char **ap1, **ap2; - - n = 1; - if (argc > 1) - n = number(argv[1]); - if (n > shellparam.nparam) - error("can't shift that many"); - INTOFF; - shellparam.nparam -= n; - for (ap1 = shellparam.p ; --n >= 0 ; ap1++) { - if (shellparam.malloc) - ckfree(*ap1); - } - ap2 = shellparam.p; - while ((*ap2++ = *ap1++) != NULL); - shellparam.optind = 1; - shellparam.optoff = -1; - INTON; - return 0; -} - - - -/* - * The set command builtin. - */ - -static int -setcmd(argc, argv) - int argc; - char **argv; -{ - if (argc == 1) - return showvarscmd(argc, argv); - INTOFF; - options(0); - optschanged(); - if (*argptr != NULL) { - setparam(argptr); - } - INTON; - return 0; -} - - -static void -getoptsreset(const char *value) -{ - shellparam.optind = number(value); - shellparam.optoff = -1; -} - -#ifdef BB_LOCALE_SUPPORT -static void change_lc_all(const char *value) -{ - if(value != 0 && *value != 0) - setlocale(LC_ALL, value); -} - -static void change_lc_ctype(const char *value) -{ - if(value != 0 && *value != 0) - setlocale(LC_CTYPE, value); -} - -#endif - -#ifdef ASH_GETOPTS -/* - * The getopts builtin. Shellparam.optnext points to the next argument - * to be processed. Shellparam.optptr points to the next character to - * be processed in the current argument. If shellparam.optnext is NULL, - * then it's the first time getopts has been called. - */ - -static int -getoptscmd(argc, argv) - int argc; - char **argv; -{ - char **optbase; - - if (argc < 3) - error("Usage: getopts optstring var [arg]"); - else if (argc == 3) { - optbase = shellparam.p; - if (shellparam.optind > shellparam.nparam + 1) { - shellparam.optind = 1; - shellparam.optoff = -1; - } - } - else { - optbase = &argv[3]; - if (shellparam.optind > argc - 2) { - shellparam.optind = 1; - shellparam.optoff = -1; - } - } - - return getopts(argv[1], argv[2], optbase, &shellparam.optind, - &shellparam.optoff); -} - -/* - * Safe version of setvar, returns 1 on success 0 on failure. - */ - -static int -setvarsafe(name, val, flags) - const char *name, *val; - int flags; -{ - struct jmploc jmploc; - struct jmploc *volatile savehandler = handler; - int err = 0; -#ifdef __GNUC__ - (void) &err; -#endif - - if (setjmp(jmploc.loc)) - err = 1; - else { - handler = &jmploc; - setvar(name, val, flags); - } - handler = savehandler; - return err; -} - -static int -getopts(optstr, optvar, optfirst, myoptind, optoff) - char *optstr; - char *optvar; - char **optfirst; - int *myoptind; - int *optoff; -{ - char *p, *q; - char c = '?'; - int done = 0; - int err = 0; - char s[10]; - char **optnext = optfirst + *myoptind - 1; - - if (*myoptind <= 1 || *optoff < 0 || !(*(optnext - 1)) || - strlen(*(optnext - 1)) < *optoff) - p = NULL; - else - p = *(optnext - 1) + *optoff; - if (p == NULL || *p == '\0') { - /* Current word is done, advance */ - if (optnext == NULL) - return 1; - p = *optnext; - if (p == NULL || *p != '-' || *++p == '\0') { -atend: - *myoptind = optnext - optfirst + 1; - p = NULL; - done = 1; - goto out; - } - optnext++; - if (p[0] == '-' && p[1] == '\0') /* check for "--" */ - goto atend; - } - - c = *p++; - for (q = optstr; *q != c; ) { - if (*q == '\0') { - if (optstr[0] == ':') { - s[0] = c; - s[1] = '\0'; - err |= setvarsafe("OPTARG", s, 0); - } - else { - out2fmt("Illegal option -%c\n", c); - (void) unsetvar("OPTARG"); - } - c = '?'; - goto bad; - } - if (*++q == ':') - q++; - } - - if (*++q == ':') { - if (*p == '\0' && (p = *optnext) == NULL) { - if (optstr[0] == ':') { - s[0] = c; - s[1] = '\0'; - err |= setvarsafe("OPTARG", s, 0); - c = ':'; - } - else { - out2fmt("No arg for -%c option\n", c); - (void) unsetvar("OPTARG"); - c = '?'; - } - goto bad; - } - - if (p == *optnext) - optnext++; - setvarsafe("OPTARG", p, 0); - p = NULL; - } - else - setvarsafe("OPTARG", "", 0); - *myoptind = optnext - optfirst + 1; - goto out; - -bad: - *myoptind = 1; - p = NULL; -out: - *optoff = p ? p - *(optnext - 1) : -1; - snprintf(s, sizeof(s), "%d", *myoptind); - err |= setvarsafe("OPTIND", s, VNOFUNC); - s[0] = c; - s[1] = '\0'; - err |= setvarsafe(optvar, s, 0); - if (err) { - *myoptind = 1; - *optoff = -1; - exraise(EXERROR); - } - return done; -} -#endif - -/* - * XXX - should get rid of. have all builtins use getopt(3). the - * library getopt must have the BSD extension static variable "optreset" - * otherwise it can't be used within the shell safely. - * - * Standard option processing (a la getopt) for builtin routines. The - * only argument that is passed to nextopt is the option string; the - * other arguments are unnecessary. It return the character, or '\0' on - * end of input. - */ - -static int -nextopt(const char *optstring) -{ - char *p; - const char *q; - char c; - - if ((p = optptr) == NULL || *p == '\0') { - p = *argptr; - if (p == NULL || *p != '-' || *++p == '\0') - return '\0'; - argptr++; - if (p[0] == '-' && p[1] == '\0') /* check for "--" */ - return '\0'; - } - c = *p++; - for (q = optstring ; *q != c ; ) { - if (*q == '\0') - error("Illegal option -%c", c); - if (*++q == ':') - q++; - } - if (*++q == ':') { - if (*p == '\0' && (p = *argptr++) == NULL) - error("No arg for -%c option", c); - optionarg = p; - p = NULL; - } - optptr = p; - return c; -} - -static void -flushall() { - INTOFF; - fflush(stdout); - INTON; -} - - -static void -out2fmt(const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); -} - -/* - * Version of write which resumes after a signal is caught. - */ - -static int -xwrite(int fd, const char *buf, int nbytes) -{ - int ntry; - int i; - int n; - - n = nbytes; - ntry = 0; - for (;;) { - i = write(fd, buf, n); - if (i > 0) { - if ((n -= i) <= 0) - return nbytes; - buf += i; - ntry = 0; - } else if (i == 0) { - if (++ntry > 10) - return nbytes - n; - } else if (errno != EINTR) { - return -1; - } - } -} - - -/* - * Shell command parser. - */ - -#define EOFMARKLEN 79 - - - -struct heredoc { - struct heredoc *next; /* next here document in list */ - union node *here; /* redirection node */ - char *eofmark; /* string indicating end of input */ - int striptabs; /* if set, strip leading tabs */ -}; - -static struct heredoc *heredoclist; /* list of here documents to read */ -static int parsebackquote; /* nonzero if we are inside backquotes */ -static int doprompt; /* if set, prompt the user */ -static int needprompt; /* true if interactive and at start of line */ -static int lasttoken; /* last token read */ - -static char *wordtext; /* text of last word returned by readtoken */ - -static struct nodelist *backquotelist; -static union node *redirnode; -static struct heredoc *heredoc; -static int quoteflag; /* set if (part of) last token was quoted */ -static int startlinno; /* line # where last token started */ - - -static union node *list (int); -static union node *andor (void); -static union node *pipeline (void); -static union node *command (void); -static union node *simplecmd (void); -static void parsefname (void); -static void parseheredoc (void); -static char peektoken (void); -static int readtoken (void); -static int xxreadtoken (void); -static int readtoken1 (int, int, const char *, int); -static int noexpand (char *); -static void synexpect (int) __attribute__((noreturn)); -static void synerror (const char *) __attribute__((noreturn)); -static void setprompt (int); - - -/* - * Read and parse a command. Returns NEOF on end of file. (NULL is a - * valid parse tree indicating a blank line.) - */ - -static union node * -parsecmd(int interact) -{ - int t; - - tokpushback = 0; - doprompt = interact; - if (doprompt) - setprompt(1); - else - setprompt(0); - needprompt = 0; - t = readtoken(); - if (t == TEOF) - return NEOF; - if (t == TNL) - return NULL; - tokpushback++; - return list(1); -} - - -static union node * -list(nlflag) - int nlflag; -{ - union node *n1, *n2, *n3; - int tok; - - checkkwd = 2; - if (nlflag == 0 && peektoken()) - return NULL; - n1 = NULL; - for (;;) { - n2 = andor(); - tok = readtoken(); - if (tok == TBACKGND) { - if (n2->type == NCMD || n2->type == NPIPE) { - n2->ncmd.backgnd = 1; - } else if (n2->type == NREDIR) { - n2->type = NBACKGND; - } else { - n3 = (union node *)stalloc(sizeof (struct nredir)); - n3->type = NBACKGND; - n3->nredir.n = n2; - n3->nredir.redirect = NULL; - n2 = n3; - } - } - if (n1 == NULL) { - n1 = n2; - } - else { - n3 = (union node *)stalloc(sizeof (struct nbinary)); - n3->type = NSEMI; - n3->nbinary.ch1 = n1; - n3->nbinary.ch2 = n2; - n1 = n3; - } - switch (tok) { - case TBACKGND: - case TSEMI: - tok = readtoken(); - /* fall through */ - case TNL: - if (tok == TNL) { - parseheredoc(); - if (nlflag) - return n1; - } else { - tokpushback++; - } - checkkwd = 2; - if (peektoken()) - return n1; - break; - case TEOF: - if (heredoclist) - parseheredoc(); - else - pungetc(); /* push back EOF on input */ - return n1; - default: - if (nlflag) - synexpect(-1); - tokpushback++; - return n1; - } - } -} - - - -static union node * -andor() { - union node *n1, *n2, *n3; - int t; - - checkkwd = 1; - n1 = pipeline(); - for (;;) { - if ((t = readtoken()) == TAND) { - t = NAND; - } else if (t == TOR) { - t = NOR; - } else { - tokpushback++; - return n1; - } - checkkwd = 2; - n2 = pipeline(); - n3 = (union node *)stalloc(sizeof (struct nbinary)); - n3->type = t; - n3->nbinary.ch1 = n1; - n3->nbinary.ch2 = n2; - n1 = n3; - } -} - - - -static union node * -pipeline() { - union node *n1, *n2, *pipenode; - struct nodelist *lp, *prev; - int negate; - - negate = 0; - TRACE(("pipeline: entered\n")); - if (readtoken() == TNOT) { - negate = !negate; - checkkwd = 1; - } else - tokpushback++; - n1 = command(); - if (readtoken() == TPIPE) { - pipenode = (union node *)stalloc(sizeof (struct npipe)); - pipenode->type = NPIPE; - pipenode->npipe.backgnd = 0; - lp = (struct nodelist *)stalloc(sizeof (struct nodelist)); - pipenode->npipe.cmdlist = lp; - lp->n = n1; - do { - prev = lp; - lp = (struct nodelist *)stalloc(sizeof (struct nodelist)); - checkkwd = 2; - lp->n = command(); - prev->next = lp; - } while (readtoken() == TPIPE); - lp->next = NULL; - n1 = pipenode; - } - tokpushback++; - if (negate) { - n2 = (union node *)stalloc(sizeof (struct nnot)); - n2->type = NNOT; - n2->nnot.com = n1; - return n2; - } else - return n1; -} - - - -static union node * -command() { - union node *n1, *n2; - union node *ap, **app; - union node *cp, **cpp; - union node *redir, **rpp; - int t; - - redir = NULL; - n1 = NULL; - rpp = &redir; - - /* Check for redirection which may precede command */ - while (readtoken() == TREDIR) { - *rpp = n2 = redirnode; - rpp = &n2->nfile.next; - parsefname(); - } - tokpushback++; - - switch (readtoken()) { - case TIF: - n1 = (union node *)stalloc(sizeof (struct nif)); - n1->type = NIF; - n1->nif.test = list(0); - if (readtoken() != TTHEN) - synexpect(TTHEN); - n1->nif.ifpart = list(0); - n2 = n1; - while (readtoken() == TELIF) { - n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif)); - n2 = n2->nif.elsepart; - n2->type = NIF; - n2->nif.test = list(0); - if (readtoken() != TTHEN) - synexpect(TTHEN); - n2->nif.ifpart = list(0); - } - if (lasttoken == TELSE) - n2->nif.elsepart = list(0); - else { - n2->nif.elsepart = NULL; - tokpushback++; - } - if (readtoken() != TFI) - synexpect(TFI); - checkkwd = 1; - break; - case TWHILE: - case TUNTIL: { - int got; - n1 = (union node *)stalloc(sizeof (struct nbinary)); - n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL; - n1->nbinary.ch1 = list(0); - if ((got=readtoken()) != TDO) { -TRACE(("expecting DO got %s %s\n", tokname(got), got == TWORD ? wordtext : "")); - synexpect(TDO); - } - n1->nbinary.ch2 = list(0); - if (readtoken() != TDONE) - synexpect(TDONE); - checkkwd = 1; - break; - } - case TFOR: - if (readtoken() != TWORD || quoteflag || ! goodname(wordtext)) - synerror("Bad for loop variable"); - n1 = (union node *)stalloc(sizeof (struct nfor)); - n1->type = NFOR; - n1->nfor.var = wordtext; - checkkwd = 1; - if (readtoken() == TIN) { - app = ≈ - while (readtoken() == TWORD) { - n2 = (union node *)stalloc(sizeof (struct narg)); - n2->type = NARG; - n2->narg.text = wordtext; - n2->narg.backquote = backquotelist; - *app = n2; - app = &n2->narg.next; - } - *app = NULL; - n1->nfor.args = ap; - if (lasttoken != TNL && lasttoken != TSEMI) - synexpect(-1); - } else { - static char argvars[5] = {CTLVAR, VSNORMAL|VSQUOTE, - '@', '=', '\0'}; - n2 = (union node *)stalloc(sizeof (struct narg)); - n2->type = NARG; - n2->narg.text = argvars; - n2->narg.backquote = NULL; - n2->narg.next = NULL; - n1->nfor.args = n2; - /* - * Newline or semicolon here is optional (but note - * that the original Bourne shell only allowed NL). - */ - if (lasttoken != TNL && lasttoken != TSEMI) - tokpushback++; - } - checkkwd = 2; - if (readtoken() != TDO) - synexpect(TDO); - n1->nfor.body = list(0); - if (readtoken() != TDONE) - synexpect(TDONE); - checkkwd = 1; - break; - case TCASE: - n1 = (union node *)stalloc(sizeof (struct ncase)); - n1->type = NCASE; - if (readtoken() != TWORD) - synexpect(TWORD); - n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg)); - n2->type = NARG; - n2->narg.text = wordtext; - n2->narg.backquote = backquotelist; - n2->narg.next = NULL; - do { - checkkwd = 1; - } while (readtoken() == TNL); - if (lasttoken != TIN) - synerror("expecting \"in\""); - cpp = &n1->ncase.cases; - checkkwd = 2, readtoken(); - do { - if (lasttoken == TLP) - readtoken(); - *cpp = cp = (union node *)stalloc(sizeof (struct nclist)); - cp->type = NCLIST; - app = &cp->nclist.pattern; - for (;;) { - *app = ap = (union node *)stalloc(sizeof (struct narg)); - ap->type = NARG; - ap->narg.text = wordtext; - ap->narg.backquote = backquotelist; - if (checkkwd = 2, readtoken() != TPIPE) - break; - app = &ap->narg.next; - readtoken(); - } - ap->narg.next = NULL; - if (lasttoken != TRP) - synexpect(TRP); - cp->nclist.body = list(0); - - checkkwd = 2; - if ((t = readtoken()) != TESAC) { - if (t != TENDCASE) - synexpect(TENDCASE); - else - checkkwd = 2, readtoken(); - } - cpp = &cp->nclist.next; - } while(lasttoken != TESAC); - *cpp = NULL; - checkkwd = 1; - break; - case TLP: - n1 = (union node *)stalloc(sizeof (struct nredir)); - n1->type = NSUBSHELL; - n1->nredir.n = list(0); - n1->nredir.redirect = NULL; - if (readtoken() != TRP) - synexpect(TRP); - checkkwd = 1; - break; - case TBEGIN: - n1 = list(0); - if (readtoken() != TEND) - synexpect(TEND); - checkkwd = 1; - break; - /* Handle an empty command like other simple commands. */ - case TSEMI: - case TAND: - case TOR: - case TNL: - case TEOF: - case TRP: - case TBACKGND: - /* - * An empty command before a ; doesn't make much sense, and - * should certainly be disallowed in the case of `if ;'. - */ - if (!redir) - synexpect(-1); - case TWORD: - tokpushback++; - n1 = simplecmd(); - return n1; - default: - synexpect(-1); - /* NOTREACHED */ - } - - /* Now check for redirection which may follow command */ - while (readtoken() == TREDIR) { - *rpp = n2 = redirnode; - rpp = &n2->nfile.next; - parsefname(); - } - tokpushback++; - *rpp = NULL; - if (redir) { - if (n1->type != NSUBSHELL) { - n2 = (union node *)stalloc(sizeof (struct nredir)); - n2->type = NREDIR; - n2->nredir.n = n1; - n1 = n2; - } - n1->nredir.redirect = redir; - } - - return n1; -} - - -static union node * -simplecmd() { - union node *args, **app; - union node *n = NULL; - union node *vars, **vpp; - union node **rpp, *redir; - - args = NULL; - app = &args; - vars = NULL; - vpp = &vars; - redir = NULL; - rpp = &redir; - - checkalias = 2; - for (;;) { - switch (readtoken()) { - case TWORD: - case TASSIGN: - n = (union node *)stalloc(sizeof (struct narg)); - n->type = NARG; - n->narg.text = wordtext; - n->narg.backquote = backquotelist; - if (lasttoken == TWORD) { - *app = n; - app = &n->narg.next; - } else { - *vpp = n; - vpp = &n->narg.next; - } - break; - case TREDIR: - *rpp = n = redirnode; - rpp = &n->nfile.next; - parsefname(); /* read name of redirection file */ - break; - case TLP: - if ( - args && app == &args->narg.next && - !vars && !redir - ) { - /* We have a function */ - if (readtoken() != TRP) - synexpect(TRP); - n->type = NDEFUN; - checkkwd = 2; - n->narg.next = command(); - return n; - } - /* fall through */ - default: - tokpushback++; - goto out; - } - } -out: - *app = NULL; - *vpp = NULL; - *rpp = NULL; - n = (union node *)stalloc(sizeof (struct ncmd)); - n->type = NCMD; - n->ncmd.backgnd = 0; - n->ncmd.args = args; - n->ncmd.assign = vars; - n->ncmd.redirect = redir; - return n; -} - -static union node * -makename(void) { - union node *n; - - n = (union node *)stalloc(sizeof (struct narg)); - n->type = NARG; - n->narg.next = NULL; - n->narg.text = wordtext; - n->narg.backquote = backquotelist; - return n; -} - -static void fixredir(union node *n, const char *text, int err) -{ - TRACE(("Fix redir %s %d\n", text, err)); - if (!err) - n->ndup.vname = NULL; - - if (is_digit(text[0]) && text[1] == '\0') - n->ndup.dupfd = digit_val(text[0]); - else if (text[0] == '-' && text[1] == '\0') - n->ndup.dupfd = -1; - else { - - if (err) - synerror("Bad fd number"); - else - n->ndup.vname = makename(); - } -} - - -static void -parsefname(void) { - union node *n = redirnode; - - if (readtoken() != TWORD) - synexpect(-1); - if (n->type == NHERE) { - struct heredoc *here = heredoc; - struct heredoc *p; - int i; - - if (quoteflag == 0) - n->type = NXHERE; - TRACE(("Here document %d\n", n->type)); - if (here->striptabs) { - while (*wordtext == '\t') - wordtext++; - } - if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN) - synerror("Illegal eof marker for << redirection"); - rmescapes(wordtext); - here->eofmark = wordtext; - here->next = NULL; - if (heredoclist == NULL) - heredoclist = here; - else { - for (p = heredoclist ; p->next ; p = p->next); - p->next = here; - } - } else if (n->type == NTOFD || n->type == NFROMFD) { - fixredir(n, wordtext, 0); - } else { - n->nfile.fname = makename(); - } -} - - -/* - * Input any here documents. - */ - -static void -parseheredoc() { - struct heredoc *here; - union node *n; - - while (heredoclist) { - here = heredoclist; - heredoclist = here->next; - if (needprompt) { - setprompt(2); - needprompt = 0; - } - readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX, - here->eofmark, here->striptabs); - n = (union node *)stalloc(sizeof (struct narg)); - n->narg.type = NARG; - n->narg.next = NULL; - n->narg.text = wordtext; - n->narg.backquote = backquotelist; - here->here->nhere.doc = n; - } -} - -static char -peektoken() { - int t; - - t = readtoken(); - tokpushback++; - return tokname_array[t][0]; -} - -static int -readtoken() { - int t; - -#ifdef ASH_ALIAS - int savecheckalias = checkalias; - int savecheckkwd = checkkwd; - struct alias *ap; -#endif - -#ifdef DEBUG - int alreadyseen = tokpushback; -#endif - -#ifdef ASH_ALIAS -top: -#endif - - t = xxreadtoken(); - -#ifdef ASH_ALIAS - checkalias = savecheckalias; -#endif - - if (checkkwd) { - /* - * eat newlines - */ - if (checkkwd == 2) { - checkkwd = 0; - while (t == TNL) { - parseheredoc(); - t = xxreadtoken(); - } - } - checkkwd = 0; - /* - * check for keywords - */ - if (t == TWORD && !quoteflag) - { - const char *const *pp; - - if ((pp = findkwd(wordtext))) { - lasttoken = t = pp - tokname_array; - TRACE(("keyword %s recognized\n", tokname(t))); - goto out; - } - } - } - - - if (t != TWORD) { - if (t != TREDIR) { - checkalias = 0; - } - } else if (checkalias == 2 && isassignment(wordtext)) { - lasttoken = t = TASSIGN; -#ifdef ASH_ALIAS - } else if (checkalias) { - if (!quoteflag && (ap = lookupalias(wordtext, 1)) != NULL) { - if (*ap->val) { - pushstring(ap->val, strlen(ap->val), ap); - } - checkkwd = savecheckkwd; - goto top; - } - checkalias = 0; -#endif - } -out: -#ifdef DEBUG - if (!alreadyseen) - TRACE(("token %s %s\n", tokname(t), t == TWORD || t == TASSIGN ? wordtext : "")); - else - TRACE(("reread token %s %s\n", tokname(t), t == TWORD || t == TASSIGN ? wordtext : "")); -#endif - return (t); -} - - -/* - * Read the next input token. - * If the token is a word, we set backquotelist to the list of cmds in - * backquotes. We set quoteflag to true if any part of the word was - * quoted. - * If the token is TREDIR, then we set redirnode to a structure containing - * the redirection. - * In all cases, the variable startlinno is set to the number of the line - * on which the token starts. - * - * [Change comment: here documents and internal procedures] - * [Readtoken shouldn't have any arguments. Perhaps we should make the - * word parsing code into a separate routine. In this case, readtoken - * doesn't need to have any internal procedures, but parseword does. - * We could also make parseoperator in essence the main routine, and - * have parseword (readtoken1?) handle both words and redirection.] - */ - -#define NEW_xxreadtoken -#ifdef NEW_xxreadtoken - -static const char xxreadtoken_chars[] = "\n()&|;"; /* singles must be first! */ -static const char xxreadtoken_tokens[] = { - TNL, TLP, TRP, /* only single occurrence allowed */ - TBACKGND, TPIPE, TSEMI, /* if single occurrence */ - TEOF, /* corresponds to trailing nul */ - TAND, TOR, TENDCASE, /* if double occurrence */ -}; - -#define xxreadtoken_doubles \ - (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars)) -#define xxreadtoken_singles \ - (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1) - -static int -xxreadtoken() { - int c; - - if (tokpushback) { - tokpushback = 0; - return lasttoken; - } - if (needprompt) { - setprompt(2); - needprompt = 0; - } - startlinno = plinno; - for (;;) { /* until token or start of word found */ - c = pgetc_macro(); - - if ((c!=' ') && (c!='\t') -#ifdef ASH_ALIAS - && (c!=PEOA) -#endif - ) { - if (c=='#') { - while ((c = pgetc()) != '\n' && c != PEOF); - pungetc(); - } else if (c=='\\') { - if (pgetc() != '\n') { - pungetc(); - goto READTOKEN1; - } - startlinno = ++plinno; - setprompt(doprompt ? 2 : 0); - } else { - const char *p - = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1; - - if (c!=PEOF) { - if (c=='\n') { - plinno++; - needprompt = doprompt; - } - - p = strchr(xxreadtoken_chars, c); - if (p == NULL) { - READTOKEN1: - return readtoken1(c, BASESYNTAX, (char *)NULL, 0); - } - - if (p-xxreadtoken_chars >= xxreadtoken_singles) { - if (pgetc() == *p) { /* double occurrence? */ - p += xxreadtoken_doubles + 1; - } else { - pungetc(); - } - } - } - - return lasttoken = xxreadtoken_tokens[p-xxreadtoken_chars]; - } - } - } -} - - -#else -#define RETURN(token) return lasttoken = token - -static int -xxreadtoken() { - int c; - - if (tokpushback) { - tokpushback = 0; - return lasttoken; - } - if (needprompt) { - setprompt(2); - needprompt = 0; - } - startlinno = plinno; - for (;;) { /* until token or start of word found */ - c = pgetc_macro(); - switch (c) { - case ' ': case '\t': -#ifdef ASH_ALIAS - case PEOA: -#endif - continue; - case '#': - while ((c = pgetc()) != '\n' && c != PEOF); - pungetc(); - continue; - case '\\': - if (pgetc() == '\n') { - startlinno = ++plinno; - if (doprompt) - setprompt(2); - else - setprompt(0); - continue; - } - pungetc(); - goto breakloop; - case '\n': - plinno++; - needprompt = doprompt; - RETURN(TNL); - case PEOF: - RETURN(TEOF); - case '&': - if (pgetc() == '&') - RETURN(TAND); - pungetc(); - RETURN(TBACKGND); - case '|': - if (pgetc() == '|') - RETURN(TOR); - pungetc(); - RETURN(TPIPE); - case ';': - if (pgetc() == ';') - RETURN(TENDCASE); - pungetc(); - RETURN(TSEMI); - case '(': - RETURN(TLP); - case ')': - RETURN(TRP); - default: - goto breakloop; - } - } -breakloop: - return readtoken1(c, BASESYNTAX, (char *)NULL, 0); -#undef RETURN -} -#endif - - -/* - * If eofmark is NULL, read a word or a redirection symbol. If eofmark - * is not NULL, read a here document. In the latter case, eofmark is the - * word which marks the end of the document and striptabs is true if - * leading tabs should be stripped from the document. The argument firstc - * is the first character of the input token or document. - * - * Because C does not have internal subroutines, I have simulated them - * using goto's to implement the subroutine linkage. The following macros - * will run code that appears at the end of readtoken1. - */ - -#define CHECKEND() {goto checkend; checkend_return:;} -#define PARSEREDIR() {goto parseredir; parseredir_return:;} -#define PARSESUB() {goto parsesub; parsesub_return:;} -#define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;} -#define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;} -#define PARSEARITH() {goto parsearith; parsearith_return:;} - -static int -readtoken1(int firstc, int syntax, const char *eofmark, int striptabs) -{ - int c = firstc; - char *out; - int len; - char line[EOFMARKLEN + 1]; - struct nodelist *bqlist; - int quotef; - int dblquote; - int varnest; /* levels of variables expansion */ - int arinest; /* levels of arithmetic expansion */ - int parenlevel; /* levels of parens in arithmetic */ - int dqvarnest; /* levels of variables expansion within double quotes */ - int oldstyle; - int prevsyntax; /* syntax before arithmetic */ -#if __GNUC__ - /* Avoid longjmp clobbering */ - (void) &out; - (void) "ef; - (void) &dblquote; - (void) &varnest; - (void) &arinest; - (void) &parenlevel; - (void) &dqvarnest; - (void) &oldstyle; - (void) &prevsyntax; - (void) &syntax; -#endif - - startlinno = plinno; - dblquote = 0; - if (syntax == DQSYNTAX) - dblquote = 1; - quotef = 0; - bqlist = NULL; - varnest = 0; - arinest = 0; - parenlevel = 0; - dqvarnest = 0; - - STARTSTACKSTR(out); - loop: { /* for each line, until end of word */ - CHECKEND(); /* set c to PEOF if at end of here document */ - for (;;) { /* until end of line or end of word */ - CHECKSTRSPACE(3, out); /* permit 3 calls to USTPUTC */ - switch(SIT(c,syntax)) { - case CNL: /* '\n' */ - if (syntax == BASESYNTAX) - goto endword; /* exit outer loop */ - USTPUTC(c, out); - plinno++; - if (doprompt) - setprompt(2); - else - setprompt(0); - c = pgetc(); - goto loop; /* continue outer loop */ - case CWORD: - USTPUTC(c, out); - break; - case CCTL: - if ((eofmark == NULL || dblquote) && - dqvarnest == 0) - USTPUTC(CTLESC, out); - USTPUTC(c, out); - break; - case CBACK: /* backslash */ - c = pgetc2(); - if (c == PEOF) { - USTPUTC('\\', out); - pungetc(); - } else if (c == '\n') { - if (doprompt) - setprompt(2); - else - setprompt(0); - } else { - if (dblquote && c != '\\' && c != '`' && c != '$' - && (c != '"' || eofmark != NULL)) - USTPUTC('\\', out); - if (SIT(c,SQSYNTAX) == CCTL) - USTPUTC(CTLESC, out); - else if (eofmark == NULL) - USTPUTC(CTLQUOTEMARK, out); - USTPUTC(c, out); - quotef++; - } - break; - case CSQUOTE: - if (eofmark == NULL) - USTPUTC(CTLQUOTEMARK, out); - syntax = SQSYNTAX; - break; - case CDQUOTE: - if (eofmark == NULL) - USTPUTC(CTLQUOTEMARK, out); - syntax = DQSYNTAX; - dblquote = 1; - break; - case CENDQUOTE: - if (eofmark != NULL && arinest == 0 && - varnest == 0) { - USTPUTC(c, out); - } else { - if (arinest) { - syntax = ARISYNTAX; - dblquote = 0; - } else if (eofmark == NULL && - dqvarnest == 0) { - syntax = BASESYNTAX; - dblquote = 0; - } - quotef++; - } - break; - case CVAR: /* '$' */ - PARSESUB(); /* parse substitution */ - break; - case CENDVAR: /* '}' */ - if (varnest > 0) { - varnest--; - if (dqvarnest > 0) { - dqvarnest--; - } - USTPUTC(CTLENDVAR, out); - } else { - USTPUTC(c, out); - } - break; -#ifdef ASH_MATH_SUPPORT - case CLP: /* '(' in arithmetic */ - parenlevel++; - USTPUTC(c, out); - break; - case CRP: /* ')' in arithmetic */ - if (parenlevel > 0) { - USTPUTC(c, out); - --parenlevel; - } else { - if (pgetc() == ')') { - if (--arinest == 0) { - USTPUTC(CTLENDARI, out); - syntax = prevsyntax; - if (syntax == DQSYNTAX) - dblquote = 1; - else - dblquote = 0; - } else - USTPUTC(')', out); - } else { - /* - * unbalanced parens - * (don't 2nd guess - no error) - */ - pungetc(); - USTPUTC(')', out); - } - } - break; -#endif - case CBQUOTE: /* '`' */ - PARSEBACKQOLD(); - break; - case CENDFILE: - goto endword; /* exit outer loop */ - case CIGN: - break; - default: - if (varnest == 0) - goto endword; /* exit outer loop */ -#ifdef ASH_ALIAS - if (c != PEOA) -#endif - USTPUTC(c, out); - - } - c = pgetc_macro(); - } - } -endword: - if (syntax == ARISYNTAX) - synerror("Missing '))'"); - if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL) - synerror("Unterminated quoted string"); - if (varnest != 0) { - startlinno = plinno; - synerror("Missing '}'"); - } - USTPUTC('\0', out); - len = out - stackblock(); - out = stackblock(); - if (eofmark == NULL) { - if ((c == '>' || c == '<') - && quotef == 0 - && len <= 2 - && (*out == '\0' || is_digit(*out))) { - PARSEREDIR(); - return lasttoken = TREDIR; - } else { - pungetc(); - } - } - quoteflag = quotef; - backquotelist = bqlist; - grabstackblock(len); - wordtext = out; - return lasttoken = TWORD; -/* end of readtoken routine */ - - - -/* - * Check to see whether we are at the end of the here document. When this - * is called, c is set to the first character of the next input line. If - * we are at the end of the here document, this routine sets the c to PEOF. - */ - -checkend: { - if (eofmark) { -#ifdef ASH_ALIAS - if (c == PEOA) { - c = pgetc2(); - } -#endif - if (striptabs) { - while (c == '\t') { - c = pgetc2(); - } - } - if (c == *eofmark) { - if (pfgets(line, sizeof line) != NULL) { - const char *p, *q; - - p = line; - for (q = eofmark + 1 ; *q && *p == *q ; p++, q++); - if (*p == '\n' && *q == '\0') { - c = PEOF; - plinno++; - needprompt = doprompt; - } else { - pushstring(line, strlen(line), NULL); - } - } - } - } - goto checkend_return; -} - - -/* - * Parse a redirection operator. The variable "out" points to a string - * specifying the fd to be redirected. The variable "c" contains the - * first character of the redirection operator. - */ - -parseredir: { - char fd = *out; - union node *np; - - np = (union node *)stalloc(sizeof (struct nfile)); - if (c == '>') { - np->nfile.fd = 1; - c = pgetc(); - if (c == '>') - np->type = NAPPEND; - else if (c == '&') - np->type = NTOFD; - else if (c == '|') - np->type = NTOOV; - else { - np->type = NTO; - pungetc(); - } - } else { /* c == '<' */ - np->nfile.fd = 0; - switch (c = pgetc()) { - case '<': - if (sizeof (struct nfile) != sizeof (struct nhere)) { - np = (union node *)stalloc(sizeof (struct nhere)); - np->nfile.fd = 0; - } - np->type = NHERE; - heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc)); - heredoc->here = np; - if ((c = pgetc()) == '-') { - heredoc->striptabs = 1; - } else { - heredoc->striptabs = 0; - pungetc(); - } - break; - - case '&': - np->type = NFROMFD; - break; - - case '>': - np->type = NFROMTO; - break; - - default: - np->type = NFROM; - pungetc(); - break; - } - } - if (fd != '\0') - np->nfile.fd = digit_val(fd); - redirnode = np; - goto parseredir_return; -} - - -/* - * Parse a substitution. At this point, we have read the dollar sign - * and nothing else. - */ - -parsesub: { - int subtype; - int typeloc; - int flags; - char *p; - static const char types[] = "}-+?="; - - c = pgetc(); - if ( - c <= PEOA || - (c != '(' && c != '{' && !is_name(c) && !is_special(c)) - ) { - USTPUTC('$', out); - pungetc(); - } else if (c == '(') { /* $(command) or $((arith)) */ - if (pgetc() == '(') { - PARSEARITH(); - } else { - pungetc(); - PARSEBACKQNEW(); - } - } else { - USTPUTC(CTLVAR, out); - typeloc = out - stackblock(); - USTPUTC(VSNORMAL, out); - subtype = VSNORMAL; - if (c == '{') { - c = pgetc(); - if (c == '#') { - if ((c = pgetc()) == '}') - c = '#'; - else - subtype = VSLENGTH; - } - else - subtype = 0; - } - if (c > PEOA && is_name(c)) { - do { - STPUTC(c, out); - c = pgetc(); - } while (c > PEOA && is_in_name(c)); - } else if (is_digit(c)) { - do { - USTPUTC(c, out); - c = pgetc(); - } while (is_digit(c)); - } - else if (is_special(c)) { - USTPUTC(c, out); - c = pgetc(); - } - else -badsub: synerror("Bad substitution"); - - STPUTC('=', out); - flags = 0; - if (subtype == 0) { - switch (c) { - case ':': - flags = VSNUL; - c = pgetc(); - /*FALLTHROUGH*/ - default: - p = strchr(types, c); - if (p == NULL) - goto badsub; - subtype = p - types + VSNORMAL; - break; - case '%': - case '#': - { - int cc = c; - subtype = c == '#' ? VSTRIMLEFT : - VSTRIMRIGHT; - c = pgetc(); - if (c == cc) - subtype++; - else - pungetc(); - break; - } - } - } else { - pungetc(); - } - if (dblquote || arinest) - flags |= VSQUOTE; - *(stackblock() + typeloc) = subtype | flags; - if (subtype != VSNORMAL) { - varnest++; - if (dblquote) { - dqvarnest++; - } - } - } - goto parsesub_return; -} - - -/* - * Called to parse command substitutions. Newstyle is set if the command - * is enclosed inside $(...); nlpp is a pointer to the head of the linked - * list of commands (passed by reference), and savelen is the number of - * characters on the top of the stack which must be preserved. - */ - -parsebackq: { - struct nodelist **nlpp; - int savepbq; - union node *n; - char *volatile str; - struct jmploc jmploc; - struct jmploc *volatile savehandler; - int savelen; - int saveprompt; -#ifdef __GNUC__ - (void) &saveprompt; -#endif - - savepbq = parsebackquote; - if (setjmp(jmploc.loc)) { - if (str) - ckfree(str); - parsebackquote = 0; - handler = savehandler; - longjmp(handler->loc, 1); - } - INTOFF; - str = NULL; - savelen = out - stackblock(); - if (savelen > 0) { - str = ckmalloc(savelen); - memcpy(str, stackblock(), savelen); - } - savehandler = handler; - handler = &jmploc; - INTON; - if (oldstyle) { - /* We must read until the closing backquote, giving special - treatment to some slashes, and then push the string and - reread it as input, interpreting it normally. */ - char *pout; - int pc; - int psavelen; - char *pstr; - - - STARTSTACKSTR(pout); - for (;;) { - if (needprompt) { - setprompt(2); - needprompt = 0; - } - switch (pc = pgetc()) { - case '`': - goto done; - - case '\\': - if ((pc = pgetc()) == '\n') { - plinno++; - if (doprompt) - setprompt(2); - else - setprompt(0); - /* - * If eating a newline, avoid putting - * the newline into the new character - * stream (via the STPUTC after the - * switch). - */ - continue; - } - if (pc != '\\' && pc != '`' && pc != '$' - && (!dblquote || pc != '"')) - STPUTC('\\', pout); - if (pc > PEOA) { - break; - } - /* fall through */ - - case PEOF: -#ifdef ASH_ALIAS - case PEOA: -#endif - startlinno = plinno; - synerror("EOF in backquote substitution"); - - case '\n': - plinno++; - needprompt = doprompt; - break; - - default: - break; - } - STPUTC(pc, pout); - } -done: - STPUTC('\0', pout); - psavelen = pout - stackblock(); - if (psavelen > 0) { - pstr = grabstackstr(pout); - setinputstring(pstr); - } - } - nlpp = &bqlist; - while (*nlpp) - nlpp = &(*nlpp)->next; - *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist)); - (*nlpp)->next = NULL; - parsebackquote = oldstyle; - - if (oldstyle) { - saveprompt = doprompt; - doprompt = 0; - } - - n = list(0); - - if (oldstyle) - doprompt = saveprompt; - else { - if (readtoken() != TRP) - synexpect(TRP); - } - - (*nlpp)->n = n; - if (oldstyle) { - /* - * Start reading from old file again, ignoring any pushed back - * tokens left from the backquote parsing - */ - popfile(); - tokpushback = 0; - } - while (stackblocksize() <= savelen) - growstackblock(); - STARTSTACKSTR(out); - if (str) { - memcpy(out, str, savelen); - STADJUST(savelen, out); - INTOFF; - ckfree(str); - str = NULL; - INTON; - } - parsebackquote = savepbq; - handler = savehandler; - if (arinest || dblquote) - USTPUTC(CTLBACKQ | CTLQUOTE, out); - else - USTPUTC(CTLBACKQ, out); - if (oldstyle) - goto parsebackq_oldreturn; - else - goto parsebackq_newreturn; -} - -/* - * Parse an arithmetic expansion (indicate start of one and set state) - */ -parsearith: { - - if (++arinest == 1) { - prevsyntax = syntax; - syntax = ARISYNTAX; - USTPUTC(CTLARI, out); - if (dblquote) - USTPUTC('"',out); - else - USTPUTC(' ',out); - } else { - /* - * we collapse embedded arithmetic expansion to - * parenthesis, which should be equivalent - */ - USTPUTC('(', out); - } - goto parsearith_return; -} - -} /* end of readtoken */ - - -/* - * Returns true if the text contains nothing to expand (no dollar signs - * or backquotes). - */ - -static int -noexpand(text) - char *text; - { - char *p; - char c; - - p = text; - while ((c = *p++) != '\0') { - if (c == CTLQUOTEMARK) - continue; - if (c == CTLESC) - p++; - else if (SIT(c,BASESYNTAX) == CCTL) - return 0; - } - return 1; -} - - -/* - * Return true if the argument is a legal variable name (a letter or - * underscore followed by zero or more letters, underscores, and digits). - */ - -static int -goodname(const char *name) -{ - const char *p; - - p = name; - if (! is_name(*p)) - return 0; - while (*++p) { - if (! is_in_name(*p)) - return 0; - } - return 1; -} - - -/* - * Called when an unexpected token is read during the parse. The argument - * is the token that is expected, or -1 if more than one type of token can - * occur at this point. - */ - -static void -synexpect(token) - int token; -{ - char msg[64]; - int l; - - l = sprintf(msg, "%s unexpected", tokname(lasttoken)); - if (token >= 0) - sprintf(msg+l, " (expecting %s)", tokname(token)); - synerror(msg); - /* NOTREACHED */ -} - - -static void -synerror(const char *msg) -{ - if (commandname) - out2fmt("%s: %d: ", commandname, startlinno); - out2fmt("Syntax error: %s\n", msg); - error((char *)NULL); - /* NOTREACHED */ -} - - -/* - * called by editline -- any expansions to the prompt - * should be added here. - */ -static void -setprompt(int whichprompt) -{ - char *prompt; - switch (whichprompt) { - case 1: - prompt = ps1val(); - break; - case 2: - prompt = ps2val(); - break; - default: /* 0 */ - prompt = ""; - } - putprompt(prompt); -} - - -/* - * Code for dealing with input/output redirection. - */ - -#define EMPTY -2 /* marks an unused slot in redirtab */ -#ifndef PIPE_BUF -# define PIPESIZE 4096 /* amount of buffering in a pipe */ -#else -# define PIPESIZE PIPE_BUF -#endif - - -/* - * Open a file in noclobber mode. - * The code was copied from bash. - */ -static inline int -noclobberopen(const char *fname) -{ - int r, fd; - struct stat finfo, finfo2; - - /* - * If the file exists and is a regular file, return an error - * immediately. - */ - r = stat(fname, &finfo); - if (r == 0 && S_ISREG(finfo.st_mode)) { - errno = EEXIST; - return -1; - } - - /* - * If the file was not present (r != 0), make sure we open it - * exclusively so that if it is created before we open it, our open - * will fail. Make sure that we do not truncate an existing file. - * Note that we don't turn on O_EXCL unless the stat failed -- if the - * file was not a regular file, we leave O_EXCL off. - */ - if (r != 0) - return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666); - fd = open(fname, O_WRONLY|O_CREAT, 0666); - - /* If the open failed, return the file descriptor right away. */ - if (fd < 0) - return fd; - - /* - * OK, the open succeeded, but the file may have been changed from a - * non-regular file to a regular file between the stat and the open. - * We are assuming that the O_EXCL open handles the case where FILENAME - * did not exist and is symlinked to an existing file between the stat - * and open. - */ - - /* - * If we can open it and fstat the file descriptor, and neither check - * revealed that it was a regular file, and the file has not been - * replaced, return the file descriptor. - */ - if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) && - finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino) - return fd; - - /* The file has been replaced. badness. */ - close(fd); - errno = EEXIST; - return -1; -} - -/* - * Handle here documents. Normally we fork off a process to write the - * data to a pipe. If the document is short, we can stuff the data in - * the pipe without forking. - */ - -static inline int -openhere(const union node *redir) -{ - int pip[2]; - int len = 0; - - if (pipe(pip) < 0) - error("Pipe call failed"); - if (redir->type == NHERE) { - len = strlen(redir->nhere.doc->narg.text); - if (len <= PIPESIZE) { - xwrite(pip[1], redir->nhere.doc->narg.text, len); - goto out; - } - } - if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) { - close(pip[0]); - signal(SIGINT, SIG_IGN); - signal(SIGQUIT, SIG_IGN); - signal(SIGHUP, SIG_IGN); -#ifdef SIGTSTP - signal(SIGTSTP, SIG_IGN); -#endif - signal(SIGPIPE, SIG_DFL); - if (redir->type == NHERE) - xwrite(pip[1], redir->nhere.doc->narg.text, len); - else - expandhere(redir->nhere.doc, pip[1]); - _exit(0); - } -out: - close(pip[1]); - return pip[0]; -} - - -static inline int -openredirect(const union node *redir) -{ - char *fname; - int f; - - switch (redir->nfile.type) { - case NFROM: - fname = redir->nfile.expfname; - if ((f = open(fname, O_RDONLY)) < 0) - goto eopen; - break; - case NFROMTO: - fname = redir->nfile.expfname; - if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0) - goto ecreate; - break; - case NTO: - /* Take care of noclobber mode. */ - if (Cflag) { - fname = redir->nfile.expfname; - if ((f = noclobberopen(fname)) < 0) - goto ecreate; - break; - } - case NTOOV: - fname = redir->nfile.expfname; -#ifdef O_CREAT - if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) - goto ecreate; -#else - if ((f = creat(fname, 0666)) < 0) - goto ecreate; -#endif - break; - case NAPPEND: - fname = redir->nfile.expfname; -#ifdef O_APPEND - if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0) - goto ecreate; -#else - if ((f = open(fname, O_WRONLY)) < 0 - && (f = creat(fname, 0666)) < 0) - goto ecreate; - lseek(f, (off_t)0, 2); -#endif - break; - default: -#ifdef DEBUG - abort(); -#endif - /* Fall through to eliminate warning. */ - case NTOFD: - case NFROMFD: - f = -1; - break; - case NHERE: - case NXHERE: - f = openhere(redir); - break; - } - - return f; -ecreate: - error("cannot create %s: %s", fname, errmsg(errno, E_CREAT)); -eopen: - error("cannot open %s: %s", fname, errmsg(errno, E_OPEN)); -} - - -/* - * Process a list of redirection commands. If the REDIR_PUSH flag is set, - * old file descriptors are stashed away so that the redirection can be - * undone by calling popredir. If the REDIR_BACKQ flag is set, then the - * standard output, and the standard error if it becomes a duplicate of - * stdout. - */ - -static void -redirect(union node *redir, int flags) -{ - union node *n; - struct redirtab *sv = NULL; - int i; - int fd; - int newfd; - int try; - int fd1dup = flags & REDIR_BACKQ;; /* stdout `cmd` redir to pipe */ - - if (flags & REDIR_PUSH) { - sv = ckmalloc(sizeof (struct redirtab)); - for (i = 0 ; i < 10 ; i++) - sv->renamed[i] = EMPTY; - sv->next = redirlist; - redirlist = sv; - } - for (n = redir ; n ; n = n->nfile.next) { - fd = n->nfile.fd; - try = 0; - if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) && - n->ndup.dupfd == fd) - continue; /* redirect from/to same file descriptor */ - - INTOFF; - newfd = openredirect(n); - if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) { - if (newfd == fd) { - try++; - } else if ((i = fcntl(fd, F_DUPFD, 10)) == -1) { - switch (errno) { - case EBADF: - if (!try) { - dupredirect(n, newfd, fd1dup); - try++; - break; - } - /* FALLTHROUGH*/ - default: - if (newfd >= 0) { - close(newfd); - } - INTON; - error("%d: %m", fd); - /* NOTREACHED */ - } - } - if (!try) { - close(fd); - if (flags & REDIR_PUSH) { - sv->renamed[fd] = i; - } - } - } else if (fd != newfd) { - close(fd); - } - if (fd == 0) - fd0_redirected++; - if (!try) - dupredirect(n, newfd, fd1dup); - INTON; - } -} - - -static void -dupredirect(const union node *redir, int f, int fd1dup) -{ - int fd = redir->nfile.fd; - - if(fd==1) - fd1dup = 0; - if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) { - if (redir->ndup.dupfd >= 0) { /* if not ">&-" */ - if (redir->ndup.dupfd!=1 || fd1dup!=1) - dup_as_newfd(redir->ndup.dupfd, fd); - } - return; - } - - if (f != fd) { - dup_as_newfd(f, fd); - close(f); - } - return; -} - - - -/* - * Undo the effects of the last redirection. - */ - -static void -popredir(void) -{ - struct redirtab *rp = redirlist; - int i; - - INTOFF; - for (i = 0 ; i < 10 ; i++) { - if (rp->renamed[i] != EMPTY) { - if (i == 0) - fd0_redirected--; - close(i); - if (rp->renamed[i] >= 0) { - dup_as_newfd(rp->renamed[i], i); - close(rp->renamed[i]); - } - } - } - redirlist = rp->next; - ckfree(rp); - INTON; -} - -/* - * Discard all saved file descriptors. - */ - -static void -clearredir(void) { - struct redirtab *rp; - int i; - - for (rp = redirlist ; rp ; rp = rp->next) { - for (i = 0 ; i < 10 ; i++) { - if (rp->renamed[i] >= 0) { - close(rp->renamed[i]); - } - rp->renamed[i] = EMPTY; - } - } -} - - -/* - * Copy a file descriptor to be >= to. Returns -1 - * if the source file descriptor is closed, EMPTY if there are no unused - * file descriptors left. - */ - -static int -dup_as_newfd(from, to) - int from; - int to; -{ - int newfd; - - newfd = fcntl(from, F_DUPFD, to); - if (newfd < 0) { - if (errno == EMFILE) - return EMPTY; - else - error("%d: %m", from); - } - return newfd; -} - -#ifdef DEBUG -static void shtree (union node *, int, char *, FILE*); -static void shcmd (union node *, FILE *); -static void sharg (union node *, FILE *); -static void indent (int, char *, FILE *); -static void trstring (char *); - - -static void -showtree(n) - union node *n; -{ - trputs("showtree called\n"); - shtree(n, 1, NULL, stdout); -} - - -static void -shtree(n, ind, pfx, fp) - union node *n; - int ind; - char *pfx; - FILE *fp; -{ - struct nodelist *lp; - const char *s; - - if (n == NULL) - return; - - indent(ind, pfx, fp); - switch(n->type) { - case NSEMI: - s = "; "; - goto binop; - case NAND: - s = " && "; - goto binop; - case NOR: - s = " || "; -binop: - shtree(n->nbinary.ch1, ind, NULL, fp); - /* if (ind < 0) */ - fputs(s, fp); - shtree(n->nbinary.ch2, ind, NULL, fp); - break; - case NCMD: - shcmd(n, fp); - if (ind >= 0) - putc('\n', fp); - break; - case NPIPE: - for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { - shcmd(lp->n, fp); - if (lp->next) - fputs(" | ", fp); - } - if (n->npipe.backgnd) - fputs(" &", fp); - if (ind >= 0) - putc('\n', fp); - break; - default: - fprintf(fp, "", n->type); - if (ind >= 0) - putc('\n', fp); - break; - } -} - - - -static void -shcmd(cmd, fp) - union node *cmd; - FILE *fp; -{ - union node *np; - int first; - const char *s; - int dftfd; - - first = 1; - for (np = cmd->ncmd.args ; np ; np = np->narg.next) { - if (! first) - putchar(' '); - sharg(np, fp); - first = 0; - } - for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) { - if (! first) - putchar(' '); -#if 1 - s = "*error*"; - dftfd = 0; - if ((np->nfile.type <= NFROMFD) && (np->nfile.type >= NTO)) { - s = redir_strings[np->nfile.type - NTO]; - if (*s == '>') { - dftfd = 1; - } - } -#else - switch (np->nfile.type) { - case NTO: s = ">"; dftfd = 1; break; - case NAPPEND: s = ">>"; dftfd = 1; break; - case NTOFD: s = ">&"; dftfd = 1; break; - case NTOOV: s = ">|"; dftfd = 1; break; - case NFROM: s = "<"; dftfd = 0; break; - case NFROMFD: s = "<&"; dftfd = 0; break; - case NFROMTO: s = "<>"; dftfd = 0; break; - default: s = "*error*"; dftfd = 0; break; - } -#endif - if (np->nfile.fd != dftfd) - fprintf(fp, "%d", np->nfile.fd); - fputs(s, fp); - if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) { - fprintf(fp, "%d", np->ndup.dupfd); - } else { - sharg(np->nfile.fname, fp); - } - first = 0; - } -} - - - -static void -sharg(arg, fp) - union node *arg; - FILE *fp; - { - char *p; - struct nodelist *bqlist; - int subtype; - - if (arg->type != NARG) { - printf("\n", arg->type); - fflush(stdout); - abort(); - } - bqlist = arg->narg.backquote; - for (p = arg->narg.text ; *p ; p++) { - switch (*p) { - case CTLESC: - putc(*++p, fp); - break; - case CTLVAR: - putc('$', fp); - putc('{', fp); - subtype = *++p; - if (subtype == VSLENGTH) - putc('#', fp); - - while (*p != '=') - putc(*p++, fp); - - if (subtype & VSNUL) - putc(':', fp); - - switch (subtype & VSTYPE) { - case VSNORMAL: - putc('}', fp); - break; - case VSMINUS: - putc('-', fp); - break; - case VSPLUS: - putc('+', fp); - break; - case VSQUESTION: - putc('?', fp); - break; - case VSASSIGN: - putc('=', fp); - break; - case VSTRIMLEFT: - putc('#', fp); - break; - case VSTRIMLEFTMAX: - putc('#', fp); - putc('#', fp); - break; - case VSTRIMRIGHT: - putc('%', fp); - break; - case VSTRIMRIGHTMAX: - putc('%', fp); - putc('%', fp); - break; - case VSLENGTH: - break; - default: - printf("", subtype); - } - break; - case CTLENDVAR: - putc('}', fp); - break; - case CTLBACKQ: - case CTLBACKQ|CTLQUOTE: - putc('$', fp); - putc('(', fp); - shtree(bqlist->n, -1, NULL, fp); - putc(')', fp); - break; - default: - putc(*p, fp); - break; - } - } -} - - -static void -indent(amount, pfx, fp) - int amount; - char *pfx; - FILE *fp; -{ - int i; - - for (i = 0 ; i < amount ; i++) { - if (pfx && i == amount - 1) - fputs(pfx, fp); - putc('\t', fp); - } -} -#endif - - - -/* - * Debugging stuff. - */ - - -#ifdef DEBUG -FILE *tracefile; - -#if DEBUG == 2 -static int debug = 1; -#else -static int debug = 0; -#endif - - -static void -trputc(c) - int c; -{ - if (tracefile == NULL) - return; - putc(c, tracefile); - if (c == '\n') - fflush(tracefile); -} - -static void -trace(const char *fmt, ...) -{ - va_list va; - va_start(va, fmt); - if (tracefile != NULL) { - (void) vfprintf(tracefile, fmt, va); - if (strchr(fmt, '\n')) - (void) fflush(tracefile); - } - va_end(va); -} - - -static void -trputs(s) - const char *s; -{ - if (tracefile == NULL) - return; - fputs(s, tracefile); - if (strchr(s, '\n')) - fflush(tracefile); -} - - -static void -trstring(s) - char *s; -{ - char *p; - char c; - - if (tracefile == NULL) - return; - putc('"', tracefile); - for (p = s ; *p ; p++) { - switch (*p) { - case '\n': c = 'n'; goto backslash; - case '\t': c = 't'; goto backslash; - case '\r': c = 'r'; goto backslash; - case '"': c = '"'; goto backslash; - case '\\': c = '\\'; goto backslash; - case CTLESC: c = 'e'; goto backslash; - case CTLVAR: c = 'v'; goto backslash; - case CTLVAR+CTLQUOTE: c = 'V'; goto backslash; - case CTLBACKQ: c = 'q'; goto backslash; - case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash; -backslash: putc('\\', tracefile); - putc(c, tracefile); - break; - default: - if (*p >= ' ' && *p <= '~') - putc(*p, tracefile); - else { - putc('\\', tracefile); - putc(*p >> 6 & 03, tracefile); - putc(*p >> 3 & 07, tracefile); - putc(*p & 07, tracefile); - } - break; - } - } - putc('"', tracefile); -} - - -static void -trargs(ap) - char **ap; -{ - if (tracefile == NULL) - return; - while (*ap) { - trstring(*ap++); - if (*ap) - putc(' ', tracefile); - else - putc('\n', tracefile); - } - fflush(tracefile); -} - - -static void -opentrace() { - char s[100]; -#ifdef O_APPEND - int flags; -#endif - - if (!debug) - return; -#ifdef not_this_way - { - char *p; - if ((p = getenv("HOME")) == NULL) { - if (geteuid() == 0) - p = "/"; - else - p = "/tmp"; - } - strcpy(s, p); - strcat(s, "/trace"); - } -#else - strcpy(s, "./trace"); -#endif /* not_this_way */ - if ((tracefile = fopen(s, "a")) == NULL) { - fprintf(stderr, "Can't open %s\n", s); - return; - } -#ifdef O_APPEND - if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0) - fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND); -#endif - fputs("\nTracing started.\n", tracefile); - fflush(tracefile); -} -#endif /* DEBUG */ - - -/* - * The trap builtin. - */ - -static int -trapcmd(argc, argv) - int argc; - char **argv; -{ - char *action; - char **ap; - int signo; - - if (argc <= 1) { - for (signo = 0 ; signo < NSIG ; signo++) { - if (trap[signo] != NULL) { - char *p; - const char *sn; - - p = single_quote(trap[signo]); - sn = sys_siglist[signo]; - if(sn==NULL) - sn = u_signal_names(0, &signo, 0); - if(sn==NULL) - sn = "???"; - printf("trap -- %s %s\n", p, sn); - stunalloc(p); - } - } - return 0; - } - ap = argv + 1; - if (argc == 2) - action = NULL; - else - action = *ap++; - while (*ap) { - if ((signo = decode_signal(*ap, 0)) < 0) - error("%s: bad trap", *ap); - INTOFF; - if (action) { - if (action[0] == '-' && action[1] == '\0') - action = NULL; - else - action = savestr(action); - } - if (trap[signo]) - ckfree(trap[signo]); - trap[signo] = action; - if (signo != 0) - setsignal(signo); - INTON; - ap++; - } - return 0; -} - - - - - - -/* - * Set the signal handler for the specified signal. The routine figures - * out what it should be set to. - */ - -static void -setsignal(int signo) -{ - int action; - char *t; - struct sigaction act; - - if ((t = trap[signo]) == NULL) - action = S_DFL; - else if (*t != '\0') - action = S_CATCH; - else - action = S_IGN; - if (rootshell && action == S_DFL) { - switch (signo) { - case SIGINT: - if (iflag || minusc || sflag == 0) - action = S_CATCH; - break; - case SIGQUIT: -#ifdef DEBUG - { - - if (debug) - break; - } -#endif - /* FALLTHROUGH */ - case SIGTERM: - if (iflag) - action = S_IGN; - break; -#ifdef JOBS - case SIGTSTP: - case SIGTTOU: - if (mflag) - action = S_IGN; - break; -#endif - } - } - - t = &sigmode[signo - 1]; - if (*t == 0) { - /* - * current setting unknown - */ - if (sigaction(signo, 0, &act) == -1) { - /* - * Pretend it worked; maybe we should give a warning - * here, but other shells don't. We don't alter - * sigmode, so that we retry every time. - */ - return; - } - if (act.sa_handler == SIG_IGN) { - if (mflag && (signo == SIGTSTP || - signo == SIGTTIN || signo == SIGTTOU)) { - *t = S_IGN; /* don't hard ignore these */ - } else - *t = S_HARD_IGN; - } else { - *t = S_RESET; /* force to be set */ - } - } - if (*t == S_HARD_IGN || *t == action) - return; - act.sa_handler = ((action == S_CATCH) ? onsig - : ((action == S_IGN) ? SIG_IGN : SIG_DFL)); - *t = action; - act.sa_flags = 0; - sigemptyset(&act.sa_mask); - sigaction(signo, &act, 0); -} - -/* - * Ignore a signal. - */ - -static void -ignoresig(signo) - int signo; -{ - if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) { - signal(signo, SIG_IGN); - } - sigmode[signo - 1] = S_HARD_IGN; -} - - -/* - * Signal handler. - */ - -static void -onsig(int signo) -{ - if (signo == SIGINT && trap[SIGINT] == NULL) { - onint(); - return; - } - gotsig[signo - 1] = 1; - pendingsigs++; -} - - -/* - * Called to execute a trap. Perhaps we should avoid entering new trap - * handlers while we are executing a trap handler. - */ - -static void -dotrap(void) -{ - int i; - int savestatus; - - for (;;) { - for (i = 1 ; ; i++) { - if (gotsig[i - 1]) - break; - if (i >= NSIG - 1) - goto done; - } - gotsig[i - 1] = 0; - savestatus=exitstatus; - evalstring(trap[i], 0); - exitstatus=savestatus; - } -done: - pendingsigs = 0; -} - -/* - * Called to exit the shell. - */ - -static void -exitshell(int status) -{ - struct jmploc loc1, loc2; - char *p; - - TRACE(("exitshell(%d) pid=%d\n", status, getpid())); - if (setjmp(loc1.loc)) { - goto l1; - } - if (setjmp(loc2.loc)) { - goto l2; - } - handler = &loc1; - if ((p = trap[0]) != NULL && *p != '\0') { - trap[0] = NULL; - evalstring(p, 0); - } -l1: handler = &loc2; /* probably unnecessary */ - flushall(); -#ifdef JOBS - setjobctl(0); -#endif -l2: _exit(status); - /* NOTREACHED */ -} - -static int decode_signal(const char *string, int minsig) -{ - int signo; - const char *name = u_signal_names(string, &signo, minsig); - - return name ? signo : -1; -} - -static struct var **hashvar (const char *); -static void showvars (const char *, int, int); -static struct var **findvar (struct var **, const char *); - -/* - * Initialize the varable symbol tables and import the environment - */ - -/* - * This routine initializes the builtin variables. It is called when the - * shell is initialized and again when a shell procedure is spawned. - */ - -static void -initvar() { - const struct varinit *ip; - struct var *vp; - struct var **vpp; - - for (ip = varinit ; (vp = ip->var) != NULL ; ip++) { - if ((vp->flags & VEXPORT) == 0) { - vpp = hashvar(ip->text); - vp->next = *vpp; - *vpp = vp; - vp->text = strdup(ip->text); - vp->flags = ip->flags; - vp->func = ip->func; - } - } - /* - * PS1 depends on uid - */ - if ((vps1.flags & VEXPORT) == 0) { - vpp = hashvar("PS1="); - vps1.next = *vpp; - *vpp = &vps1; - vps1.text = strdup(geteuid() ? "PS1=$ " : "PS1=# "); - vps1.flags = VSTRFIXED|VTEXTFIXED; - } -} - -/* - * Set the value of a variable. The flags argument is ored with the - * flags of the variable. If val is NULL, the variable is unset. - */ - -static void -setvar(name, val, flags) - const char *name, *val; - int flags; -{ - const char *p; - int len; - int namelen; - char *nameeq; - int isbad; - int vallen = 0; - - isbad = 0; - p = name; - if (! is_name(*p)) - isbad = 1; - p++; - for (;;) { - if (! is_in_name(*p)) { - if (*p == '\0' || *p == '=') - break; - isbad = 1; - } - p++; - } - namelen = p - name; - if (isbad) - error("%.*s: bad variable name", namelen, name); - len = namelen + 2; /* 2 is space for '=' and '\0' */ - if (val == NULL) { - flags |= VUNSET; - } else { - len += vallen = strlen(val); - } - INTOFF; - nameeq = ckmalloc(len); - memcpy(nameeq, name, namelen); - nameeq[namelen] = '='; - if (val) { - memcpy(nameeq + namelen + 1, val, vallen + 1); - } else { - nameeq[namelen + 1] = '\0'; - } - setvareq(nameeq, flags); - INTON; -} - - - -/* - * Same as setvar except that the variable and value are passed in - * the first argument as name=value. Since the first argument will - * be actually stored in the table, it should not be a string that - * will go away. - */ - -static void -setvareq(s, flags) - char *s; - int flags; -{ - struct var *vp, **vpp; - - vpp = hashvar(s); - flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1)); - if ((vp = *findvar(vpp, s))) { - if (vp->flags & VREADONLY) { - size_t len = strchr(s, '=') - s; - error("%.*s: is read only", len, s); - } - INTOFF; - - if (vp->func && (flags & VNOFUNC) == 0) - (*vp->func)(strchr(s, '=') + 1); - - if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0) - ckfree(vp->text); - - vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET); - vp->flags |= flags; - vp->text = s; - - /* - * We could roll this to a function, to handle it as - * a regular variable function callback, but why bother? - */ - if (iflag && (vp == &vmpath || (vp == &vmail && !mpathset()))) - chkmail(1); - INTON; - return; - } - /* not found */ - vp = ckmalloc(sizeof (*vp)); - vp->flags = flags; - vp->text = s; - vp->next = *vpp; - vp->func = NULL; - *vpp = vp; -} - - - -/* - * Process a linked list of variable assignments. - */ - -static void -listsetvar(mylist) - struct strlist *mylist; - { - struct strlist *lp; - - INTOFF; - for (lp = mylist ; lp ; lp = lp->next) { - setvareq(savestr(lp->text), 0); - } - INTON; -} - - - -/* - * Find the value of a variable. Returns NULL if not set. - */ - -static const char * -lookupvar(name) - const char *name; - { - struct var *v; - - if ((v = *findvar(hashvar(name), name)) && !(v->flags & VUNSET)) { - return strchr(v->text, '=') + 1; - } - return NULL; -} - - - -/* - * Search the environment of a builtin command. - */ - -static const char * -bltinlookup(const char *name) -{ - const struct strlist *sp; - - for (sp = cmdenviron ; sp ; sp = sp->next) { - if (varequal(sp->text, name)) - return strchr(sp->text, '=') + 1; - } - return lookupvar(name); -} - - - -/* - * Generate a list of exported variables. This routine is used to construct - * the third argument to execve when executing a program. - */ - -static char ** -environment() { - int nenv; - struct var **vpp; - struct var *vp; - char **env; - char **ep; - - nenv = 0; - for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { - for (vp = *vpp ; vp ; vp = vp->next) - if (vp->flags & VEXPORT) - nenv++; - } - ep = env = stalloc((nenv + 1) * sizeof *env); - for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { - for (vp = *vpp ; vp ; vp = vp->next) - if (vp->flags & VEXPORT) - *ep++ = vp->text; - } - *ep = NULL; - return env; -} - - -/* - * Called when a shell procedure is invoked to clear out nonexported - * variables. It is also necessary to reallocate variables of with - * VSTACK set since these are currently allocated on the stack. - */ - -static void -shprocvar(void) { - struct var **vpp; - struct var *vp, **prev; - - for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { - for (prev = vpp ; (vp = *prev) != NULL ; ) { - if ((vp->flags & VEXPORT) == 0) { - *prev = vp->next; - if ((vp->flags & VTEXTFIXED) == 0) - ckfree(vp->text); - if ((vp->flags & VSTRFIXED) == 0) - ckfree(vp); - } else { - if (vp->flags & VSTACK) { - vp->text = savestr(vp->text); - vp->flags &=~ VSTACK; - } - prev = &vp->next; - } - } - } - initvar(); -} - - - -/* - * Command to list all variables which are set. Currently this command - * is invoked from the set command when the set command is called without - * any variables. - */ - -static int -showvarscmd(argc, argv) - int argc; - char **argv; -{ - showvars(nullstr, VUNSET, VUNSET); - return 0; -} - - - -/* - * The export and readonly commands. - */ - -static int -exportcmd(argc, argv) - int argc; - char **argv; -{ - struct var *vp; - char *name; - const char *p; - int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT; - int pflag; - - listsetvar(cmdenviron); - pflag = (nextopt("p") == 'p'); - if (argc > 1 && !pflag) { - while ((name = *argptr++) != NULL) { - if ((p = strchr(name, '=')) != NULL) { - p++; - } else { - if ((vp = *findvar(hashvar(name), name))) { - vp->flags |= flag; - goto found; - } - } - setvar(name, p, flag); -found:; - } - } else { - showvars(argv[0], flag, 0); - } - return 0; -} - - -/* - * The "local" command. - */ - -/* funcnest nonzero if we are currently evaluating a function */ - -static int -localcmd(argc, argv) - int argc; - char **argv; -{ - char *name; - - if (! funcnest) - error("Not in a function"); - while ((name = *argptr++) != NULL) { - mklocal(name); - } - return 0; -} - - -/* - * Make a variable a local variable. When a variable is made local, it's - * value and flags are saved in a localvar structure. The saved values - * will be restored when the shell function returns. We handle the name - * "-" as a special case. - */ - -static void -mklocal(name) - char *name; - { - struct localvar *lvp; - struct var **vpp; - struct var *vp; - - INTOFF; - lvp = ckmalloc(sizeof (struct localvar)); - if (name[0] == '-' && name[1] == '\0') { - char *p; - p = ckmalloc(sizeof optet_vals); - lvp->text = memcpy(p, optet_vals, sizeof optet_vals); - vp = NULL; - } else { - vpp = hashvar(name); - vp = *findvar(vpp, name); - if (vp == NULL) { - if (strchr(name, '=')) - setvareq(savestr(name), VSTRFIXED); - else - setvar(name, NULL, VSTRFIXED); - vp = *vpp; /* the new variable */ - lvp->text = NULL; - lvp->flags = VUNSET; - } else { - lvp->text = vp->text; - lvp->flags = vp->flags; - vp->flags |= VSTRFIXED|VTEXTFIXED; - if (strchr(name, '=')) - setvareq(savestr(name), 0); - } - } - lvp->vp = vp; - lvp->next = localvars; - localvars = lvp; - INTON; -} - - -/* - * Called after a function returns. - */ - -static void -poplocalvars() { - struct localvar *lvp; - struct var *vp; - - while ((lvp = localvars) != NULL) { - localvars = lvp->next; - vp = lvp->vp; - if (vp == NULL) { /* $- saved */ - memcpy(optet_vals, lvp->text, sizeof optet_vals); - ckfree(lvp->text); - } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) { - (void)unsetvar(vp->text); - } else { - if ((vp->flags & VTEXTFIXED) == 0) - ckfree(vp->text); - vp->flags = lvp->flags; - vp->text = lvp->text; - } - ckfree(lvp); - } -} - - -static int -setvarcmd(argc, argv) - int argc; - char **argv; -{ - if (argc <= 2) - return unsetcmd(argc, argv); - else if (argc == 3) - setvar(argv[1], argv[2], 0); - else - error("List assignment not implemented"); - return 0; -} - - -/* - * The unset builtin command. We unset the function before we unset the - * variable to allow a function to be unset when there is a readonly variable - * with the same name. - */ - -static int -unsetcmd(argc, argv) - int argc; - char **argv; -{ - char **ap; - int i; - int flg_func = 0; - int flg_var = 0; - int ret = 0; - - while ((i = nextopt("vf")) != '\0') { - if (i == 'f') - flg_func = 1; - else - flg_var = 1; - } - if (flg_func == 0 && flg_var == 0) - flg_var = 1; - - for (ap = argptr; *ap ; ap++) { - if (flg_func) - unsetfunc(*ap); - if (flg_var) - ret |= unsetvar(*ap); - } - return ret; -} - - -/* - * Unset the specified variable. - */ - -static int -unsetvar(const char *s) -{ - struct var **vpp; - struct var *vp; - - vpp = findvar(hashvar(s), s); - vp = *vpp; - if (vp) { - if (vp->flags & VREADONLY) - return (1); - INTOFF; - if (*(strchr(vp->text, '=') + 1) != '\0') - setvar(s, nullstr, 0); - vp->flags &= ~VEXPORT; - vp->flags |= VUNSET; - if ((vp->flags & VSTRFIXED) == 0) { - if ((vp->flags & VTEXTFIXED) == 0) - ckfree(vp->text); - *vpp = vp->next; - ckfree(vp); - } - INTON; - return (0); - } - - return (0); -} - - - -/* - * Find the appropriate entry in the hash table from the name. - */ - -static struct var ** -hashvar(const char *p) -{ - unsigned int hashval; - - hashval = ((unsigned char) *p) << 4; - while (*p && *p != '=') - hashval += (unsigned char) *p++; - return &vartab[hashval % VTABSIZE]; -} - - - -/* - * Returns true if the two strings specify the same varable. The first - * variable name is terminated by '='; the second may be terminated by - * either '=' or '\0'. - */ - -static int -varequal(const char *p, const char *q) -{ - while (*p == *q++) { - if (*p++ == '=') - return 1; - } - if (*p == '=' && *(q - 1) == '\0') - return 1; - return 0; -} - -static void -showvars(const char *myprefix, int mask, int xor) -{ - struct var **vpp; - struct var *vp; - const char *sep = myprefix == nullstr ? myprefix : spcstr; - - for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { - for (vp = *vpp ; vp ; vp = vp->next) { - if ((vp->flags & mask) ^ xor) { - char *p; - int len; - - p = strchr(vp->text, '=') + 1; - len = p - vp->text; - p = single_quote(p); - - printf("%s%s%.*s%s\n", myprefix, sep, len, - vp->text, p); - stunalloc(p); - } - } - } -} - -static struct var ** -findvar(struct var **vpp, const char *name) -{ - for (; *vpp; vpp = &(*vpp)->next) { - if (varequal((*vpp)->text, name)) { - break; - } - } - return vpp; -} - -/* - * Copyright (c) 1999 Herbert Xu - * This file contains code for the times builtin. - * $Id: ash.c,v 1.28 2001/10/19 00:22:22 andersen Exp $ - */ -static int timescmd (int argc, char **argv) -{ - struct tms buf; - long int clk_tck = sysconf(_SC_CLK_TCK); - - times(&buf); - printf("%dm%fs %dm%fs\n%dm%fs %dm%fs\n", - (int) (buf.tms_utime / clk_tck / 60), - ((double) buf.tms_utime) / clk_tck, - (int) (buf.tms_stime / clk_tck / 60), - ((double) buf.tms_stime) / clk_tck, - (int) (buf.tms_cutime / clk_tck / 60), - ((double) buf.tms_cutime) / clk_tck, - (int) (buf.tms_cstime / clk_tck / 60), - ((double) buf.tms_cstime) / clk_tck); - return 0; -} - -#ifdef ASH_MATH_SUPPORT -/* The let builtin. */ -int letcmd(int argc, char **argv) -{ - int errcode; - long result=0; - if (argc == 2) { - char *tmp, *expression, p[13]; - expression = strchr(argv[1], '='); - if (!expression) { - /* Cannot use 'error()' here, or the return code - * will be incorrect */ - out2fmt("sh: let: syntax error: \"%s\"\n", argv[1]); - return 0; - } - *expression = '\0'; - tmp = ++expression; - result = arith(tmp, &errcode); - if (errcode < 0) { - /* Cannot use 'error()' here, or the return code - * will be incorrect */ - out2fmt("sh: let: "); - if(errcode == -2) - out2fmt("divide by zero"); - else - out2fmt("syntax error: \"%s=%s\"\n", argv[1], expression); - return 0; - } - snprintf(p, 12, "%ld", result); - setvar(argv[1], savestr(p), 0); - } else if (argc >= 3) - synerror("invalid operand"); - return !result; -} -#endif - - - -/*- - * Copyright (c) 1989, 1991, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. - * - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ diff --git a/basename.c b/basename.c deleted file mode 100644 index c15afd533..000000000 --- a/basename.c +++ /dev/null @@ -1,52 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini basename implementation for busybox - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* getopt not needed */ - -#include -#include "busybox.h" -#include - -extern int basename_main(int argc, char **argv) -{ - int m, n; - char *s; - - if ((argc < 2) || (**(argv + 1) == '-')) { - show_usage(); - } - - argv++; - - s = get_last_path_component(*argv); - - if (argc>2) { - argv++; - n = strlen(*argv); - m = strlen(s); - if (m>n && strncmp(s+m-n, *argv, n)==0) - s[m-n] = '\0'; - } - puts(s); - return EXIT_SUCCESS; -} diff --git a/bunzip2.c b/bunzip2.c deleted file mode 100644 index 757654dab..000000000 --- a/bunzip2.c +++ /dev/null @@ -1,2340 +0,0 @@ -/* Modified for busybox by Glenn McGrath */ -/*-- - This file is a part of bzip2 and/or libbzip2, a program and - library for lossless, block-sorting data compression. - - Copyright (C) 1996-2000 Julian R Seward. All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. The origin of this software must not be misrepresented; you must - not claim that you wrote the original software. If you use this - software in a product, an acknowledgment in the product - documentation would be appreciated but is not required. - - 3. Altered source versions must be plainly marked as such, and must - not be misrepresented as being the original software. - - 4. The name of the author may not be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - Julian Seward, Cambridge, UK. - jseward@acm.org - bzip2/libbzip2 version 1.0 of 21 March 2000 - - This program is based on (at least) the work of: - Mike Burrows - David Wheeler - Peter Fenwick - Alistair Moffat - Radford Neal - Ian H. Witten - Robert Sedgewick - Jon L. Bentley - - For more information on these sources, see the manual. ---*/ - -#include -#include -#include -#include - -//#define TRUE 1 -//#define FALSE 0 - -#define MTFA_SIZE 4096 -#define MTFL_SIZE 16 -#define BZ_N_GROUPS 6 -#define BZ_G_SIZE 50 -#define BZ_MAX_ALPHA_SIZE 258 - -#define BZ_OK 0 -#define BZ_RUN_OK 1 -#define BZ_FLUSH_OK 2 -#define BZ_FINISH_OK 3 -#define BZ_STREAM_END 4 -#define BZ_SEQUENCE_ERROR (-1) -#define BZ_PARAM_ERROR (-2) -#define BZ_MEM_ERROR (-3) -#define BZ_DATA_ERROR (-4) -#define BZ_DATA_ERROR_MAGIC (-5) -#define BZ_IO_ERROR (-6) -#define BZ_UNEXPECTED_EOF (-7) -#define BZ_OUTBUFF_FULL (-8) -#define BZ_CONFIG_ERROR (-9) - -#define BZ_RUNA 0 -#define BZ_RUNB 1 - -#define BZ_MAX_UNUSED 5000 -#define FILE_NAME_LEN 1034 -/*-- states for decompression. --*/ - -#define BZ_X_IDLE 1 -#define BZ_X_OUTPUT 2 - -#define BZ_X_MAGIC_1 10 -#define BZ_X_MAGIC_2 11 -#define BZ_X_MAGIC_3 12 -#define BZ_X_MAGIC_4 13 -#define BZ_X_BLKHDR_1 14 -#define BZ_X_BLKHDR_2 15 -#define BZ_X_BLKHDR_3 16 -#define BZ_X_BLKHDR_4 17 -#define BZ_X_BLKHDR_5 18 -#define BZ_X_BLKHDR_6 19 -#define BZ_X_BCRC_1 20 -#define BZ_X_BCRC_2 21 -#define BZ_X_BCRC_3 22 -#define BZ_X_BCRC_4 23 -#define BZ_X_RANDBIT 24 -#define BZ_X_ORIGPTR_1 25 -#define BZ_X_ORIGPTR_2 26 -#define BZ_X_ORIGPTR_3 27 -#define BZ_X_MAPPING_1 28 -#define BZ_X_MAPPING_2 29 -#define BZ_X_SELECTOR_1 30 -#define BZ_X_SELECTOR_2 31 -#define BZ_X_SELECTOR_3 32 -#define BZ_X_CODING_1 33 -#define BZ_X_CODING_2 34 -#define BZ_X_CODING_3 35 -#define BZ_X_MTF_1 36 -#define BZ_X_MTF_2 37 -#define BZ_X_MTF_3 38 -#define BZ_X_MTF_4 39 -#define BZ_X_MTF_5 40 -#define BZ_X_MTF_6 41 -#define BZ_X_ENDHDR_2 42 -#define BZ_X_ENDHDR_3 43 -#define BZ_X_ENDHDR_4 44 -#define BZ_X_ENDHDR_5 45 -#define BZ_X_ENDHDR_6 46 -#define BZ_X_CCRC_1 47 -#define BZ_X_CCRC_2 48 -#define BZ_X_CCRC_3 49 -#define BZ_X_CCRC_4 50 - -#define BZ_MAX_CODE_LEN 23 -#define BZ_VERSION "1.0.1, 23-June-2000" -#define OM_TEST 3 -#define SM_F2F 3 - -typedef struct { - char *next_in; - unsigned int avail_in; - unsigned int total_in_lo32; - unsigned int total_in_hi32; - - char *next_out; - unsigned int avail_out; - unsigned int total_out_lo32; - unsigned int total_out_hi32; - - void *state; - - void *(*bzalloc)(void *,int,int); - void (*bzfree)(void *,void *); - void *opaque; -} bz_stream; - -typedef struct { - bz_stream strm; - FILE *handle; - unsigned char initialisedOk; - unsigned char writing; - char buf[BZ_MAX_UNUSED]; - int lastErr; - int bufN; -} bzFile; - -/*-- Structure holding all the decompression-side stuff. --*/ -typedef struct { - /* pointer back to the struct bz_stream */ - bz_stream* strm; - - /* state indicator for this stream */ - int state; - - /* for doing the final run-length decoding */ - unsigned char state_out_ch; - int state_out_len; - unsigned char blockRandomised; - int rNToGo; - int rTPos; - - /* the buffer for bit stream reading */ - unsigned int bsBuff; - int bsLive; - - /* misc administratium */ - int blockSize100k; - unsigned char smallDecompress; - int currBlockNo; - int verbosity; - - /* for undoing the Burrows-Wheeler transform */ - int origPtr; - unsigned int tPos; - int k0; - int unzftab[256]; - int nblock_used; - int cftab[257]; - int cftabCopy[257]; - - /* for undoing the Burrows-Wheeler transform (FAST) */ - unsigned int *tt; - - /* for undoing the Burrows-Wheeler transform (SMALL) */ - unsigned short *ll16; - unsigned char *ll4; - - /* stored and calculated CRCs */ - unsigned int storedBlockCRC; - unsigned int storedCombinedCRC; - unsigned int calculatedBlockCRC; - unsigned int calculatedCombinedCRC; - - /* map of bytes used in block */ - int nInUse; - unsigned char inUse[256]; - unsigned char inUse16[16]; - unsigned char seqToUnseq[256]; - - /* for decoding the MTF values */ - unsigned char mtfa [MTFA_SIZE]; - unsigned char selector [2 + (900000 / BZ_G_SIZE)]; - unsigned char selectorMtf[2 + (900000 / BZ_G_SIZE)]; - unsigned char len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; - int mtfbase[256 / MTFL_SIZE]; - - int limit [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; - int base [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; - int perm [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE]; - int minLens[BZ_N_GROUPS]; - - /* save area for scalars in the main decompress code */ - int save_i; - int save_j; - int save_t; - int save_alphaSize; - int save_nGroups; - int save_nSelectors; - int save_EOB; - int save_groupNo; - int save_groupPos; - int save_nextSym; - int save_nblockMAX; - int save_nblock; - int save_es; - int save_N; - int save_curr; - int save_zt; - int save_zn; - int save_zvec; - int save_zj; - int save_gSel; - int save_gMinlen; - int *save_gLimit; - int *save_gBase; - int *save_gPerm; -} DState; - -int BZ2_rNums[512]; -//int verbosity_level; -unsigned char smallMode; -unsigned char noisy; -char *progName; -char inName[FILE_NAME_LEN]; -char outName[FILE_NAME_LEN]; -int srcMode; -int opMode; -unsigned char deleteOutputOnInterrupt; -FILE *outputHandleJustInCase; -int numFileNames; -int numFilesProcessed; -int exitValue; - -unsigned int BZ2_crc32Table[256] = { - - /*-- Ugly, innit? --*/ - - 0x00000000L, 0x04c11db7L, 0x09823b6eL, 0x0d4326d9L, - 0x130476dcL, 0x17c56b6bL, 0x1a864db2L, 0x1e475005L, - 0x2608edb8L, 0x22c9f00fL, 0x2f8ad6d6L, 0x2b4bcb61L, - 0x350c9b64L, 0x31cd86d3L, 0x3c8ea00aL, 0x384fbdbdL, - 0x4c11db70L, 0x48d0c6c7L, 0x4593e01eL, 0x4152fda9L, - 0x5f15adacL, 0x5bd4b01bL, 0x569796c2L, 0x52568b75L, - 0x6a1936c8L, 0x6ed82b7fL, 0x639b0da6L, 0x675a1011L, - 0x791d4014L, 0x7ddc5da3L, 0x709f7b7aL, 0x745e66cdL, - 0x9823b6e0L, 0x9ce2ab57L, 0x91a18d8eL, 0x95609039L, - 0x8b27c03cL, 0x8fe6dd8bL, 0x82a5fb52L, 0x8664e6e5L, - 0xbe2b5b58L, 0xbaea46efL, 0xb7a96036L, 0xb3687d81L, - 0xad2f2d84L, 0xa9ee3033L, 0xa4ad16eaL, 0xa06c0b5dL, - 0xd4326d90L, 0xd0f37027L, 0xddb056feL, 0xd9714b49L, - 0xc7361b4cL, 0xc3f706fbL, 0xceb42022L, 0xca753d95L, - 0xf23a8028L, 0xf6fb9d9fL, 0xfbb8bb46L, 0xff79a6f1L, - 0xe13ef6f4L, 0xe5ffeb43L, 0xe8bccd9aL, 0xec7dd02dL, - 0x34867077L, 0x30476dc0L, 0x3d044b19L, 0x39c556aeL, - 0x278206abL, 0x23431b1cL, 0x2e003dc5L, 0x2ac12072L, - 0x128e9dcfL, 0x164f8078L, 0x1b0ca6a1L, 0x1fcdbb16L, - 0x018aeb13L, 0x054bf6a4L, 0x0808d07dL, 0x0cc9cdcaL, - 0x7897ab07L, 0x7c56b6b0L, 0x71159069L, 0x75d48ddeL, - 0x6b93dddbL, 0x6f52c06cL, 0x6211e6b5L, 0x66d0fb02L, - 0x5e9f46bfL, 0x5a5e5b08L, 0x571d7dd1L, 0x53dc6066L, - 0x4d9b3063L, 0x495a2dd4L, 0x44190b0dL, 0x40d816baL, - 0xaca5c697L, 0xa864db20L, 0xa527fdf9L, 0xa1e6e04eL, - 0xbfa1b04bL, 0xbb60adfcL, 0xb6238b25L, 0xb2e29692L, - 0x8aad2b2fL, 0x8e6c3698L, 0x832f1041L, 0x87ee0df6L, - 0x99a95df3L, 0x9d684044L, 0x902b669dL, 0x94ea7b2aL, - 0xe0b41de7L, 0xe4750050L, 0xe9362689L, 0xedf73b3eL, - 0xf3b06b3bL, 0xf771768cL, 0xfa325055L, 0xfef34de2L, - 0xc6bcf05fL, 0xc27dede8L, 0xcf3ecb31L, 0xcbffd686L, - 0xd5b88683L, 0xd1799b34L, 0xdc3abdedL, 0xd8fba05aL, - 0x690ce0eeL, 0x6dcdfd59L, 0x608edb80L, 0x644fc637L, - 0x7a089632L, 0x7ec98b85L, 0x738aad5cL, 0x774bb0ebL, - 0x4f040d56L, 0x4bc510e1L, 0x46863638L, 0x42472b8fL, - 0x5c007b8aL, 0x58c1663dL, 0x558240e4L, 0x51435d53L, - 0x251d3b9eL, 0x21dc2629L, 0x2c9f00f0L, 0x285e1d47L, - 0x36194d42L, 0x32d850f5L, 0x3f9b762cL, 0x3b5a6b9bL, - 0x0315d626L, 0x07d4cb91L, 0x0a97ed48L, 0x0e56f0ffL, - 0x1011a0faL, 0x14d0bd4dL, 0x19939b94L, 0x1d528623L, - 0xf12f560eL, 0xf5ee4bb9L, 0xf8ad6d60L, 0xfc6c70d7L, - 0xe22b20d2L, 0xe6ea3d65L, 0xeba91bbcL, 0xef68060bL, - 0xd727bbb6L, 0xd3e6a601L, 0xdea580d8L, 0xda649d6fL, - 0xc423cd6aL, 0xc0e2d0ddL, 0xcda1f604L, 0xc960ebb3L, - 0xbd3e8d7eL, 0xb9ff90c9L, 0xb4bcb610L, 0xb07daba7L, - 0xae3afba2L, 0xaafbe615L, 0xa7b8c0ccL, 0xa379dd7bL, - 0x9b3660c6L, 0x9ff77d71L, 0x92b45ba8L, 0x9675461fL, - 0x8832161aL, 0x8cf30badL, 0x81b02d74L, 0x857130c3L, - 0x5d8a9099L, 0x594b8d2eL, 0x5408abf7L, 0x50c9b640L, - 0x4e8ee645L, 0x4a4ffbf2L, 0x470cdd2bL, 0x43cdc09cL, - 0x7b827d21L, 0x7f436096L, 0x7200464fL, 0x76c15bf8L, - 0x68860bfdL, 0x6c47164aL, 0x61043093L, 0x65c52d24L, - 0x119b4be9L, 0x155a565eL, 0x18197087L, 0x1cd86d30L, - 0x029f3d35L, 0x065e2082L, 0x0b1d065bL, 0x0fdc1becL, - 0x3793a651L, 0x3352bbe6L, 0x3e119d3fL, 0x3ad08088L, - 0x2497d08dL, 0x2056cd3aL, 0x2d15ebe3L, 0x29d4f654L, - 0xc5a92679L, 0xc1683bceL, 0xcc2b1d17L, 0xc8ea00a0L, - 0xd6ad50a5L, 0xd26c4d12L, 0xdf2f6bcbL, 0xdbee767cL, - 0xe3a1cbc1L, 0xe760d676L, 0xea23f0afL, 0xeee2ed18L, - 0xf0a5bd1dL, 0xf464a0aaL, 0xf9278673L, 0xfde69bc4L, - 0x89b8fd09L, 0x8d79e0beL, 0x803ac667L, 0x84fbdbd0L, - 0x9abc8bd5L, 0x9e7d9662L, 0x933eb0bbL, 0x97ffad0cL, - 0xafb010b1L, 0xab710d06L, 0xa6322bdfL, 0xa2f33668L, - 0xbcb4666dL, 0xb8757bdaL, 0xb5365d03L, 0xb1f740b4L -}; - -void bz_rand_udp_mask(DState *s) -{ - if (s->rNToGo == 0) { - s->rNToGo = BZ2_rNums[s->rTPos]; - s->rTPos++; - if (s->rTPos == 512) { - s->rTPos = 0; - } - } - s->rNToGo--; -} - -static unsigned char myfeof(FILE *f) -{ - int c = fgetc(f); - if (c == EOF) { - return(TRUE); - } - ungetc(c, f); - return(FALSE); -} - -static void cleanUpAndFail(int ec) -{ - int retVal; - - if ((srcMode == SM_F2F) && (opMode != OM_TEST) && deleteOutputOnInterrupt) { - if (noisy) { - error_msg("%s: Deleting output file %s, if it exists.\n", progName, outName); - } - if (outputHandleJustInCase != NULL) { - fclose(outputHandleJustInCase); - } - retVal = remove(outName); - if (retVal != 0) { - error_msg("%s: WARNING: deletion of output file (apparently) failed.\n", progName); - } - } - if (noisy && (numFileNames > 0) && (numFilesProcessed < numFileNames)) { - error_msg("%s: WARNING: some files have not been processed:\n" - "\t%d specified on command line, %d not processed yet.\n\n", - progName, numFileNames, numFileNames - numFilesProcessed ); - } - - exit(ec); -} - - -void panic(char *s) -{ - error_msg("\n%s: PANIC -- internal consistency error:\n" - "\t%s\n" - "\tThis is a BUG. Please report it to me at:\n" - "\tjseward@acm.org\n", - progName, s); - cleanUpAndFail( 3 ); -} - -void BZ2_hbCreateDecodeTables(int *limit, int *base, int *perm, unsigned char *length, int minLen, int maxLen, int alphaSize ) -{ - int pp, i, j, vec; - - pp = 0; - for (i = minLen; i <= maxLen; i++) { - for (j = 0; j < alphaSize; j++) { - if (length[j] == i) { - perm[pp] = j; - pp++; - } - } - } - - for (i = 0; i < BZ_MAX_CODE_LEN; i++) { - base[i] = 0; - } - - for (i = 0; i < alphaSize; i++) { - base[length[i]+1]++; - } - - for (i = 1; i < BZ_MAX_CODE_LEN; i++) { - base[i] += base[i-1]; - } - - for (i = 0; i < BZ_MAX_CODE_LEN; i++) { - limit[i] = 0; - } - vec = 0; - - for (i = minLen; i <= maxLen; i++) { - vec += (base[i+1] - base[i]); - limit[i] = vec-1; - vec <<= 1; - } - for (i = minLen + 1; i <= maxLen; i++) { - base[i] = ((limit[i-1] + 1) << 1) - base[i]; - } -} - -int bz_get_small(DState *s) -{ - int cccc; - int nb, na, mid; - nb = 0; - na = 256; - do { - mid = (nb + na) >> 1; - if (s->tPos >= s->cftab[mid]) { - nb = mid; - } else { - na = mid; - } - } - while (na - nb != 1); - cccc = nb; - s->tPos = (((unsigned int)s->ll16[s->tPos]) | - (((((unsigned int)(s->ll4[(s->tPos) >> 1])) >> - (((s->tPos) << 2) & 0x4)) & 0xF) << 16)); - return(cccc); -} - -void assert_h(int errcode) -{ - error_msg_and_die("\n\nbzip2/libbzip2: internal error number %d.\n" - "This is a bug in bzip2/libbzip2, %s.\n" - "Please report it to me at: jseward@acm.org. If this happened\n" - "when you were using some program which uses libbzip2 as a\n" - "component, you should also report this bug to the author(s)\n" - "of that program. Please make an effort to report this bug;\n" - "timely and accurate bug reports eventually lead to higher\n" - "quality software. Thanks. Julian Seward, 21 March 2000.\n\n", - errcode, BZ_VERSION); -} - -static int get_bits(DState *s, int *vvv, char nnn) -{ - while (1) { - if (s->bsLive >= nnn) { - *vvv = (s->bsBuff >> (s->bsLive-nnn)) & ((1 << nnn)-1); - s->bsLive -= nnn; - break; - } - if (s->strm->avail_in == 0) { - return(FALSE); - } - s->bsBuff = (s->bsBuff << 8) | ((unsigned int) (*((unsigned char*)(s->strm->next_in)))); - s->bsLive += 8; - s->strm->next_in++; - s->strm->avail_in--; - s->strm->total_in_lo32++; - if (s->strm->total_in_lo32 == 0) { - s->strm->total_in_hi32++; - } - } - return(TRUE); -} - -int bz_get_fast(DState *s) -{ - int cccc; - s->tPos = s->tt[s->tPos]; - cccc = (unsigned char)(s->tPos & 0xff); - s->tPos >>= 8; - return(cccc); -} - -/*---------------------------------------------------*/ -int BZ2_decompress(DState *s) -{ - int uc = 0; - int retVal; - int minLen, maxLen; - bz_stream *strm = s->strm; - - /* stuff that needs to be saved/restored */ - int i; - int j; - int t; - int alphaSize; - int nGroups; - int nSelectors; - int EOB; - int groupNo; - int groupPos; - int nextSym; - int nblockMAX; - int nblock; - int es; - int N; - int curr; - int zt; - int zn; - int zvec; - int zj; - int gSel; - int gMinlen; - int *gLimit; - int *gBase; - int *gPerm; - int switch_val; - - int get_mtf_val_init(void) - { - if (groupPos == 0) { - groupNo++; - if (groupNo >= nSelectors) { - retVal = BZ_DATA_ERROR; - return(FALSE); - } - groupPos = BZ_G_SIZE; - gSel = s->selector[groupNo]; - gMinlen = s->minLens[gSel]; - gLimit = &(s->limit[gSel][0]); - gPerm = &(s->perm[gSel][0]); - gBase = &(s->base[gSel][0]); - } - groupPos--; - zn = gMinlen; - return(TRUE); - } - - if (s->state == BZ_X_MAGIC_1) { - /*initialise the save area*/ - s->save_i = 0; - s->save_j = 0; - s->save_t = 0; - s->save_alphaSize = 0; - s->save_nGroups = 0; - s->save_nSelectors = 0; - s->save_EOB = 0; - s->save_groupNo = 0; - s->save_groupPos = 0; - s->save_nextSym = 0; - s->save_nblockMAX = 0; - s->save_nblock = 0; - s->save_es = 0; - s->save_N = 0; - s->save_curr = 0; - s->save_zt = 0; - s->save_zn = 0; - s->save_zvec = 0; - s->save_zj = 0; - s->save_gSel = 0; - s->save_gMinlen = 0; - s->save_gLimit = NULL; - s->save_gBase = NULL; - s->save_gPerm = NULL; - } - - /*restore from the save area*/ - i = s->save_i; - j = s->save_j; - t = s->save_t; - alphaSize = s->save_alphaSize; - nGroups = s->save_nGroups; - nSelectors = s->save_nSelectors; - EOB = s->save_EOB; - groupNo = s->save_groupNo; - groupPos = s->save_groupPos; - nextSym = s->save_nextSym; - nblockMAX = s->save_nblockMAX; - nblock = s->save_nblock; - es = s->save_es; - N = s->save_N; - curr = s->save_curr; - zt = s->save_zt; - zn = s->save_zn; - zvec = s->save_zvec; - zj = s->save_zj; - gSel = s->save_gSel; - gMinlen = s->save_gMinlen; - gLimit = s->save_gLimit; - gBase = s->save_gBase; - gPerm = s->save_gPerm; - - retVal = BZ_OK; - switch_val = s->state; - switch (switch_val) { - case BZ_X_MAGIC_1: - s->state = BZ_X_MAGIC_1; - if (get_bits(s, &uc, 8) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - if (uc != 'B') { - retVal = BZ_DATA_ERROR_MAGIC; - goto save_state_and_return; - } - - case BZ_X_MAGIC_2: - s->state = BZ_X_MAGIC_2; - if (get_bits(s, &uc, 8) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - if (uc != 'Z') { - retVal = BZ_DATA_ERROR_MAGIC; - goto save_state_and_return; - } - - case BZ_X_MAGIC_3: - s->state = BZ_X_MAGIC_3; - if (get_bits(s, &uc, 8) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - if (uc != 'h') { - retVal = BZ_DATA_ERROR_MAGIC; - goto save_state_and_return; - } - - case BZ_X_MAGIC_4: - s->state = BZ_X_MAGIC_4; - if (get_bits(s, &s->blockSize100k, 8) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - if ((s->blockSize100k < '1') || (s->blockSize100k > '9')) { - retVal = BZ_DATA_ERROR_MAGIC; - goto save_state_and_return; - } - s->blockSize100k -= '0'; - - if (s->smallDecompress) { - s->ll16 = (strm->bzalloc)(strm->opaque, s->blockSize100k * 100000 * sizeof(unsigned short), 1); - s->ll4 = (strm->bzalloc)(strm->opaque, ((1 + s->blockSize100k * 100000) >> 1) * sizeof(unsigned char), 1); - - if (s->ll16 == NULL || s->ll4 == NULL) { - retVal = BZ_MEM_ERROR; - goto save_state_and_return; - } - } else { - s->tt = (strm->bzalloc)(strm->opaque, s->blockSize100k * 100000 * sizeof(int), 1); - if (s->tt == NULL) { - retVal = BZ_MEM_ERROR; - goto save_state_and_return; - } - } - - case BZ_X_BLKHDR_1: - s->state = BZ_X_BLKHDR_1; - if (get_bits(s, &uc, 8) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - - if (uc == 0x17) { - goto endhdr_2; - } - if (uc != 0x31) { - retVal = BZ_DATA_ERROR; - goto save_state_and_return; - } - - case BZ_X_BLKHDR_2: - s->state = BZ_X_BLKHDR_2; - if (get_bits(s, &uc, 8) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - if (uc != 0x41) { - retVal = BZ_DATA_ERROR; - goto save_state_and_return; - } - - case BZ_X_BLKHDR_3: - s->state = BZ_X_BLKHDR_3; - if (get_bits(s, &uc, 8) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - if (uc != 0x59) { - retVal = BZ_DATA_ERROR; - goto save_state_and_return; - } - - case BZ_X_BLKHDR_4: - s->state = BZ_X_BLKHDR_4; - if (get_bits(s, &uc, 8) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - if (uc != 0x26) { - retVal = BZ_DATA_ERROR; - goto save_state_and_return; - } - - case BZ_X_BLKHDR_5: - s->state = BZ_X_BLKHDR_5; - if (get_bits(s, &uc, 8) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - if (uc != 0x53) { - retVal = BZ_DATA_ERROR; - goto save_state_and_return; - } - - case BZ_X_BLKHDR_6: - s->state = BZ_X_BLKHDR_6; - if (get_bits(s, &uc, 8) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - if (uc != 0x59) { - retVal = BZ_DATA_ERROR; - goto save_state_and_return; - } - - s->currBlockNo++; - if (s->verbosity >= 2) { - error_msg("\n [%d: huff+mtf ", s->currBlockNo); - } - s->storedBlockCRC = 0; - - case BZ_X_BCRC_1: - s->state = BZ_X_BCRC_1; - if (get_bits(s, &uc, 8) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - s->storedBlockCRC = (s->storedBlockCRC << 8) | ((unsigned int)uc); - - case BZ_X_BCRC_2: - s->state = BZ_X_BCRC_2; - if (get_bits(s, &uc, 8) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - s->storedBlockCRC = (s->storedBlockCRC << 8) | ((unsigned int)uc); - - case BZ_X_BCRC_3: - s->state = BZ_X_BCRC_3; - if (get_bits(s, &uc, 8) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - s->storedBlockCRC = (s->storedBlockCRC << 8) | ((unsigned int)uc); - - case BZ_X_BCRC_4: - s->state = BZ_X_BCRC_4; - if (get_bits(s, &uc, 8) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - s->storedBlockCRC = (s->storedBlockCRC << 8) | ((unsigned int)uc); - - case BZ_X_RANDBIT: - s->state = BZ_X_RANDBIT; - { - int tmp = s->blockRandomised; - const int ret = get_bits(s, &tmp, 1); - s->blockRandomised = tmp; - if (ret == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - } - - s->origPtr = 0; - - case BZ_X_ORIGPTR_1: - s->state = BZ_X_ORIGPTR_1; - if (get_bits(s, &uc, 8) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - s->origPtr = (s->origPtr << 8) | ((int)uc); - - case BZ_X_ORIGPTR_2: - s->state = BZ_X_ORIGPTR_2; - if (get_bits(s, &uc, 8) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - s->origPtr = (s->origPtr << 8) | ((int)uc); - - case BZ_X_ORIGPTR_3: - s->state = BZ_X_ORIGPTR_3; - if (get_bits(s, &uc, 8) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - s->origPtr = (s->origPtr << 8) | ((int)uc); - - if (s->origPtr < 0) { - retVal = BZ_DATA_ERROR; - goto save_state_and_return; - } - if (s->origPtr > 10 + 100000*s->blockSize100k) { - retVal = BZ_DATA_ERROR; - goto save_state_and_return; - } - - /*--- Receive the mapping table ---*/ - case BZ_X_MAPPING_1: - for (i = 0; i < 16; i++) { - s->state = BZ_X_MAPPING_1; - if (get_bits(s, &uc, 1) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - if (uc == 1) { - s->inUse16[i] = TRUE; - } else { - s->inUse16[i] = FALSE; - } - } - - for (i = 0; i < 256; i++) { - s->inUse[i] = FALSE; - } - - for (i = 0; i < 16; i++) { - if (s->inUse16[i]) { - for (j = 0; j < 16; j++) { - case BZ_X_MAPPING_2: - s->state = BZ_X_MAPPING_2; - if (get_bits(s, &uc, 1) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - if (uc == 1) { - s->inUse[i * 16 + j] = TRUE; - } - } - } - } - - s->nInUse = 0; - for (i = 0; i < 256; i++) { - if (s->inUse[i]) { - s->seqToUnseq[s->nInUse] = i; - s->nInUse++; - } - } - if (s->nInUse == 0) { - retVal = BZ_DATA_ERROR; - goto save_state_and_return; - } - alphaSize = s->nInUse+2; - - /*--- Now the selectors ---*/ - case BZ_X_SELECTOR_1: - s->state = BZ_X_SELECTOR_1; - if (get_bits(s, &nGroups, 3) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - if (nGroups < 2 || nGroups > 6) { - retVal = BZ_DATA_ERROR; - goto save_state_and_return; - } - - case BZ_X_SELECTOR_2: - s->state = BZ_X_SELECTOR_2; - if (get_bits(s, &nSelectors, 15) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - if (nSelectors < 1) { - retVal = BZ_DATA_ERROR; - goto save_state_and_return; - } - - - - for (i = 0; i < nSelectors; i++) { - j = 0; - while (1) { - case BZ_X_SELECTOR_3: - s->state = BZ_X_SELECTOR_3; - if (get_bits(s, &uc, 1) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - if (uc == 0) { - break; - } - j++; - if (j >= nGroups) { - retVal = BZ_DATA_ERROR; - goto save_state_and_return; - } - } - s->selectorMtf[i] = j; - } - - /*--- Undo the MTF values for the selectors. ---*/ - { - unsigned char pos[BZ_N_GROUPS], tmp, v; - for (v = 0; v < nGroups; v++) { - pos[v] = v; - } - for (i = 0; i < nSelectors; i++) { - v = s->selectorMtf[i]; - tmp = pos[v]; - while (v > 0) { - pos[v] = pos[v-1]; - v--; - } - pos[0] = tmp; - s->selector[i] = tmp; - } - } - - /*--- Now the coding tables ---*/ - for (t = 0; t < nGroups; t++) { - case BZ_X_CODING_1: - s->state = BZ_X_CODING_1; - if (get_bits(s, &curr, 5) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - for (i = 0; i < alphaSize; i++) { - while (TRUE) { - if (curr < 1 || curr > 20) { - retVal = BZ_DATA_ERROR; - goto save_state_and_return; - } - - case BZ_X_CODING_2: - s->state = BZ_X_CODING_2; - if (get_bits(s, &uc, 1) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - if (uc == 0) { - break; - } - - case BZ_X_CODING_3: - s->state = BZ_X_CODING_3; - if (get_bits(s, &uc, 1) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - if (uc == 0) { - curr++; - } else { - curr--; - } - } - s->len[t][i] = curr; - } - } - - /*--- Create the Huffman decoding tables ---*/ - for (t = 0; t < nGroups; t++) { - minLen = 32; - maxLen = 0; - for (i = 0; i < alphaSize; i++) { - if (s->len[t][i] > maxLen) { - maxLen = s->len[t][i]; - } - if (s->len[t][i] < minLen) { - minLen = s->len[t][i]; - } - } - - BZ2_hbCreateDecodeTables ( - &(s->limit[t][0]), - &(s->base[t][0]), - &(s->perm[t][0]), - &(s->len[t][0]), - minLen, maxLen, alphaSize - ); - - - s->minLens[t] = minLen; - } - - /*--- Now the MTF values ---*/ - - EOB = s->nInUse+1; - nblockMAX = 100000 * s->blockSize100k; - groupNo = -1; - groupPos = 0; - - for (i = 0; i <= 255; i++) { - s->unzftab[i] = 0; - } - /*-- MTF init --*/ - { - int ii, jj, kk; - kk = MTFA_SIZE-1; - for (ii = 256 / MTFL_SIZE - 1; ii >= 0; ii--) { - for (jj = MTFL_SIZE-1; jj >= 0; jj--) { - s->mtfa[kk] = (unsigned char)(ii * MTFL_SIZE + jj); - kk--; - } - s->mtfbase[ii] = kk + 1; - } - } - /*-- end MTF init --*/ - - nblock = 0; - - if (get_mtf_val_init() == FALSE) { - goto save_state_and_return; - } - case BZ_X_MTF_1: - s->state = BZ_X_MTF_1; - if (get_bits(s, &zvec, zn) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - while (1) { - if (zn > 20 /* the longest code */) { - retVal = BZ_DATA_ERROR; - goto save_state_and_return; - } - if (zvec <= gLimit[zn]) { - break; - } - zn++; - - case BZ_X_MTF_2: - s->state = BZ_X_MTF_2; - if (get_bits(s, &zj, 1) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - zvec = (zvec << 1) | zj; - } - if (zvec - gBase[zn] < 0 || zvec - gBase[zn] >= BZ_MAX_ALPHA_SIZE) { - retVal = BZ_DATA_ERROR; - goto save_state_and_return; - } - nextSym = gPerm[zvec - gBase[zn]]; - - while (1) { - if (nextSym == EOB) { - break; - } - - if (nextSym == BZ_RUNA || nextSym == BZ_RUNB) { - es = -1; - N = 1; - do { - if (nextSym == BZ_RUNA) { - es = es + (0+1) * N; - } else { - if (nextSym == BZ_RUNB) { - es = es + (1+1) * N; - } - } - N = N * 2; - if (get_mtf_val_init() == FALSE) { - goto save_state_and_return; - } - case BZ_X_MTF_3: - s->state = BZ_X_MTF_3; - if (get_bits(s, &zvec, zn) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - while (1) { - if (zn > 20 /* the longest code */) { - retVal = BZ_DATA_ERROR; - goto save_state_and_return; - } - if (zvec <= gLimit[zn]) { - break; - } - zn++; - - case BZ_X_MTF_4: - s->state = BZ_X_MTF_4; - if (get_bits(s, &zj, 1) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - zvec = (zvec << 1) | zj; - } - if (zvec - gBase[zn] < 0 || zvec - gBase[zn] >= BZ_MAX_ALPHA_SIZE) { - retVal = BZ_DATA_ERROR; - goto save_state_and_return; - - } - nextSym = gPerm[zvec - gBase[zn]]; - } - while (nextSym == BZ_RUNA || nextSym == BZ_RUNB); - - es++; - uc = s->seqToUnseq[ s->mtfa[s->mtfbase[0]] ]; - s->unzftab[uc] += es; - - if (s->smallDecompress) { - while (es > 0) { - if (nblock >= nblockMAX) { - retVal = BZ_DATA_ERROR; - goto save_state_and_return; - } - s->ll16[nblock] = (unsigned short)uc; - nblock++; - es--; - } - } else { - while (es > 0) { - if (nblock >= nblockMAX) { - retVal = BZ_DATA_ERROR; - goto save_state_and_return; - } - s->tt[nblock] = (unsigned int)uc; - nblock++; - es--; - } - } - continue; - } else { - if (nblock >= nblockMAX) { - retVal = BZ_DATA_ERROR; - goto save_state_and_return; - } - /*-- uc = MTF ( nextSym-1 ) --*/ - { - int ii, jj, kk, pp, lno, off; - unsigned int nn; - nn = (unsigned int)(nextSym - 1); - - if (nn < MTFL_SIZE) { - /* avoid general-case expense */ - pp = s->mtfbase[0]; - uc = s->mtfa[pp+nn]; - while (nn > 3) { - int z = pp+nn; - s->mtfa[(z) ] = s->mtfa[(z)-1]; - s->mtfa[(z)-1] = s->mtfa[(z)-2]; - s->mtfa[(z)-2] = s->mtfa[(z)-3]; - s->mtfa[(z)-3] = s->mtfa[(z)-4]; - nn -= 4; - } - while (nn > 0) { - s->mtfa[(pp+nn)] = s->mtfa[(pp+nn)-1]; nn--; - } - s->mtfa[pp] = uc; - } else { - /* general case */ - lno = nn / MTFL_SIZE; - off = nn % MTFL_SIZE; - pp = s->mtfbase[lno] + off; - uc = s->mtfa[pp]; - while (pp > s->mtfbase[lno]) { - s->mtfa[pp] = s->mtfa[pp-1]; - pp--; - } - s->mtfbase[lno]++; - while (lno > 0) { - s->mtfbase[lno]--; - s->mtfa[s->mtfbase[lno]] = s->mtfa[s->mtfbase[lno-1] + MTFL_SIZE - 1]; - lno--; - } - s->mtfbase[0]--; - s->mtfa[s->mtfbase[0]] = uc; - if (s->mtfbase[0] == 0) { - kk = MTFA_SIZE-1; - for (ii = 256 / MTFL_SIZE-1; ii >= 0; ii--) { - for (jj = MTFL_SIZE-1; jj >= 0; jj--) { - s->mtfa[kk] = s->mtfa[s->mtfbase[ii] + jj]; - kk--; - } - s->mtfbase[ii] = kk + 1; - } - } - } - } - /*-- end uc = MTF ( nextSym-1 ) --*/ - - s->unzftab[s->seqToUnseq[uc]]++; - if (s->smallDecompress) { - s->ll16[nblock] = (unsigned short)(s->seqToUnseq[uc]); - } else { - s->tt[nblock] = (unsigned int)(s->seqToUnseq[uc]); - } - nblock++; - - if (get_mtf_val_init() == FALSE) { - goto save_state_and_return; - } - case BZ_X_MTF_5: - s->state = BZ_X_MTF_5; - if (get_bits(s, &zvec, zn) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - while (1) { - if (zn > 20 /* the longest code */) { - retVal = BZ_DATA_ERROR; - goto save_state_and_return; - } - if (zvec <= gLimit[zn]) { - break; - } - zn++; - - case BZ_X_MTF_6: - s->state = BZ_X_MTF_6; - if (get_bits(s, &zj, 1) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - zvec = (zvec << 1) | zj; - } - if (zvec - gBase[zn] < 0 || zvec - gBase[zn] >= BZ_MAX_ALPHA_SIZE) { - retVal = BZ_DATA_ERROR; - goto save_state_and_return; - } - nextSym = gPerm[zvec - gBase[zn]]; - continue; - } - } - - /* Now we know what nblock is, we can do a better sanity - check on s->origPtr. - */ - if (s->origPtr < 0 || s->origPtr >= nblock) { - retVal = BZ_DATA_ERROR; - goto save_state_and_return; - } - s->state_out_len = 0; - s->state_out_ch = 0; - s->calculatedBlockCRC = 0xffffffffL; - s->state = BZ_X_OUTPUT; - if (s->verbosity >= 2) { - error_msg("rt+rld"); - } - - /*-- Set up cftab to facilitate generation of T^(-1) --*/ - s->cftab[0] = 0; - for (i = 1; i <= 256; i++) { - s->cftab[i] = s->unzftab[i-1]; - } - for (i = 1; i <= 256; i++) { - s->cftab[i] += s->cftab[i-1]; - } - - if (s->smallDecompress) { - - /*-- Make a copy of cftab, used in generation of T --*/ - for (i = 0; i <= 256; i++) { - s->cftabCopy[i] = s->cftab[i]; - } - - /*-- compute the T vector --*/ - for (i = 0; i < nblock; i++) { - uc = (unsigned char)(s->ll16[i]); - s->ll16[i] = (unsigned short)(s->cftabCopy[uc] & 0x0000ffff); - if (((i) & 0x1) == 0) { - s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0xf0) | (s->cftabCopy[uc] >> 16); - } else { - s->ll4[(i) >> 1] = (s->ll4[(i) >> 1] & 0x0f) | ((s->cftabCopy[uc] >> 16) << 4); - } - s->cftabCopy[uc]++; - } - - /*-- Compute T^(-1) by pointer reversal on T --*/ - i = s->origPtr; - j = (((unsigned int)s->ll16[i]) | - (((((unsigned int)(s->ll4[(i) >> 1])) >> - (((i) << 2) & 0x4)) & 0xF) << 16)); - - do { - const int tmp = (((unsigned int)s->ll16[j]) | - (((((unsigned int)(s->ll4[(j) >> 1])) >> - (((j) << 2) & 0x4)) & 0xF) << 16)); - - s->ll16[j] = (unsigned short)(i & 0x0000ffff); - if (((j) & 0x1) == 0) { - s->ll4[(j) >> 1] = (s->ll4[(j) >> 1] & 0xf0) | (i >> 16); - } else { - s->ll4[(j) >> 1] = (s->ll4[(j) >> 1] & 0x0f) | ((i >> 16) << 4); - } - i = j; - j = tmp; - } - while (i != s->origPtr); - s->tPos = s->origPtr; - s->nblock_used = 0; - if (s->blockRandomised) { - s->rNToGo = 0; - s->rTPos = 0; - s->k0 = bz_get_small(s); - s->nblock_used++; - bz_rand_udp_mask(s); - s->k0 ^= ((s->rNToGo == 1) ? 1 : 0); - } else { - s->k0 = bz_get_small(s); - s->nblock_used++; - } - } else { - /*-- compute the T^(-1) vector --*/ - for (i = 0; i < nblock; i++) { - uc = (unsigned char)(s->tt[i] & 0xff); - s->tt[s->cftab[uc]] |= (i << 8); - s->cftab[uc]++; - } - - s->tPos = s->tt[s->origPtr] >> 8; - s->nblock_used = 0; - if (s->blockRandomised) { - s->rNToGo = 0; - s->rTPos = 0; - s->k0 = bz_get_fast(s); - - s->nblock_used++; - bz_rand_udp_mask(s); - s->k0 ^= ((s->rNToGo == 1) ? 1 : 0); - } else { - s->k0 = bz_get_fast(s); - s->nblock_used++; - } - } - - retVal = BZ_OK; - goto save_state_and_return; - -endhdr_2: - case BZ_X_ENDHDR_2: - s->state = BZ_X_ENDHDR_2; - if (get_bits(s, &uc, 8) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - if (uc != 0x72) { - retVal = BZ_DATA_ERROR; - goto save_state_and_return; - } - - case BZ_X_ENDHDR_3: - s->state = BZ_X_ENDHDR_3; - if (get_bits(s, &uc, 8) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - if (uc != 0x45) { - retVal = BZ_DATA_ERROR; - goto save_state_and_return; - } - - case BZ_X_ENDHDR_4: - s->state = BZ_X_ENDHDR_4; - if (get_bits(s, &uc, 8) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - if (uc != 0x38) { - retVal = BZ_DATA_ERROR; - goto save_state_and_return; - } - - case BZ_X_ENDHDR_5: - s->state = BZ_X_ENDHDR_5; - if (get_bits(s, &uc, 8) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - if (uc != 0x50) { - retVal = BZ_DATA_ERROR; - goto save_state_and_return; - } - - case BZ_X_ENDHDR_6: - s->state = BZ_X_ENDHDR_6; - if (get_bits(s, &uc, 8) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - if (uc != 0x90) { - retVal = BZ_DATA_ERROR; - goto save_state_and_return; - } - s->storedCombinedCRC = 0; - - case BZ_X_CCRC_1: - s->state = BZ_X_CCRC_1; - if (get_bits(s, &uc, 8) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((unsigned int)uc); - case BZ_X_CCRC_2: - s->state = BZ_X_CCRC_2; - if (get_bits(s, &uc, 8) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((unsigned int)uc); - - case BZ_X_CCRC_3: - s->state = BZ_X_CCRC_3; - if (get_bits(s, &uc, 8) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((unsigned int)uc); - - case BZ_X_CCRC_4: - s->state = BZ_X_CCRC_4; - if (get_bits(s, &uc, 8) == FALSE) { - retVal = BZ_OK; - goto save_state_and_return; - } - s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((unsigned int)uc); - - s->state = BZ_X_IDLE; - retVal = BZ_STREAM_END; - goto save_state_and_return; - -default: - printf("switch val is %d\n", switch_val); - assert_h(4001); - } - - assert_h(4002); - -save_state_and_return: - s->save_i = i; - s->save_j = j; - s->save_t = t; - s->save_alphaSize = alphaSize; - s->save_nGroups = nGroups; - s->save_nSelectors = nSelectors; - s->save_EOB = EOB; - s->save_groupNo = groupNo; - s->save_groupPos = groupPos; - s->save_nextSym = nextSym; - s->save_nblockMAX = nblockMAX; - s->save_nblock = nblock; - s->save_es = es; - s->save_N = N; - s->save_curr = curr; - s->save_zt = zt; - s->save_zn = zn; - s->save_zvec = zvec; - s->save_zj = zj; - s->save_gSel = gSel; - s->save_gMinlen = gMinlen; - s->save_gLimit = gLimit; - s->save_gBase = gBase; - s->save_gPerm = gPerm; - - return retVal; -} - -static void *default_bzalloc(void *opaque, int items, int size) -{ - void *v = xmalloc(items *size); - return v; -} - -static void default_bzfree(void *opaque, void *addr) -{ - if (addr != NULL) { - free(addr); - } -} - -//int BZ2_bzDecompressInit(bz_stream* strm, int verbosity_level, int small) -int BZ2_bzDecompressInit(bz_stream* strm, int small) -{ - DState* s; - - if (sizeof(int) != 4) { - return BZ_CONFIG_ERROR; - } - if (sizeof(short) != 2) { - return BZ_CONFIG_ERROR; - } - if (sizeof(char) != 1) { - return BZ_CONFIG_ERROR; - } - if (strm == NULL) { - return BZ_PARAM_ERROR; - } - if (small != 0 && small != 1) { - return BZ_PARAM_ERROR; - } -// if (verbosity_level < 0 || verbosity_level > 4) { -// return BZ_PARAM_ERROR; -// } - if (strm->bzalloc == NULL) { - strm->bzalloc = default_bzalloc; - } - if (strm->bzfree == NULL) { - strm->bzfree = default_bzfree; - } - s = (strm->bzalloc)(strm->opaque, sizeof(DState), 1); - if (s == NULL) { - return BZ_MEM_ERROR; - } - s->strm = strm; - strm->state = s; - s->state = BZ_X_MAGIC_1; - s->bsLive = 0; - s->bsBuff = 0; - s->calculatedCombinedCRC = 0; - strm->total_in_lo32 = 0; - strm->total_in_hi32 = 0; - strm->total_out_lo32 = 0; - strm->total_out_hi32 = 0; - s->smallDecompress = (unsigned char)small; - s->ll4 = NULL; - s->ll16 = NULL; - s->tt = NULL; - s->currBlockNo = 0; -// s->verbosity = verbosity_level; - - return BZ_OK; -} - -void bz_seterr(int eee, int *bzerror, bzFile **bzf) -{ - if (bzerror != NULL) { - *bzerror = eee; - } - if (*bzf != NULL) { - (*bzf)->lastErr = eee; - } -} - -void BZ2_bzReadClose(int *bzerror, void *b) -{ - bzFile* bzf = (bzFile*)b; - - bz_seterr(BZ_OK, bzerror, &bzf); - if (bzf == NULL) { - bz_seterr(BZ_OK, bzerror, &bzf); - return; - } - - if (bzf->writing) { - bz_seterr(BZ_SEQUENCE_ERROR, bzerror, &bzf); - return; - } - - if (bzf->initialisedOk) { - bz_stream *strm = &(bzf->strm); - DState *s; - if (strm == NULL) { - return; - } - s = strm->state; - if ((s == NULL) || (s->strm != strm)) { - return; - } - if (s->tt != NULL) { - (strm->bzfree)(strm->opaque,(s->tt)); - } - if (s->ll16 != NULL) { - (strm->bzfree)(strm->opaque,(s->ll16)); - } - if (s->ll4 != NULL) { - (strm->bzfree)(strm->opaque,(s->ll4)); - } - (strm->bzfree)(strm->opaque,(strm->state)); - strm->state = NULL; - return; - } - free(bzf); -} - -static void unRLE_obuf_to_output_FAST(DState *s) -{ - unsigned char k1; - - if (s->blockRandomised) { - while (1) { - /* try to finish existing run */ - while (1) { - if (s->strm->avail_out == 0) { - return; - } - if (s->state_out_len == 0) { - break; - } - *((unsigned char *)(s->strm->next_out)) = s->state_out_ch; - s->calculatedBlockCRC = (s->calculatedBlockCRC << 8) ^ - BZ2_crc32Table[(s->calculatedBlockCRC >> 24) ^ - ((unsigned char)s->state_out_ch)]; - s->state_out_len--; - s->strm->next_out++; - s->strm->avail_out--; - s->strm->total_out_lo32++; - if (s->strm->total_out_lo32 == 0) { - s->strm->total_out_hi32++; - } - } - - /* can a new run be started? */ - if (s->nblock_used == s->save_nblock+1) { - return; - } - s->state_out_len = 1; - s->state_out_ch = s->k0; - k1 = bz_get_fast(s); - bz_rand_udp_mask(s); - k1 ^= ((s->rNToGo == 1) ? 1 : 0); - s->nblock_used++; - if (s->nblock_used == s->save_nblock+1) { - continue; - } - if (k1 != s->k0) { - s->k0 = k1; - continue; - } - - s->state_out_len = 2; - k1 = bz_get_fast(s); - bz_rand_udp_mask(s); - k1 ^= ((s->rNToGo == 1) ? 1 : 0); - s->nblock_used++; - if (s->nblock_used == s->save_nblock+1) { - continue; - } - if (k1 != s->k0) { - s->k0 = k1; - continue; - } - s->state_out_len = 3; - k1 = bz_get_fast(s); - bz_rand_udp_mask(s); - k1 ^= ((s->rNToGo == 1) ? 1 : 0); - s->nblock_used++; - if (s->nblock_used == s->save_nblock+1) { - continue; - } - if (k1 != s->k0) { - s->k0 = k1; - continue; - } - - k1 = bz_get_fast(s); - bz_rand_udp_mask(s); - k1 ^= ((s->rNToGo == 1) ? 1 : 0); - s->nblock_used++; - s->state_out_len = ((int)k1) + 4; - s->k0 = bz_get_fast(s); - bz_rand_udp_mask(s); - s->k0 ^= ((s->rNToGo == 1) ? 1 : 0); - s->nblock_used++; - } - } else { - /* restore */ - unsigned int c_calculatedBlockCRC = s->calculatedBlockCRC; - unsigned char c_state_out_ch = s->state_out_ch; - int c_state_out_len = s->state_out_len; - int c_nblock_used = s->nblock_used; - int c_k0 = s->k0; - unsigned int *c_tt = s->tt; - unsigned int c_tPos = s->tPos; - char *cs_next_out = s->strm->next_out; - unsigned int cs_avail_out = s->strm->avail_out; - /* end restore */ - - unsigned int avail_out_INIT = cs_avail_out; - int s_save_nblockPP = s->save_nblock+1; - unsigned int total_out_lo32_old; - - while (1) { - /* try to finish existing run */ - if (c_state_out_len > 0) { - while (TRUE) { - if (cs_avail_out == 0) { - goto return_notr; - } - if (c_state_out_len == 1) { - break; - } - *((unsigned char *)(cs_next_out)) = c_state_out_ch; - c_calculatedBlockCRC = (c_calculatedBlockCRC << 8) ^ - BZ2_crc32Table[(c_calculatedBlockCRC >> 24) ^ - ((unsigned char)c_state_out_ch)]; - c_state_out_len--; - cs_next_out++; - cs_avail_out--; - } -s_state_out_len_eq_one: - { - if (cs_avail_out == 0) { - c_state_out_len = 1; - goto return_notr; - } - *((unsigned char *)(cs_next_out)) = c_state_out_ch; - c_calculatedBlockCRC = (c_calculatedBlockCRC << 8) ^ - BZ2_crc32Table[(c_calculatedBlockCRC >> 24) ^ - ((unsigned char)c_state_out_ch)]; - cs_next_out++; - cs_avail_out--; - } - } - /* can a new run be started? */ - if (c_nblock_used == s_save_nblockPP) { - c_state_out_len = 0; goto return_notr; - } - c_state_out_ch = c_k0; - c_tPos = c_tt[c_tPos]; - k1 = (unsigned char)(c_tPos & 0xff); - c_tPos >>= 8; - - c_nblock_used++; - - if (k1 != c_k0) { - c_k0 = k1; - goto s_state_out_len_eq_one; - } - - if (c_nblock_used == s_save_nblockPP) { - goto s_state_out_len_eq_one; - } - - c_state_out_len = 2; - c_tPos = c_tt[c_tPos]; - k1 = (unsigned char)(c_tPos & 0xff); - c_tPos >>= 8; - - c_nblock_used++; - if (c_nblock_used == s_save_nblockPP) { - continue; - } - if (k1 != c_k0) { - c_k0 = k1; - continue; - } - - c_state_out_len = 3; - c_tPos = c_tt[c_tPos]; - k1 = (unsigned char)(c_tPos & 0xff); - c_tPos >>= 8; - - c_nblock_used++; - if (c_nblock_used == s_save_nblockPP) { - continue; - } - if (k1 != c_k0) { - c_k0 = k1; - continue; - } - - c_tPos = c_tt[c_tPos]; - k1 = (unsigned char)(c_tPos & 0xff); - c_tPos >>= 8; - - c_nblock_used++; - c_state_out_len = ((int)k1) + 4; - - c_tPos = c_tt[c_tPos]; - c_k0 = (unsigned char)(c_tPos & 0xff); - c_tPos >>= 8; - - c_nblock_used++; - } - -return_notr: - total_out_lo32_old = s->strm->total_out_lo32; - s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out); - if (s->strm->total_out_lo32 < total_out_lo32_old) { - s->strm->total_out_hi32++; - } - - /* save */ - s->calculatedBlockCRC = c_calculatedBlockCRC; - s->state_out_ch = c_state_out_ch; - s->state_out_len = c_state_out_len; - s->nblock_used = c_nblock_used; - s->k0 = c_k0; - s->tt = c_tt; - s->tPos = c_tPos; - s->strm->next_out = cs_next_out; - s->strm->avail_out = cs_avail_out; - /* end save */ - } -} - -static void unRLE_obuf_to_output_SMALL(DState *s) -{ - unsigned char k1; - - if (s->blockRandomised) { - while (1) { - /* try to finish existing run */ - while (1) { - if (s->strm->avail_out == 0) { - return; - } - if (s->state_out_len == 0) { - break; - } - *((unsigned char *)(s->strm->next_out)) = s->state_out_ch; - s->calculatedBlockCRC = (s->calculatedBlockCRC << 8) ^ - BZ2_crc32Table[(s->calculatedBlockCRC >> 24) ^ - ((unsigned char)s->state_out_ch)]; - s->state_out_len--; - s->strm->next_out++; - s->strm->avail_out--; - s->strm->total_out_lo32++; - if (s->strm->total_out_lo32 == 0) { - s->strm->total_out_hi32++; - } - } - - /* can a new run be started? */ - if (s->nblock_used == s->save_nblock+1) { - return; - } - - s->state_out_len = 1; - s->state_out_ch = s->k0; - k1 = bz_get_small(s); - bz_rand_udp_mask(s); - k1 ^= ((s->rNToGo == 1) ? 1 : 0); - s->nblock_used++; - if (s->nblock_used == s->save_nblock+1) { - continue; - } - if (k1 != s->k0) { - s->k0 = k1; - continue; - } - - s->state_out_len = 2; - k1 = bz_get_small(s); - bz_rand_udp_mask(s); - k1 ^= ((s->rNToGo == 1) ? 1 : 0); - s->nblock_used++; - if (s->nblock_used == s->save_nblock+1) { - continue; - } - if (k1 != s->k0) { - s->k0 = k1; - continue; - } - - s->state_out_len = 3; - k1 = bz_get_small(s); - bz_rand_udp_mask(s); - k1 ^= ((s->rNToGo == 1) ? 1 : 0); - s->nblock_used++; - if (s->nblock_used == s->save_nblock+1) { - continue; - } - if (k1 != s->k0) { - s->k0 = k1; - continue; - } - k1 = bz_get_small(s); - bz_rand_udp_mask(s); - k1 ^= ((s->rNToGo == 1) ? 1 : 0); - s->nblock_used++; - s->state_out_len = ((int)k1) + 4; - s->k0 = bz_get_small(s); - bz_rand_udp_mask(s); - s->k0 ^= ((s->rNToGo == 1) ? 1 : 0); - s->nblock_used++; - } - } else { - while (1) { - /* try to finish existing run */ - while (1) { - if (s->strm->avail_out == 0) { - return; - } - if (s->state_out_len == 0) { - break; - } - *((unsigned char *)(s->strm->next_out)) = s->state_out_ch; - s->calculatedBlockCRC = (s->calculatedBlockCRC << 8) ^ - BZ2_crc32Table[(s->calculatedBlockCRC >> 24) ^ - ((unsigned char)s->state_out_ch)]; - s->state_out_len--; - s->strm->next_out++; - s->strm->avail_out--; - s->strm->total_out_lo32++; - if (s->strm->total_out_lo32 == 0) { - s->strm->total_out_hi32++; - } - } - - /* can a new run be started? */ - if (s->nblock_used == s->save_nblock+1) { - return; - } - - s->state_out_len = 1; - s->state_out_ch = s->k0; - k1 = bz_get_small(s); - s->nblock_used++; - if (s->nblock_used == s->save_nblock+1) { - continue; - } - if (k1 != s->k0) { - s->k0 = k1; - continue; - } - - s->state_out_len = 2; - k1 = bz_get_small(s); - s->nblock_used++; - if (s->nblock_used == s->save_nblock+1) { - continue; - } - if (k1 != s->k0) { - s->k0 = k1; - continue; - } - - s->state_out_len = 3; - k1 = bz_get_small(s); - s->nblock_used++; - if (s->nblock_used == s->save_nblock+1) { - continue; - } - if (k1 != s->k0) { - s->k0 = k1; - continue; - } - - k1 = bz_get_small(s); - s->nblock_used++; - s->state_out_len = ((int)k1) + 4; - s->k0 = bz_get_small(s); - s->nblock_used++; - } - } -} - -int BZ2_bzDecompress(bz_stream *strm) -{ - DState* s; - if (strm == NULL) { - return BZ_PARAM_ERROR; - } - s = strm->state; - if (s == NULL) { - return BZ_PARAM_ERROR; - } - if (s->strm != strm) { - return BZ_PARAM_ERROR; - } - - while (1) { - if (s->state == BZ_X_IDLE) { - return BZ_SEQUENCE_ERROR; - } - if (s->state == BZ_X_OUTPUT) { - if (s->smallDecompress) { - unRLE_obuf_to_output_SMALL(s); - } else { - unRLE_obuf_to_output_FAST(s); - } - if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) { - s->calculatedBlockCRC = ~(s->calculatedBlockCRC); - if (s->verbosity >= 3) { - error_msg("{0x%x, 0x%x}", s->storedBlockCRC, s->calculatedBlockCRC); - } - if (s->verbosity >= 2) { - error_msg("]"); - } - if (s->calculatedBlockCRC != s->storedBlockCRC) { - return BZ_DATA_ERROR; - } - s->calculatedCombinedCRC = (s->calculatedCombinedCRC << 1) | (s->calculatedCombinedCRC >> 31); - s->calculatedCombinedCRC ^= s->calculatedBlockCRC; - s->state = BZ_X_BLKHDR_1; - } else { - return BZ_OK; - } - } - if (s->state >= BZ_X_MAGIC_1) { - int r = BZ2_decompress(s); - if (r == BZ_STREAM_END) { - if (s->verbosity >= 3) { - error_msg("\n combined CRCs: stored = 0x%x, computed = 0x%x", - s->storedCombinedCRC, s->calculatedCombinedCRC ); - } - if (s->calculatedCombinedCRC != s->storedCombinedCRC) { - return BZ_DATA_ERROR; - } - return r; - } - if (s->state != BZ_X_OUTPUT) { - return r; - } - } - } - - assert_h(6001); - - return(0); /*NOTREACHED*/ -} - -int BZ2_bzRead(int *bzerror, void *b, void *buf, int len) -{ - int n, ret; - bzFile *bzf = (bzFile*)b; - - bz_seterr(BZ_OK, bzerror, &bzf); - - if (bzf == NULL || buf == NULL || len < 0) { - bz_seterr(BZ_PARAM_ERROR, bzerror, &bzf); - return 0; - } - - if (bzf->writing) { - bz_seterr(BZ_SEQUENCE_ERROR, bzerror, &bzf); - return 0; - } - - if (len == 0) { - bz_seterr(BZ_OK, bzerror, &bzf); - return 0; - } - - bzf->strm.avail_out = len; - bzf->strm.next_out = buf; - - while (1) { - if (ferror(bzf->handle)) { - bz_seterr(BZ_IO_ERROR, bzerror, &bzf); - return 0; - } - if ((bzf->strm.avail_in == 0) && !myfeof(bzf->handle)) { - n = fread(bzf->buf, sizeof(unsigned char), BZ_MAX_UNUSED, bzf->handle); - if (ferror(bzf->handle)) { - bz_seterr(BZ_IO_ERROR, bzerror, &bzf); - return 0; - } - bzf->bufN = n; - bzf->strm.avail_in = bzf->bufN; - bzf->strm.next_in = bzf->buf; - } - - ret = BZ2_bzDecompress(&(bzf->strm)); - - if ((ret != BZ_OK) && (ret != BZ_STREAM_END)) { - bz_seterr(ret, bzerror, &bzf); - return 0; - } - - if ((ret == BZ_OK) && myfeof(bzf->handle) && - (bzf->strm.avail_in == 0) && (bzf->strm.avail_out > 0)) { - bz_seterr(BZ_UNEXPECTED_EOF, bzerror, &bzf); - return(0); - } - - if (ret == BZ_STREAM_END) { - bz_seterr(BZ_STREAM_END, bzerror, &bzf); - return(len - bzf->strm.avail_out); - } - if (bzf->strm.avail_out == 0) { - bz_seterr(BZ_OK, bzerror, &bzf); - return(len); - } - } - return(0); /*not reached*/ -} - -void BZ2_bzReadGetUnused(int *bzerror, void *b, void **unused, int *nUnused) -{ - bzFile *bzf = (bzFile*)b; - if (bzf == NULL) { - bz_seterr(BZ_PARAM_ERROR, bzerror, &bzf); - return; - } - if (bzf->lastErr != BZ_STREAM_END) { - bz_seterr(BZ_SEQUENCE_ERROR, bzerror, &bzf); - return; - } - if (unused == NULL || nUnused == NULL) { - bz_seterr(BZ_PARAM_ERROR, bzerror, &bzf); - return; - } - - bz_seterr(BZ_OK, bzerror, &bzf); - *nUnused = bzf->strm.avail_in; - *unused = bzf->strm.next_in; -} - -void *BZ2_bzReadOpen(int *bzerror, FILE *f, int small, void *unused, int nUnused) -{ - bzFile *bzf = NULL; - int ret; - - bz_seterr(BZ_OK, bzerror, &bzf); - - if (f == NULL || (small != 0 && small != 1) || - (unused != NULL && (nUnused < 0 || nUnused > BZ_MAX_UNUSED)) || -// (verbosity_level < 0 || verbosity_level > 4) || - (unused == NULL && nUnused != 0)) { - bz_seterr(BZ_PARAM_ERROR, bzerror, &bzf); - return NULL; - } - - if (ferror(f)) { - bz_seterr(BZ_IO_ERROR, bzerror, &bzf); - return NULL; - } - - bzf = xmalloc(sizeof(bzFile)); - if (bzf == NULL) { - bz_seterr(BZ_MEM_ERROR, bzerror, &bzf); - return NULL; - } - bz_seterr(BZ_OK, bzerror, &bzf); - - bzf->initialisedOk = FALSE; - bzf->handle = f; - bzf->bufN = 0; - bzf->writing = FALSE; - bzf->strm.bzalloc = NULL; - bzf->strm.bzfree = NULL; - bzf->strm.opaque = NULL; - - while (nUnused > 0) { - bzf->buf[bzf->bufN] = *((unsigned char *)(unused)); bzf->bufN++; - unused = ((void *)( 1 + ((unsigned char *)(unused)) )); - nUnused--; - } - - ret = BZ2_bzDecompressInit(&(bzf->strm), small); - if (ret != BZ_OK) { - bz_seterr(ret, bzerror, &bzf); - free(bzf); - return NULL; - } - - bzf->strm.avail_in = bzf->bufN; - bzf->strm.next_in = bzf->buf; - - bzf->initialisedOk = TRUE; - return bzf; -} - -static unsigned char uncompressStream(FILE *zStream, FILE *stream) -{ - unsigned char unused[BZ_MAX_UNUSED]; - unsigned char *unusedTmp; - unsigned char obuf[5000]; - void *bzf = NULL; - int bzerr_dummy; - int bzerr; - int nread; - int nUnused; - int streamNo; - int ret; - int i; - - nUnused = 0; - streamNo = 0; - - if (ferror(stream)) { - goto errhandler_io; - } - if (ferror(zStream)) { - goto errhandler_io; - } - - while(1) { - bzf = BZ2_bzReadOpen(&bzerr, zStream, (int)smallMode, unused, nUnused); - if (bzf == NULL || bzerr != BZ_OK) { - goto errhandler; - } - streamNo++; - - while (bzerr == BZ_OK) { - nread = BZ2_bzRead(&bzerr, bzf, obuf, 5000); - if (bzerr == BZ_DATA_ERROR_MAGIC) { - goto errhandler; - } - if ((bzerr == BZ_OK || bzerr == BZ_STREAM_END) && nread > 0) { - fwrite(obuf, sizeof(unsigned char), nread, stream); - } - if (ferror(stream)) { - goto errhandler_io; - } - } - if (bzerr != BZ_STREAM_END) { - goto errhandler; - } - BZ2_bzReadGetUnused(&bzerr, bzf, (void **)(&unusedTmp), &nUnused); - if (bzerr != BZ_OK) { - panic("decompress:bzReadGetUnused"); - } - for (i = 0; i < nUnused; i++) { - unused[i] = unusedTmp[i]; - } - BZ2_bzReadClose(&bzerr, bzf); - if (bzerr != BZ_OK) { - panic("decompress:bzReadGetUnused"); - } - if ((nUnused == 0) && myfeof(zStream)) { - break; - } - } - - if (ferror(zStream)) { - goto errhandler_io; - } - ret = fclose(zStream); - if (ret == EOF) { - goto errhandler_io; - } - if (ferror(stream)) { - goto errhandler_io; - } - ret = fflush(stream); - if (ret != 0) { - goto errhandler_io; - } - if (stream != stdout) { - ret = fclose(stream); - if (ret == EOF) { - goto errhandler_io; - } - } -// if (verbosity_level >= 2) { -// fprintf(stderr,"\n "); -// } - return TRUE; - -errhandler: - BZ2_bzReadClose ( &bzerr_dummy, bzf ); - switch (bzerr) { - case BZ_CONFIG_ERROR: - error_msg("bzip2: I'm not configured correctly for this platform!\n" - "\tI require Int32, Int16 and Char to have sizes\n" - "\tof 4, 2 and 1 bytes to run properly, and they don't.\n" - "\tProbably you can fix this by defining them correctly,\n" - "\tand recompiling. Bye!\n" ); - exit(3); - case BZ_IO_ERROR: -errhandler_io: - error_msg("\n%s: I/O or other error, bailing out. " - "Possible reason follows.\n", progName); - perror(progName); - cleanUpAndFail(1); - case BZ_DATA_ERROR: - error_msg("\n%s: Data integrity error when decompressing.\n", progName); - cleanUpAndFail(2); - case BZ_MEM_ERROR: - error_msg("\n%s: couldn't allocate enough memory\n", progName); - cleanUpAndFail(1); - case BZ_UNEXPECTED_EOF: - error_msg("\n%s: Compressed file ends unexpectedly;\n\t" - "perhaps it is corrupted? *Possible* reason follows.\n", progName); - perror(progName); - cleanUpAndFail(2); - case BZ_DATA_ERROR_MAGIC: - if (zStream != stdin) { - fclose(zStream); - } - if (stream != stdout) { - fclose(stream); - } - if (streamNo == 1) { - return FALSE; - } else { - if (noisy) { - error_msg("\n%s: %s: trailing garbage after EOF ignored\n", progName, inName ); - } - return TRUE; - } - default: - panic ( "decompress:unexpected error" ); - } - - panic("decompress:end"); - return(TRUE); /*notreached*/ -} - -int bunzip2_main(int argc, char **argv) -{ - FILE *src_stream; - FILE *dst_stream; - char *save_name; - char *save_name_ptr; - if (argc != 2) { - show_usage(); - } - src_stream = xfopen(argv[1], "r"); - save_name = strdup(argv[1]); - save_name_ptr = strrchr(save_name, '.'); - if (save_name_ptr == NULL) { - return(FALSE); - } - if (strcmp(save_name_ptr, ".bz2") != 0) { - error_msg("Invalid extension, expected .bz2"); - } - *save_name_ptr = '\0'; - dst_stream = xfopen(save_name, "w"); - uncompressStream(src_stream, dst_stream); - - return(TRUE); -} diff --git a/busybox.c b/busybox.c deleted file mode 100644 index 33efb5d84..000000000 --- a/busybox.c +++ /dev/null @@ -1,181 +0,0 @@ -/* vi: set sw=4 ts=4: */ -#include -#include -#include -#include -#include -#include "busybox.h" -#ifdef BB_LOCALE_SUPPORT -#include -#endif - -int been_there_done_that = 0; /* Also used in applets.c */ -const char *applet_name; - -#ifdef BB_FEATURE_INSTALLER -/* - * directory table - * this should be consistent w/ the enum, busybox.h::Location, - * or else... - */ -static char* install_dir[] = { - "/", - "/bin", - "/sbin", - "/usr/bin", - "/usr/sbin", -}; - -/* abstract link() */ -typedef int (*__link_f)(const char *, const char *); - -/* - * Where in the filesystem is this busybox? - * [return] - * malloc'd string w/ full pathname of busybox's location - * NULL on failure - */ -static char *busybox_fullpath() -{ - return xreadlink("/proc/self/exe"); -} - -/* create (sym)links for each applet */ -static void install_links(const char *busybox, int use_symbolic_links) -{ - __link_f Link = link; - - char *fpc; - int i; - int rc; - - if (use_symbolic_links) - Link = symlink; - - for (i = 0; applets[i].name != NULL; i++) { - fpc = concat_path_file( - install_dir[applets[i].location], applets[i].name); - rc = Link(busybox, fpc); - if (rc!=0 && errno!=EEXIST) { - perror_msg("%s", fpc); - } - free(fpc); - } -} - -#endif /* BB_FEATURE_INSTALLER */ - -int main(int argc, char **argv) -{ - const char *s; - - applet_name = argv[0]; - - if (applet_name[0] == '-') - applet_name++; - - for (s = applet_name; *s != '\0';) { - if (*s++ == '/') - applet_name = s; - } - -#ifdef BB_LOCALE_SUPPORT -#ifdef BB_INIT - if(getpid()!=1) /* Do not set locale for `init' */ -#endif - { - setlocale(LC_ALL, ""); - } -#endif - - run_applet_by_name(applet_name, argc, argv); - error_msg_and_die("applet not found"); -} - - -int busybox_main(int argc, char **argv) -{ - int col = 0, len, i; - -#ifdef BB_FEATURE_INSTALLER - /* - * This style of argument parsing doesn't scale well - * in the event that busybox starts wanting more --options. - * If someone has a cleaner approach, by all means implement it. - */ - if (argc > 1 && (strcmp(argv[1], "--install") == 0)) { - int use_symbolic_links = 0; - int rc = 0; - char *busybox; - - /* to use symlinks, or not to use symlinks... */ - if (argc > 2) { - if ((strcmp(argv[2], "-s") == 0)) { - use_symbolic_links = 1; - } - } - - /* link */ - busybox = busybox_fullpath(); - if (busybox) { - install_links(busybox, use_symbolic_links); - free(busybox); - } else { - rc = 1; - } - return rc; - } -#endif /* BB_FEATURE_INSTALLER */ - - argc--; - - /* If we've already been here once, exit now */ - if (been_there_done_that == 1 || argc < 1) { - const struct BB_applet *a = applets; - - fprintf(stderr, "%s\n\n" - "Usage: busybox [function] [arguments]...\n" - " or: [function] [arguments]...\n\n" - "\tBusyBox is a multi-call binary that combines many common Unix\n" - "\tutilities into a single executable. Most people will create a\n" - "\tlink to busybox for each function they wish to use, and BusyBox\n" - "\twill act like whatever it was invoked as.\n" - "\nCurrently defined functions:\n", full_version); - - while (a->name != 0) { - col += - fprintf(stderr, "%s%s", ((col == 0) ? "\t" : ", "), - (a++)->name); - if (col > 60 && a->name != 0) { - fprintf(stderr, ",\n"); - col = 0; - } - } - fprintf(stderr, "\n\n"); - exit(0); - } - - /* Flag that we've been here already */ - been_there_done_that = 1; - - /* Move the command line down a notch */ - len = argv[argc] + strlen(argv[argc]) - argv[1]; - memmove(argv[0], argv[1], len); - memset(argv[0] + len, 0, argv[1] - argv[0]); - - /* Fix up the argv pointers */ - len = argv[1] - argv[0]; - memmove(argv, argv + 1, sizeof(char *) * (argc + 1)); - for (i = 0; i < argc; i++) - argv[i] -= len; - - return (main(argc, argv)); -} - -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ diff --git a/busybox.h b/busybox.h deleted file mode 100644 index f79dac8c8..000000000 --- a/busybox.h +++ /dev/null @@ -1,106 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Busybox main internal header file - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * - */ -#ifndef _BB_INTERNAL_H_ -#define _BB_INTERNAL_H_ 1 - -#include "Config.h" - -#include -#include -#include -#include - -#define BB_BANNER "BusyBox v" BB_VER " (" BB_BT ")" - -#ifdef DMALLOC -#include "dmalloc.h" -#endif - -#include - - -enum Location { - _BB_DIR_ROOT = 0, - _BB_DIR_BIN, - _BB_DIR_SBIN, - _BB_DIR_USR_BIN, - _BB_DIR_USR_SBIN -}; - -struct BB_applet { - const char* name; - int (*main)(int argc, char** argv); - enum Location location; -}; -/* From busybox.c */ -extern const struct BB_applet applets[]; - -/* Automagically pull in all the applet function prototypes and - * applet usage strings. These are all of the form: - * extern int foo_main(int argc, char **argv); - * extern const char foo_usage[]; - * These are all autogenerated from the set of currently defined applets. - */ -#define PROTOTYPES -#include "applets.h" -#undef PROTOTYPES - -#ifdef BB_FEATURE_BUFFERS_GO_ON_STACK -#define RESERVE_BB_BUFFER(buffer,len) char buffer[len] -#define RESERVE_BB_UBUFFER(buffer,len) unsigned char buffer[len] -#define RELEASE_BB_BUFFER(buffer) ((void)0) -#else -#ifdef BB_FEATURE_BUFFERS_GO_IN_BSS -#define RESERVE_BB_BUFFER(buffer,len) static char buffer[len] -#define RESERVE_BB_UBUFFER(buffer,len) static unsigned char buffer[len] -#define RELEASE_BB_BUFFER(buffer) ((void)0) -#else -#define RESERVE_BB_BUFFER(buffer,len) char *buffer=xmalloc(len) -#define RESERVE_BB_UBUFFER(buffer,len) unsigned char *buffer=xmalloc(len) -#define RELEASE_BB_BUFFER(buffer) free (buffer) -#endif -#endif - - -/* Bit map related macros -- libc5 doens't provide these... sigh. */ -#ifndef setbit -#define NBBY CHAR_BIT -#define setbit(a,i) ((a)[(i)/NBBY] |= 1<<((i)%NBBY)) -#define clrbit(a,i) ((a)[(i)/NBBY] &= ~(1<<((i)%NBBY))) -#define isset(a,i) ((a)[(i)/NBBY] & (1<<((i)%NBBY))) -#define isclr(a,i) (((a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0) -#endif - -#ifndef RB_POWER_OFF -/* Stop system and switch power off if possible. */ -#define RB_POWER_OFF 0x4321fedc -#endif - - -/* Pull in the utility routines from libbb */ -#include "libbb/libbb.h" - - - -#endif /* _BB_INTERNAL_H_ */ diff --git a/busybox.mkll b/busybox.mkll deleted file mode 100755 index 4e15e1611..000000000 --- a/busybox.mkll +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh -# Make busybox links list file. - -# input $1: full path to Config.h -# input $2: full path to applets.h -# output (stdout): list of pathnames that should be linked to busybox - -# Maintainer: Larry Doolittle - -export LC_ALL=POSIX -export LC_CTYPE=POSIX - -CONFIG_H=${1:-Config.h} -APPLETS_H=${2:-applets.h} -gcc -E -DMAKE_LINKS -include $CONFIG_H $APPLETS_H | - awk '/^[ \t]*LINK/{ - dir=substr($2,8) - gsub("_","/",dir) - if(dir=="/ROOT") dir="" - file=$3 - gsub("\"","",file) - if (file=="busybox") next - print tolower(dir) "/" file - }' diff --git a/busybox.sh b/busybox.sh deleted file mode 100755 index 9ab0f4bdb..000000000 --- a/busybox.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh - -export LC_ALL=POSIX -export LC_CTYPE=POSIX - -RAW=` \ - $CC -E -dM ${1:-Config.h} | \ - sed -n -e '/^.*BB_FEATURE.*$/d;s/^#define.*\/\1.c/gp;' \ - | tr A-Z a-z | sort -` -test "${RAW}" != "" || exit -if [ -d "$BB_SRC_DIR" ]; then cd $BB_SRC_DIR; fi -# By running $RAW through "ls", we avoid listing -# source files that don't exist. -ls $RAW 2>/dev/null | tr '\n' ' ' - diff --git a/busybox.spec b/busybox.spec deleted file mode 100644 index cce20583e..000000000 --- a/busybox.spec +++ /dev/null @@ -1,44 +0,0 @@ -%define name busybox -%define epoch 0 -%define version 0.61.pre -%define release %(date -I | sed -e 's/-/_/g') -%define serial 1 - -Name: %{name} -#Epoch: %{epoch} -Version: %{version} -Release: %{release} -Serial: %{serial} -Copyright: GPL -Group: System/Utilities -Summary: BusyBox is a tiny suite of Unix utilities in a multi-call binary. -URL: http://busybox.lineo.com/ -Source: ftp://oss.lineo.com/busybox/%{name}-%{version}.tar.gz -Buildroot: /var/tmp/%{name}-%{version} -Packager : Erik Andersen - -%Description -BusyBox combines tiny versions of many common UNIX utilities into a single -small executable. It provides minimalist replacements for most of the utilities -you usually find in fileutils, shellutils, findutils, textutils, grep, gzip, -tar, etc. BusyBox provides a fairly complete POSIX environment for any small -or emdedded system. The utilities in BusyBox generally have fewer options then -their full featured GNU cousins; however, the options that are provided behave -very much like their GNU counterparts. - -%Prep -%setup -q -n %{name}-%{version} - -%Build -make - -%Install -rm -rf $RPM_BUILD_ROOT -make PREFIX=$RPM_BUILD_ROOT install - -%Clean -rm -rf $RPM_BUILD_ROOT - -%Files -%defattr(-,root,root) -/ diff --git a/cat.c b/cat.c deleted file mode 100644 index aa8528d6a..000000000 --- a/cat.c +++ /dev/null @@ -1,53 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini Cat implementation for busybox - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include "busybox.h" - -extern int cat_main(int argc, char **argv) -{ - int status = EXIT_SUCCESS; - - if (argc == 1) { - print_file(stdin); - return status; - } - - while (--argc > 0) { - if(!(strcmp(*++argv, "-"))) { - print_file(stdin); - } else if (print_file_by_name(*argv) == FALSE) { - status = EXIT_FAILURE; - } - } - return status; -} - -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ diff --git a/chgrp.c b/chgrp.c deleted file mode 100644 index fbc1036a8..000000000 --- a/chgrp.c +++ /dev/null @@ -1,91 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini chown/chmod/chgrp implementation for busybox - * - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include "busybox.h" - -/* Don't use lchown for libc5 or glibc older then 2.1.x */ -#if (__GLIBC__ <= 2) && (__GLIBC_MINOR__ < 1) -#define lchown chown -#endif - - -static long gid; - -static int fileAction(const char *fileName, struct stat *statbuf, void* junk) -{ - if (lchown(fileName, statbuf->st_uid, (gid == -1) ? statbuf->st_gid : gid) == 0) { - return (TRUE); - } - perror(fileName); - return (FALSE); -} - -int chgrp_main(int argc, char **argv) -{ - int opt; - int recursiveFlag = FALSE; - char *p=NULL; - - /* do normal option parsing */ - while ((opt = getopt(argc, argv, "R")) > 0) { - switch (opt) { - case 'R': - recursiveFlag = TRUE; - break; - default: - show_usage(); - } - } - - if (argc > optind && argc > 2 && argv[optind]) { - /* Find the selected group */ - gid = strtoul(argv[optind], &p, 10); /* maybe it's already numeric */ - if (argv[optind] == p) - gid = my_getgrnam(argv[optind]); - } else { - error_msg_and_die(too_few_args); - } - - /* Ok, ready to do the deed now */ - while (++optind < argc) { - if (recursive_action (argv[optind], recursiveFlag, FALSE, FALSE, - fileAction, fileAction, NULL) == FALSE) { - return EXIT_FAILURE; - } - } - return EXIT_SUCCESS; - -} - -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ diff --git a/chmod.c b/chmod.c deleted file mode 100644 index 9139b3f4d..000000000 --- a/chmod.c +++ /dev/null @@ -1,85 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini chown/chmod/chgrp implementation for busybox - * - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include "busybox.h" - -static int fileAction(const char *fileName, struct stat *statbuf, void* junk) -{ - if (!parse_mode((char *)junk, &(statbuf->st_mode))) - error_msg_and_die("internal error"); - if (chmod(fileName, statbuf->st_mode) == 0) - return (TRUE); - perror(fileName); - return (FALSE); -} - -int chmod_main(int argc, char **argv) -{ - int i; - int opt; - int recursiveFlag = FALSE; - - /* do normal option parsing */ - while ((opt = getopt(argc, argv, "R")) > 0) { - switch (opt) { - case 'R': - recursiveFlag = TRUE; - break; - default: - show_usage(); - } - } - - if (argc > optind && argc > 2 && argv[optind]) { - /* Parse the specified mode */ - mode_t mode; - if (parse_mode(argv[optind], &mode) == FALSE) { - error_msg_and_die( "unknown mode: %s", argv[optind]); - } - } else { - error_msg_and_die(too_few_args); - } - - /* Ok, ready to do the deed now */ - for (i = optind + 1; i < argc; i++) { - if (recursive_action (argv[i], recursiveFlag, FALSE, FALSE, fileAction, - fileAction, argv[optind]) == FALSE) { - return EXIT_FAILURE; - } - } - return EXIT_SUCCESS; -} - -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ diff --git a/chown.c b/chown.c deleted file mode 100644 index d1e52deda..000000000 --- a/chown.c +++ /dev/null @@ -1,113 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini chown/chmod/chgrp implementation for busybox - * - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include "busybox.h" - -/* Don't use lchown for libc5 or glibc older then 2.1.x */ -#if (__GLIBC__ <= 2) && (__GLIBC_MINOR__ < 1) -#define lchown chown -#endif - -static long uid; -static long gid; - -static int (*chown_func)(const char *, __uid_t, __gid_t) = chown; - -static int fileAction(const char *fileName, struct stat *statbuf, void* junk) -{ - if (chown_func(fileName, uid, (gid == -1) ? statbuf->st_gid : gid) == 0) { - return (TRUE); - } - perror(fileName); - return (FALSE); -} - -int chown_main(int argc, char **argv) -{ - int opt; - int recursiveFlag = FALSE, - noderefFlag = FALSE; - char *groupName=NULL; - char *p=NULL; - - /* do normal option parsing */ - while ((opt = getopt(argc, argv, "Rh")) > 0) { - switch (opt) { - case 'R': - recursiveFlag = TRUE; - break; - case 'h': - noderefFlag = TRUE; - break; - default: - show_usage(); - } - } - - if (noderefFlag) chown_func = lchown; - - if (argc > optind && argc > 2 && argv[optind]) { - /* First, check if there is a group name here */ - groupName = strchr(argv[optind], '.'); - if (groupName == NULL) - groupName = strchr(argv[optind], ':'); - if (groupName) { - *groupName++ = '\0'; - gid = strtoul(groupName, &p, 10); - if (groupName == p) - gid = my_getgrnam(groupName); - } else { - gid = -1; - } - /* Now check for the username */ - uid = strtoul(argv[optind], &p, 10); /* Is is numeric? */ - if (argv[optind] == p) { - uid = my_getpwnam(argv[optind]); - } - } else { - error_msg_and_die(too_few_args); - } - - /* Ok, ready to do the deed now */ - while (++optind < argc) { - if (recursive_action (argv[optind], recursiveFlag, FALSE, FALSE, - fileAction, fileAction, NULL) == FALSE) { - return EXIT_FAILURE; - } - } - return EXIT_SUCCESS; - -} - -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ diff --git a/chroot.c b/chroot.c deleted file mode 100644 index de6a2ea50..000000000 --- a/chroot.c +++ /dev/null @@ -1,75 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini chroot implementation for busybox - * - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include "busybox.h" - -int chroot_main(int argc, char **argv) -{ - char *prog; - - if ((argc < 2) || (**(argv + 1) == '-')) { - show_usage(); - } - argc--; - argv++; - - if (chroot(*argv) || (chdir("/"))) { - perror_msg_and_die("cannot change root directory to %s", *argv); - } - - argc--; - argv++; - if (argc >= 1) { - prog = *argv; - execvp(*argv, argv); - } else { -#if defined shell_main && defined BB_FEATURE_SH_STANDALONE_SHELL - char shell[] = "/bin/sh"; - char *shell_argv[2] = { shell, NULL }; - applet_name = shell; - shell_main(1, shell_argv); - return EXIT_SUCCESS; -#else - prog = getenv("SHELL"); - if (!prog) - prog = "/bin/sh"; - execlp(prog, prog, NULL); -#endif - } - perror_msg_and_die("cannot execute %s", prog); - -} - - -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ diff --git a/chvt.c b/chvt.c deleted file mode 100644 index c76e9c780..000000000 --- a/chvt.c +++ /dev/null @@ -1,43 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * chvt.c - aeb - 940227 - Change virtual terminal - * - * busyboxed by Erik Andersen - */ - -/* getopt not needed */ - -#include -#include -#include -#include -#include -#include "busybox.h" - -/* From */ -static const int VT_ACTIVATE = 0x5606; /* make vt active */ -static const int VT_WAITACTIVE = 0x5607; /* wait for vt active */ - -int chvt_main(int argc, char **argv) -{ - int fd, num; - - if ((argc != 2) || (**(argv + 1) == '-')) - show_usage(); - fd = get_console_fd("/dev/console"); - num = atoi(argv[1]); - if (ioctl(fd, VT_ACTIVATE, num)) - perror_msg_and_die("VT_ACTIVATE"); - if (ioctl(fd, VT_WAITACTIVE, num)) - perror_msg_and_die("VT_WAITACTIVE"); - return EXIT_SUCCESS; -} - - -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ diff --git a/clear.c b/clear.c deleted file mode 100644 index 503bafa16..000000000 --- a/clear.c +++ /dev/null @@ -1,34 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini clear implementation for busybox - * - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include "busybox.h" - - -extern int clear_main(int argc, char **argv) -{ - printf("\033[H\033[J"); - return EXIT_SUCCESS; -} diff --git a/cmdedit.c b/cmdedit.c deleted file mode 100644 index 16ec2f823..000000000 --- a/cmdedit.c +++ /dev/null @@ -1,1521 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Termios command line History and Editting. - * - * Copyright (c) 1986-2001 may safely be consumed by a BSD or GPL license. - * Written by: Vladimir Oleynik - * - * Used ideas: - * Adam Rogoyski - * Dave Cinege - * Jakub Jelinek (c) 1995 - * Erik Andersen (Majorly adjusted for busybox) - * - * This code is 'as is' with no warranty. - * - * - */ - -/* - Usage and Known bugs: - Terminal key codes are not extensive, and more will probably - need to be added. This version was created on Debian GNU/Linux 2.x. - Delete, Backspace, Home, End, and the arrow keys were tested - to work in an Xterm and console. Ctrl-A also works as Home. - Ctrl-E also works as End. - - Small bugs (simple effect): - - not true viewing if terminal size (x*y symbols) less - size (prompt + editor`s line + 2 symbols) - - not true viewing if length prompt less terminal width - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "busybox.h" - -#ifdef BB_LOCALE_SUPPORT -#define Isprint(c) isprint((c)) -#else -#define Isprint(c) ( (c) >= ' ' && (c) != ((unsigned char)'\233') ) -#endif - -#ifndef TEST - -#define D(x) - -#else - -#define BB_FEATURE_COMMAND_EDITING -#define BB_FEATURE_COMMAND_TAB_COMPLETION -#define BB_FEATURE_COMMAND_USERNAME_COMPLETION -#define BB_FEATURE_NONPRINTABLE_INVERSE_PUT -#define BB_FEATURE_CLEAN_UP - -#define D(x) x - -#endif /* TEST */ - -#ifdef BB_FEATURE_COMMAND_TAB_COMPLETION -#include -#include -#endif - -#ifdef BB_FEATURE_COMMAND_EDITING - -#ifndef BB_FEATURE_COMMAND_TAB_COMPLETION -#undef BB_FEATURE_COMMAND_USERNAME_COMPLETION -#endif - -#if defined(BB_FEATURE_COMMAND_USERNAME_COMPLETION) || defined(BB_FEATURE_SH_FANCY_PROMPT) -#define BB_FEATURE_GETUSERNAME_AND_HOMEDIR -#endif - -#ifdef BB_FEATURE_GETUSERNAME_AND_HOMEDIR -# ifndef TEST -# include "pwd_grp/pwd.h" -# else -# include -# endif /* TEST */ -#endif /* advanced FEATURES */ - - - -struct history { - char *s; - struct history *p; - struct history *n; -}; - -/* Maximum length of the linked list for the command line history */ -static const int MAX_HISTORY = 15; - -/* First element in command line list */ -static struct history *his_front = NULL; - -/* Last element in command line list */ -static struct history *his_end = NULL; - - -#include -#define setTermSettings(fd,argp) tcsetattr(fd,TCSANOW,argp) -#define getTermSettings(fd,argp) tcgetattr(fd, argp); - -/* Current termio and the previous termio before starting sh */ -static struct termios initial_settings, new_settings; - - -static -volatile int cmdedit_termw = 80; /* actual terminal width */ -static int history_counter = 0; /* Number of commands in history list */ -static -volatile int handlers_sets = 0; /* Set next bites: */ - -enum { - SET_ATEXIT = 1, /* when atexit() has been called - and get euid,uid,gid to fast compare */ - SET_WCHG_HANDLERS = 2, /* winchg signal handler */ - SET_RESET_TERM = 4, /* if the terminal needs to be reset upon exit */ -}; - - -static int cmdedit_x; /* real x terminal position */ -static int cmdedit_y; /* pseudoreal y terminal position */ -static int cmdedit_prmt_len; /* lenght prompt without colores string */ - -static int cursor; /* required global for signal handler */ -static int len; /* --- "" - - "" - -"- --""-- --""--- */ -static char *command_ps; /* --- "" - - "" - -"- --""-- --""--- */ -static -#ifndef BB_FEATURE_SH_FANCY_PROMPT - const -#endif -char *cmdedit_prompt; /* --- "" - - "" - -"- --""-- --""--- */ - -#ifdef BB_FEATURE_GETUSERNAME_AND_HOMEDIR -static char *user_buf = ""; -static char *home_pwd_buf = ""; -static int my_euid; -#endif - -#ifdef BB_FEATURE_SH_FANCY_PROMPT -static char *hostname_buf = ""; -static int num_ok_lines = 1; -#endif - - -#ifdef BB_FEATURE_COMMAND_TAB_COMPLETION - -#ifndef BB_FEATURE_GETUSERNAME_AND_HOMEDIR -static int my_euid; -#endif - -static int my_uid; -static int my_gid; - -#endif /* BB_FEATURE_COMMAND_TAB_COMPLETION */ - -/* It seems that libc5 doesn't know what a sighandler_t is... */ -#if (__GLIBC__ <= 2) && (__GLIBC_MINOR__ < 1) -typedef void (*sighandler_t) (int); -#endif - -static void cmdedit_setwidth(int w, int redraw_flg); - -static void win_changed(int nsig) -{ - struct winsize win = { 0, 0, 0, 0 }; - static sighandler_t previous_SIGWINCH_handler; /* for reset */ - - /* emulate || signal call */ - if (nsig == -SIGWINCH || nsig == SIGWINCH) { - ioctl(0, TIOCGWINSZ, &win); - if (win.ws_col > 0) { - cmdedit_setwidth(win.ws_col, nsig == SIGWINCH); - } - } - /* Unix not all standart in recall signal */ - - if (nsig == -SIGWINCH) /* save previous handler */ - previous_SIGWINCH_handler = signal(SIGWINCH, win_changed); - else if (nsig == SIGWINCH) /* signaled called handler */ - signal(SIGWINCH, win_changed); /* set for next call */ - else /* nsig == 0 */ - /* set previous handler */ - signal(SIGWINCH, previous_SIGWINCH_handler); /* reset */ -} - -static void cmdedit_reset_term(void) -{ - if ((handlers_sets & SET_RESET_TERM) != 0) { -/* sparc and other have broken termios support: use old termio handling. */ - setTermSettings(fileno(stdin), (void *) &initial_settings); - handlers_sets &= ~SET_RESET_TERM; - } - if ((handlers_sets & SET_WCHG_HANDLERS) != 0) { - /* reset SIGWINCH handler to previous (default) */ - win_changed(0); - handlers_sets &= ~SET_WCHG_HANDLERS; - } - fflush(stdout); -#ifdef BB_FEATURE_CLEAN_UP - if (his_front) { - struct history *n; - - while (his_front != his_end) { - n = his_front->n; - free(his_front->s); - free(his_front); - his_front = n; - } - } -#endif -} - - -/* special for recount position for scroll and remove terminal margin effect */ -static void cmdedit_set_out_char(int next_char) -{ - - int c = (int)((unsigned char) command_ps[cursor]); - - if (c == 0) - c = ' '; /* destroy end char? */ -#ifdef BB_FEATURE_NONPRINTABLE_INVERSE_PUT - if (!Isprint(c)) { /* Inverse put non-printable characters */ - if (c >= 128) - c -= 128; - if (c < ' ') - c += '@'; - if (c == 127) - c = '?'; - printf("\033[7m%c\033[0m", c); - } else -#endif - putchar(c); - if (++cmdedit_x >= cmdedit_termw) { - /* terminal is scrolled down */ - cmdedit_y++; - cmdedit_x = 0; - - if (!next_char) - next_char = ' '; - /* destroy "(auto)margin" */ - putchar(next_char); - putchar('\b'); - } - cursor++; -} - -/* Move to end line. Bonus: rewrite line from cursor */ -static void input_end(void) -{ - while (cursor < len) - cmdedit_set_out_char(0); -} - -/* Go to the next line */ -static void goto_new_line(void) -{ - input_end(); - if (cmdedit_x) - putchar('\n'); -} - - -static inline void out1str(const char *s) -{ - fputs(s, stdout); -} -static inline void beep(void) -{ - putchar('\007'); -} - -/* Move back one charactor */ -/* special for slow terminal */ -static void input_backward(int num) -{ - if (num > cursor) - num = cursor; - cursor -= num; /* new cursor (in command, not terminal) */ - - if (cmdedit_x >= num) { /* no to up line */ - cmdedit_x -= num; - if (num < 4) - while (num-- > 0) - putchar('\b'); - - else - printf("\033[%dD", num); - } else { - int count_y; - - if (cmdedit_x) { - putchar('\r'); /* back to first terminal pos. */ - num -= cmdedit_x; /* set previous backward */ - } - count_y = 1 + num / cmdedit_termw; - printf("\033[%dA", count_y); - cmdedit_y -= count_y; - /* require forward after uping */ - cmdedit_x = cmdedit_termw * count_y - num; - printf("\033[%dC", cmdedit_x); /* set term cursor */ - } -} - -static void put_prompt(void) -{ - out1str(cmdedit_prompt); - cmdedit_x = cmdedit_prmt_len; /* count real x terminal position */ - cursor = 0; - cmdedit_y = 0; /* new quasireal y */ -} - -#ifndef BB_FEATURE_SH_FANCY_PROMPT -static void parse_prompt(const char *prmt_ptr) -{ - cmdedit_prompt = prmt_ptr; - cmdedit_prmt_len = strlen(prmt_ptr); - put_prompt(); -} -#else -static void parse_prompt(const char *prmt_ptr) -{ - int prmt_len = 0; - int sub_len = 0; - char flg_not_length = '['; - char *prmt_mem_ptr = xcalloc(1, 1); - char *pwd_buf = xgetcwd(0); - char buf2[PATH_MAX + 1]; - char buf[2]; - char c; - char *pbuf; - - if (!pwd_buf) { - pwd_buf=(char *)unknown; - } - - while (*prmt_ptr) { - pbuf = buf; - pbuf[1] = 0; - c = *prmt_ptr++; - if (c == '\\') { - const char *cp = prmt_ptr; - int l; - - c = process_escape_sequence(&prmt_ptr); - if(prmt_ptr==cp) { - if (*cp == 0) - break; - c = *prmt_ptr++; - switch (c) { -#ifdef BB_FEATURE_GETUSERNAME_AND_HOMEDIR - case 'u': - pbuf = user_buf; - break; -#endif - case 'h': - pbuf = hostname_buf; - if (*pbuf == 0) { - pbuf = xcalloc(256, 1); - if (gethostname(pbuf, 255) < 0) { - strcpy(pbuf, "?"); - } else { - char *s = strchr(pbuf, '.'); - - if (s) - *s = 0; - } - hostname_buf = pbuf; - } - break; - case '$': - c = my_euid == 0 ? '#' : '$'; - break; -#ifdef BB_FEATURE_GETUSERNAME_AND_HOMEDIR - case 'w': - pbuf = pwd_buf; - l = strlen(home_pwd_buf); - if (home_pwd_buf[0] != 0 && - strncmp(home_pwd_buf, pbuf, l) == 0 && - (pbuf[l]=='/' || pbuf[l]=='\0') && - strlen(pwd_buf+l) UCHAR_MAX || (pbuf - buf2) < l) { - l--; - break; - } - prmt_ptr++; - } - buf2[l] = 0; - c = (char)strtol(buf2, 0, 16); - if(c==0) - c = '?'; - pbuf = buf; - break; - case '[': case ']': - if (c == flg_not_length) { - flg_not_length = flg_not_length == '[' ? ']' : '['; - continue; - } - break; - } - } - } - if(pbuf == buf) - *pbuf = c; - prmt_len += strlen(pbuf); - prmt_mem_ptr = strcat(xrealloc(prmt_mem_ptr, prmt_len+1), pbuf); - if (flg_not_length == ']') - sub_len++; - } - if(pwd_buf!=(char *)unknown) - free(pwd_buf); - cmdedit_prompt = prmt_mem_ptr; - cmdedit_prmt_len = prmt_len - sub_len; - put_prompt(); -} -#endif - - -/* draw promt, editor line, and clear tail */ -static void redraw(int y, int back_cursor) -{ - if (y > 0) /* up to start y */ - printf("\033[%dA", y); - putchar('\r'); - put_prompt(); - input_end(); /* rewrite */ - printf("\033[J"); /* destroy tail after cursor */ - input_backward(back_cursor); -} - -/* Delete the char in front of the cursor */ -static void input_delete(void) -{ - int j = cursor; - - if (j == len) - return; - - strcpy(command_ps + j, command_ps + j + 1); - len--; - input_end(); /* rewtite new line */ - cmdedit_set_out_char(0); /* destroy end char */ - input_backward(cursor - j); /* back to old pos cursor */ -} - -/* Delete the char in back of the cursor */ -static void input_backspace(void) -{ - if (cursor > 0) { - input_backward(1); - input_delete(); - } -} - - -/* Move forward one charactor */ -static void input_forward(void) -{ - if (cursor < len) - cmdedit_set_out_char(command_ps[cursor + 1]); -} - - -static void cmdedit_setwidth(int w, int redraw_flg) -{ - cmdedit_termw = cmdedit_prmt_len + 2; - if (w <= cmdedit_termw) { - cmdedit_termw = cmdedit_termw % w; - } - if (w > cmdedit_termw) { - cmdedit_termw = w; - - if (redraw_flg) { - /* new y for current cursor */ - int new_y = (cursor + cmdedit_prmt_len) / w; - - /* redraw */ - redraw((new_y >= cmdedit_y ? new_y : cmdedit_y), len - cursor); - fflush(stdout); - } - } -} - -static void cmdedit_init(void) -{ - cmdedit_prmt_len = 0; - if ((handlers_sets & SET_WCHG_HANDLERS) == 0) { - /* emulate usage handler to set handler and call yours work */ - win_changed(-SIGWINCH); - handlers_sets |= SET_WCHG_HANDLERS; - } - - if ((handlers_sets & SET_ATEXIT) == 0) { -#ifdef BB_FEATURE_GETUSERNAME_AND_HOMEDIR - struct passwd *entry; - - my_euid = geteuid(); - entry = getpwuid(my_euid); - if (entry) { - user_buf = xstrdup(entry->pw_name); - home_pwd_buf = xstrdup(entry->pw_dir); - } -#endif - -#ifdef BB_FEATURE_COMMAND_TAB_COMPLETION - -#ifndef BB_FEATURE_GETUSERNAME_AND_HOMEDIR - my_euid = geteuid(); -#endif - my_uid = getuid(); - my_gid = getgid(); -#endif /* BB_FEATURE_COMMAND_TAB_COMPLETION */ - handlers_sets |= SET_ATEXIT; - atexit(cmdedit_reset_term); /* be sure to do this only once */ - } -} - -#ifdef BB_FEATURE_COMMAND_TAB_COMPLETION - -static int is_execute(const struct stat *st) -{ - if ((!my_euid && (st->st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) || - (my_uid == st->st_uid && (st->st_mode & S_IXUSR)) || - (my_gid == st->st_gid && (st->st_mode & S_IXGRP)) || - (st->st_mode & S_IXOTH)) return TRUE; - return FALSE; -} - -#ifdef BB_FEATURE_COMMAND_USERNAME_COMPLETION - -static char **username_tab_completion(char *ud, int *num_matches) -{ - struct passwd *entry; - int userlen; - char *temp; - - - ud++; /* ~user/... to user/... */ - userlen = strlen(ud); - - if (num_matches == 0) { /* "~/..." or "~user/..." */ - char *sav_ud = ud - 1; - char *home = 0; - - if (*ud == '/') { /* "~/..." */ - home = home_pwd_buf; - } else { - /* "~user/..." */ - temp = strchr(ud, '/'); - *temp = 0; /* ~user\0 */ - entry = getpwnam(ud); - *temp = '/'; /* restore ~user/... */ - ud = temp; - if (entry) - home = entry->pw_dir; - } - if (home) { - if ((userlen + strlen(home) + 1) < BUFSIZ) { - char temp2[BUFSIZ]; /* argument size */ - - /* /home/user/... */ - sprintf(temp2, "%s%s", home, ud); - strcpy(sav_ud, temp2); - } - } - return 0; /* void, result save to argument :-) */ - } else { - /* "~[^/]*" */ - char **matches = (char **) NULL; - int nm = 0; - - setpwent(); - - while ((entry = getpwent()) != NULL) { - /* Null usernames should result in all users as possible completions. */ - if ( /*!userlen || */ !strncmp(ud, entry->pw_name, userlen)) { - - temp = xmalloc(3 + strlen(entry->pw_name)); - sprintf(temp, "~%s/", entry->pw_name); - matches = xrealloc(matches, (nm + 1) * sizeof(char *)); - - matches[nm++] = temp; - } - } - - endpwent(); - (*num_matches) = nm; - return (matches); - } -} -#endif /* BB_FEATURE_COMMAND_USERNAME_COMPLETION */ - -enum { - FIND_EXE_ONLY = 0, - FIND_DIR_ONLY = 1, - FIND_FILE_ONLY = 2, -}; - -static int path_parse(char ***p, int flags) -{ - int npth; - char *tmp; - char *pth; - - /* if not setenv PATH variable, to search cur dir "." */ - if (flags != FIND_EXE_ONLY || (pth = getenv("PATH")) == 0 || - /* PATH= or PATH=: */ - *pth == 0 || (*pth == ':' && *(pth + 1) == 0)) { - return 1; - } - - tmp = pth; - npth = 0; - - for (;;) { - npth++; /* count words is + 1 count ':' */ - tmp = strchr(tmp, ':'); - if (tmp) { - if (*++tmp == 0) - break; /* : */ - } else - break; - } - - *p = xmalloc(npth * sizeof(char *)); - - tmp = pth; - (*p)[0] = xstrdup(tmp); - npth = 1; /* count words is + 1 count ':' */ - - for (;;) { - tmp = strchr(tmp, ':'); - if (tmp) { - (*p)[0][(tmp - pth)] = 0; /* ':' -> '\0' */ - if (*++tmp == 0) - break; /* : */ - } else - break; - (*p)[npth++] = &(*p)[0][(tmp - pth)]; /* p[next]=p[0][&'\0'+1] */ - } - - return npth; -} - -static char *add_quote_for_spec_chars(char *found) -{ - int l = 0; - char *s = xmalloc((strlen(found) + 1) * 2); - - while (*found) { - if (strchr(" `\"#$%^&*()=+{}[]:;\'|\\<>", *found)) - s[l++] = '\\'; - s[l++] = *found++; - } - s[l] = 0; - return s; -} - -static char **exe_n_cwd_tab_completion(char *command, int *num_matches, - int type) -{ - - char **matches = 0; - DIR *dir; - struct dirent *next; - char dirbuf[BUFSIZ]; - int nm = *num_matches; - struct stat st; - char *path1[1]; - char **paths = path1; - int npaths; - int i; - char *found; - char *pfind = strrchr(command, '/'); - - path1[0] = "."; - - if (pfind == NULL) { - /* no dir, if flags==EXE_ONLY - get paths, else "." */ - npaths = path_parse(&paths, type); - pfind = command; - } else { - /* with dir */ - /* save for change */ - strcpy(dirbuf, command); - /* set dir only */ - dirbuf[(pfind - command) + 1] = 0; -#ifdef BB_FEATURE_COMMAND_USERNAME_COMPLETION - if (dirbuf[0] == '~') /* ~/... or ~user/... */ - username_tab_completion(dirbuf, 0); -#endif - /* "strip" dirname in command */ - pfind++; - - paths[0] = dirbuf; - npaths = 1; /* only 1 dir */ - } - - for (i = 0; i < npaths; i++) { - - dir = opendir(paths[i]); - if (!dir) /* Don't print an error */ - continue; - - while ((next = readdir(dir)) != NULL) { - char *str_found = next->d_name; - - /* matched ? */ - if (strncmp(str_found, pfind, strlen(pfind))) - continue; - /* not see .name without .match */ - if (*str_found == '.' && *pfind == 0) { - if (*paths[i] == '/' && paths[i][1] == 0 - && str_found[1] == 0) str_found = ""; /* only "/" */ - else - continue; - } - found = concat_path_file(paths[i], str_found); - /* hmm, remover in progress? */ - if (stat(found, &st) < 0) - goto cont; - /* find with dirs ? */ - if (paths[i] != dirbuf) - strcpy(found, next->d_name); /* only name */ - if (S_ISDIR(st.st_mode)) { - /* name is directory */ - str_found = found; - found = concat_path_file(found, ""); - free(str_found); - str_found = add_quote_for_spec_chars(found); - } else { - /* not put found file if search only dirs for cd */ - if (type == FIND_DIR_ONLY) - goto cont; - str_found = add_quote_for_spec_chars(found); - if (type == FIND_FILE_ONLY || - (type == FIND_EXE_ONLY && is_execute(&st) == TRUE)) - strcat(str_found, " "); - } - /* Add it to the list */ - matches = xrealloc(matches, (nm + 1) * sizeof(char *)); - - matches[nm++] = str_found; -cont: - free(found); - } - closedir(dir); - } - if (paths != path1) { - free(paths[0]); /* allocated memory only in first member */ - free(paths); - } - *num_matches = nm; - return (matches); -} - -static int match_compare(const void *a, const void *b) -{ - return strcmp(*(char **) a, *(char **) b); -} - - - -#define QUOT (UCHAR_MAX+1) - -#define collapse_pos(is, in) { \ - memcpy(int_buf+is, int_buf+in, (BUFSIZ+1-is-in)*sizeof(int)); \ - memcpy(pos_buf+is, pos_buf+in, (BUFSIZ+1-is-in)*sizeof(int)); } - -static int find_match(char *matchBuf, int *len_with_quotes) -{ - int i, j; - int command_mode; - int c, c2; - int int_buf[BUFSIZ + 1]; - int pos_buf[BUFSIZ + 1]; - - /* set to integer dimension characters and own positions */ - for (i = 0;; i++) { - int_buf[i] = (int) ((unsigned char) matchBuf[i]); - if (int_buf[i] == 0) { - pos_buf[i] = -1; /* indicator end line */ - break; - } else - pos_buf[i] = i; - } - - /* mask \+symbol and convert '\t' to ' ' */ - for (i = j = 0; matchBuf[i]; i++, j++) - if (matchBuf[i] == '\\') { - collapse_pos(j, j + 1); - int_buf[j] |= QUOT; - i++; -#ifdef BB_FEATURE_NONPRINTABLE_INVERSE_PUT - if (matchBuf[i] == '\t') /* algorithm equivalent */ - int_buf[j] = ' ' | QUOT; -#endif - } -#ifdef BB_FEATURE_NONPRINTABLE_INVERSE_PUT - else if (matchBuf[i] == '\t') - int_buf[j] = ' '; -#endif - - /* mask "symbols" or 'symbols' */ - c2 = 0; - for (i = 0; int_buf[i]; i++) { - c = int_buf[i]; - if (c == '\'' || c == '"') { - if (c2 == 0) - c2 = c; - else { - if (c == c2) - c2 = 0; - else - int_buf[i] |= QUOT; - } - } else if (c2 != 0 && c != '$') - int_buf[i] |= QUOT; - } - - /* skip commands with arguments if line have commands delimiters */ - /* ';' ';;' '&' '|' '&&' '||' but `>&' `<&' `>|' */ - for (i = 0; int_buf[i]; i++) { - c = int_buf[i]; - c2 = int_buf[i + 1]; - j = i ? int_buf[i - 1] : -1; - command_mode = 0; - if (c == ';' || c == '&' || c == '|') { - command_mode = 1 + (c == c2); - if (c == '&') { - if (j == '>' || j == '<') - command_mode = 0; - } else if (c == '|' && j == '>') - command_mode = 0; - } - if (command_mode) { - collapse_pos(0, i + command_mode); - i = -1; /* hack incremet */ - } - } - /* collapse `command...` */ - for (i = 0; int_buf[i]; i++) - if (int_buf[i] == '`') { - for (j = i + 1; int_buf[j]; j++) - if (int_buf[j] == '`') { - collapse_pos(i, j + 1); - j = 0; - break; - } - if (j) { - /* not found close ` - command mode, collapse all previous */ - collapse_pos(0, i + 1); - break; - } else - i--; /* hack incremet */ - } - - /* collapse (command...(command...)...) or {command...{command...}...} */ - c = 0; /* "recursive" level */ - c2 = 0; - for (i = 0; int_buf[i]; i++) - if (int_buf[i] == '(' || int_buf[i] == '{') { - if (int_buf[i] == '(') - c++; - else - c2++; - collapse_pos(0, i + 1); - i = -1; /* hack incremet */ - } - for (i = 0; pos_buf[i] >= 0 && (c > 0 || c2 > 0); i++) - if ((int_buf[i] == ')' && c > 0) || (int_buf[i] == '}' && c2 > 0)) { - if (int_buf[i] == ')') - c--; - else - c2--; - collapse_pos(0, i + 1); - i = -1; /* hack incremet */ - } - - /* skip first not quote space */ - for (i = 0; int_buf[i]; i++) - if (int_buf[i] != ' ') - break; - if (i) - collapse_pos(0, i); - - /* set find mode for completion */ - command_mode = FIND_EXE_ONLY; - for (i = 0; int_buf[i]; i++) - if (int_buf[i] == ' ' || int_buf[i] == '<' || int_buf[i] == '>') { - if (int_buf[i] == ' ' && command_mode == FIND_EXE_ONLY - && matchBuf[pos_buf[0]]=='c' - && matchBuf[pos_buf[1]]=='d' ) - command_mode = FIND_DIR_ONLY; - else { - command_mode = FIND_FILE_ONLY; - break; - } - } - /* "strlen" */ - for (i = 0; int_buf[i]; i++); - /* find last word */ - for (--i; i >= 0; i--) { - c = int_buf[i]; - if (c == ' ' || c == '<' || c == '>' || c == '|' || c == '&') { - collapse_pos(0, i + 1); - break; - } - } - /* skip first not quoted '\'' or '"' */ - for (i = 0; int_buf[i] == '\'' || int_buf[i] == '"'; i++); - /* collapse quote or unquote // or /~ */ - while ((int_buf[i] & ~QUOT) == '/' && - ((int_buf[i + 1] & ~QUOT) == '/' - || (int_buf[i + 1] & ~QUOT) == '~')) { - i++; - } - - /* set only match and destroy quotes */ - j = 0; - for (c = 0; pos_buf[i] >= 0; i++) { - matchBuf[c++] = matchBuf[pos_buf[i]]; - j = pos_buf[i] + 1; - } - matchBuf[c] = 0; - /* old lenght matchBuf with quotes symbols */ - *len_with_quotes = j ? j - pos_buf[0] : 0; - - return command_mode; -} - - -static void input_tab(int *lastWasTab) -{ - /* Do TAB completion */ - static int num_matches; - static char **matches; - - if (lastWasTab == 0) { /* free all memory */ - if (matches) { - while (num_matches > 0) - free(matches[--num_matches]); - free(matches); - matches = (char **) NULL; - } - return; - } - if (*lastWasTab == FALSE) { - - char *tmp; - int len_found; - char matchBuf[BUFSIZ]; - int find_type; - int recalc_pos; - - *lastWasTab = TRUE; /* flop trigger */ - - /* Make a local copy of the string -- up - * to the position of the cursor */ - tmp = strncpy(matchBuf, command_ps, cursor); - tmp[cursor] = 0; - - find_type = find_match(matchBuf, &recalc_pos); - - /* Free up any memory already allocated */ - input_tab(0); - -#ifdef BB_FEATURE_COMMAND_USERNAME_COMPLETION - /* If the word starts with `~' and there is no slash in the word, - * then try completing this word as a username. */ - - if (matchBuf[0] == '~' && strchr(matchBuf, '/') == 0) - matches = username_tab_completion(matchBuf, &num_matches); -#endif - /* Try to match any executable in our path and everything - * in the current working directory that matches. */ - if (!matches) - matches = - exe_n_cwd_tab_completion(matchBuf, - &num_matches, find_type); - /* Remove duplicate found */ - if(matches) { - int i, j; - /* bubble */ - for(i=0; i<(num_matches-1); i++) - for(j=i+1; j 1) { - char *tmp1; - - beep(); - if (!matches) - return; /* not found */ - /* sort */ - qsort(matches, num_matches, sizeof(char *), match_compare); - - /* find minimal match */ - tmp = xstrdup(matches[0]); - for (tmp1 = tmp; *tmp1; tmp1++) - for (len_found = 1; len_found < num_matches; len_found++) - if (matches[len_found][(tmp1 - tmp)] != *tmp1) { - *tmp1 = 0; - break; - } - if (*tmp == 0) { /* have unique */ - free(tmp); - return; - } - } else { /* one match */ - tmp = matches[0]; - /* for next completion current found */ - *lastWasTab = FALSE; - } - - len_found = strlen(tmp); - /* have space to placed match? */ - if ((len_found - strlen(matchBuf) + len) < BUFSIZ) { - - /* before word for match */ - command_ps[cursor - recalc_pos] = 0; - /* save tail line */ - strcpy(matchBuf, command_ps + cursor); - /* add match */ - strcat(command_ps, tmp); - /* add tail */ - strcat(command_ps, matchBuf); - /* back to begin word for match */ - input_backward(recalc_pos); - /* new pos */ - recalc_pos = cursor + len_found; - /* new len */ - len = strlen(command_ps); - /* write out the matched command */ - redraw(cmdedit_y, len - recalc_pos); - } - if (tmp != matches[0]) - free(tmp); - } else { - /* Ok -- the last char was a TAB. Since they - * just hit TAB again, print a list of all the - * available choices... */ - if (matches && num_matches > 0) { - int i, col, l; - int sav_cursor = cursor; /* change goto_new_line() */ - - /* Go to the next line */ - goto_new_line(); - for (i = 0, col = 0; i < num_matches; i++) { - l = strlen(matches[i]); - if (l < 14) - l = 14; - printf("%-14s ", matches[i]); - if ((l += 2) > 16) - while (l % 16) { - putchar(' '); - l++; - } - col += l; - col -= (col / cmdedit_termw) * cmdedit_termw; - if (col > 60 && matches[i + 1] != NULL) { - putchar('\n'); - col = 0; - } - } - /* Go to the next line and rewrite */ - putchar('\n'); - redraw(0, len - sav_cursor); - } - } -} -#endif /* BB_FEATURE_COMMAND_TAB_COMPLETION */ - -static void get_previous_history(struct history **hp, struct history *p) -{ - if ((*hp)->s) - free((*hp)->s); - (*hp)->s = xstrdup(command_ps); - *hp = p; -} - -static inline void get_next_history(struct history **hp) -{ - get_previous_history(hp, (*hp)->n); -} - -enum { - ESC = 27, - DEL = 127, -}; - - -/* - * This function is used to grab a character buffer - * from the input file descriptor and allows you to - * a string with full command editing (sortof like - * a mini readline). - * - * The following standard commands are not implemented: - * ESC-b -- Move back one word - * ESC-f -- Move forward one word - * ESC-d -- Delete back one word - * ESC-h -- Delete forward one word - * CTL-t -- Transpose two characters - * - * Furthermore, the "vi" command editing keys are not implemented. - * - */ - - -int cmdedit_read_input(char *prompt, char command[BUFSIZ]) -{ - - int break_out = 0; - int lastWasTab = FALSE; - unsigned char c = 0; - struct history *hp = his_end; - - /* prepare before init handlers */ - cmdedit_y = 0; /* quasireal y, not true work if line > xt*yt */ - len = 0; - command_ps = command; - - getTermSettings(0, (void *) &initial_settings); - memcpy(&new_settings, &initial_settings, sizeof(struct termios)); - new_settings.c_lflag &= ~ICANON; /* unbuffered input */ - /* Turn off echoing and CTRL-C, so we can trap it */ - new_settings.c_lflag &= ~(ECHO | ECHONL | ISIG); -#ifndef linux - /* Hmm, in linux c_cc[] not parsed if set ~ICANON */ - new_settings.c_cc[VMIN] = 1; - new_settings.c_cc[VTIME] = 0; - /* Turn off CTRL-C, so we can trap it */ -# ifndef _POSIX_VDISABLE -# define _POSIX_VDISABLE '\0' -# endif - new_settings.c_cc[VINTR] = _POSIX_VDISABLE; -#endif - command[0] = 0; - - setTermSettings(0, (void *) &new_settings); - handlers_sets |= SET_RESET_TERM; - - /* Now initialize things */ - cmdedit_init(); - /* Print out the command prompt */ - parse_prompt(prompt); - - while (1) { - - fflush(stdout); /* buffered out to fast */ - - if (safe_read(0, &c, 1) < 1) - /* if we can't read input then exit */ - goto prepare_to_die; - - switch (c) { - case '\n': - case '\r': - /* Enter */ - goto_new_line(); - break_out = 1; - break; - case 1: - /* Control-a -- Beginning of line */ - input_backward(cursor); - break; - case 2: - /* Control-b -- Move back one character */ - input_backward(1); - break; - case 3: - /* Control-c -- stop gathering input */ - goto_new_line(); - command[0] = 0; - len = 0; - lastWasTab = FALSE; - put_prompt(); - break; - case 4: - /* Control-d -- Delete one character, or exit - * if the len=0 and no chars to delete */ - if (len == 0) { -prepare_to_die: -#if !defined(BB_ASH) - printf("exit"); - goto_new_line(); - /* cmdedit_reset_term() called in atexit */ - exit(EXIT_SUCCESS); -#else - break_out = -1; /* for control stoped jobs */ - break; -#endif - } else { - input_delete(); - } - break; - case 5: - /* Control-e -- End of line */ - input_end(); - break; - case 6: - /* Control-f -- Move forward one character */ - input_forward(); - break; - case '\b': - case DEL: - /* Control-h and DEL */ - input_backspace(); - break; - case '\t': -#ifdef BB_FEATURE_COMMAND_TAB_COMPLETION - input_tab(&lastWasTab); -#endif - break; - case 14: - /* Control-n -- Get next command in history */ - if (hp && hp->n && hp->n->s) { - get_next_history(&hp); - goto rewrite_line; - } else { - beep(); - } - break; - case 16: - /* Control-p -- Get previous command from history */ - if (hp && hp->p) { - get_previous_history(&hp, hp->p); - goto rewrite_line; - } else { - beep(); - } - break; - case 21: - /* Control-U -- Clear line before cursor */ - if (cursor) { - strcpy(command, command + cursor); - redraw(cmdedit_y, len -= cursor); - } - break; - - case ESC:{ - /* escape sequence follows */ - if (safe_read(0, &c, 1) < 1) - goto prepare_to_die; - /* different vt100 emulations */ - if (c == '[' || c == 'O') { - if (safe_read(0, &c, 1) < 1) - goto prepare_to_die; - } - switch (c) { -#ifdef BB_FEATURE_COMMAND_TAB_COMPLETION - case '\t': /* Alt-Tab */ - - input_tab(&lastWasTab); - break; -#endif - case 'A': - /* Up Arrow -- Get previous command from history */ - if (hp && hp->p) { - get_previous_history(&hp, hp->p); - goto rewrite_line; - } else { - beep(); - } - break; - case 'B': - /* Down Arrow -- Get next command in history */ - if (hp && hp->n && hp->n->s) { - get_next_history(&hp); - goto rewrite_line; - } else { - beep(); - } - break; - - /* Rewrite the line with the selected history item */ - rewrite_line: - /* change command */ - len = strlen(strcpy(command, hp->s)); - /* redraw and go to end line */ - redraw(cmdedit_y, 0); - break; - case 'C': - /* Right Arrow -- Move forward one character */ - input_forward(); - break; - case 'D': - /* Left Arrow -- Move back one character */ - input_backward(1); - break; - case '3': - /* Delete */ - input_delete(); - break; - case '1': - case 'H': - /* Home (Ctrl-A) */ - input_backward(cursor); - break; - case '4': - case 'F': - /* End (Ctrl-E) */ - input_end(); - break; - default: - if (!(c >= '1' && c <= '9')) - c = 0; - beep(); - } - if (c >= '1' && c <= '9') - do - if (safe_read(0, &c, 1) < 1) - goto prepare_to_die; - while (c != '~'); - break; - } - - default: /* If it's regular input, do the normal thing */ -#ifdef BB_FEATURE_NONPRINTABLE_INVERSE_PUT - /* Control-V -- Add non-printable symbol */ - if (c == 22) { - if (safe_read(0, &c, 1) < 1) - goto prepare_to_die; - if (c == 0) { - beep(); - break; - } - } else -#endif - if (!Isprint(c)) /* Skip non-printable characters */ - break; - - if (len >= (BUFSIZ - 2)) /* Need to leave space for enter */ - break; - - len++; - - if (cursor == (len - 1)) { /* Append if at the end of the line */ - *(command + cursor) = c; - *(command + cursor + 1) = 0; - cmdedit_set_out_char(0); - } else { /* Insert otherwise */ - int sc = cursor; - - memmove(command + sc + 1, command + sc, len - sc); - *(command + sc) = c; - sc++; - /* rewrite from cursor */ - input_end(); - /* to prev x pos + 1 */ - input_backward(cursor - sc); - } - - break; - } - if (break_out) /* Enter is the command terminator, no more input. */ - break; - - if (c != '\t') - lastWasTab = FALSE; - } - - setTermSettings(0, (void *) &initial_settings); - handlers_sets &= ~SET_RESET_TERM; - - /* Handle command history log */ - if (len) { /* no put empty line */ - - struct history *h = his_end; - char *ss; - - ss = xstrdup(command); /* duplicate */ - - if (h == 0) { - /* No previous history -- this memory is never freed */ - h = his_front = xmalloc(sizeof(struct history)); - h->n = xmalloc(sizeof(struct history)); - - h->p = NULL; - h->s = ss; - h->n->p = h; - h->n->n = NULL; - h->n->s = NULL; - his_end = h->n; - history_counter++; - } else { - /* Add a new history command -- this memory is never freed */ - h->n = xmalloc(sizeof(struct history)); - - h->n->p = h; - h->n->n = NULL; - h->n->s = NULL; - h->s = ss; - his_end = h->n; - - /* After max history, remove the oldest command */ - if (history_counter >= MAX_HISTORY) { - - struct history *p = his_front->n; - - p->p = NULL; - free(his_front->s); - free(his_front); - his_front = p; - } else { - history_counter++; - } - } -#if defined(BB_FEATURE_SH_FANCY_PROMPT) - num_ok_lines++; -#endif - } - if(break_out>0) { - command[len++] = '\n'; /* set '\n' */ - command[len] = 0; - } -#if defined(BB_FEATURE_CLEAN_UP) && defined(BB_FEATURE_COMMAND_TAB_COMPLETION) - input_tab(0); /* strong free */ -#endif -#if defined(BB_FEATURE_SH_FANCY_PROMPT) - free(cmdedit_prompt); -#endif - cmdedit_reset_term(); - return len; -} - - - -#endif /* BB_FEATURE_COMMAND_EDITING */ - - -#ifdef TEST - -const char *applet_name = "debug stuff usage"; -const char *memory_exhausted = "Memory exhausted"; - -#ifdef BB_FEATURE_NONPRINTABLE_INVERSE_PUT -#include -#endif - -int main(int argc, char **argv) -{ - char buff[BUFSIZ]; - char *prompt = -#if defined(BB_FEATURE_SH_FANCY_PROMPT) - "\\[\\033[32;1m\\]\\u@\\[\\x1b[33;1m\\]\\h:\ -\\[\\033[34;1m\\]\\w\\[\\033[35;1m\\] \ -\\!\\[\\e[36;1m\\]\\$ \\[\\E[0m\\]"; -#else - "% "; -#endif - -#ifdef BB_FEATURE_NONPRINTABLE_INVERSE_PUT - setlocale(LC_ALL, ""); -#endif - while(1) { - int l; - cmdedit_read_input(prompt, buff); - l = strlen(buff); - if(l==0) - break; - if(l > 0 && buff[l-1] == '\n') - buff[l-1] = 0; - printf("*** cmdedit_read_input() returned line =%s=\n", buff); - } - printf("*** cmdedit_read_input() detect ^C\n"); - return 0; -} - -#endif /* TEST */ diff --git a/cmdedit.h b/cmdedit.h deleted file mode 100644 index 83893572a..000000000 --- a/cmdedit.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef CMDEDIT_H -#define CMDEDIT_H - -int cmdedit_read_input(char* promptStr, char* command); - -#endif /* CMDEDIT_H */ diff --git a/cmp.c b/cmp.c deleted file mode 100644 index 6d579461d..000000000 --- a/cmp.c +++ /dev/null @@ -1,80 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini cmp implementation for busybox - * - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Matt Kraai - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include "busybox.h" - -int cmp_main(int argc, char **argv) -{ - FILE *fp1 = NULL, *fp2 = stdin; - char *filename1, *filename2 = "-"; - int c, c1, c2, char_pos = 1, line_pos = 1, silent = FALSE; - - while ((c = getopt(argc, argv, "s")) != EOF) { - switch (c) { - case 's': - silent = TRUE; - break; - default: - show_usage(); - } - } - - filename1 = argv[optind]; - switch (argc - optind) { - case 2: - fp2 = xfopen(filename2 = argv[optind + 1], "r"); - case 1: - fp1 = xfopen(filename1, "r"); - break; - default: - show_usage(); - } - - do { - c1 = fgetc(fp1); - c2 = fgetc(fp2); - if (c1 != c2) { - if (silent) - return EXIT_FAILURE; - if (c1 == EOF) - printf("EOF on %s\n", filename1); - else if (c2 == EOF) - printf("EOF on %s\n", filename2); - else - printf("%s %s differ: char %d, line %d\n", filename1, filename2, - char_pos, line_pos); - return EXIT_FAILURE; - } - char_pos++; - if (c1 == '\n') - line_pos++; - } while (c1 != EOF); - - return EXIT_SUCCESS; -} diff --git a/console-tools/Makefile b/console-tools/Makefile new file mode 100644 index 000000000..a67e4bb7b --- /dev/null +++ b/console-tools/Makefile @@ -0,0 +1,43 @@ +# Makefile for busybox +# +# Copyright (C) 1999,2000,2001 by Erik Andersen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +TOPDIR :=.. +L_TARGET := console-tools.a + +obj-y := +obj-n := +obj- := + +obj-$(CONFIG_CHVT) += chvt.o +obj-$(CONFIG_CLEAR) += clear.o +obj-$(CONFIG_DEALLOCVT) += deallocvt.o +obj-$(CONFIG_DUMPKMAP) += dumpkmap.o +obj-$(CONFIG_LOADACM) += loadacm.o +obj-$(CONFIG_LOADFONT) += loadfont.o +obj-$(CONFIG_LOADKMAP) += loadkmap.o +obj-$(CONFIG_RESET) += reset.o +obj-$(CONFIG_SETKEYCODES) += setkeycodes.o + + +# Hand off to toplevel Rules.mak +include $(TOPDIR)/Rules.mak + +clean: + rm -f $(L_TARGET) *.o core + diff --git a/console-tools/clear.c b/console-tools/clear.c index 503bafa16..55e02e3d8 100644 --- a/console-tools/clear.c +++ b/console-tools/clear.c @@ -2,9 +2,8 @@ /* * Mini clear implementation for busybox * - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , + * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/console-tools/config.in b/console-tools/config.in new file mode 100644 index 000000000..53d5ac6b4 --- /dev/null +++ b/console-tools/config.in @@ -0,0 +1,18 @@ +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +mainmenu_option next_comment +comment 'Console Utilities' +bool 'chvt' CONFIG_CHVT +bool 'clear' CONFIG_CLEAR +bool 'deallocvt' CONFIG_DEALLOCVT +bool 'dumpkmap' CONFIG_DUMPKMAP +bool 'loadacm' CONFIG_LOADACM +bool 'loadfont' CONFIG_LOADFONT +bool 'loadkmap' CONFIG_LOADKMAP +bool 'reset' CONFIG_RESET +bool 'setkeycodes' CONFIG_SETKEYCODES + +endmenu diff --git a/console-tools/reset.c b/console-tools/reset.c index 755c4c335..84cbb447a 100644 --- a/console-tools/reset.c +++ b/console-tools/reset.c @@ -2,10 +2,9 @@ /* * Mini reset implementation for busybox * - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , - * and Kent Robotti + * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen + * Written by Erik Andersen and Kent Robotti * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/coreutils/basename.c b/coreutils/basename.c index c15afd533..bdbcec17a 100644 --- a/coreutils/basename.c +++ b/coreutils/basename.c @@ -2,8 +2,8 @@ /* * Mini basename implementation for busybox * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , + * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/coreutils/cat.c b/coreutils/cat.c index aa8528d6a..820b6342e 100644 --- a/coreutils/cat.c +++ b/coreutils/cat.c @@ -2,8 +2,8 @@ /* * Mini Cat implementation for busybox * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , + * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/coreutils/chgrp.c b/coreutils/chgrp.c index fbc1036a8..43ffeb7e6 100644 --- a/coreutils/chgrp.c +++ b/coreutils/chgrp.c @@ -1,10 +1,9 @@ /* vi: set sw=4 ts=4: */ /* - * Mini chown/chmod/chgrp implementation for busybox + * Mini chgrp implementation for busybox * - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , + * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/coreutils/chmod.c b/coreutils/chmod.c index 9139b3f4d..53230b568 100644 --- a/coreutils/chmod.c +++ b/coreutils/chmod.c @@ -1,10 +1,9 @@ /* vi: set sw=4 ts=4: */ /* - * Mini chown/chmod/chgrp implementation for busybox + * Mini chmod implementation for busybox * - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , + * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/coreutils/chown.c b/coreutils/chown.c index d1e52deda..c1b992c37 100644 --- a/coreutils/chown.c +++ b/coreutils/chown.c @@ -1,10 +1,9 @@ /* vi: set sw=4 ts=4: */ /* - * Mini chown/chmod/chgrp implementation for busybox + * Mini chown implementation for busybox * - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , + * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/coreutils/chroot.c b/coreutils/chroot.c index de6a2ea50..ba3e5f864 100644 --- a/coreutils/chroot.c +++ b/coreutils/chroot.c @@ -2,9 +2,8 @@ /* * Mini chroot implementation for busybox * - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , + * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -48,7 +47,7 @@ int chroot_main(int argc, char **argv) prog = *argv; execvp(*argv, argv); } else { -#if defined shell_main && defined BB_FEATURE_SH_STANDALONE_SHELL +#if defined shell_main && defined CONFIG_FEATURE_SH_STANDALONE_SHELL char shell[] = "/bin/sh"; char *shell_argv[2] = { shell, NULL }; applet_name = shell; diff --git a/coreutils/cmp.c b/coreutils/cmp.c index 6d579461d..07bf3be92 100644 --- a/coreutils/cmp.c +++ b/coreutils/cmp.c @@ -2,9 +2,7 @@ /* * Mini cmp implementation for busybox * - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Matt Kraai + * Copyright (C) 2000,2001 by Matt Kraai * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/coreutils/df.c b/coreutils/df.c index 8cb13fa6d..0e9e5d61a 100644 --- a/coreutils/df.c +++ b/coreutils/df.c @@ -2,8 +2,8 @@ /* * Mini df implementation for busybox * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , + * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen * based on original code by (I think) Bruce Perens . * * This program is free software; you can redistribute it and/or modify @@ -31,7 +31,7 @@ #include "busybox.h" extern const char mtab_file[]; /* Defined in utility.c */ -#ifdef BB_FEATURE_HUMAN_READABLE +#ifdef CONFIG_FEATURE_HUMAN_READABLE static unsigned long df_disp_hr = KILOBYTE; #endif @@ -61,7 +61,7 @@ static int do_df(char *device, const char *mount_point) if(device==NULL) return FALSE; } -#ifdef BB_FEATURE_HUMAN_READABLE +#ifdef CONFIG_FEATURE_HUMAN_READABLE printf("%-20s %9s ", device, make_human_readable_str(s.f_blocks, s.f_bsize, df_disp_hr)); @@ -92,13 +92,13 @@ extern int df_main(int argc, char **argv) char disp_units_hdr[80] = "1k-blocks"; /* default display is kilobytes */ while ((opt = getopt(argc, argv, "k" -#ifdef BB_FEATURE_HUMAN_READABLE +#ifdef CONFIG_FEATURE_HUMAN_READABLE "hm" #endif )) > 0) { switch (opt) { -#ifdef BB_FEATURE_HUMAN_READABLE +#ifdef CONFIG_FEATURE_HUMAN_READABLE case 'h': df_disp_hr = 0; strcpy(disp_units_hdr, " Size"); diff --git a/coreutils/dirname.c b/coreutils/dirname.c index b534e6950..387233789 100644 --- a/coreutils/dirname.c +++ b/coreutils/dirname.c @@ -2,8 +2,8 @@ /* * Mini dirname implementation for busybox * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , + * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/coreutils/du.c b/coreutils/du.c index fb649aee5..c378837d0 100644 --- a/coreutils/du.c +++ b/coreutils/du.c @@ -2,9 +2,8 @@ /* * Mini du implementation for busybox * - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by John Beppu + * Copyright (C) 1999,2000,2001 by Lineo, inc. and John Beppu + * Copyright (C) 1999,2000,2001 by John Beppu * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,7 +32,7 @@ #include "busybox.h" -#ifdef BB_FEATURE_HUMAN_READABLE +#ifdef CONFIG_FEATURE_HUMAN_READABLE static unsigned long disp_hr = KILOBYTE; #endif @@ -46,7 +45,7 @@ static Display *print; static void print_normal(long size, char *filename) { -#ifdef BB_FEATURE_HUMAN_READABLE +#ifdef CONFIG_FEATURE_HUMAN_READABLE printf("%s\t%s\n", make_human_readable_str(size<<10, 1, disp_hr), filename); #else printf("%ld\t%s\n", size, filename); @@ -207,7 +206,7 @@ int du_main(int argc, char **argv) /* parse argv[] */ while ((c = getopt(argc, argv, "sl" -#ifdef BB_FEATURE_HUMAN_READABLE +#ifdef CONFIG_FEATURE_HUMAN_READABLE "hm" #endif "k")) != EOF) { @@ -218,7 +217,7 @@ int du_main(int argc, char **argv) case 'l': count_hardlinks = 1; break; -#ifdef BB_FEATURE_HUMAN_READABLE +#ifdef CONFIG_FEATURE_HUMAN_READABLE case 'h': disp_hr = 0; break; case 'm': disp_hr = MEGABYTE; break; #endif @@ -247,7 +246,7 @@ int du_main(int argc, char **argv) return status; } -/* $Id: du.c,v 1.50 2001/06/30 17:54:20 andersen Exp $ */ +/* $Id: du.c,v 1.51 2001/10/24 04:59:27 andersen Exp $ */ /* Local Variables: c-file-style: "linux" diff --git a/coreutils/head.c b/coreutils/head.c index 688c250b1..4a1677146 100644 --- a/coreutils/head.c +++ b/coreutils/head.c @@ -2,9 +2,8 @@ /* * Mini head implementation for busybox * - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by John Beppu + * Copyright (C) 1999 by Lineo, inc. and John Beppu + * Copyright (C) 1999,2000,2001 by John Beppu * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/coreutils/ln.c b/coreutils/ln.c index 7412a86fd..213db9b72 100644 --- a/coreutils/ln.c +++ b/coreutils/ln.c @@ -2,8 +2,8 @@ /* * Mini ln implementation for busybox * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , + * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/coreutils/ls.c b/coreutils/ls.c index 8d0282dfe..672a3bb3c 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c @@ -65,7 +65,7 @@ enum { #include #include "busybox.h" -#ifdef BB_FEATURE_LS_TIMESTAMPS +#ifdef CONFIG_FEATURE_LS_TIMESTAMPS #include #endif @@ -108,7 +108,7 @@ STYLE_COLUMNS = 3 /* fill columns */ #define DISP_RECURSIVE (1<<4) /* show directory and everything below it */ #define DISP_ROWS (1<<5) /* print across rows */ -#ifdef BB_FEATURE_LS_SORTFILES +#ifdef CONFIG_FEATURE_LS_SORTFILES /* how will the files be sorted */ static const int SORT_FORWARD = 0; /* sort in reverse order */ static const int SORT_REVERSE = 1; /* sort in reverse order */ @@ -122,7 +122,7 @@ static const int SORT_EXT = 8; /* sort by file name extension */ static const int SORT_DIR = 9; /* sort by file or directory */ #endif -#ifdef BB_FEATURE_LS_TIMESTAMPS +#ifdef CONFIG_FEATURE_LS_TIMESTAMPS /* which of the three times will be used */ static const int TIME_MOD = 0; static const int TIME_CHANGE = 1; @@ -142,7 +142,7 @@ static const int SPLIT_SUBDIR = 2; #define TYPEINDEX(mode) (((mode) >> 12) & 0x0f) #define TYPECHAR(mode) ("0pcCd?bB-?l?s???" [TYPEINDEX(mode)]) -#ifdef BB_FEATURE_LS_FILETYPES +#ifdef CONFIG_FEATURE_LS_FILETYPES #define APPCHAR(mode) ("\0|\0\0/\0\0\0\0\0@\0=\0\0\0" [TYPEINDEX(mode)]) #endif @@ -164,19 +164,19 @@ static int list_single(struct dnode *); static unsigned int disp_opts; static unsigned int style_fmt; static unsigned int list_fmt; -#ifdef BB_FEATURE_LS_SORTFILES +#ifdef CONFIG_FEATURE_LS_SORTFILES static unsigned int sort_opts; static unsigned int sort_order; #endif -#ifdef BB_FEATURE_LS_TIMESTAMPS +#ifdef CONFIG_FEATURE_LS_TIMESTAMPS static unsigned int time_fmt; #endif -#ifdef BB_FEATURE_LS_FOLLOWLINKS +#ifdef CONFIG_FEATURE_LS_FOLLOWLINKS static unsigned int follow_links=FALSE; #endif static unsigned short column = 0; -#ifdef BB_FEATURE_AUTOWIDTH +#ifdef CONFIG_FEATURE_AUTOWIDTH static unsigned short terminal_width = TERMINAL_WIDTH; static unsigned short column_width = COLUMN_WIDTH; static unsigned short tabstops = COLUMN_GAP; @@ -186,13 +186,13 @@ static unsigned short column_width = COLUMN_WIDTH; static int status = EXIT_SUCCESS; -#ifdef BB_FEATURE_HUMAN_READABLE +#ifdef CONFIG_FEATURE_HUMAN_READABLE static unsigned long ls_disp_hr = 0; #endif static int my_stat(struct dnode *cur) { -#ifdef BB_FEATURE_LS_FOLLOWLINKS +#ifdef CONFIG_FEATURE_LS_FOLLOWLINKS if (follow_links == TRUE) { if (stat(cur->fullname, &cur->dstat)) { perror_msg("%s", cur->fullname); @@ -222,7 +222,7 @@ static void newline(void) } /*----------------------------------------------------------------------*/ -#ifdef BB_FEATURE_LS_FILETYPES +#ifdef CONFIG_FEATURE_LS_FILETYPES static char append_char(mode_t mode) { if ( !(list_fmt & LIST_FILETYPE)) @@ -304,7 +304,7 @@ static struct dnode **dnalloc(int num) return(p); } -#ifdef BB_FEATURE_LS_RECURSIVE +#ifdef CONFIG_FEATURE_LS_RECURSIVE static void dfree(struct dnode **dnp) { struct dnode *cur, *next; @@ -361,7 +361,7 @@ static struct dnode **splitdnarray(struct dnode **dn, int nfiles, int which) } /*----------------------------------------------------------------------*/ -#ifdef BB_FEATURE_LS_SORTFILES +#ifdef CONFIG_FEATURE_LS_SORTFILES static int sortcmp(struct dnode *d1, struct dnode *d2) { int cmp, dif; @@ -426,13 +426,13 @@ static void shellsort(struct dnode **dn, int size) static void showfiles(struct dnode **dn, int nfiles) { int i, ncols, nrows, row, nc; -#ifdef BB_FEATURE_AUTOWIDTH +#ifdef CONFIG_FEATURE_AUTOWIDTH int len; #endif if(dn==NULL || nfiles < 1) return; -#ifdef BB_FEATURE_AUTOWIDTH +#ifdef CONFIG_FEATURE_AUTOWIDTH /* find the longest file name- use that as the column width */ column_width= 0; for (i=0; i 0) { /* list all files at this level */ -#ifdef BB_FEATURE_LS_SORTFILES +#ifdef CONFIG_FEATURE_LS_SORTFILES shellsort(subdnp, nfiles); #endif showfiles(subdnp, nfiles); -#ifdef BB_FEATURE_LS_RECURSIVE +#ifdef CONFIG_FEATURE_LS_RECURSIVE if (disp_opts & DISP_RECURSIVE) { /* recursive- list the sub-dirs */ dnd= splitdnarray(subdnp, nfiles, SPLIT_SUBDIR); dndirs= countsubdirs(subdnp, nfiles); if (dndirs > 0) { -#ifdef BB_FEATURE_LS_SORTFILES +#ifdef CONFIG_FEATURE_LS_SORTFILES shellsort(dnd, dndirs); #endif showdirs(dnd, dndirs); @@ -582,26 +582,26 @@ static int list_single(struct dnode *dn) { int i; char scratch[BUFSIZ + 1]; -#ifdef BB_FEATURE_LS_TIMESTAMPS +#ifdef CONFIG_FEATURE_LS_TIMESTAMPS char *filetime; time_t ttime, age; #endif -#if defined (BB_FEATURE_LS_FILETYPES) +#if defined (CONFIG_FEATURE_LS_FILETYPES) struct stat info; #endif -#ifdef BB_FEATURE_LS_FILETYPES +#ifdef CONFIG_FEATURE_LS_FILETYPES char append; #endif if (dn==NULL || dn->fullname==NULL) return(0); -#ifdef BB_FEATURE_LS_TIMESTAMPS +#ifdef CONFIG_FEATURE_LS_TIMESTAMPS ttime= dn->dstat.st_mtime; /* the default time */ if (time_fmt & TIME_ACCESS) ttime= dn->dstat.st_atime; if (time_fmt & TIME_CHANGE) ttime= dn->dstat.st_ctime; filetime= ctime(&ttime); #endif -#ifdef BB_FEATURE_LS_FILETYPES +#ifdef CONFIG_FEATURE_LS_FILETYPES append = append_char(dn->dstat.st_mode); #endif @@ -612,7 +612,7 @@ static int list_single(struct dnode *dn) column += 8; break; case LIST_BLOCKS: -#ifdef BB_FEATURE_HUMAN_READABLE +#ifdef CONFIG_FEATURE_HUMAN_READABLE fprintf(stdout, "%6s ", make_human_readable_str(dn->dstat.st_blocks>>1, KILOBYTE, (ls_disp_hr==TRUE)? 0: KILOBYTE)); #else @@ -633,7 +633,7 @@ static int list_single(struct dnode *dn) column += 10; break; case LIST_ID_NAME: -#ifdef BB_FEATURE_LS_USERNAME +#ifdef CONFIG_FEATURE_LS_USERNAME my_getpwuid(scratch, dn->dstat.st_uid); printf("%-8.8s ", scratch); my_getgrgid(scratch, dn->dstat.st_gid); @@ -650,7 +650,7 @@ static int list_single(struct dnode *dn) if (S_ISBLK(dn->dstat.st_mode) || S_ISCHR(dn->dstat.st_mode)) { printf("%4d, %3d ", (int)MAJOR(dn->dstat.st_rdev), (int)MINOR(dn->dstat.st_rdev)); } else { -#ifdef BB_FEATURE_HUMAN_READABLE +#ifdef CONFIG_FEATURE_HUMAN_READABLE if (ls_disp_hr==TRUE) { fprintf(stdout, "%8s ", make_human_readable_str(dn->dstat.st_size, 1, 0)); } else @@ -665,7 +665,7 @@ static int list_single(struct dnode *dn) } column += 10; break; -#ifdef BB_FEATURE_LS_TIMESTAMPS +#ifdef CONFIG_FEATURE_LS_TIMESTAMPS case LIST_FULLTIME: case LIST_DATE_TIME: if (list_fmt & LIST_FULLTIME) { @@ -693,7 +693,7 @@ static int list_single(struct dnode *dn) char *lpath = xreadlink(dn->fullname); if (lpath) { printf(" -> %s", lpath); -#ifdef BB_FEATURE_LS_FILETYPES +#ifdef CONFIG_FEATURE_LS_FILETYPES if (!stat(dn->fullname, &info)) { append = append_char(info.st_mode); } @@ -703,7 +703,7 @@ static int list_single(struct dnode *dn) } } break; -#ifdef BB_FEATURE_LS_FILETYPES +#ifdef CONFIG_FEATURE_LS_FILETYPES case LIST_FILETYPE: if (append != '\0') { printf("%1c", append); @@ -727,21 +727,21 @@ extern int ls_main(int argc, char **argv) int opt; int oi, ac; char **av; -#ifdef BB_FEATURE_AUTOWIDTH +#ifdef CONFIG_FEATURE_AUTOWIDTH struct winsize win = { 0, 0, 0, 0 }; #endif disp_opts= DISP_NORMAL; style_fmt= STYLE_AUTO; list_fmt= LIST_SHORT; -#ifdef BB_FEATURE_LS_SORTFILES +#ifdef CONFIG_FEATURE_LS_SORTFILES sort_opts= SORT_NAME; sort_order= SORT_FORWARD; #endif -#ifdef BB_FEATURE_LS_TIMESTAMPS +#ifdef CONFIG_FEATURE_LS_TIMESTAMPS time_fmt= TIME_MOD; #endif -#ifdef BB_FEATURE_AUTOWIDTH +#ifdef CONFIG_FEATURE_AUTOWIDTH ioctl(fileno(stdout), TIOCGWINSZ, &win); if (win.ws_row > 4) column_width = win.ws_row - 2; @@ -752,25 +752,25 @@ extern int ls_main(int argc, char **argv) /* process options */ while ((opt = getopt(argc, argv, "1AaCdgilnsx" -#ifdef BB_FEATURE_AUTOWIDTH +#ifdef CONFIG_FEATURE_AUTOWIDTH "T:w:" #endif -#ifdef BB_FEATURE_LS_FILETYPES +#ifdef CONFIG_FEATURE_LS_FILETYPES "Fp" #endif -#ifdef BB_FEATURE_LS_RECURSIVE +#ifdef CONFIG_FEATURE_LS_RECURSIVE "R" #endif -#ifdef BB_FEATURE_LS_SORTFILES +#ifdef CONFIG_FEATURE_LS_SORTFILES "rSvX" #endif -#ifdef BB_FEATURE_LS_TIMESTAMPS +#ifdef CONFIG_FEATURE_LS_TIMESTAMPS "cetu" #endif -#ifdef BB_FEATURE_LS_FOLLOWLINKS +#ifdef CONFIG_FEATURE_LS_FOLLOWLINKS "L" #endif -#ifdef BB_FEATURE_HUMAN_READABLE +#ifdef CONFIG_FEATURE_HUMAN_READABLE "h" #endif "k")) > 0) { @@ -785,54 +785,54 @@ extern int ls_main(int argc, char **argv) case 'l': style_fmt = STYLE_LONG; list_fmt |= LIST_LONG; -#ifdef BB_FEATURE_HUMAN_READABLE +#ifdef CONFIG_FEATURE_HUMAN_READABLE ls_disp_hr = FALSE; #endif break; case 'n': list_fmt |= LIST_ID_NUMERIC; break; case 's': list_fmt |= LIST_BLOCKS; break; case 'x': disp_opts = DISP_ROWS; break; -#ifdef BB_FEATURE_LS_FILETYPES +#ifdef CONFIG_FEATURE_LS_FILETYPES case 'F': list_fmt |= LIST_FILETYPE | LIST_EXEC; break; case 'p': list_fmt |= LIST_FILETYPE; break; #endif -#ifdef BB_FEATURE_LS_RECURSIVE +#ifdef CONFIG_FEATURE_LS_RECURSIVE case 'R': disp_opts |= DISP_RECURSIVE; break; #endif -#ifdef BB_FEATURE_LS_SORTFILES +#ifdef CONFIG_FEATURE_LS_SORTFILES case 'r': sort_order |= SORT_REVERSE; break; case 'S': sort_opts= SORT_SIZE; break; case 'v': sort_opts= SORT_VERSION; break; case 'X': sort_opts= SORT_EXT; break; #endif -#ifdef BB_FEATURE_LS_TIMESTAMPS +#ifdef CONFIG_FEATURE_LS_TIMESTAMPS case 'e': list_fmt |= LIST_FULLTIME; break; case 'c': time_fmt = TIME_CHANGE; -#ifdef BB_FEATURE_LS_SORTFILES +#ifdef CONFIG_FEATURE_LS_SORTFILES sort_opts= SORT_CTIME; #endif break; case 'u': time_fmt = TIME_ACCESS; -#ifdef BB_FEATURE_LS_SORTFILES +#ifdef CONFIG_FEATURE_LS_SORTFILES sort_opts= SORT_ATIME; #endif break; case 't': -#ifdef BB_FEATURE_LS_SORTFILES +#ifdef CONFIG_FEATURE_LS_SORTFILES sort_opts= SORT_MTIME; #endif break; #endif -#ifdef BB_FEATURE_LS_FOLLOWLINKS +#ifdef CONFIG_FEATURE_LS_FOLLOWLINKS case 'L': follow_links= TRUE; break; #endif -#ifdef BB_FEATURE_AUTOWIDTH +#ifdef CONFIG_FEATURE_AUTOWIDTH case 'T': tabstops= atoi(optarg); break; case 'w': terminal_width= atoi(optarg); break; #endif -#ifdef BB_FEATURE_HUMAN_READABLE +#ifdef CONFIG_FEATURE_HUMAN_READABLE case 'h': ls_disp_hr = TRUE; break; #endif case 'k': break; @@ -842,17 +842,17 @@ extern int ls_main(int argc, char **argv) } /* sort out which command line options take precedence */ -#ifdef BB_FEATURE_LS_RECURSIVE +#ifdef CONFIG_FEATURE_LS_RECURSIVE if (disp_opts & DISP_NOLIST) disp_opts &= ~DISP_RECURSIVE; /* no recurse if listing only dir */ #endif -#if defined (BB_FEATURE_LS_TIMESTAMPS) && defined (BB_FEATURE_LS_SORTFILES) +#if defined (CONFIG_FEATURE_LS_TIMESTAMPS) && defined (CONFIG_FEATURE_LS_SORTFILES) if (time_fmt & TIME_CHANGE) sort_opts= SORT_CTIME; if (time_fmt & TIME_ACCESS) sort_opts= SORT_ATIME; #endif if (style_fmt != STYLE_LONG) list_fmt &= ~LIST_ID_NUMERIC; /* numeric uid only for long list */ -#ifdef BB_FEATURE_LS_USERNAME +#ifdef CONFIG_FEATURE_LS_USERNAME if (style_fmt == STYLE_LONG && (list_fmt & LIST_ID_NUMERIC)) list_fmt &= ~LIST_ID_NAME; /* don't list names if numeric uid */ #endif @@ -908,7 +908,7 @@ extern int ls_main(int argc, char **argv) if (disp_opts & DISP_NOLIST) { -#ifdef BB_FEATURE_LS_SORTFILES +#ifdef CONFIG_FEATURE_LS_SORTFILES shellsort(dnp, nfiles); #endif if (nfiles > 0) showfiles(dnp, nfiles); @@ -918,13 +918,13 @@ extern int ls_main(int argc, char **argv) dndirs= countdirs(dnp, nfiles); dnfiles= nfiles - dndirs; if (dnfiles > 0) { -#ifdef BB_FEATURE_LS_SORTFILES +#ifdef CONFIG_FEATURE_LS_SORTFILES shellsort(dnf, dnfiles); #endif showfiles(dnf, dnfiles); } if (dndirs > 0) { -#ifdef BB_FEATURE_LS_SORTFILES +#ifdef CONFIG_FEATURE_LS_SORTFILES shellsort(dnd, dndirs); #endif showdirs(dnd, dndirs); diff --git a/coreutils/rmdir.c b/coreutils/rmdir.c index cac27cac9..83b27c9bd 100644 --- a/coreutils/rmdir.c +++ b/coreutils/rmdir.c @@ -2,9 +2,8 @@ /* * Mini rmdir implementation for busybox * - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , + * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/coreutils/sort.c b/coreutils/sort.c index 4f4979cc5..fc12dfb01 100644 --- a/coreutils/sort.c +++ b/coreutils/sort.c @@ -43,10 +43,10 @@ int sort_main(int argc, char **argv) char *line, **lines = NULL; int i, opt, nlines = 0; int (*compare)(const void *, const void *) = compare_ascii; -#ifdef BB_FEATURE_SORT_REVERSE +#ifdef CONFIG_FEATURE_SORT_REVERSE int reverse = FALSE; #endif -#ifdef BB_FEATURE_SORT_UNIQUE +#ifdef CONFIG_FEATURE_SORT_UNIQUE int unique = FALSE; #endif @@ -55,12 +55,12 @@ int sort_main(int argc, char **argv) case 'n': compare = compare_numeric; break; -#ifdef BB_FEATURE_SORT_REVERSE +#ifdef CONFIG_FEATURE_SORT_REVERSE case 'r': reverse = TRUE; break; #endif -#ifdef BB_FEATURE_SORT_UNIQUE +#ifdef CONFIG_FEATURE_SORT_UNIQUE case 'u': unique = TRUE; break; @@ -88,17 +88,17 @@ int sort_main(int argc, char **argv) qsort(lines, nlines, sizeof(char *), compare); /* print it */ -#ifdef BB_FEATURE_SORT_REVERSE +#ifdef CONFIG_FEATURE_SORT_REVERSE if (reverse) { for (i = --nlines; 0 <= i; i--) -#ifdef BB_FEATURE_SORT_UNIQUE +#ifdef CONFIG_FEATURE_SORT_UNIQUE if((!unique) || (i == nlines) || (strcmp(lines[i + 1], lines[i]))) #endif puts(lines[i]); } else #endif for (i = 0; i < nlines; i++) -#ifdef BB_FEATURE_SORT_UNIQUE +#ifdef CONFIG_FEATURE_SORT_UNIQUE if((!unique) || (!i) || (strcmp(lines[i - 1], lines[i]))) #endif puts(lines[i]); diff --git a/coreutils/tail.c b/coreutils/tail.c index 5e5fbc14f..0c8dec26a 100644 --- a/coreutils/tail.c +++ b/coreutils/tail.c @@ -73,7 +73,7 @@ int tail_main(int argc, char **argv) case 'f': follow = 1; break; -#ifdef BB_FEATURE_FANCY_TAIL +#ifdef CONFIG_FEATURE_FANCY_TAIL case 'c': units = BYTES; /* FALLS THROUGH */ @@ -85,7 +85,7 @@ int tail_main(int argc, char **argv) if (optarg[0] == '+') from_top = 1; break; -#ifdef BB_FEATURE_FANCY_TAIL +#ifdef CONFIG_FEATURE_FANCY_TAIL case 'q': hide_headers = 1; break; @@ -118,7 +118,7 @@ int tail_main(int argc, char **argv) } } -#ifdef BB_FEATURE_FANCY_TAIL +#ifdef CONFIG_FEATURE_FANCY_TAIL /* tail the files */ if (!from_top && units == BYTES) tailbuf = xmalloc(count); @@ -136,7 +136,7 @@ int tail_main(int argc, char **argv) printf("%s==> %s <==\n", i == 0 ? "" : "\n", argv[optind + i]); while ((nread = safe_read(fds[i], buf, sizeof(buf))) > 0) { if (from_top) { -#ifdef BB_FEATURE_FANCY_TAIL +#ifdef CONFIG_FEATURE_FANCY_TAIL if (units == BYTES) { if (count - 1 <= seen) nwrite = nread; @@ -169,7 +169,7 @@ int tail_main(int argc, char **argv) break; } } else { -#ifdef BB_FEATURE_FANCY_TAIL +#ifdef CONFIG_FEATURE_FANCY_TAIL if (units == BYTES) { if (nread < count) { memmove(tailbuf, tailbuf + nread, count - nread); @@ -203,7 +203,7 @@ int tail_main(int argc, char **argv) status = EXIT_FAILURE; } -#ifdef BB_FEATURE_FANCY_TAIL +#ifdef CONFIG_FEATURE_FANCY_TAIL if (!from_top && units == BYTES) { if (count < seen) seen = count; diff --git a/coreutils/tee.c b/coreutils/tee.c index 64a0922b7..1c145426a 100644 --- a/coreutils/tee.c +++ b/coreutils/tee.c @@ -2,8 +2,7 @@ /* * Mini tee implementation for busybox * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Matt Kraai + * Copyright (C) 2000,2001 by Matt Kraai * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/coreutils/touch.c b/coreutils/touch.c index 1718da71e..267349596 100644 --- a/coreutils/touch.c +++ b/coreutils/touch.c @@ -2,9 +2,8 @@ /* * Mini touch implementation for busybox * - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , + * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/coreutils/tr.c b/coreutils/tr.c index 5b7b8d091..2665d926f 100644 --- a/coreutils/tr.c +++ b/coreutils/tr.c @@ -155,11 +155,11 @@ extern int tr_main(int argc, char **argv) int output_length=0, input_length; int idx = 1; int i; - RESERVE_BB_BUFFER(output, BUFSIZ); - RESERVE_BB_BUFFER(input, BUFSIZ); - RESERVE_BB_UBUFFER(vector, ASCII+1); - RESERVE_BB_BUFFER(invec, ASCII+1); - RESERVE_BB_BUFFER(outvec, ASCII+1); + RESERVE_CONFIG_BUFFER(output, BUFSIZ); + RESERVE_CONFIG_BUFFER(input, BUFSIZ); + RESERVE_CONFIG_UBUFFER(vector, ASCII+1); + RESERVE_CONFIG_BUFFER(invec, ASCII+1); + RESERVE_CONFIG_BUFFER(outvec, ASCII+1); /* ... but make them available globally */ poutput = output; diff --git a/coreutils/uniq.c b/coreutils/uniq.c index 53e3c64f2..cb63c4277 100644 --- a/coreutils/uniq.c +++ b/coreutils/uniq.c @@ -2,9 +2,8 @@ /* * Mini uniq implementation for busybox * - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by John Beppu + * Copyright (C) 1999 by Lineo, inc. and John Beppu + * Copyright (C) 1999,2000,2001 by John Beppu * Rewritten by Matt Kraai * * This program is free software; you can redistribute it and/or modify diff --git a/coreutils/uuencode.c b/coreutils/uuencode.c index fc037403a..0a362a262 100644 --- a/coreutils/uuencode.c +++ b/coreutils/uuencode.c @@ -84,8 +84,8 @@ int uuencode_main(int argc, char **argv) { const int src_buf_size = 60; // This *MUST* be a multiple of 3 const int dst_buf_size = 4 * ((src_buf_size + 2) / 3); - RESERVE_BB_BUFFER(src_buf, src_buf_size + 1); - RESERVE_BB_BUFFER(dst_buf, dst_buf_size + 1); + RESERVE_CONFIG_BUFFER(src_buf, src_buf_size + 1); + RESERVE_CONFIG_BUFFER(dst_buf, dst_buf_size + 1); struct stat stat_buf; FILE *src_stream = stdin; char *tbl = tbl_std; diff --git a/cp.c b/cp.c deleted file mode 100644 index 8f8fe5ed3..000000000 --- a/cp.c +++ /dev/null @@ -1,114 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini cp implementation for busybox - * - * - * Copyright (C) 2000 by Matt Kraai - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "busybox.h" - -extern int cp_main(int argc, char **argv) -{ - int status = 0; - int opt; - int flags = FILEUTILS_DEREFERENCE; - int i; - - while ((opt = getopt(argc, argv, "adfipR")) != -1) - switch (opt) { - case 'a': - flags |= FILEUTILS_PRESERVE_STATUS | FILEUTILS_RECUR; - /* fallthrough */ - case 'd': - flags &= ~FILEUTILS_DEREFERENCE; - break; - case 'f': - flags |= FILEUTILS_FORCE; - break; - case 'i': - flags |= FILEUTILS_INTERACTIVE; - break; - case 'p': - flags |= FILEUTILS_PRESERVE_STATUS; - break; - case 'R': - flags |= FILEUTILS_RECUR; - break; - default: - show_usage(); - } - - if (optind + 2 > argc) - show_usage(); - - /* If there are only two arguments and... */ - if (optind + 2 == argc) { - struct stat source_stat; - struct stat dest_stat; - int source_exists = 1; - int dest_exists = 1; - - if ((!(flags & FILEUTILS_DEREFERENCE) && - lstat(argv[optind], &source_stat) < 0) || - ((flags & FILEUTILS_DEREFERENCE) && - stat(argv[optind], &source_stat))) { - if (errno != ENOENT) - perror_msg_and_die("unable to stat `%s'", argv[optind]); - source_exists = 0; - } - - if (stat(argv[optind + 1], &dest_stat) < 0) { - if (errno != ENOENT) - perror_msg_and_die("unable to stat `%s'", argv[optind + 1]); - dest_exists = 0; - } - - /* ...if neither is a directory or... */ - if (((!source_exists || !S_ISDIR(source_stat.st_mode)) && - (!dest_exists || !S_ISDIR(dest_stat.st_mode))) || - /* ...recursing, the first is a directory, and the - * second doesn't exist, then... */ - ((flags & FILEUTILS_RECUR) && S_ISDIR(source_stat.st_mode) && - !dest_exists)) { - /* ...do a simple copy. */ - if (copy_file(argv[optind], argv[optind + 1], flags) < 0) - status = 1; - return status; - } - } - - for (i = optind; i < argc - 1; i++) { - char *dest = concat_path_file(argv[argc - 1], - get_last_path_component(argv[i])); - if (copy_file(argv[i], dest, flags) < 0) - status = 1; - free(dest); - } - - return status; -} diff --git a/cpio.c b/cpio.c deleted file mode 100644 index 372f9f5b1..000000000 --- a/cpio.c +++ /dev/null @@ -1,95 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini cpio implementation for busybox - * - * Copyright (C) 2001 by Glenn McGrath - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Limitations: - * Doesn't check CRC's - * Only supports new ASCII and CRC formats - * - */ -#include -#include -#include -#include -#include -#include "busybox.h" - -extern int cpio_main(int argc, char **argv) -{ - FILE *src_stream = stdin; - char **extract_names = NULL; - int extract_function = 0; - int num_of_entries = 0; - int opt = 0; - mode_t oldmask = 0; - - while ((opt = getopt(argc, argv, "idmuvtF:")) != -1) { - switch (opt) { - case 'i': // extract - extract_function |= extract_all_to_fs; - break; - case 'd': // create _leading_ directories - extract_function |= extract_create_leading_dirs; - oldmask = umask(077); /* Make make_directory act like GNU cpio */ - break; - case 'm': // preserve modification time - extract_function |= extract_preserve_date; - break; - case 'v': // verbosly list files - extract_function |= extract_verbose_list; - break; - case 'u': // unconditional - extract_function |= extract_unconditional; - break; - case 't': // list files - extract_function |= extract_list; - break; - case 'F': - src_stream = xfopen(optarg, "r"); - break; - default: - show_usage(); - } - } - - if ((extract_function & extract_all_to_fs) && (extract_function & extract_list)) { - extract_function ^= extract_all_to_fs; /* If specify t, don't extract*/ - } - - if ((extract_function & extract_all_to_fs) && (extract_function & extract_verbose_list)) { - /* The meaning of v changes on extract */ - extract_function ^= extract_verbose_list; - extract_function |= extract_list; - } - - while (optind < argc) { - extract_names = xrealloc(extract_names, sizeof(char *) * (num_of_entries + 2)); - extract_names[num_of_entries] = xstrdup(argv[optind]); - num_of_entries++; - extract_names[num_of_entries] = NULL; - optind++; - } - - unarchive(src_stream, stdout, &get_header_cpio, extract_function, "./", extract_names, NULL); - if (oldmask) { - umask(oldmask); /* Restore umask if we changed it */ - } - return EXIT_SUCCESS; -} - diff --git a/cut.c b/cut.c deleted file mode 100644 index 3ed264870..000000000 --- a/cut.c +++ /dev/null @@ -1,356 +0,0 @@ -/* - * cut.c - minimalist version of cut - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Mark Whitley , - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include /* getopt */ -#include -#include -#include "busybox.h" - - -/* globals from other files */ -extern int optind; -extern char *optarg; - - -/* option vars */ -static char part = 0; /* (b)yte, (c)har, (f)ields */ -static unsigned int supress_non_delimited_lines = 0; -static char delim = '\t'; /* delimiter, default is tab */ - -struct cut_list { - int startpos; - int endpos; -}; - -static const int BOL = 0; -static const int EOL = INT_MAX; -static const int NON_RANGE = -1; - -static struct cut_list *cut_lists = NULL; /* growable array holding a series of lists */ -static unsigned int nlists = 0; /* number of elements in above list */ - - -static int cmpfunc(const void *a, const void *b) -{ - struct cut_list *la = (struct cut_list *)a; - struct cut_list *lb = (struct cut_list *)b; - - if (la->startpos > lb->startpos) - return 1; - if (la->startpos < lb->startpos) - return -1; - return 0; -} - - -/* - * parse_lists() - parses a list and puts values into startpos and endpos. - * valid list formats: N, N-, N-M, -M - * more than one list can be seperated by commas - */ -static void parse_lists(char *lists) -{ - char *ltok = NULL; - char *ntok = NULL; - char *junk; - int s = 0, e = 0; - - /* take apart the lists, one by one (they are seperated with commas */ - while ((ltok = strsep(&lists, ",")) != NULL) { - - /* it's actually legal to pass an empty list */ - if (strlen(ltok) == 0) - continue; - - /* get the start pos */ - ntok = strsep(<ok, "-"); - if (ntok == NULL) { - fprintf(stderr, "Help ntok is null for starting position! What do I do?\n"); - } else if (strlen(ntok) == 0) { - s = BOL; - } else { - s = strtoul(ntok, &junk, 10); - if(*junk != '\0' || s < 0) - error_msg_and_die("invalid byte or field list"); - - /* account for the fact that arrays are zero based, while the user - * expects the first char on the line to be char # 1 */ - if (s != 0) - s--; - } - - /* get the end pos */ - ntok = strsep(<ok, "-"); - if (ntok == NULL) { - e = NON_RANGE; - } else if (strlen(ntok) == 0) { - e = EOL; - } else { - e = strtoul(ntok, &junk, 10); - if(*junk != '\0' || e < 0) - error_msg_and_die("invalid byte or field list"); - /* if the user specified and end position of 0, that means "til the - * end of the line */ - if (e == 0) - e = INT_MAX; - e--; /* again, arrays are zero based, lines are 1 based */ - if (e == s) - e = NON_RANGE; - } - - /* if there's something left to tokenize, the user past an invalid list */ - if (ltok) - error_msg_and_die("invalid byte or field list"); - - /* add the new list */ - cut_lists = xrealloc(cut_lists, sizeof(struct cut_list) * (++nlists)); - cut_lists[nlists-1].startpos = s; - cut_lists[nlists-1].endpos = e; - } - - /* make sure we got some cut positions out of all that */ - if (nlists == 0) - error_msg_and_die("missing list of positions"); - - /* now that the lists are parsed, we need to sort them to make life easier - * on us when it comes time to print the chars / fields / lines */ - qsort(cut_lists, nlists, sizeof(struct cut_list), cmpfunc); - -} - - -static void cut_line_by_chars(const char *line) -{ - int c, l; - /* set up a list so we can keep track of what's been printed */ - char *printed = xcalloc(strlen(line), sizeof(char)); - - /* print the chars specified in each cut list */ - for (c = 0; c < nlists; c++) { - l = cut_lists[c].startpos; - while (l < strlen(line)) { - if (!printed[l]) { - putchar(line[l]); - printed[l] = 'X'; - } - l++; - if (cut_lists[c].endpos == NON_RANGE || l > cut_lists[c].endpos) - break; - } - } - putchar('\n'); /* cuz we were handed a chomped line */ - free(printed); -} - - -static void cut_line_by_fields(char *line) -{ - int c, f; - int ndelim = -1; /* zero-based / one-based problem */ - int nfields_printed = 0; - char *field = NULL; - char d[2] = { delim, 0 }; - char *printed; - - /* test the easy case first: does this line contain any delimiters? */ - if (strchr(line, delim) == NULL) { - if (!supress_non_delimited_lines) - puts(line); - return; - } - - /* set up a list so we can keep track of what's been printed */ - printed = xcalloc(strlen(line), sizeof(char)); - - /* process each list on this line, for as long as we've got a line to process */ - for (c = 0; c < nlists && line; c++) { - f = cut_lists[c].startpos; - do { - - /* find the field we're looking for */ - while (line && ndelim < f) { - field = strsep(&line, d); - ndelim++; - } - - /* we found it, and it hasn't been printed yet */ - if (field && ndelim == f && !printed[ndelim]) { - /* if this isn't our first time through, we need to print the - * delimiter after the last field that was printed */ - if (nfields_printed > 0) - putchar(delim); - fputs(field, stdout); - printed[ndelim] = 'X'; - nfields_printed++; - } - - f++; - - /* keep going as long as we have a line to work with, this is a - * list, and we're not at the end of that list */ - } while (line && cut_lists[c].endpos != NON_RANGE && f <= cut_lists[c].endpos); - } - - /* if we printed anything at all, we need to finish it with a newline cuz - * we were handed a chomped line */ - putchar('\n'); - - free(printed); -} - - -static void cut_file_by_lines(const char *line, unsigned int linenum) -{ - static int c = 0; - static int l = -1; - - /* I can't initialize this above cuz the "initializer isn't - * constant" *sigh* */ - if (l == -1) - l = cut_lists[c].startpos; - - /* get out if we have no more lists to process or if the lines are lower - * than what we're interested in */ - if (c >= nlists || linenum < l) - return; - - /* if the line we're looking for is lower than the one we were passed, it - * means we displayed it already, so move on */ - while (l < linenum) { - l++; - /* move on to the next list if we're at the end of this one */ - if (cut_lists[c].endpos == NON_RANGE || l > cut_lists[c].endpos) { - c++; - /* get out if there's no more lists to process */ - if (c >= nlists) - return; - l = cut_lists[c].startpos; - /* get out if the current line is lower than the one we just became - * interested in */ - if (linenum < l) - return; - } - } - - /* If we made it here, it means we've found the line we're looking for, so print it */ - puts(line); -} - - -/* - * snippy-snip - */ -static void cut_file(FILE *file) -{ - char *line = NULL; - unsigned int linenum = 0; /* keep these zero-based to be consistent */ - - /* go through every line in the file */ - while ((line = get_line_from_file(file)) != NULL) { - chomp(line); - - /* cut based on chars/bytes XXX: only works when sizeof(char) == byte */ - if (part == 'c' || part == 'b') - cut_line_by_chars(line); - - /* cut based on fields */ - else if (part == 'f') { - if (delim == '\n') - cut_file_by_lines(line, linenum); - else - cut_line_by_fields(line); - } - - linenum++; - free(line); - } -} - - -extern int cut_main(int argc, char **argv) -{ - int opt; - - while ((opt = getopt(argc, argv, "b:c:d:f:ns")) > 0) { - switch (opt) { - case 'b': - case 'c': - case 'f': - /* make sure they didn't ask for two types of lists */ - if (part != 0) { - error_msg_and_die("only one type of list may be specified"); - } - part = (char)opt; - parse_lists(optarg); - break; - case 'd': - if (strlen(optarg) > 1) { - error_msg_and_die("the delimiter must be a single character"); - } - delim = optarg[0]; - break; - case 'n': - /* no-op */ - break; - case 's': - supress_non_delimited_lines++; - break; - } - } - - if (part == 0) { - error_msg_and_die("you must specify a list of bytes, characters, or fields"); - } - - /* non-field (char or byte) cutting has some special handling */ - if (part != 'f') { - if (supress_non_delimited_lines) { - error_msg_and_die("suppressing non-delimited lines makes sense" - " only when operating on fields"); - } - if (delim != '\t' && part != 'f') { - error_msg_and_die("a delimiter may be specified only when operating on fields"); - } - } - - /* argv[(optind)..(argc-1)] should be names of file to process. If no - * files were specified or '-' was specified, take input from stdin. - * Otherwise, we process all the files specified. */ - if (argv[optind] == NULL || (strcmp(argv[optind], "-") == 0)) { - cut_file(stdin); - } - else { - int i; - FILE *file; - for (i = optind; i < argc; i++) { - file = wfopen(argv[i], "r"); - if(file) { - cut_file(file); - fclose(file); - } - } - } - - return EXIT_SUCCESS; -} diff --git a/date.c b/date.c deleted file mode 100644 index 6db3e2838..000000000 --- a/date.c +++ /dev/null @@ -1,247 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini date implementation for busybox - * - * by Matthew Grant - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" - - -/* This 'date' command supports only 2 time setting formats, - all the GNU strftime stuff (its in libc, lets use it), - setting time using UTC and displaying int, as well as - an RFC 822 complient date output for shell scripting - mail commands */ - -/* Input parsing code is always bulky - used heavy duty libc stuff as - much as possible, missed out a lot of bounds checking */ - -/* Default input handling to save suprising some people */ - -static struct tm *date_conv_time(struct tm *tm_time, const char *t_string) -{ - int nr; - - nr = sscanf(t_string, "%2d%2d%2d%2d%d", - &(tm_time->tm_mon), - &(tm_time->tm_mday), - &(tm_time->tm_hour), - &(tm_time->tm_min), &(tm_time->tm_year)); - - if (nr < 4 || nr > 5) { - error_msg_and_die(invalid_date, t_string); - } - - /* correct for century - minor Y2K problem here? */ - if (tm_time->tm_year >= 1900) - tm_time->tm_year -= 1900; - /* adjust date */ - tm_time->tm_mon -= 1; - - return (tm_time); - -} - - -/* The new stuff for LRP */ - -static struct tm *date_conv_ftime(struct tm *tm_time, const char *t_string) -{ - struct tm t; - - /* Parse input and assign appropriately to tm_time */ - - if (t=*tm_time,sscanf(t_string, "%d:%d:%d", - &t.tm_hour, &t.tm_min, &t.tm_sec) == 3) { - /* no adjustments needed */ - - } else if (t=*tm_time,sscanf(t_string, "%d:%d", - &t.tm_hour, &t.tm_min) == 2) { - /* no adjustments needed */ - - - } else if (t=*tm_time,sscanf(t_string, "%d.%d-%d:%d:%d", - &t.tm_mon, - &t.tm_mday, - &t.tm_hour, - &t.tm_min, &t.tm_sec) == 5) { - - t.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */ - - } else if (t=*tm_time,sscanf(t_string, "%d.%d-%d:%d", - &t.tm_mon, - &t.tm_mday, - &t.tm_hour, &t.tm_min) == 4) { - - t.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */ - - } else if (t=*tm_time,sscanf(t_string, "%d.%d.%d-%d:%d:%d", - &t.tm_year, - &t.tm_mon, - &t.tm_mday, - &t.tm_hour, - &t.tm_min, &t.tm_sec) == 6) { - - t.tm_year -= 1900; /* Adjust years */ - t.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */ - - } else if (t=*tm_time,sscanf(t_string, "%d.%d.%d-%d:%d", - &t.tm_year, - &t.tm_mon, - &t.tm_mday, - &t.tm_hour, &t.tm_min) == 5) { - t.tm_year -= 1900; /* Adjust years */ - t.tm_mon -= 1; /* Adjust dates from 1-12 to 0-11 */ - - } else { - error_msg_and_die(invalid_date, t_string); - } - *tm_time = t; - return (tm_time); -} - - -int date_main(int argc, char **argv) -{ - char *date_str = NULL; - char *date_fmt = NULL; - char *t_buff; - int c; - int set_time = 0; - int rfc822 = 0; - int utc = 0; - int use_arg = 0; - time_t tm; - struct tm tm_time; - - /* Interpret command line args */ - while ((c = getopt(argc, argv, "Rs:ud:")) != EOF) { - switch (c) { - case 'R': - rfc822 = 1; - break; - case 's': - set_time = 1; - if ((date_str != NULL) || ((date_str = optarg) == NULL)) { - show_usage(); - } - break; - case 'u': - utc = 1; - if (putenv("TZ=UTC0") != 0) - error_msg_and_die(memory_exhausted); - break; - case 'd': - use_arg = 1; - if ((date_str != NULL) || ((date_str = optarg) == NULL)) - show_usage(); - break; - default: - show_usage(); - } - } - - if ((date_fmt == NULL) && (optind < argc) && (argv[optind][0] == '+')) - date_fmt = &argv[optind][1]; /* Skip over the '+' */ - else if (date_str == NULL) { - set_time = 1; - date_str = argv[optind]; - } -#if 0 - else { - error_msg("date_str='%s' date_fmt='%s'\n", date_str, date_fmt); - show_usage(); - } -#endif - - /* Now we have parsed all the information except the date format - which depends on whether the clock is being set or read */ - - time(&tm); - memcpy(&tm_time, localtime(&tm), sizeof(tm_time)); - /* Zero out fields - take her back to midnight! */ - if (date_str != NULL) { - tm_time.tm_sec = 0; - tm_time.tm_min = 0; - tm_time.tm_hour = 0; - } - - /* Process any date input to UNIX time since 1 Jan 1970 */ - if (date_str != NULL) { - - if (strchr(date_str, ':') != NULL) { - date_conv_ftime(&tm_time, date_str); - } else { - date_conv_time(&tm_time, date_str); - } - - /* Correct any day of week and day of year etc. fields */ - tm = mktime(&tm_time); - if (tm < 0) - error_msg_and_die(invalid_date, date_str); - if ( utc ) { - if (putenv("TZ=UTC0") != 0) - error_msg_and_die(memory_exhausted); - } - - /* if setting time, set it */ - if (set_time) { - if (stime(&tm) < 0) { - perror_msg("cannot set date"); - } - } - } - - /* Display output */ - - /* Deal with format string */ - if (date_fmt == NULL) { - date_fmt = (rfc822 - ? (utc - ? "%a, %_d %b %Y %H:%M:%S GMT" - : "%a, %_d %b %Y %H:%M:%S %z") - : "%a %b %e %H:%M:%S %Z %Y"); - - } else if (*date_fmt == '\0') { - /* Imitate what GNU 'date' does with NO format string! */ - printf("\n"); - return EXIT_SUCCESS; - } - - /* Handle special conversions */ - - if (strncmp(date_fmt, "%f", 2) == 0) { - date_fmt = "%Y.%m.%d-%H:%M:%S"; - } - - /* Print OUTPUT (after ALL that!) */ - t_buff = xmalloc(201); - strftime(t_buff, 200, date_fmt, &tm_time); - puts(t_buff); - - return EXIT_SUCCESS; -} diff --git a/dc.c b/dc.c deleted file mode 100644 index 8d7a92a28..000000000 --- a/dc.c +++ /dev/null @@ -1,182 +0,0 @@ -/* vi: set sw=4 ts=4: */ -#include -#include -#include -#include -#include -#include -#include "busybox.h" - -/* Tiny RPN calculator, because "expr" didn't give me bitwise operations. */ - -static double stack[100]; -static unsigned int pointer; - -static void push(double a) -{ - if (pointer >= (sizeof(stack) / sizeof(*stack))) - error_msg_and_die("stack overflow"); - stack[pointer++] = a; -} - -static double pop() -{ - if (pointer == 0) - error_msg_and_die("stack underflow"); - return stack[--pointer]; -} - -static void add() -{ - push(pop() + pop()); -} - -static void sub() -{ - double subtrahend = pop(); - - push(pop() - subtrahend); -} - -static void mul() -{ - push(pop() * pop()); -} - -static void divide() -{ - double divisor = pop(); - - push(pop() / divisor); -} - -static void and() -{ - push((unsigned int) pop() & (unsigned int) pop()); -} - -static void or() -{ - push((unsigned int) pop() | (unsigned int) pop()); -} - -static void eor() -{ - push((unsigned int) pop() ^ (unsigned int) pop()); -} - -static void not() -{ - push(~(unsigned int) pop()); -} - -static void print() -{ - printf("%g\n", pop()); -} - -struct op { - const char *name; - void (*function) (); -}; - -static const struct op operators[] = { - {"+", add}, - {"add", add}, - {"-", sub}, - {"sub", sub}, - {"*", mul}, - {"mul", mul}, - {"/", divide}, - {"div", divide}, - {"and", and}, - {"or", or}, - {"not", not}, - {"eor", eor}, - {0, 0} -}; - -static void stack_machine(const char *argument) -{ - char *endPointer = 0; - double d; - const struct op *o = operators; - - if (argument == 0) { - print(); - return; - } - - d = strtod(argument, &endPointer); - - if (endPointer != argument) { - push(d); - return; - } - - while (o->name != 0) { - if (strcmp(o->name, argument) == 0) { - (*(o->function)) (); - return; - } - o++; - } - error_msg_and_die("%s: syntax error.", argument); -} - -/* return pointer to next token in buffer and set *buffer to one char - * past the end of the above mentioned token - */ -static char *get_token(char **buffer) -{ - char *start = NULL; - char *current = *buffer; - - while (isspace(*current)) { current++; } - if (*current != 0) { - start = current; - while (!isspace(*current) && current != 0) { current++; } - *buffer = current; - } - return start; -} - -/* In Perl one might say, scalar m|\s*(\S+)\s*|g */ -static int number_of_tokens(char *buffer) -{ - int i = 0; - char *b = buffer; - while (get_token(&b)) { i++; } - return i; -} - -int dc_main(int argc, char **argv) -{ - /* take stuff from stdin if no args are given */ - if (argc <= 1) { - int i, len; - char *line = NULL; - char *cursor = NULL; - char *token = NULL; - while ((line = get_line_from_file(stdin))) { - cursor = line; - len = number_of_tokens(line); - for (i = 0; i < len; i++) { - token = get_token(&cursor); - *cursor++ = 0; - stack_machine(token); - } - free(line); - } - } else { - if (*argv[1]=='-') - show_usage(); - while (argc >= 2) { - stack_machine(argv[1]); - argv++; - argc--; - } - } - stack_machine(0); - return EXIT_SUCCESS; -} diff --git a/dd.c b/dd.c deleted file mode 100644 index d46db82a0..000000000 --- a/dd.c +++ /dev/null @@ -1,154 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini dd implementation for busybox - * - * - * Copyright (C) 2000 by Matt Kraai - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include "busybox.h" - - -static const struct suffix_mult dd_suffixes[] = { - { "c", 1 }, - { "w", 2 }, - { "b", 512 }, - { "kD", 1000 }, - { "k", 1024 }, - { "MD", 1000000 }, - { "M", 1048576 }, - { "GD", 1000000000 }, - { "G", 1073741824 }, - { NULL, 0 } -}; - -int dd_main(int argc, char **argv) -{ - int i, ifd, ofd, oflag, sync_flag = FALSE, trunc = TRUE; - size_t in_full = 0, in_part = 0, out_full = 0, out_part = 0; - size_t bs = 512, count = -1; - ssize_t n; - off_t seek = 0, skip = 0; - char *infile = NULL, *outfile = NULL, *buf; - - for (i = 1; i < argc; i++) { - if (strncmp("bs=", argv[i], 3) == 0) - bs = parse_number(argv[i]+3, dd_suffixes); - else if (strncmp("count=", argv[i], 6) == 0) - count = parse_number(argv[i]+6, dd_suffixes); - else if (strncmp("seek=", argv[i], 5) == 0) - seek = parse_number(argv[i]+5, dd_suffixes); - else if (strncmp("skip=", argv[i], 5) == 0) - skip = parse_number(argv[i]+5, dd_suffixes); - else if (strncmp("if=", argv[i], 3) == 0) - infile = argv[i]+3; - else if (strncmp("of=", argv[i], 3) == 0) - outfile = argv[i]+3; - else if (strncmp("conv=", argv[i], 5) == 0) { - buf = argv[i]+5; - while (1) { - if (strncmp("notrunc", buf, 7) == 0) { - trunc = FALSE; - buf += 7; - } else if (strncmp("sync", buf, 4) == 0) { - sync_flag = TRUE; - buf += 4; - } else { - error_msg_and_die("invalid conversion `%s'", argv[i]+5); - } - if (buf[0] == '\0') - break; - if (buf[0] == ',') - buf++; - } - } else - show_usage(); - } - - buf = xmalloc(bs); - - if (infile != NULL) { - if ((ifd = open(infile, O_RDONLY)) < 0) - perror_msg_and_die("%s", infile); - } else { - ifd = STDIN_FILENO; - infile = "standard input"; - } - - if (outfile != NULL) { - oflag = O_WRONLY | O_CREAT; - - if (!seek && trunc) - oflag |= O_TRUNC; - - if ((ofd = open(outfile, oflag, 0666)) < 0) - perror_msg_and_die("%s", outfile); - - if (seek && trunc) { - if (ftruncate(ofd, seek * bs) < 0) - perror_msg_and_die("%s", outfile); - } - } else { - ofd = STDOUT_FILENO; - outfile = "standard output"; - } - - if (skip) { - if (lseek(ifd, skip * bs, SEEK_CUR) < 0) - perror_msg_and_die("%s", infile); - } - - if (seek) { - if (lseek(ofd, seek * bs, SEEK_CUR) < 0) - perror_msg_and_die("%s", outfile); - } - - while (in_full + in_part != count) { - n = safe_read(ifd, buf, bs); - if (n < 0) - perror_msg_and_die("%s", infile); - if (n == 0) - break; - if (n == bs) - in_full++; - else - in_part++; - if (sync_flag) { - memset(buf + n, '\0', bs - n); - n = bs; - } - n = full_write(ofd, buf, n); - if (n < 0) - perror_msg_and_die("%s", outfile); - if (n == bs) - out_full++; - else - out_part++; - } - - fprintf(stderr, "%ld+%ld records in\n", (long)in_full, (long)in_part); - fprintf(stderr, "%ld+%ld records out\n", (long)out_full, (long)out_part); - - return EXIT_SUCCESS; -} diff --git a/deallocvt.c b/deallocvt.c deleted file mode 100644 index 15cd0c9b9..000000000 --- a/deallocvt.c +++ /dev/null @@ -1,43 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * disalloc.c - aeb - 940501 - Disallocate virtual terminal(s) - * Renamed deallocvt. - */ -#include -#include -#include -#include -#include -#include "busybox.h" - -/* From */ -static const int VT_DISALLOCATE = 0x5608; /* free memory associated to vt */ - -int deallocvt_main(int argc, char *argv[]) -{ - int fd, num, i; - - //if ((argc > 2) || ((argv == 2) && (**(argv + 1) == '-'))) - if (argc > 2) - show_usage(); - - fd = get_console_fd("/dev/console"); - - if (argc == 1) { - /* deallocate all unused consoles */ - if (ioctl(fd, VT_DISALLOCATE, 0)) - perror_msg_and_die("VT_DISALLOCATE"); - } else { - for (i = 1; i < argc; i++) { - num = atoi(argv[i]); - if (num == 0) - error_msg("0: illegal VT number"); - else if (num == 1) - error_msg("VT 1 cannot be deallocated"); - else if (ioctl(fd, VT_DISALLOCATE, num)) - perror_msg_and_die("VT_DISALLOCATE"); - } - } - - return EXIT_SUCCESS; -} diff --git a/debian/Config.h-deb b/debian/Config.h-deb index fd848e192..818d66d53 100644 --- a/debian/Config.h-deb +++ b/debian/Config.h-deb @@ -3,142 +3,142 @@ // When you turn things off here, they won't be compiled in at all. // //// This file is parsed by sed. You MUST use single line comments. -// i.e., //#define BB_BLAH +// i.e., //#define CONFIG_BLAH // // // BusyBox Applications -//#define BB_ADJTIMEX -#define BB_AR -//#define BB_ASH -#define BB_BASENAME -#define BB_CAT -#define BB_CHGRP -#define BB_CHMOD -#define BB_CHOWN -#define BB_CHROOT -#define BB_CHVT -#define BB_CLEAR -//#define BB_CMP -#define BB_CP -//#define BB_CPIO -#define BB_CUT -#define BB_DATE -//#define BB_DC -#define BB_DD -//#define BB_DEALLOCVT -#define BB_DF -#define BB_DIRNAME -#define BB_DMESG -//#define BB_DOS2UNIX -//#define BB_DPKG -//#define BB_DPKG_DEB -//#define BB_DUTMP -#define BB_DU -//#define BB_DUMPKMAP -#define BB_ECHO -#define BB_ENV -#define BB_EXPR -//#define BB_FBSET -//#define BB_FDFLUSH -#define BB_FIND -#define BB_FREE -//#define BB_FREERAMDISK -//#define BB_FSCK_MINIX -//#define BB_GETOPT -#define BB_GREP -#define BB_GUNZIP -#define BB_GZIP -#define BB_HALT -#define BB_HEAD -//#define BB_HOSTID -//#define BB_HOSTNAME -//#define BB_HUSH -#define BB_ID -//#define BB_IFCONFIG -#define BB_INIT -//#define BB_INSMOD -#define BB_KILL -#define BB_KILLALL -#define BB_KLOGD -//#define BB_LASH -//#define BB_LENGTH -#define BB_LN -//#define BB_LOADACM -//#define BB_LOADFONT -#define BB_LOADKMAP -#define BB_LOGGER -//#define BB_LOGNAME -#define BB_LS -#define BB_LSMOD -//#define BB_MAKEDEVS -#define BB_MD5SUM -#define BB_MKDIR -//#define BB_MKFIFO -//#define BB_MKFS_MINIX -#define BB_MKNOD -#define BB_MKSWAP -//#define BB_MKTEMP -//#define BB_MODPROBE -#define BB_MORE -#define BB_MOUNT -//#define BB_MSH -//#define BB_MT -#define BB_MV -//#define BB_NC -//#define BB_NSLOOKUP -//#define BB_PIDOF -#define BB_PING -//#define BB_PIVOT_ROOT -#define BB_POWEROFF -//#define BB_PRINTF -#define BB_PS -#define BB_PWD -//#define BB_RDATE -//#define BB_READLINK -#define BB_REBOOT -//#define BB_RENICE -#define BB_RESET -#define BB_RM -#define BB_RMDIR -//#define BB_RMMOD -//#define BB_ROUTE -//#define BB_RPM2CPIO -#define BB_SED -//#define BB_SETKEYCODES -#define BB_SLEEP -#define BB_SORT -//#define BB_STTY -#define BB_SWAPONOFF -#define BB_SYNC -#define BB_SYSLOGD -#define BB_TAIL -#define BB_TAR -//#define BB_TEE -//#define BB_TEST -#define BB_TELNET -//#define BB_TFTP -#define BB_TOUCH -#define BB_TR -//#define BB_TRACEROUTE -#define BB_TRUE_FALSE -#define BB_TTY -//#define BB_UNIX2DOS -//#define BB_UUENCODE -//#define BB_UUDECODE -#define BB_UMOUNT -#define BB_UNIQ -#define BB_UNAME -//#define BB_UPDATE -#define BB_UPTIME -//#define BB_USLEEP -#define BB_VI -//#define BB_WATCHDOG -#define BB_WC -#define BB_WGET -#define BB_WHICH -#define BB_WHOAMI -#define BB_XARGS -#define BB_YES +//#define CONFIG_ADJTIMEX +#define CONFIG_AR +//#define CONFIG_ASH +#define CONFIG_BASENAME +#define CONFIG_CAT +#define CONFIG_CHGRP +#define CONFIG_CHMOD +#define CONFIG_CHOWN +#define CONFIG_CHROOT +#define CONFIG_CHVT +#define CONFIG_CLEAR +//#define CONFIG_CMP +#define CONFIG_CP +//#define CONFIG_CPIO +#define CONFIG_CUT +#define CONFIG_DATE +//#define CONFIG_DC +#define CONFIG_DD +//#define CONFIG_DEALLOCVT +#define CONFIG_DF +#define CONFIG_DIRNAME +#define CONFIG_DMESG +//#define CONFIG_DOS2UNIX +//#define CONFIG_DPKG +//#define CONFIG_DPKG_DEB +//#define CONFIG_DUTMP +#define CONFIG_DU +//#define CONFIG_DUMPKMAP +#define CONFIG_ECHO +#define CONFIG_ENV +#define CONFIG_EXPR +//#define CONFIG_FBSET +//#define CONFIG_FDFLUSH +#define CONFIG_FIND +#define CONFIG_FREE +//#define CONFIG_FREERAMDISK +//#define CONFIG_FSCK_MINIX +//#define CONFIG_GETOPT +#define CONFIG_GREP +#define CONFIG_GUNZIP +#define CONFIG_GZIP +#define CONFIG_HALT +#define CONFIG_HEAD +//#define CONFIG_HOSTID +//#define CONFIG_HOSTNAME +//#define CONFIG_HUSH +#define CONFIG_ID +//#define CONFIG_IFCONFIG +#define CONFIG_INIT +//#define CONFIG_INSMOD +#define CONFIG_KILL +#define CONFIG_KILLALL +#define CONFIG_KLOGD +//#define CONFIG_LASH +//#define CONFIG_LENGTH +#define CONFIG_LN +//#define CONFIG_LOADACM +//#define CONFIG_LOADFONT +#define CONFIG_LOADKMAP +#define CONFIG_LOGGER +//#define CONFIG_LOGNAME +#define CONFIG_LS +#define CONFIG_LSMOD +//#define CONFIG_MAKEDEVS +#define CONFIG_MD5SUM +#define CONFIG_MKDIR +//#define CONFIG_MKFIFO +//#define CONFIG_MKFS_MINIX +#define CONFIG_MKNOD +#define CONFIG_MKSWAP +//#define CONFIG_MKTEMP +//#define CONFIG_MODPROBE +#define CONFIG_MORE +#define CONFIG_MOUNT +//#define CONFIG_MSH +//#define CONFIG_MT +#define CONFIG_MV +//#define CONFIG_NC +//#define CONFIG_NSLOOKUP +//#define CONFIG_PIDOF +#define CONFIG_PING +//#define CONFIG_PIVOT_ROOT +#define CONFIG_POWEROFF +//#define CONFIG_PRINTF +#define CONFIG_PS +#define CONFIG_PWD +//#define CONFIG_RDATE +//#define CONFIG_READLINK +#define CONFIG_REBOOT +//#define CONFIG_RENICE +#define CONFIG_RESET +#define CONFIG_RM +#define CONFIG_RMDIR +//#define CONFIG_RMMOD +//#define CONFIG_ROUTE +//#define CONFIG_RPM2CPIO +#define CONFIG_SED +//#define CONFIG_SETKEYCODES +#define CONFIG_SLEEP +#define CONFIG_SORT +//#define CONFIG_STTY +#define CONFIG_SWAPONOFF +#define CONFIG_SYNC +#define CONFIG_SYSLOGD +#define CONFIG_TAIL +#define CONFIG_TAR +//#define CONFIG_TEE +//#define CONFIG_TEST +#define CONFIG_TELNET +//#define CONFIG_TFTP +#define CONFIG_TOUCH +#define CONFIG_TR +//#define CONFIG_TRACEROUTE +#define CONFIG_TRUE_FALSE +#define CONFIG_TTY +//#define CONFIG_UNIX2DOS +//#define CONFIG_UUENCODE +//#define CONFIG_UUDECODE +#define CONFIG_UMOUNT +#define CONFIG_UNIQ +#define CONFIG_UNAME +//#define CONFIG_UPDATE +#define CONFIG_UPTIME +//#define CONFIG_USLEEP +#define CONFIG_VI +//#define CONFIG_WATCHDOG +#define CONFIG_WC +#define CONFIG_WGET +#define CONFIG_WHICH +#define CONFIG_WHOAMI +#define CONFIG_XARGS +#define CONFIG_YES // End of Applications List // // @@ -151,21 +151,21 @@ // // If you enabled one or more of the shells, you may select which one // should be run when sh is invoked: -//#define BB_FEATURE_SH_IS_ASH -//#define BB_FEATURE_SH_IS_HUSH -//#define BB_FEATURE_SH_IS_LASH -#define BB_FEATURE_SH_IS_MSH +//#define CONFIG_FEATURE_SH_IS_ASH +//#define CONFIG_FEATURE_SH_IS_HUSH +//#define CONFIG_FEATURE_SH_IS_LASH +#define CONFIG_FEATURE_SH_IS_MSH // // BusyBox will, by default, malloc space for its buffers. This costs code // size for the call to xmalloc. You can use the following feature to have // them put on the stack. For some very small machines with limited stack // space, this can be deadly. For most folks, this works just fine... -//#define BB_FEATURE_BUFFERS_GO_ON_STACK +//#define CONFIG_FEATURE_BUFFERS_GO_ON_STACK // The third alternative for buffer allocation is to use BSS. This works // beautifully for computers with a real MMU (and OS support), but wastes // runtime RAM for uCLinux. This behavior was the only one available for // BusyBox versions 0.48 and earlier. -//#define BB_FEATURE_BUFFERS_GO_IN_BSS +//#define CONFIG_FEATURE_BUFFERS_GO_IN_BSS // // Turn this on to use Erik's very cool devps, and devmtab kernel drivers, // thereby eliminating the need for the /proc filesystem and thereby saving @@ -176,212 +176,212 @@ // mknod /dev/mtab c 10 22 // mknod /dev/ps c 10 21 // I emailed Linus and this patch will not be going into the stock kernel. -//#define BB_FEATURE_USE_DEVPS_PATCH +//#define CONFIG_FEATURE_USE_DEVPS_PATCH // // show verbose usage messages -//#define BB_FEATURE_VERBOSE_USAGE +//#define CONFIG_FEATURE_VERBOSE_USAGE // // Use termios to manipulate the screen ('more' is prettier with this on) -#define BB_FEATURE_USE_TERMIOS +#define CONFIG_FEATURE_USE_TERMIOS // // calculate terminal & column widths (for more and ls) -#define BB_FEATURE_AUTOWIDTH +#define CONFIG_FEATURE_AUTOWIDTH // // show username/groupnames for ls -#define BB_FEATURE_LS_USERNAME +#define CONFIG_FEATURE_LS_USERNAME // // show file timestamps in ls -#define BB_FEATURE_LS_TIMESTAMPS +#define CONFIG_FEATURE_LS_TIMESTAMPS // // enable ls -p and -F -#define BB_FEATURE_LS_FILETYPES +#define CONFIG_FEATURE_LS_FILETYPES // // sort the file names -#define BB_FEATURE_LS_SORTFILES +#define CONFIG_FEATURE_LS_SORTFILES // // enable ls -R -#define BB_FEATURE_LS_RECURSIVE +#define CONFIG_FEATURE_LS_RECURSIVE // // enable ls -L -#define BB_FEATURE_LS_FOLLOWLINKS +#define CONFIG_FEATURE_LS_FOLLOWLINKS // // Disable for a smaller (but less functional) ping -#define BB_FEATURE_FANCY_PING +#define CONFIG_FEATURE_FANCY_PING // // Make init use a simplified /etc/inittab file (recommended). -#define BB_FEATURE_USE_INITTAB +#define CONFIG_FEATURE_USE_INITTAB // //Enable init being called as /linuxrc -#define BB_FEATURE_LINUXRC +#define CONFIG_FEATURE_INITRD // //Have init enable core dumping for child processes (for debugging only) -//#define BB_FEATURE_INIT_COREDUMPS +//#define CONFIG_FEATURE_INIT_COREDUMPS // //Make sure nothing is printed to the console on boot -//#define BB_FEATURE_EXTRA_QUIET +//#define CONFIG_FEATURE_EXTRA_QUIET // // enable syslogd -R remotehost -#define BB_FEATURE_REMOTE_LOG +#define CONFIG_FEATURE_REMOTE_LOG // // enable syslogd -C -//#define BB_FEATURE_IPC_SYSLOG +//#define CONFIG_FEATURE_IPC_SYSLOG // //Disable for a simple tail implementation (2.34k vs 3k for the full one). //Both provide 'tail -f', but this cuts out -c, -q, -s, and -v. -#define BB_FEATURE_FANCY_TAIL +#define CONFIG_FEATURE_FANCY_TAIL // // Enable support for loop devices in mount -#define BB_FEATURE_MOUNT_LOOP +#define CONFIG_FEATURE_MOUNT_LOOP // // Enable support for a real /etc/mtab file instead of /proc/mounts -//#define BB_FEATURE_MTAB_SUPPORT +//#define CONFIG_FEATURE_MTAB_SUPPORT // // Enable support for mounting remote NFS volumes. // You may need to mount with "-o nolock" if you are // not running a local portmapper daemon... -#define BB_FEATURE_NFSMOUNT +#define CONFIG_FEATURE_NFSMOUNT // // Enable support forced filesystem unmounting // (i.e., in case of an unreachable NFS system). -#define BB_FEATURE_MOUNT_FORCE +#define CONFIG_FEATURE_MOUNT_FORCE // // Enable support for creation of tar files. -#define BB_FEATURE_TAR_CREATE +#define CONFIG_FEATURE_TAR_CREATE // // Enable support for "--exclude" and "-X" for excluding files -#define BB_FEATURE_TAR_EXCLUDE +#define CONFIG_FEATURE_TAR_EXCLUDE // // Enable support for tar -z option (currently only works for inflating) -#define BB_FEATURE_TAR_GZIP +#define CONFIG_FEATURE_TAR_GZIP // // Enable reverse sort -#define BB_FEATURE_SORT_REVERSE +#define CONFIG_FEATURE_SORT_REVERSE // // Enable uniqe sort -#define BB_FEATURE_SORT_UNIQUE +#define CONFIG_FEATURE_SORT_UNIQUE // // Enable command line editing in the shell. // Only relevant if a shell is enabled. On by default. -#define BB_FEATURE_COMMAND_EDITING +#define CONFIG_FEATURE_COMMAND_EDITING // // Enable tab completion in the shell. This is now working quite nicely. // This feature adds a bit over 4k. Only relevant if a shell is enabled. -#define BB_FEATURE_COMMAND_TAB_COMPLETION +#define CONFIG_FEATURE_COMMAND_TAB_COMPLETION // // Attempts to match usernames in a ~-prefixed path -//#define BB_FEATURE_COMMAND_USERNAME_COMPLETION +//#define CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION // //Allow the shell to invoke all the compiled in BusyBox applets as if they //were shell builtins. Nice for staticly linking an emergency rescue shell, //among other things. Off by default. // Only relevant if a shell is enabled. -//#define BB_FEATURE_SH_STANDALONE_SHELL +//#define CONFIG_FEATURE_SH_STANDALONE_SHELL // //When this is enabled, busybox shell applets can be called using full path //names. This causes applets (i.e., most busybox commands) to override //real commands on the filesystem. For example, if you run run /bin/cat, it //will use BusyBox cat even if /bin/cat exists on the filesystem and is _not_ //busybox. Some systems want this, others do not. Choose wisely. :-) This -//only has meaning when BB_FEATURE_SH_STANDALONE_SHELL is enabled. +//only has meaning when CONFIG_FEATURE_SH_STANDALONE_SHELL is enabled. // Only relevant if a shell is enabled. Off by default. -//#define BB_FEATURE_SH_APPLETS_ALWAYS_WIN +//#define CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN // // Uncomment this option for a fancy shell prompt that includes the // current username and hostname. On systems that don't have usernames // or hostnames, this can look hideous. // Only relevant if a shell is enabled. -//#define BB_FEATURE_SH_FANCY_PROMPT +//#define CONFIG_FEATURE_SH_FANCY_PROMPT // //Turn on extra fbset options -//#define BB_FEATURE_FBSET_FANCY +//#define CONFIG_FEATURE_FBSET_FANCY // //Turn on fbset readmode support -//#define BB_FEATURE_FBSET_READMODE +//#define CONFIG_FEATURE_FBSET_READMODE // // Support insmod/lsmod/rmmod for post 2.1 kernels -//#define BB_FEATURE_NEW_MODULE_INTERFACE +//#define CONFIG_FEATURE_NEW_MODULE_INTERFACE // // Support insmod/lsmod/rmmod for pre 2.1 kernels -//#define BB_FEATURE_OLD_MODULE_INTERFACE +//#define CONFIG_FEATURE_OLD_MODULE_INTERFACE // // Support module version checking -//#define BB_FEATURE_INSMOD_VERSION_CHECKING +//#define CONFIG_FEATURE_INSMOD_VERSION_CHECKING // // Support for uClinux memory usage optimization, which will load the image // directly into the kernel memory. This divides memory requrements by three. // If you are not running uClinux (i.e., your CPU has an MMU) leave this // disabled... -//#define BB_FEATURE_INSMOD_LOADINKMEM +//#define CONFIG_FEATURE_INSMOD_LOADINKMEM // // Support for Minix filesystem, version 2 -//#define BB_FEATURE_MINIX2 +//#define CONFIG_FEATURE_MINIX2 // // Enable ifconfig status reporting output -- this feature adds 12k. -#define BB_FEATURE_IFCONFIG_STATUS +#define CONFIG_FEATURE_IFCONFIG_STATUS // // Enable ifconfig slip-specific options "keepalive" and "outfill" -//#define BB_FEATURE_IFCONFIG_SLIP +//#define CONFIG_FEATURE_IFCONFIG_SLIP // // Enable ifconfig options "mem_start", "io_addr", and "irq". -//#define BB_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ +//#define CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ // // Enable ifconfig option "hw". Currently works for only with "ether". -#define BB_FEATURE_IFCONFIG_HW +#define CONFIG_FEATURE_IFCONFIG_HW // // Enable busybox --install [-s] // to create links (or symlinks) for all the commands that are // compiled into the binary. (needs /proc filesystem) -#define BB_FEATURE_INSTALLER +#define CONFIG_FEATURE_INSTALLER // // Enable a nifty progress meter in wget (adds just under 2k) -#define BB_FEATURE_WGET_STATUSBAR +#define CONFIG_FEATURE_WGET_STATUSBAR // // Enable HTTP authentication in wget -#define BB_FEATURE_WGET_AUTHENTICATION +#define CONFIG_FEATURE_WGET_AUTHENTICATION // // Clean up all memory before exiting -- usually not needed // as the OS can clean up... Don't enable this unless you // have a really good reason for cleaning things up manually. -//#define BB_FEATURE_CLEAN_UP +//#define CONFIG_FEATURE_CLEAN_UP // // Support for human readable output by ls, du, etc.(example 13k, 23M, 235G) -#define BB_FEATURE_HUMAN_READABLE +#define CONFIG_FEATURE_HUMAN_READABLE // // Support for the find -type option. -#define BB_FEATURE_FIND_TYPE +#define CONFIG_FEATURE_FIND_TYPE // // Support for the find -perm option. -#define BB_FEATURE_FIND_PERM +#define CONFIG_FEATURE_FIND_PERM // // Support for the find -mtine option. -#define BB_FEATURE_FIND_MTIME +#define CONFIG_FEATURE_FIND_MTIME // // Support for the -A -B and -C context flags in grep -//#define BB_FEATURE_GREP_CONTEXT +//#define CONFIG_FEATURE_GREP_CONTEXT // // Support for the EGREP applet (alias to the grep applet) -//#define BB_FEATURE_GREP_EGREP_ALIAS +//#define CONFIG_FEATURE_GREP_EGREP_ALIAS // // Tell tftp what commands that should be supported. -#define BB_FEATURE_TFTP_PUT -#define BB_FEATURE_TFTP_GET +#define CONFIG_FEATURE_TFTP_PUT +#define CONFIG_FEATURE_TFTP_GET // // features for vi -#define BB_FEATURE_VI_COLON // ":" colon commands, no "ex" mode -#define BB_FEATURE_VI_YANKMARK // Yank/Put commands and Mark cmds -#define BB_FEATURE_VI_SEARCH // search and replace cmds -#define BB_FEATURE_VI_USE_SIGNALS // catch signals -#define BB_FEATURE_VI_DOT_CMD // remember previous cmd and "." cmd -#define BB_FEATURE_VI_READONLY // vi -R and "view" mode -#define BB_FEATURE_VI_SETOPTS // set-able options, ai ic showmatch -#define BB_FEATURE_VI_SET // :set -#define BB_FEATURE_VI_WIN_RESIZE // handle window resize +#define CONFIG_FEATURE_VI_COLON // ":" colon commands, no "ex" mode +#define CONFIG_FEATURE_VI_YANKMARK // Yank/Put commands and Mark cmds +#define CONFIG_FEATURE_VI_SEARCH // search and replace cmds +#define CONFIG_FEATURE_VI_USE_SIGNALS // catch signals +#define CONFIG_FEATURE_VI_DOT_CMD // remember previous cmd and "." cmd +#define CONFIG_FEATURE_VI_READONLY // vi -R and "view" mode +#define CONFIG_FEATURE_VI_SETOPTS // set-able options, ai ic showmatch +#define CONFIG_FEATURE_VI_SET // :set +#define CONFIG_FEATURE_VI_WIN_RESIZE // handle window resize // // Enable a if you system have setuped locale -//#define BB_LOCALE_SUPPORT +//#define CONFIG_LOCALE_SUPPORT // // Support for TELNET to pass TERM type to remote host. Adds 384 bytes. -#define BB_FEATURE_TELNET_TTYPE +#define CONFIG_FEATURE_TELNET_TTYPE // // End of Features List // @@ -396,74 +396,74 @@ // #include #if defined __UCLIBC__ && ! defined __UCLIBC_HAS_MMU__ - #undef BB_RPM2CPIO /* Uses gz_open(), which uses fork() */ - #undef BB_DPKG_DEB /* Uses gz_open(), which uses fork() */ - #undef BB_ASH /* Uses fork() */ - #undef BB_HUSH /* Uses fork() */ - #undef BB_LASH /* Uses fork() */ - #undef BB_INIT /* Uses fork() */ - #undef BB_FEATURE_TAR_GZIP /* Uses fork() */ - #undef BB_SYSLOGD /* Uses daemon() */ - #undef BB_KLOGD /* Uses daemon() */ - #undef BB_UPDATE /* Uses daemon() */ + #undef CONFIG_RPM2CPIO /* Uses gz_open(), which uses fork() */ + #undef CONFIG_DPKG_DEB /* Uses gz_open(), which uses fork() */ + #undef CONFIG_ASH /* Uses fork() */ + #undef CONFIG_HUSH /* Uses fork() */ + #undef CONFIG_LASH /* Uses fork() */ + #undef CONFIG_INIT /* Uses fork() */ + #undef CONFIG_FEATURE_TAR_GZIP /* Uses fork() */ + #undef CONFIG_SYSLOGD /* Uses daemon() */ + #undef CONFIG_KLOGD /* Uses daemon() */ + #undef CONFIG_UPDATE /* Uses daemon() */ #endif -#if defined BB_ASH || defined BB_HUSH || defined BB_LASH || defined BB_MSH - #if defined BB_FEATURE_COMMAND_EDITING - #define BB_CMDEDIT +#if defined CONFIG_ASH || defined CONFIG_HUSH || defined CONFIG_LASH || defined CONFIG_MSH + #if defined CONFIG_FEATURE_COMMAND_EDITING + #define CONFIG_CMDEDIT #else - #undef BB_FEATURE_COMMAND_EDITING - #undef BB_FEATURE_COMMAND_TAB_COMPLETION - #undef BB_FEATURE_COMMAND_USERNAME_COMPLETION - #undef BB_FEATURE_SH_FANCY_PROMPT + #undef CONFIG_FEATURE_COMMAND_EDITING + #undef CONFIG_FEATURE_COMMAND_TAB_COMPLETION + #undef CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION + #undef CONFIG_FEATURE_SH_FANCY_PROMPT #endif #else - #undef BB_FEATURE_SH_APPLETS_ALWAYS_WIN - #undef BB_FEATURE_SH_STANDALONE_SHELL - #undef BB_FEATURE_SH_FANCY_PROMPT + #undef CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN + #undef CONFIG_FEATURE_SH_STANDALONE_SHELL + #undef CONFIG_FEATURE_SH_FANCY_PROMPT #endif // -#ifdef BB_KILLALL - #ifndef BB_KILL - #define BB_KILL +#ifdef CONFIG_KILLALL + #ifndef CONFIG_KILL + #define CONFIG_KILL #endif #endif // -#ifndef BB_INIT - #undef BB_FEATURE_LINUXRC +#ifndef CONFIG_INIT + #undef CONFIG_FEATURE_INITRD #endif // -#if defined BB_MOUNT && defined BB_FEATURE_NFSMOUNT - #define BB_NFSMOUNT +#if defined CONFIG_MOUNT && defined CONFIG_FEATURE_NFSMOUNT + #define CONFIG_NFSMOUNT #endif // -#if defined BB_FEATURE_AUTOWIDTH - #ifndef BB_FEATURE_USE_TERMIOS - #define BB_FEATURE_USE_TERMIOS +#if defined CONFIG_FEATURE_AUTOWIDTH + #ifndef CONFIG_FEATURE_USE_TERMIOS + #define CONFIG_FEATURE_USE_TERMIOS #endif #endif // -#if defined BB_INSMOD || defined BB_LSMOD - #if ! defined BB_FEATURE_NEW_MODULE_INTERFACE && ! defined BB_FEATURE_OLD_MODULE_INTERFACE - #define BB_FEATURE_NEW_MODULE_INTERFACE +#if defined CONFIG_INSMOD || defined CONFIG_LSMOD + #if ! defined CONFIG_FEATURE_NEW_MODULE_INTERFACE && ! defined CONFIG_FEATURE_OLD_MODULE_INTERFACE + #define CONFIG_FEATURE_NEW_MODULE_INTERFACE #endif #endif // -#ifdef BB_UNIX2DOS - #define BB_DOS2UNIX +#ifdef CONFIG_UNIX2DOS + #define CONFIG_DOS2UNIX #endif // -#ifdef BB_SYSLOGD - #if defined BB_FEATURE_IPC_SYSLOG - #define BB_LOGREAD +#ifdef CONFIG_SYSLOGD + #if defined CONFIG_FEATURE_IPC_SYSLOG + #define CONFIG_LOGREAD #endif #endif // -#if defined BB_ASH && defined BB_FEATURE_SH_IS_ASH +#if defined CONFIG_ASH && defined CONFIG_FEATURE_SH_IS_ASH # define shell_main ash_main -#elif defined BB_HUSH && defined BB_FEATURE_SH_IS_HUSH +#elif defined CONFIG_HUSH && defined CONFIG_FEATURE_SH_IS_HUSH # define shell_main hush_main -#elif defined BB_LASH && defined BB_FEATURE_SH_IS_LASH +#elif defined CONFIG_LASH && defined CONFIG_FEATURE_SH_IS_LASH # define shell_main lash_main -#elif defined BB_MSH && defined BB_FEATURE_SH_IS_MSH +#elif defined CONFIG_MSH && defined CONFIG_FEATURE_SH_IS_MSH # define shell_main msh_main #endif diff --git a/debian/Config.h-static b/debian/Config.h-static index 094b1f9b4..215bfda65 100644 --- a/debian/Config.h-static +++ b/debian/Config.h-static @@ -3,142 +3,142 @@ // When you turn things off here, they won't be compiled in at all. // //// This file is parsed by sed. You MUST use single line comments. -// i.e., //#define BB_BLAH +// i.e., //#define CONFIG_BLAH // // // BusyBox Applications -//#define BB_ADJTIMEX -#define BB_AR -#define BB_ASH -#define BB_BASENAME -#define BB_CAT -#define BB_CHGRP -#define BB_CHMOD -#define BB_CHOWN -#define BB_CHROOT -#define BB_CHVT -#define BB_CLEAR -#define BB_CMP -#define BB_CP -#define BB_CPIO -#define BB_CUT -#define BB_DATE -#define BB_DC -#define BB_DD -#define BB_DEALLOCVT -#define BB_DF -#define BB_DIRNAME -#define BB_DMESG -#define BB_DOS2UNIX -#define BB_DPKG -#define BB_DPKG_DEB -#define BB_DUTMP -#define BB_DU -#define BB_DUMPKMAP -#define BB_ECHO -#define BB_ENV -#define BB_EXPR -#define BB_FBSET -#define BB_FDFLUSH -#define BB_FIND -#define BB_FREE -#define BB_FREERAMDISK -#define BB_FSCK_MINIX -#define BB_GETOPT -#define BB_GREP -#define BB_GUNZIP -#define BB_GZIP -#define BB_HALT -#define BB_HEAD -#define BB_HOSTID -#define BB_HOSTNAME -//#define BB_HUSH -#define BB_ID -#define BB_IFCONFIG -#define BB_INIT -//#define BB_INSMOD -#define BB_KILL -#define BB_KILLALL -#define BB_KLOGD -//#define BB_LASH -#define BB_LENGTH -#define BB_LN -#define BB_LOADACM -#define BB_LOADFONT -#define BB_LOADKMAP -#define BB_LOGGER -#define BB_LOGNAME -#define BB_LS -#define BB_LSMOD -#define BB_MAKEDEVS -#define BB_MD5SUM -#define BB_MKDIR -#define BB_MKFIFO -#define BB_MKFS_MINIX -#define BB_MKNOD -#define BB_MKSWAP -#define BB_MKTEMP -//#define BB_MODPROBE -#define BB_MORE -#define BB_MOUNT -//#define BB_MSH -#define BB_MT -#define BB_MV -#define BB_NC -#define BB_NSLOOKUP -#define BB_PIDOF -#define BB_PING -#define BB_PIVOT_ROOT -#define BB_POWEROFF -#define BB_PRINTF -#define BB_PS -#define BB_PWD -#define BB_RDATE -#define BB_READLINK -#define BB_REBOOT -#define BB_RENICE -#define BB_RESET -#define BB_RM -#define BB_RMDIR -#define BB_RMMOD -#define BB_ROUTE -#define BB_RPM2CPIO -#define BB_SED -#define BB_SETKEYCODES -#define BB_SLEEP -#define BB_SORT -#define BB_STTY -#define BB_SWAPONOFF -#define BB_SYNC -#define BB_SYSLOGD -#define BB_TAIL -#define BB_TAR -#define BB_TEE -#define BB_TEST -#define BB_TELNET -#define BB_TFTP -#define BB_TOUCH -#define BB_TR -#define BB_TRACEROUTE -#define BB_TRUE_FALSE -#define BB_TTY -#define BB_UNIX2DOS -#define BB_UUENCODE -#define BB_UUDECODE -#define BB_UMOUNT -#define BB_UNIQ -#define BB_UNAME -#define BB_UPDATE -#define BB_UPTIME -#define BB_USLEEP -#define BB_VI -#define BB_WATCHDOG -#define BB_WC -#define BB_WGET -#define BB_WHICH -#define BB_WHOAMI -#define BB_XARGS -#define BB_YES +//#define CONFIG_ADJTIMEX +#define CONFIG_AR +#define CONFIG_ASH +#define CONFIG_BASENAME +#define CONFIG_CAT +#define CONFIG_CHGRP +#define CONFIG_CHMOD +#define CONFIG_CHOWN +#define CONFIG_CHROOT +#define CONFIG_CHVT +#define CONFIG_CLEAR +#define CONFIG_CMP +#define CONFIG_CP +#define CONFIG_CPIO +#define CONFIG_CUT +#define CONFIG_DATE +#define CONFIG_DC +#define CONFIG_DD +#define CONFIG_DEALLOCVT +#define CONFIG_DF +#define CONFIG_DIRNAME +#define CONFIG_DMESG +#define CONFIG_DOS2UNIX +#define CONFIG_DPKG +#define CONFIG_DPKG_DEB +#define CONFIG_DUTMP +#define CONFIG_DU +#define CONFIG_DUMPKMAP +#define CONFIG_ECHO +#define CONFIG_ENV +#define CONFIG_EXPR +#define CONFIG_FBSET +#define CONFIG_FDFLUSH +#define CONFIG_FIND +#define CONFIG_FREE +#define CONFIG_FREERAMDISK +#define CONFIG_FSCK_MINIX +#define CONFIG_GETOPT +#define CONFIG_GREP +#define CONFIG_GUNZIP +#define CONFIG_GZIP +#define CONFIG_HALT +#define CONFIG_HEAD +#define CONFIG_HOSTID +#define CONFIG_HOSTNAME +//#define CONFIG_HUSH +#define CONFIG_ID +#define CONFIG_IFCONFIG +#define CONFIG_INIT +//#define CONFIG_INSMOD +#define CONFIG_KILL +#define CONFIG_KILLALL +#define CONFIG_KLOGD +//#define CONFIG_LASH +#define CONFIG_LENGTH +#define CONFIG_LN +#define CONFIG_LOADACM +#define CONFIG_LOADFONT +#define CONFIG_LOADKMAP +#define CONFIG_LOGGER +#define CONFIG_LOGNAME +#define CONFIG_LS +#define CONFIG_LSMOD +#define CONFIG_MAKEDEVS +#define CONFIG_MD5SUM +#define CONFIG_MKDIR +#define CONFIG_MKFIFO +#define CONFIG_MKFS_MINIX +#define CONFIG_MKNOD +#define CONFIG_MKSWAP +#define CONFIG_MKTEMP +//#define CONFIG_MODPROBE +#define CONFIG_MORE +#define CONFIG_MOUNT +//#define CONFIG_MSH +#define CONFIG_MT +#define CONFIG_MV +#define CONFIG_NC +#define CONFIG_NSLOOKUP +#define CONFIG_PIDOF +#define CONFIG_PING +#define CONFIG_PIVOT_ROOT +#define CONFIG_POWEROFF +#define CONFIG_PRINTF +#define CONFIG_PS +#define CONFIG_PWD +#define CONFIG_RDATE +#define CONFIG_READLINK +#define CONFIG_REBOOT +#define CONFIG_RENICE +#define CONFIG_RESET +#define CONFIG_RM +#define CONFIG_RMDIR +#define CONFIG_RMMOD +#define CONFIG_ROUTE +#define CONFIG_RPM2CPIO +#define CONFIG_SED +#define CONFIG_SETKEYCODES +#define CONFIG_SLEEP +#define CONFIG_SORT +#define CONFIG_STTY +#define CONFIG_SWAPONOFF +#define CONFIG_SYNC +#define CONFIG_SYSLOGD +#define CONFIG_TAIL +#define CONFIG_TAR +#define CONFIG_TEE +#define CONFIG_TEST +#define CONFIG_TELNET +#define CONFIG_TFTP +#define CONFIG_TOUCH +#define CONFIG_TR +#define CONFIG_TRACEROUTE +#define CONFIG_TRUE_FALSE +#define CONFIG_TTY +#define CONFIG_UNIX2DOS +#define CONFIG_UUENCODE +#define CONFIG_UUDECODE +#define CONFIG_UMOUNT +#define CONFIG_UNIQ +#define CONFIG_UNAME +#define CONFIG_UPDATE +#define CONFIG_UPTIME +#define CONFIG_USLEEP +#define CONFIG_VI +#define CONFIG_WATCHDOG +#define CONFIG_WC +#define CONFIG_WGET +#define CONFIG_WHICH +#define CONFIG_WHOAMI +#define CONFIG_XARGS +#define CONFIG_YES // End of Applications List // // @@ -151,21 +151,21 @@ // // If you enabled one or more of the shells, you may select which one // should be run when sh is invoked: -#define BB_FEATURE_SH_IS_ASH -//#define BB_FEATURE_SH_IS_HUSH -//#define BB_FEATURE_SH_IS_LASH -//#define BB_FEATURE_SH_IS_MSH +#define CONFIG_FEATURE_SH_IS_ASH +//#define CONFIG_FEATURE_SH_IS_HUSH +//#define CONFIG_FEATURE_SH_IS_LASH +//#define CONFIG_FEATURE_SH_IS_MSH // // BusyBox will, by default, malloc space for its buffers. This costs code // size for the call to xmalloc. You can use the following feature to have // them put on the stack. For some very small machines with limited stack // space, this can be deadly. For most folks, this works just fine... -//#define BB_FEATURE_BUFFERS_GO_ON_STACK +//#define CONFIG_FEATURE_BUFFERS_GO_ON_STACK // The third alternative for buffer allocation is to use BSS. This works // beautifully for computers with a real MMU (and OS support), but wastes // runtime RAM for uCLinux. This behavior was the only one available for // BusyBox versions 0.48 and earlier. -//#define BB_FEATURE_BUFFERS_GO_IN_BSS +//#define CONFIG_FEATURE_BUFFERS_GO_IN_BSS // // Turn this on to use Erik's very cool devps, and devmtab kernel drivers, // thereby eliminating the need for the /proc filesystem and thereby saving @@ -176,212 +176,212 @@ // mknod /dev/mtab c 10 22 // mknod /dev/ps c 10 21 // I emailed Linus and this patch will not be going into the stock kernel. -//#define BB_FEATURE_USE_DEVPS_PATCH +//#define CONFIG_FEATURE_USE_DEVPS_PATCH // // show verbose usage messages -#define BB_FEATURE_VERBOSE_USAGE +#define CONFIG_FEATURE_VERBOSE_USAGE // // Use termios to manipulate the screen ('more' is prettier with this on) -#define BB_FEATURE_USE_TERMIOS +#define CONFIG_FEATURE_USE_TERMIOS // // calculate terminal & column widths (for more and ls) -#define BB_FEATURE_AUTOWIDTH +#define CONFIG_FEATURE_AUTOWIDTH // // show username/groupnames for ls -#define BB_FEATURE_LS_USERNAME +#define CONFIG_FEATURE_LS_USERNAME // // show file timestamps in ls -#define BB_FEATURE_LS_TIMESTAMPS +#define CONFIG_FEATURE_LS_TIMESTAMPS // // enable ls -p and -F -#define BB_FEATURE_LS_FILETYPES +#define CONFIG_FEATURE_LS_FILETYPES // // sort the file names -#define BB_FEATURE_LS_SORTFILES +#define CONFIG_FEATURE_LS_SORTFILES // // enable ls -R -#define BB_FEATURE_LS_RECURSIVE +#define CONFIG_FEATURE_LS_RECURSIVE // // enable ls -L -#define BB_FEATURE_LS_FOLLOWLINKS +#define CONFIG_FEATURE_LS_FOLLOWLINKS // // Disable for a smaller (but less functional) ping -#define BB_FEATURE_FANCY_PING +#define CONFIG_FEATURE_FANCY_PING // // Make init use a simplified /etc/inittab file (recommended). -#define BB_FEATURE_USE_INITTAB +#define CONFIG_FEATURE_USE_INITTAB // //Enable init being called as /linuxrc -#define BB_FEATURE_LINUXRC +#define CONFIG_FEATURE_INITRD // //Have init enable core dumping for child processes (for debugging only) -//#define BB_FEATURE_INIT_COREDUMPS +//#define CONFIG_FEATURE_INIT_COREDUMPS // //Make sure nothing is printed to the console on boot -//#define BB_FEATURE_EXTRA_QUIET +//#define CONFIG_FEATURE_EXTRA_QUIET // // enable syslogd -R remotehost -#define BB_FEATURE_REMOTE_LOG +#define CONFIG_FEATURE_REMOTE_LOG // // enable syslogd -C -//#define BB_FEATURE_IPC_SYSLOG +//#define CONFIG_FEATURE_IPC_SYSLOG // //Disable for a simple tail implementation (2.34k vs 3k for the full one). //Both provide 'tail -f', but this cuts out -c, -q, -s, and -v. -#define BB_FEATURE_FANCY_TAIL +#define CONFIG_FEATURE_FANCY_TAIL // // Enable support for loop devices in mount -#define BB_FEATURE_MOUNT_LOOP +#define CONFIG_FEATURE_MOUNT_LOOP // // Enable support for a real /etc/mtab file instead of /proc/mounts -//#define BB_FEATURE_MTAB_SUPPORT +//#define CONFIG_FEATURE_MTAB_SUPPORT // // Enable support for mounting remote NFS volumes. // You may need to mount with "-o nolock" if you are // not running a local portmapper daemon... -#define BB_FEATURE_NFSMOUNT +#define CONFIG_FEATURE_NFSMOUNT // // Enable support forced filesystem unmounting // (i.e., in case of an unreachable NFS system). -#define BB_FEATURE_MOUNT_FORCE +#define CONFIG_FEATURE_MOUNT_FORCE // // Enable support for creation of tar files. -#define BB_FEATURE_TAR_CREATE +#define CONFIG_FEATURE_TAR_CREATE // // Enable support for "--exclude" and "-X" for excluding files -#define BB_FEATURE_TAR_EXCLUDE +#define CONFIG_FEATURE_TAR_EXCLUDE // // Enable support for tar -z option (currently only works for inflating) -#define BB_FEATURE_TAR_GZIP +#define CONFIG_FEATURE_TAR_GZIP // // Enable reverse sort -#define BB_FEATURE_SORT_REVERSE +#define CONFIG_FEATURE_SORT_REVERSE // // Enable uniqe sort -#define BB_FEATURE_SORT_UNIQUE +#define CONFIG_FEATURE_SORT_UNIQUE // // Enable command line editing in the shell. // Only relevant if a shell is enabled. On by default. -#define BB_FEATURE_COMMAND_EDITING +#define CONFIG_FEATURE_COMMAND_EDITING // // Enable tab completion in the shell. This is now working quite nicely. // This feature adds a bit over 4k. Only relevant if a shell is enabled. -#define BB_FEATURE_COMMAND_TAB_COMPLETION +#define CONFIG_FEATURE_COMMAND_TAB_COMPLETION // // Attempts to match usernames in a ~-prefixed path -//#define BB_FEATURE_COMMAND_USERNAME_COMPLETION +//#define CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION // //Allow the shell to invoke all the compiled in BusyBox applets as if they //were shell builtins. Nice for staticly linking an emergency rescue shell, //among other things. Off by default. // Only relevant if a shell is enabled. -#define BB_FEATURE_SH_STANDALONE_SHELL +#define CONFIG_FEATURE_SH_STANDALONE_SHELL // //When this is enabled, busybox shell applets can be called using full path //names. This causes applets (i.e., most busybox commands) to override //real commands on the filesystem. For example, if you run run /bin/cat, it //will use BusyBox cat even if /bin/cat exists on the filesystem and is _not_ //busybox. Some systems want this, others do not. Choose wisely. :-) This -//only has meaning when BB_FEATURE_SH_STANDALONE_SHELL is enabled. +//only has meaning when CONFIG_FEATURE_SH_STANDALONE_SHELL is enabled. // Only relevant if a shell is enabled. Off by default. -#define BB_FEATURE_SH_APPLETS_ALWAYS_WIN +#define CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN // // Uncomment this option for a fancy shell prompt that includes the // current username and hostname. On systems that don't have usernames // or hostnames, this can look hideous. // Only relevant if a shell is enabled. -#define BB_FEATURE_SH_FANCY_PROMPT +#define CONFIG_FEATURE_SH_FANCY_PROMPT // //Turn on extra fbset options -//#define BB_FEATURE_FBSET_FANCY +//#define CONFIG_FEATURE_FBSET_FANCY // //Turn on fbset readmode support -//#define BB_FEATURE_FBSET_READMODE +//#define CONFIG_FEATURE_FBSET_READMODE // // Support insmod/lsmod/rmmod for post 2.1 kernels -#define BB_FEATURE_NEW_MODULE_INTERFACE +#define CONFIG_FEATURE_NEW_MODULE_INTERFACE // // Support insmod/lsmod/rmmod for pre 2.1 kernels -//#define BB_FEATURE_OLD_MODULE_INTERFACE +//#define CONFIG_FEATURE_OLD_MODULE_INTERFACE // // Support module version checking -//#define BB_FEATURE_INSMOD_VERSION_CHECKING +//#define CONFIG_FEATURE_INSMOD_VERSION_CHECKING // // Support for uClinux memory usage optimization, which will load the image // directly into the kernel memory. This divides memory requrements by three. // If you are not running uClinux (i.e., your CPU has an MMU) leave this // disabled... -//#define BB_FEATURE_INSMOD_LOADINKMEM +//#define CONFIG_FEATURE_INSMOD_LOADINKMEM // // Support for Minix filesystem, version 2 -//#define BB_FEATURE_MINIX2 +//#define CONFIG_FEATURE_MINIX2 // // Enable ifconfig status reporting output -- this feature adds 12k. -#define BB_FEATURE_IFCONFIG_STATUS +#define CONFIG_FEATURE_IFCONFIG_STATUS // // Enable ifconfig slip-specific options "keepalive" and "outfill" -//#define BB_FEATURE_IFCONFIG_SLIP +//#define CONFIG_FEATURE_IFCONFIG_SLIP // // Enable ifconfig options "mem_start", "io_addr", and "irq". -//#define BB_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ +//#define CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ // // Enable ifconfig option "hw". Currently works for only with "ether". -#define BB_FEATURE_IFCONFIG_HW +#define CONFIG_FEATURE_IFCONFIG_HW // // Enable busybox --install [-s] // to create links (or symlinks) for all the commands that are // compiled into the binary. (needs /proc filesystem) -#define BB_FEATURE_INSTALLER +#define CONFIG_FEATURE_INSTALLER // // Enable a nifty progress meter in wget (adds just under 2k) -#define BB_FEATURE_WGET_STATUSBAR +#define CONFIG_FEATURE_WGET_STATUSBAR // // Enable HTTP authentication in wget -#define BB_FEATURE_WGET_AUTHENTICATION +#define CONFIG_FEATURE_WGET_AUTHENTICATION // // Clean up all memory before exiting -- usually not needed // as the OS can clean up... Don't enable this unless you // have a really good reason for cleaning things up manually. -//#define BB_FEATURE_CLEAN_UP +//#define CONFIG_FEATURE_CLEAN_UP // // Support for human readable output by ls, du, etc.(example 13k, 23M, 235G) -#define BB_FEATURE_HUMAN_READABLE +#define CONFIG_FEATURE_HUMAN_READABLE // // Support for the find -type option. -#define BB_FEATURE_FIND_TYPE +#define CONFIG_FEATURE_FIND_TYPE // // Support for the find -perm option. -#define BB_FEATURE_FIND_PERM +#define CONFIG_FEATURE_FIND_PERM // // Support for the find -mtine option. -#define BB_FEATURE_FIND_MTIME +#define CONFIG_FEATURE_FIND_MTIME // // Support for the -A -B and -C context flags in grep -//#define BB_FEATURE_GREP_CONTEXT +//#define CONFIG_FEATURE_GREP_CONTEXT // // Support for the EGREP applet (alias to the grep applet) -//#define BB_FEATURE_GREP_EGREP_ALIAS +//#define CONFIG_FEATURE_GREP_EGREP_ALIAS // // Tell tftp what commands that should be supported. -#define BB_FEATURE_TFTP_PUT -#define BB_FEATURE_TFTP_GET +#define CONFIG_FEATURE_TFTP_PUT +#define CONFIG_FEATURE_TFTP_GET // // features for vi -#define BB_FEATURE_VI_COLON // ":" colon commands, no "ex" mode -#define BB_FEATURE_VI_YANKMARK // Yank/Put commands and Mark cmds -#define BB_FEATURE_VI_SEARCH // search and replace cmds -#define BB_FEATURE_VI_USE_SIGNALS // catch signals -#define BB_FEATURE_VI_DOT_CMD // remember previous cmd and "." cmd -#define BB_FEATURE_VI_READONLY // vi -R and "view" mode -#define BB_FEATURE_VI_SETOPTS // set-able options, ai ic showmatch -#define BB_FEATURE_VI_SET // :set -#define BB_FEATURE_VI_WIN_RESIZE // handle window resize +#define CONFIG_FEATURE_VI_COLON // ":" colon commands, no "ex" mode +#define CONFIG_FEATURE_VI_YANKMARK // Yank/Put commands and Mark cmds +#define CONFIG_FEATURE_VI_SEARCH // search and replace cmds +#define CONFIG_FEATURE_VI_USE_SIGNALS // catch signals +#define CONFIG_FEATURE_VI_DOT_CMD // remember previous cmd and "." cmd +#define CONFIG_FEATURE_VI_READONLY // vi -R and "view" mode +#define CONFIG_FEATURE_VI_SETOPTS // set-able options, ai ic showmatch +#define CONFIG_FEATURE_VI_SET // :set +#define CONFIG_FEATURE_VI_WIN_RESIZE // handle window resize // // Enable a if you system have setuped locale -//#define BB_LOCALE_SUPPORT +//#define CONFIG_LOCALE_SUPPORT // // Support for TELNET to pass TERM type to remote host. Adds 384 bytes. -#define BB_FEATURE_TELNET_TTYPE +#define CONFIG_FEATURE_TELNET_TTYPE // // End of Features List // @@ -396,74 +396,74 @@ // #include #if defined __UCLIBC__ && ! defined __UCLIBC_HAS_MMU__ - #undef BB_RPM2CPIO /* Uses gz_open(), which uses fork() */ - #undef BB_DPKG_DEB /* Uses gz_open(), which uses fork() */ - #undef BB_ASH /* Uses fork() */ - #undef BB_HUSH /* Uses fork() */ - #undef BB_LASH /* Uses fork() */ - #undef BB_INIT /* Uses fork() */ - #undef BB_FEATURE_TAR_GZIP /* Uses fork() */ - #undef BB_SYSLOGD /* Uses daemon() */ - #undef BB_KLOGD /* Uses daemon() */ - #undef BB_UPDATE /* Uses daemon() */ + #undef CONFIG_RPM2CPIO /* Uses gz_open(), which uses fork() */ + #undef CONFIG_DPKG_DEB /* Uses gz_open(), which uses fork() */ + #undef CONFIG_ASH /* Uses fork() */ + #undef CONFIG_HUSH /* Uses fork() */ + #undef CONFIG_LASH /* Uses fork() */ + #undef CONFIG_INIT /* Uses fork() */ + #undef CONFIG_FEATURE_TAR_GZIP /* Uses fork() */ + #undef CONFIG_SYSLOGD /* Uses daemon() */ + #undef CONFIG_KLOGD /* Uses daemon() */ + #undef CONFIG_UPDATE /* Uses daemon() */ #endif -#if defined BB_ASH || defined BB_HUSH || defined BB_LASH || defined BB_MSH - #if defined BB_FEATURE_COMMAND_EDITING - #define BB_CMDEDIT +#if defined CONFIG_ASH || defined CONFIG_HUSH || defined CONFIG_LASH || defined CONFIG_MSH + #if defined CONFIG_FEATURE_COMMAND_EDITING + #define CONFIG_CMDEDIT #else - #undef BB_FEATURE_COMMAND_EDITING - #undef BB_FEATURE_COMMAND_TAB_COMPLETION - #undef BB_FEATURE_COMMAND_USERNAME_COMPLETION - #undef BB_FEATURE_SH_FANCY_PROMPT + #undef CONFIG_FEATURE_COMMAND_EDITING + #undef CONFIG_FEATURE_COMMAND_TAB_COMPLETION + #undef CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION + #undef CONFIG_FEATURE_SH_FANCY_PROMPT #endif #else - #undef BB_FEATURE_SH_APPLETS_ALWAYS_WIN - #undef BB_FEATURE_SH_STANDALONE_SHELL - #undef BB_FEATURE_SH_FANCY_PROMPT + #undef CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN + #undef CONFIG_FEATURE_SH_STANDALONE_SHELL + #undef CONFIG_FEATURE_SH_FANCY_PROMPT #endif // -#ifdef BB_KILLALL - #ifndef BB_KILL - #define BB_KILL +#ifdef CONFIG_KILLALL + #ifndef CONFIG_KILL + #define CONFIG_KILL #endif #endif // -#ifndef BB_INIT - #undef BB_FEATURE_LINUXRC +#ifndef CONFIG_INIT + #undef CONFIG_FEATURE_INITRD #endif // -#if defined BB_MOUNT && defined BB_FEATURE_NFSMOUNT - #define BB_NFSMOUNT +#if defined CONFIG_MOUNT && defined CONFIG_FEATURE_NFSMOUNT + #define CONFIG_NFSMOUNT #endif // -#if defined BB_FEATURE_AUTOWIDTH - #ifndef BB_FEATURE_USE_TERMIOS - #define BB_FEATURE_USE_TERMIOS +#if defined CONFIG_FEATURE_AUTOWIDTH + #ifndef CONFIG_FEATURE_USE_TERMIOS + #define CONFIG_FEATURE_USE_TERMIOS #endif #endif // -#if defined BB_INSMOD || defined BB_LSMOD - #if ! defined BB_FEATURE_NEW_MODULE_INTERFACE && ! defined BB_FEATURE_OLD_MODULE_INTERFACE - #define BB_FEATURE_NEW_MODULE_INTERFACE +#if defined CONFIG_INSMOD || defined CONFIG_LSMOD + #if ! defined CONFIG_FEATURE_NEW_MODULE_INTERFACE && ! defined CONFIG_FEATURE_OLD_MODULE_INTERFACE + #define CONFIG_FEATURE_NEW_MODULE_INTERFACE #endif #endif // -#ifdef BB_UNIX2DOS - #define BB_DOS2UNIX +#ifdef CONFIG_UNIX2DOS + #define CONFIG_DOS2UNIX #endif // -#ifdef BB_SYSLOGD - #if defined BB_FEATURE_IPC_SYSLOG - #define BB_LOGREAD +#ifdef CONFIG_SYSLOGD + #if defined CONFIG_FEATURE_IPC_SYSLOG + #define CONFIG_LOGREAD #endif #endif // -#if defined BB_ASH && defined BB_FEATURE_SH_IS_ASH +#if defined CONFIG_ASH && defined CONFIG_FEATURE_SH_IS_ASH # define shell_main ash_main -#elif defined BB_HUSH && defined BB_FEATURE_SH_IS_HUSH +#elif defined CONFIG_HUSH && defined CONFIG_FEATURE_SH_IS_HUSH # define shell_main hush_main -#elif defined BB_LASH && defined BB_FEATURE_SH_IS_LASH +#elif defined CONFIG_LASH && defined CONFIG_FEATURE_SH_IS_LASH # define shell_main lash_main -#elif defined BB_MSH && defined BB_FEATURE_SH_IS_MSH +#elif defined CONFIG_MSH && defined CONFIG_FEATURE_SH_IS_MSH # define shell_main msh_main #endif diff --git a/debian/Config.h-udeb b/debian/Config.h-udeb index 8e7594dc4..28c4031c5 100644 --- a/debian/Config.h-udeb +++ b/debian/Config.h-udeb @@ -3,142 +3,142 @@ // When you turn things off here, they won't be compiled in at all. // //// This file is parsed by sed. You MUST use single line comments. -// i.e., //#define BB_BLAH +// i.e., //#define CONFIG_BLAH // // // BusyBox Applications -//#define BB_ADJTIMEX -//#define BB_AR -//#define BB_ASH -#define BB_BASENAME -#define BB_CAT -#define BB_CHGRP -#define BB_CHMOD -#define BB_CHOWN -#define BB_CHROOT -#define BB_CHVT -#define BB_CLEAR -//#define BB_CMP -#define BB_CP -//#define BB_CPIO -#define BB_CUT -#define BB_DATE -//#define BB_DC -#define BB_DD -//#define BB_DEALLOCVT -#define BB_DF -#define BB_DIRNAME -#define BB_DMESG -//#define BB_DOS2UNIX -//#define BB_DPKG -//#define BB_DPKG_DEB -//#define BB_DUTMP -#define BB_DU -//#define BB_DUMPKMAP -#define BB_ECHO -#define BB_ENV -#define BB_EXPR -//#define BB_FBSET -//#define BB_FDFLUSH -#define BB_FIND -#define BB_FREE -#define BB_FREERAMDISK -//#define BB_FSCK_MINIX -//#define BB_GETOPT -#define BB_GREP -#define BB_GUNZIP -#define BB_GZIP -#define BB_HALT -#define BB_HEAD -//#define BB_HOSTID -//#define BB_HOSTNAME -//#define BB_HUSH -#define BB_ID -//#define BB_IFCONFIG -#define BB_INIT -//#define BB_INSMOD -#define BB_KILL -#define BB_KILLALL -#define BB_KLOGD -//#define BB_LASH -//#define BB_LENGTH -#define BB_LN -//#define BB_LOADACM -//#define BB_LOADFONT -#define BB_LOADKMAP -#define BB_LOGGER -//#define BB_LOGNAME -#define BB_LS -#define BB_LSMOD -//#define BB_MAKEDEVS -#define BB_MD5SUM -#define BB_MKDIR -//#define BB_MKFIFO -//#define BB_MKFS_MINIX -#define BB_MKNOD -#define BB_MKSWAP -//#define BB_MKTEMP -//#define BB_MODPROBE -#define BB_MORE -#define BB_MOUNT -//#define BB_MSH -//#define BB_MT -#define BB_MV -//#define BB_NC -//#define BB_NSLOOKUP -//#define BB_PIDOF -#define BB_PING -#define BB_PIVOT_ROOT -#define BB_POWEROFF -//#define BB_PRINTF -#define BB_PS -#define BB_PWD -//#define BB_RDATE -//#define BB_READLINK -#define BB_REBOOT -//#define BB_RENICE -#define BB_RESET -#define BB_RM -#define BB_RMDIR -//#define BB_RMMOD -//#define BB_ROUTE -//#define BB_RPM2CPIO -#define BB_SED -//#define BB_SETKEYCODES -#define BB_SLEEP -#define BB_SORT -//#define BB_STTY -#define BB_SWAPONOFF -#define BB_SYNC -#define BB_SYSLOGD -#define BB_TAIL -#define BB_TAR -//#define BB_TEE -//#define BB_TEST -#define BB_TELNET -//#define BB_TFTP -#define BB_TOUCH -#define BB_TR -//#define BB_TRACEROUTE -#define BB_TRUE_FALSE -#define BB_TTY -//#define BB_UNIX2DOS -//#define BB_UUENCODE -//#define BB_UUDECODE -#define BB_UMOUNT -#define BB_UNIQ -#define BB_UNAME -//#define BB_UPDATE -#define BB_UPTIME -//#define BB_USLEEP -#define BB_VI -//#define BB_WATCHDOG -#define BB_WC -#define BB_WGET -#define BB_WHICH -#define BB_WHOAMI -#define BB_XARGS -#define BB_YES +//#define CONFIG_ADJTIMEX +//#define CONFIG_AR +//#define CONFIG_ASH +#define CONFIG_BASENAME +#define CONFIG_CAT +#define CONFIG_CHGRP +#define CONFIG_CHMOD +#define CONFIG_CHOWN +#define CONFIG_CHROOT +#define CONFIG_CHVT +#define CONFIG_CLEAR +//#define CONFIG_CMP +#define CONFIG_CP +//#define CONFIG_CPIO +#define CONFIG_CUT +#define CONFIG_DATE +//#define CONFIG_DC +#define CONFIG_DD +//#define CONFIG_DEALLOCVT +#define CONFIG_DF +#define CONFIG_DIRNAME +#define CONFIG_DMESG +//#define CONFIG_DOS2UNIX +//#define CONFIG_DPKG +//#define CONFIG_DPKG_DEB +//#define CONFIG_DUTMP +#define CONFIG_DU +//#define CONFIG_DUMPKMAP +#define CONFIG_ECHO +#define CONFIG_ENV +#define CONFIG_EXPR +//#define CONFIG_FBSET +//#define CONFIG_FDFLUSH +#define CONFIG_FIND +#define CONFIG_FREE +#define CONFIG_FREERAMDISK +//#define CONFIG_FSCK_MINIX +//#define CONFIG_GETOPT +#define CONFIG_GREP +#define CONFIG_GUNZIP +#define CONFIG_GZIP +#define CONFIG_HALT +#define CONFIG_HEAD +//#define CONFIG_HOSTID +//#define CONFIG_HOSTNAME +//#define CONFIG_HUSH +#define CONFIG_ID +//#define CONFIG_IFCONFIG +#define CONFIG_INIT +//#define CONFIG_INSMOD +#define CONFIG_KILL +#define CONFIG_KILLALL +#define CONFIG_KLOGD +//#define CONFIG_LASH +//#define CONFIG_LENGTH +#define CONFIG_LN +//#define CONFIG_LOADACM +//#define CONFIG_LOADFONT +#define CONFIG_LOADKMAP +#define CONFIG_LOGGER +//#define CONFIG_LOGNAME +#define CONFIG_LS +#define CONFIG_LSMOD +//#define CONFIG_MAKEDEVS +#define CONFIG_MD5SUM +#define CONFIG_MKDIR +//#define CONFIG_MKFIFO +//#define CONFIG_MKFS_MINIX +#define CONFIG_MKNOD +#define CONFIG_MKSWAP +//#define CONFIG_MKTEMP +//#define CONFIG_MODPROBE +#define CONFIG_MORE +#define CONFIG_MOUNT +//#define CONFIG_MSH +//#define CONFIG_MT +#define CONFIG_MV +//#define CONFIG_NC +//#define CONFIG_NSLOOKUP +//#define CONFIG_PIDOF +#define CONFIG_PING +#define CONFIG_PIVOT_ROOT +#define CONFIG_POWEROFF +//#define CONFIG_PRINTF +#define CONFIG_PS +#define CONFIG_PWD +//#define CONFIG_RDATE +//#define CONFIG_READLINK +#define CONFIG_REBOOT +//#define CONFIG_RENICE +#define CONFIG_RESET +#define CONFIG_RM +#define CONFIG_RMDIR +//#define CONFIG_RMMOD +//#define CONFIG_ROUTE +//#define CONFIG_RPM2CPIO +#define CONFIG_SED +//#define CONFIG_SETKEYCODES +#define CONFIG_SLEEP +#define CONFIG_SORT +//#define CONFIG_STTY +#define CONFIG_SWAPONOFF +#define CONFIG_SYNC +#define CONFIG_SYSLOGD +#define CONFIG_TAIL +#define CONFIG_TAR +//#define CONFIG_TEE +//#define CONFIG_TEST +#define CONFIG_TELNET +//#define CONFIG_TFTP +#define CONFIG_TOUCH +#define CONFIG_TR +//#define CONFIG_TRACEROUTE +#define CONFIG_TRUE_FALSE +#define CONFIG_TTY +//#define CONFIG_UNIX2DOS +//#define CONFIG_UUENCODE +//#define CONFIG_UUDECODE +#define CONFIG_UMOUNT +#define CONFIG_UNIQ +#define CONFIG_UNAME +//#define CONFIG_UPDATE +#define CONFIG_UPTIME +//#define CONFIG_USLEEP +#define CONFIG_VI +//#define CONFIG_WATCHDOG +#define CONFIG_WC +#define CONFIG_WGET +#define CONFIG_WHICH +#define CONFIG_WHOAMI +#define CONFIG_XARGS +#define CONFIG_YES // End of Applications List // // @@ -151,21 +151,21 @@ // // If you enabled one or more of the shells, you may select which one // should be run when sh is invoked: -//#define BB_FEATURE_SH_IS_ASH -//#define BB_FEATURE_SH_IS_HUSH -//#define BB_FEATURE_SH_IS_LASH -#define BB_FEATURE_SH_IS_MSH +//#define CONFIG_FEATURE_SH_IS_ASH +//#define CONFIG_FEATURE_SH_IS_HUSH +//#define CONFIG_FEATURE_SH_IS_LASH +#define CONFIG_FEATURE_SH_IS_MSH // // BusyBox will, by default, malloc space for its buffers. This costs code // size for the call to xmalloc. You can use the following feature to have // them put on the stack. For some very small machines with limited stack // space, this can be deadly. For most folks, this works just fine... -//#define BB_FEATURE_BUFFERS_GO_ON_STACK +//#define CONFIG_FEATURE_BUFFERS_GO_ON_STACK // The third alternative for buffer allocation is to use BSS. This works // beautifully for computers with a real MMU (and OS support), but wastes // runtime RAM for uCLinux. This behavior was the only one available for // BusyBox versions 0.48 and earlier. -//#define BB_FEATURE_BUFFERS_GO_IN_BSS +//#define CONFIG_FEATURE_BUFFERS_GO_IN_BSS // // Turn this on to use Erik's very cool devps, and devmtab kernel drivers, // thereby eliminating the need for the /proc filesystem and thereby saving @@ -176,212 +176,212 @@ // mknod /dev/mtab c 10 22 // mknod /dev/ps c 10 21 // I emailed Linus and this patch will not be going into the stock kernel. -//#define BB_FEATURE_USE_DEVPS_PATCH +//#define CONFIG_FEATURE_USE_DEVPS_PATCH // // show verbose usage messages -//#define BB_FEATURE_VERBOSE_USAGE +//#define CONFIG_FEATURE_VERBOSE_USAGE // // Use termios to manipulate the screen ('more' is prettier with this on) -#define BB_FEATURE_USE_TERMIOS +#define CONFIG_FEATURE_USE_TERMIOS // // calculate terminal & column widths (for more and ls) -#define BB_FEATURE_AUTOWIDTH +#define CONFIG_FEATURE_AUTOWIDTH // // show username/groupnames for ls -#define BB_FEATURE_LS_USERNAME +#define CONFIG_FEATURE_LS_USERNAME // // show file timestamps in ls -#define BB_FEATURE_LS_TIMESTAMPS +#define CONFIG_FEATURE_LS_TIMESTAMPS // // enable ls -p and -F -#define BB_FEATURE_LS_FILETYPES +#define CONFIG_FEATURE_LS_FILETYPES // // sort the file names -#define BB_FEATURE_LS_SORTFILES +#define CONFIG_FEATURE_LS_SORTFILES // // enable ls -R -#define BB_FEATURE_LS_RECURSIVE +#define CONFIG_FEATURE_LS_RECURSIVE // // enable ls -L -#define BB_FEATURE_LS_FOLLOWLINKS +#define CONFIG_FEATURE_LS_FOLLOWLINKS // // Disable for a smaller (but less functional) ping -#define BB_FEATURE_FANCY_PING +#define CONFIG_FEATURE_FANCY_PING // // Make init use a simplified /etc/inittab file (recommended). -#define BB_FEATURE_USE_INITTAB +#define CONFIG_FEATURE_USE_INITTAB // //Enable init being called as /linuxrc -#define BB_FEATURE_LINUXRC +#define CONFIG_FEATURE_INITRD // //Have init enable core dumping for child processes (for debugging only) -//#define BB_FEATURE_INIT_COREDUMPS +//#define CONFIG_FEATURE_INIT_COREDUMPS // //Make sure nothing is printed to the console on boot -//#define BB_FEATURE_EXTRA_QUIET +//#define CONFIG_FEATURE_EXTRA_QUIET // // enable syslogd -R remotehost -#define BB_FEATURE_REMOTE_LOG +#define CONFIG_FEATURE_REMOTE_LOG // // enable syslogd -C -//#define BB_FEATURE_IPC_SYSLOG +//#define CONFIG_FEATURE_IPC_SYSLOG // //Disable for a simple tail implementation (2.34k vs 3k for the full one). //Both provide 'tail -f', but this cuts out -c, -q, -s, and -v. -#define BB_FEATURE_FANCY_TAIL +#define CONFIG_FEATURE_FANCY_TAIL // // Enable support for loop devices in mount -#define BB_FEATURE_MOUNT_LOOP +#define CONFIG_FEATURE_MOUNT_LOOP // // Enable support for a real /etc/mtab file instead of /proc/mounts -//#define BB_FEATURE_MTAB_SUPPORT +//#define CONFIG_FEATURE_MTAB_SUPPORT // // Enable support for mounting remote NFS volumes. // You may need to mount with "-o nolock" if you are // not running a local portmapper daemon... -#define BB_FEATURE_NFSMOUNT +#define CONFIG_FEATURE_NFSMOUNT // // Enable support forced filesystem unmounting // (i.e., in case of an unreachable NFS system). -#define BB_FEATURE_MOUNT_FORCE +#define CONFIG_FEATURE_MOUNT_FORCE // // Enable support for creation of tar files. -#define BB_FEATURE_TAR_CREATE +#define CONFIG_FEATURE_TAR_CREATE // // Enable support for "--exclude" and "-X" for excluding files -#define BB_FEATURE_TAR_EXCLUDE +#define CONFIG_FEATURE_TAR_EXCLUDE // // Enable support for tar -z option (currently only works for inflating) -#define BB_FEATURE_TAR_GZIP +#define CONFIG_FEATURE_TAR_GZIP // // Enable reverse sort -#define BB_FEATURE_SORT_REVERSE +#define CONFIG_FEATURE_SORT_REVERSE // // Enable uniqe sort -#define BB_FEATURE_SORT_UNIQUE +#define CONFIG_FEATURE_SORT_UNIQUE // // Enable command line editing in the shell. // Only relevant if a shell is enabled. On by default. -#define BB_FEATURE_COMMAND_EDITING +#define CONFIG_FEATURE_COMMAND_EDITING // // Enable tab completion in the shell. This is now working quite nicely. // This feature adds a bit over 4k. Only relevant if a shell is enabled. -#define BB_FEATURE_COMMAND_TAB_COMPLETION +#define CONFIG_FEATURE_COMMAND_TAB_COMPLETION // // Attempts to match usernames in a ~-prefixed path -//#define BB_FEATURE_COMMAND_USERNAME_COMPLETION +//#define CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION // //Allow the shell to invoke all the compiled in BusyBox applets as if they //were shell builtins. Nice for staticly linking an emergency rescue shell, //among other things. Off by default. // Only relevant if a shell is enabled. -//#define BB_FEATURE_SH_STANDALONE_SHELL +//#define CONFIG_FEATURE_SH_STANDALONE_SHELL // //When this is enabled, busybox shell applets can be called using full path //names. This causes applets (i.e., most busybox commands) to override //real commands on the filesystem. For example, if you run run /bin/cat, it //will use BusyBox cat even if /bin/cat exists on the filesystem and is _not_ //busybox. Some systems want this, others do not. Choose wisely. :-) This -//only has meaning when BB_FEATURE_SH_STANDALONE_SHELL is enabled. +//only has meaning when CONFIG_FEATURE_SH_STANDALONE_SHELL is enabled. // Only relevant if a shell is enabled. Off by default. -//#define BB_FEATURE_SH_APPLETS_ALWAYS_WIN +//#define CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN // // Uncomment this option for a fancy shell prompt that includes the // current username and hostname. On systems that don't have usernames // or hostnames, this can look hideous. // Only relevant if a shell is enabled. -//#define BB_FEATURE_SH_FANCY_PROMPT +//#define CONFIG_FEATURE_SH_FANCY_PROMPT // //Turn on extra fbset options -//#define BB_FEATURE_FBSET_FANCY +//#define CONFIG_FEATURE_FBSET_FANCY // //Turn on fbset readmode support -//#define BB_FEATURE_FBSET_READMODE +//#define CONFIG_FEATURE_FBSET_READMODE // // Support insmod/lsmod/rmmod for post 2.1 kernels -//#define BB_FEATURE_NEW_MODULE_INTERFACE +//#define CONFIG_FEATURE_NEW_MODULE_INTERFACE // // Support insmod/lsmod/rmmod for pre 2.1 kernels -//#define BB_FEATURE_OLD_MODULE_INTERFACE +//#define CONFIG_FEATURE_OLD_MODULE_INTERFACE // // Support module version checking -//#define BB_FEATURE_INSMOD_VERSION_CHECKING +//#define CONFIG_FEATURE_INSMOD_VERSION_CHECKING // // Support for uClinux memory usage optimization, which will load the image // directly into the kernel memory. This divides memory requrements by three. // If you are not running uClinux (i.e., your CPU has an MMU) leave this // disabled... -//#define BB_FEATURE_INSMOD_LOADINKMEM +//#define CONFIG_FEATURE_INSMOD_LOADINKMEM // // Support for Minix filesystem, version 2 -//#define BB_FEATURE_MINIX2 +//#define CONFIG_FEATURE_MINIX2 // // Enable ifconfig status reporting output -- this feature adds 12k. -#define BB_FEATURE_IFCONFIG_STATUS +#define CONFIG_FEATURE_IFCONFIG_STATUS // // Enable ifconfig slip-specific options "keepalive" and "outfill" -//#define BB_FEATURE_IFCONFIG_SLIP +//#define CONFIG_FEATURE_IFCONFIG_SLIP // // Enable ifconfig options "mem_start", "io_addr", and "irq". -//#define BB_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ +//#define CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ // // Enable ifconfig option "hw". Currently works for only with "ether". -#define BB_FEATURE_IFCONFIG_HW +#define CONFIG_FEATURE_IFCONFIG_HW // // Enable busybox --install [-s] // to create links (or symlinks) for all the commands that are // compiled into the binary. (needs /proc filesystem) -#define BB_FEATURE_INSTALLER +#define CONFIG_FEATURE_INSTALLER // // Enable a nifty progress meter in wget (adds just under 2k) -#define BB_FEATURE_WGET_STATUSBAR +#define CONFIG_FEATURE_WGET_STATUSBAR // // Enable HTTP authentication in wget -#define BB_FEATURE_WGET_AUTHENTICATION +#define CONFIG_FEATURE_WGET_AUTHENTICATION // // Clean up all memory before exiting -- usually not needed // as the OS can clean up... Don't enable this unless you // have a really good reason for cleaning things up manually. -//#define BB_FEATURE_CLEAN_UP +//#define CONFIG_FEATURE_CLEAN_UP // // Support for human readable output by ls, du, etc.(example 13k, 23M, 235G) -#define BB_FEATURE_HUMAN_READABLE +#define CONFIG_FEATURE_HUMAN_READABLE // // Support for the find -type option. -#define BB_FEATURE_FIND_TYPE +#define CONFIG_FEATURE_FIND_TYPE // // Support for the find -perm option. -#define BB_FEATURE_FIND_PERM +#define CONFIG_FEATURE_FIND_PERM // // Support for the find -mtine option. -#define BB_FEATURE_FIND_MTIME +#define CONFIG_FEATURE_FIND_MTIME // // Support for the -A -B and -C context flags in grep -//#define BB_FEATURE_GREP_CONTEXT +//#define CONFIG_FEATURE_GREP_CONTEXT // // Support for the EGREP applet (alias to the grep applet) -//#define BB_FEATURE_GREP_EGREP_ALIAS +//#define CONFIG_FEATURE_GREP_EGREP_ALIAS // // Tell tftp what commands that should be supported. -#define BB_FEATURE_TFTP_PUT -#define BB_FEATURE_TFTP_GET +#define CONFIG_FEATURE_TFTP_PUT +#define CONFIG_FEATURE_TFTP_GET // // features for vi -#define BB_FEATURE_VI_COLON // ":" colon commands, no "ex" mode -#define BB_FEATURE_VI_YANKMARK // Yank/Put commands and Mark cmds -#define BB_FEATURE_VI_SEARCH // search and replace cmds -#define BB_FEATURE_VI_USE_SIGNALS // catch signals -#define BB_FEATURE_VI_DOT_CMD // remember previous cmd and "." cmd -#define BB_FEATURE_VI_READONLY // vi -R and "view" mode -#define BB_FEATURE_VI_SETOPTS // set-able options, ai ic showmatch -#define BB_FEATURE_VI_SET // :set -#define BB_FEATURE_VI_WIN_RESIZE // handle window resize +#define CONFIG_FEATURE_VI_COLON // ":" colon commands, no "ex" mode +#define CONFIG_FEATURE_VI_YANKMARK // Yank/Put commands and Mark cmds +#define CONFIG_FEATURE_VI_SEARCH // search and replace cmds +#define CONFIG_FEATURE_VI_USE_SIGNALS // catch signals +#define CONFIG_FEATURE_VI_DOT_CMD // remember previous cmd and "." cmd +#define CONFIG_FEATURE_VI_READONLY // vi -R and "view" mode +#define CONFIG_FEATURE_VI_SETOPTS // set-able options, ai ic showmatch +#define CONFIG_FEATURE_VI_SET // :set +#define CONFIG_FEATURE_VI_WIN_RESIZE // handle window resize // // Enable a if you system have setuped locale -//#define BB_LOCALE_SUPPORT +//#define CONFIG_LOCALE_SUPPORT // // Support for TELNET to pass TERM type to remote host. Adds 384 bytes. -#define BB_FEATURE_TELNET_TTYPE +#define CONFIG_FEATURE_TELNET_TTYPE // // End of Features List // @@ -396,74 +396,74 @@ // #include #if defined __UCLIBC__ && ! defined __UCLIBC_HAS_MMU__ - #undef BB_RPM2CPIO /* Uses gz_open(), which uses fork() */ - #undef BB_DPKG_DEB /* Uses gz_open(), which uses fork() */ - #undef BB_ASH /* Uses fork() */ - #undef BB_HUSH /* Uses fork() */ - #undef BB_LASH /* Uses fork() */ - #undef BB_INIT /* Uses fork() */ - #undef BB_FEATURE_TAR_GZIP /* Uses fork() */ - #undef BB_SYSLOGD /* Uses daemon() */ - #undef BB_KLOGD /* Uses daemon() */ - #undef BB_UPDATE /* Uses daemon() */ + #undef CONFIG_RPM2CPIO /* Uses gz_open(), which uses fork() */ + #undef CONFIG_DPKG_DEB /* Uses gz_open(), which uses fork() */ + #undef CONFIG_ASH /* Uses fork() */ + #undef CONFIG_HUSH /* Uses fork() */ + #undef CONFIG_LASH /* Uses fork() */ + #undef CONFIG_INIT /* Uses fork() */ + #undef CONFIG_FEATURE_TAR_GZIP /* Uses fork() */ + #undef CONFIG_SYSLOGD /* Uses daemon() */ + #undef CONFIG_KLOGD /* Uses daemon() */ + #undef CONFIG_UPDATE /* Uses daemon() */ #endif -#if defined BB_ASH || defined BB_HUSH || defined BB_LASH || defined BB_MSH - #if defined BB_FEATURE_COMMAND_EDITING - #define BB_CMDEDIT +#if defined CONFIG_ASH || defined CONFIG_HUSH || defined CONFIG_LASH || defined CONFIG_MSH + #if defined CONFIG_FEATURE_COMMAND_EDITING + #define CONFIG_CMDEDIT #else - #undef BB_FEATURE_COMMAND_EDITING - #undef BB_FEATURE_COMMAND_TAB_COMPLETION - #undef BB_FEATURE_COMMAND_USERNAME_COMPLETION - #undef BB_FEATURE_SH_FANCY_PROMPT + #undef CONFIG_FEATURE_COMMAND_EDITING + #undef CONFIG_FEATURE_COMMAND_TAB_COMPLETION + #undef CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION + #undef CONFIG_FEATURE_SH_FANCY_PROMPT #endif #else - #undef BB_FEATURE_SH_APPLETS_ALWAYS_WIN - #undef BB_FEATURE_SH_STANDALONE_SHELL - #undef BB_FEATURE_SH_FANCY_PROMPT + #undef CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN + #undef CONFIG_FEATURE_SH_STANDALONE_SHELL + #undef CONFIG_FEATURE_SH_FANCY_PROMPT #endif // -#ifdef BB_KILLALL - #ifndef BB_KILL - #define BB_KILL +#ifdef CONFIG_KILLALL + #ifndef CONFIG_KILL + #define CONFIG_KILL #endif #endif // -#ifndef BB_INIT - #undef BB_FEATURE_LINUXRC +#ifndef CONFIG_INIT + #undef CONFIG_FEATURE_INITRD #endif // -#if defined BB_MOUNT && defined BB_FEATURE_NFSMOUNT - #define BB_NFSMOUNT +#if defined CONFIG_MOUNT && defined CONFIG_FEATURE_NFSMOUNT + #define CONFIG_NFSMOUNT #endif // -#if defined BB_FEATURE_AUTOWIDTH - #ifndef BB_FEATURE_USE_TERMIOS - #define BB_FEATURE_USE_TERMIOS +#if defined CONFIG_FEATURE_AUTOWIDTH + #ifndef CONFIG_FEATURE_USE_TERMIOS + #define CONFIG_FEATURE_USE_TERMIOS #endif #endif // -#if defined BB_INSMOD || defined BB_LSMOD - #if ! defined BB_FEATURE_NEW_MODULE_INTERFACE && ! defined BB_FEATURE_OLD_MODULE_INTERFACE - #define BB_FEATURE_NEW_MODULE_INTERFACE +#if defined CONFIG_INSMOD || defined CONFIG_LSMOD + #if ! defined CONFIG_FEATURE_NEW_MODULE_INTERFACE && ! defined CONFIG_FEATURE_OLD_MODULE_INTERFACE + #define CONFIG_FEATURE_NEW_MODULE_INTERFACE #endif #endif // -#ifdef BB_UNIX2DOS - #define BB_DOS2UNIX +#ifdef CONFIG_UNIX2DOS + #define CONFIG_DOS2UNIX #endif // -#ifdef BB_SYSLOGD - #if defined BB_FEATURE_IPC_SYSLOG - #define BB_LOGREAD +#ifdef CONFIG_SYSLOGD + #if defined CONFIG_FEATURE_IPC_SYSLOG + #define CONFIG_LOGREAD #endif #endif // -#if defined BB_ASH && defined BB_FEATURE_SH_IS_ASH +#if defined CONFIG_ASH && defined CONFIG_FEATURE_SH_IS_ASH # define shell_main ash_main -#elif defined BB_HUSH && defined BB_FEATURE_SH_IS_HUSH +#elif defined CONFIG_HUSH && defined CONFIG_FEATURE_SH_IS_HUSH # define shell_main hush_main -#elif defined BB_LASH && defined BB_FEATURE_SH_IS_LASH +#elif defined CONFIG_LASH && defined CONFIG_FEATURE_SH_IS_LASH # define shell_main lash_main -#elif defined BB_MSH && defined BB_FEATURE_SH_IS_MSH +#elif defined CONFIG_MSH && defined CONFIG_FEATURE_SH_IS_MSH # define shell_main msh_main #endif diff --git a/debian/rules b/debian/rules index 1d7413c35..45a6c604c 100755 --- a/debian/rules +++ b/debian/rules @@ -28,8 +28,8 @@ debian/build-stamp-busybox: mkdir -p $(bbbd) cp Makefile $(bbbd) cp debian/Config.h-deb $(bbbd)/Config.h - -(cd $(bbbd); $(MAKE) "BB_SRC_DIR=../../" applet_source_list) - (cd $(bbbd); $(MAKE) USE_SYSTEM_PWD_GRP=false "BB_SRC_DIR=../../") + -(cd $(bbbd); $(MAKE) "CONFIG_SRC_DIR=../../" applet_source_list) + (cd $(bbbd); $(MAKE) USE_SYSTEM_PWD_GRP=false "CONFIG_SRC_DIR=../../") touch debian/build-stamp-busybox install: build @@ -39,7 +39,7 @@ install: build dh_installdirs # Do not run 'make install', since we do not want all the symlinks. # This just installes the busybox binary... - #(cd $(bbbd); $(MAKE) "BB_SRC_DIR=../../" "PREFIX=../../$(bb)" install) + #(cd $(bbbd); $(MAKE) "CONFIG_SRC_DIR=../../" "PREFIX=../../$(bb)" install) mkdir -p $(bb)/bin/ cp $(bbbd)/busybox $(bb)/bin/busybox mkdir -p $(bb)/usr/share/doc/busybox/busybox.lineo.com @@ -54,7 +54,7 @@ debian/build-stamp-busybox-static: mkdir -p $(bbsbd) cp Makefile $(bbsbd) cp debian/Config.h-static $(bbsbd)/Config.h - (cd $(bbsbd); $(MAKE) DOSTATIC=true USE_SYSTEM_PWD_GRP=false "BB_SRC_DIR=../../") + (cd $(bbsbd); $(MAKE) DOSTATIC=true USE_SYSTEM_PWD_GRP=false "CONFIG_SRC_DIR=../../") touch debian/build-stamp-busybox-static install-static: build @@ -64,7 +64,7 @@ install-static: build dh_installdirs # Do not run 'make install', since we do not want all the symlinks. # This just installes the busybox binary... - #(cd $(bbsbd); $(MAKE) "BB_SRC_DIR=../../" "PREFIX=../../$(bbs)" install) + #(cd $(bbsbd); $(MAKE) "CONFIG_SRC_DIR=../../" "PREFIX=../../$(bbs)" install) mkdir -p $(bbs)/bin/ cp $(bbsbd)/busybox $(bbs)/bin/busybox mkdir -p $(bbs)/usr/share/doc/busybox-static/busybox.lineo.com @@ -94,7 +94,7 @@ debian/build-stamp-busybox-udeb: mkdir -p $(bbubd) cp Makefile $(bbubd) cp debian/Config.h-udeb $(bbubd)/Config.h - (cd $(bbubd); $(MAKE) USE_SYSTEM_PWD_GRP=false "BB_SRC_DIR=../../") + (cd $(bbubd); $(MAKE) USE_SYSTEM_PWD_GRP=false "CONFIG_SRC_DIR=../../") touch debian/build-stamp-busybox-udeb install-udeb: build @@ -102,7 +102,7 @@ install-udeb: build dh_testroot dh_clean -k dh_installdirs - (cd $(bbubd); $(MAKE) "BB_SRC_DIR=../../" "PREFIX=../../$(bbu)" install) + (cd $(bbubd); $(MAKE) "CONFIG_SRC_DIR=../../" "PREFIX=../../$(bbu)" install) mkdir -p $(bbu)/usr/share/man/man1/ cp $(bbubd)/docs/BusyBox.1 $(bbu)/usr/share/man/man1/busybox.1 diff --git a/deluser.c b/deluser.c deleted file mode 100644 index bb6e10996..000000000 --- a/deluser.c +++ /dev/null @@ -1,175 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * deluser (remove lusers from the system ;) for TinyLogin - * - * - * Copyright (C) 1999 by Lineo, inc. - * Written by John Beppu - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include "busybox.h" - -#define PASSWD_FILE "/etc/passwd" -#define GROUP_FILE "/etc/group" - -/* where to start and stop deletion */ -typedef struct { - size_t start; - size_t stop; -} Bounds; - -/* An interesting side-effect of boundary()'s - * implementation is that the first user (typically root) - * cannot be removed. Let's call it a feature. */ -static Bounds boundary(const char *buffer, const char *login) -{ - char needle[256]; - char *start; - char *stop; - Bounds b; - - snprintf(needle, 256, "\n%s", login); - needle[255] = 0; - start = strstr(buffer, needle); - if (!start) { - b.start = 0; - b.stop = 0; - return b; - } - start++; - - stop = index(start, '\n'); /* index is a BSD-ism */ - b.start = start - buffer; - b.stop = stop - buffer; - return b; -} - -/* grep -v ^login (except it only deletes the first match) */ -/* ...in fact, I think I'm going to simplify this later */ -static int del_line_matching(char *login, char *filename) -{ - char *buffer; - FILE *passwd; - size_t len; - Bounds b; - struct stat statbuf; - - /* load into buffer */ - passwd = fopen(filename, "r"); - if (!passwd) { - return 1; - } - stat(filename, &statbuf); - len = statbuf.st_size; - buffer = (char *) malloc(len * sizeof(char)); - - if (!buffer) { - fclose(passwd); - return 1; - } - fread(buffer, len, sizeof(char), passwd); - - fclose(passwd); - - /* find the user to remove */ - b = boundary(buffer, login); - if (b.stop == 0) { - free(buffer); - return 1; - } - - /* write the file w/o the user */ - passwd = fopen(filename, "w"); - if (!passwd) { - return 1; - } - fwrite(buffer, (b.start - 1), sizeof(char), passwd); - fwrite(&buffer[b.stop], (len - b.stop), sizeof(char), passwd); - - fclose(passwd); - - return 0; -} - -/* ________________________________________________________________________ */ -int delgroup_main(int argc, char **argv) -{ - /* int successful; */ - int failure; - - if (argc != 2) { - show_usage(); - } else { - - failure = del_line_matching(argv[1], GROUP_FILE); -#ifdef TLG_FEATURE_SHADOWPASSWDS - if (access(GSHADOW_FILE, W_OK) == 0) { - /* EDR the |= works if the error is not 0, so he had it wrong */ - failure |= del_line_matching(argv[1], GSHADOW_FILE); - } -#endif /* TLG_FEATURE_SHADOWPASSWDS */ - /* if (!successful) { */ - if (failure) { - error_msg_and_die("%s: Group could not be removed\n", argv[1]); - } - - } - return (EXIT_SUCCESS); -} - -/* ________________________________________________________________________ */ -int deluser_main(int argc, char **argv) -{ - /* int successful; */ - int failure; - - if (argc != 2) { - show_usage(); - } else { - - failure = del_line_matching(argv[1], PASSWD_FILE); - /* if (!successful) { */ - if (failure) { - error_msg_and_die("%s: User could not be removed from %s\n", - argv[1], PASSWD_FILE); - } -#ifdef TLG_FEATURE_SHADOWPASSWDS - failure = del_line_matching(argv[1], SHADOW_FILE); - /* if (!successful) { */ - if (failure) { - error_msg_and_die("%s: User could not be removed from %s\n", - argv[1], SHADOW_FILE); - } -#endif /* TLG_FEATURE_SHADOWPASSWDS */ - failure = del_line_matching(argv[1], GROUP_FILE); - /* if (!successful) { */ - if (failure) { - error_msg_and_die("%s: User could not be removed from %s\n", - argv[1], GROUP_FILE); - } - - } - return (EXIT_SUCCESS); -} - -/* $Id: deluser.c,v 1.1 2001/08/21 16:18:59 andersen Exp $ */ diff --git a/df.c b/df.c deleted file mode 100644 index 8cb13fa6d..000000000 --- a/df.c +++ /dev/null @@ -1,158 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini df implementation for busybox - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , - * based on original code by (I think) Bruce Perens . - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include "busybox.h" - -extern const char mtab_file[]; /* Defined in utility.c */ -#ifdef BB_FEATURE_HUMAN_READABLE -static unsigned long df_disp_hr = KILOBYTE; -#endif - -static int do_df(char *device, const char *mount_point) -{ - struct statfs s; - long blocks_used; - long blocks_percent_used; - - if (statfs(mount_point, &s) != 0) { - perror_msg("%s", mount_point); - return FALSE; - } - - if (s.f_blocks > 0) { - blocks_used = s.f_blocks - s.f_bfree; - if(blocks_used == 0) - blocks_percent_used = 0; - else { - blocks_percent_used = (long) - (blocks_used * 100.0 / (blocks_used + s.f_bavail) + 0.5); - } - if (strcmp(device, "/dev/root") == 0) { - /* Adjusts device to be the real root device, - * or leaves device alone if it can't find it */ - device = find_real_root_device_name(device); - if(device==NULL) - return FALSE; - } -#ifdef BB_FEATURE_HUMAN_READABLE - printf("%-20s %9s ", device, - make_human_readable_str(s.f_blocks, s.f_bsize, df_disp_hr)); - - printf("%9s ", - make_human_readable_str( (s.f_blocks - s.f_bfree), s.f_bsize, df_disp_hr)); - - printf("%9s %3ld%% %s\n", - make_human_readable_str(s.f_bavail, s.f_bsize, df_disp_hr), - blocks_percent_used, mount_point); -#else - printf("%-20s %9ld %9ld %9ld %3ld%% %s\n", - device, - (long) (s.f_blocks * (s.f_bsize / (double)KILOBYTE)), - (long) ((s.f_blocks - s.f_bfree)*(s.f_bsize/(double)KILOBYTE)), - (long) (s.f_bavail * (s.f_bsize / (double)KILOBYTE)), - blocks_percent_used, mount_point); -#endif - } - - return TRUE; -} - -extern int df_main(int argc, char **argv) -{ - int status = EXIT_SUCCESS; - int opt = 0; - int i = 0; - char disp_units_hdr[80] = "1k-blocks"; /* default display is kilobytes */ - - while ((opt = getopt(argc, argv, "k" -#ifdef BB_FEATURE_HUMAN_READABLE - "hm" -#endif -)) > 0) - { - switch (opt) { -#ifdef BB_FEATURE_HUMAN_READABLE - case 'h': - df_disp_hr = 0; - strcpy(disp_units_hdr, " Size"); - break; - case 'm': - df_disp_hr = MEGABYTE; - strcpy(disp_units_hdr, "1M-blocks"); - break; -#endif - case 'k': - /* default display is kilobytes */ - break; - default: - show_usage(); - } - } - - printf("%-20s %-14s %s %s %s %s\n", "Filesystem", disp_units_hdr, - "Used", "Available", "Use%", "Mounted on"); - - if(optind < argc) { - struct mntent *mount_entry; - for(i = optind; i < argc; i++) - { - if ((mount_entry = find_mount_point(argv[i], mtab_file)) == 0) { - error_msg("%s: can't find mount point.", argv[i]); - status = EXIT_FAILURE; - } else if (!do_df(mount_entry->mnt_fsname, mount_entry->mnt_dir)) - status = EXIT_FAILURE; - } - } else { - FILE *mount_table; - struct mntent *mount_entry; - - mount_table = setmntent(mtab_file, "r"); - if (mount_table == 0) { - perror_msg("%s", mtab_file); - return EXIT_FAILURE; - } - - while ((mount_entry = getmntent(mount_table))) { - if (!do_df(mount_entry->mnt_fsname, mount_entry->mnt_dir)) - status = EXIT_FAILURE; - } - endmntent(mount_table); - } - - return status; -} - -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ diff --git a/dirname.c b/dirname.c deleted file mode 100644 index b534e6950..000000000 --- a/dirname.c +++ /dev/null @@ -1,40 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini dirname implementation for busybox - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* getopt not needed */ - -#include -#include -#include -#include "busybox.h" - -extern int dirname_main(int argc, char **argv) -{ - if ((argc < 2) || (**(argv + 1) == '-')) - show_usage(); - argv++; - - puts (dirname (argv[0])); - - return EXIT_SUCCESS; -} diff --git a/dmesg.c b/dmesg.c deleted file mode 100644 index 73de6d1ae..000000000 --- a/dmesg.c +++ /dev/null @@ -1,95 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* dmesg.c -- Print out the contents of the kernel ring buffer - * Created: Sat Oct 9 16:19:47 1993 - * Revised: Thu Oct 28 21:52:17 1993 by faith@cs.unc.edu - * Copyright 1993 Theodore Ts'o (tytso@athena.mit.edu) - * This program comes with ABSOLUTELY NO WARRANTY. - * Modifications by Rick Sladkey (jrs@world.std.com) - * Larger buffersize 3 June 1998 by Nicolai Langfeldt, based on a patch - * by Peeter Joot. This was also suggested by John Hudson. - * 1999-02-22 Arkadiusz Mi¶kiewicz - * - added Native Language Support - * - * from util-linux -- adapted for busybox by - * Erik Andersen . I ripped out Native Language - * Support, replaced getopt, added some gotos for redundant stuff. - */ - -#include -#include -#include - -#if __GNU_LIBRARY__ < 5 -# ifdef __alpha__ -# define klogctl syslog -# endif -#else -# include -#endif - -#include "busybox.h" - -int dmesg_main(int argc, char **argv) -{ - char *buf; - int c; - int bufsize = 8196; - int i; - int n; - int level = 0; - int lastc; - int cmd = 3; - - while ((c = getopt(argc, argv, "cn:s:")) != EOF) { - switch (c) { - case 'c': - cmd = 4; - break; - case 'n': - cmd = 8; - if (optarg == NULL) - show_usage(); - level = atoi(optarg); - break; - case 's': - if (optarg == NULL) - show_usage(); - bufsize = atoi(optarg); - break; - default: - show_usage(); - } - } - - if (optind < argc) { - show_usage(); - } - - if (cmd == 8) { - if (klogctl(cmd, NULL, level) < 0) - perror_msg_and_die("klogctl"); - return EXIT_SUCCESS; - } - - if (bufsize < 4096) - bufsize = 4096; - buf = (char *) xmalloc(bufsize); - if ((n = klogctl(cmd, buf, bufsize)) < 0) - perror_msg_and_die("klogctl"); - - lastc = '\n'; - for (i = 0; i < n; i++) { - if (lastc == '\n' && buf[i] == '<') { - i++; - while (buf[i] >= '0' && buf[i] <= '9') - i++; - if (buf[i] == '>') - i++; - } - lastc = buf[i]; - putchar(lastc); - } - if (lastc != '\n') - putchar('\n'); - return EXIT_SUCCESS; -} diff --git a/docs/autodocifier.pl b/docs/autodocifier.pl index d753300c1..3016e4022 100755 --- a/docs/autodocifier.pl +++ b/docs/autodocifier.pl @@ -251,7 +251,7 @@ a command. I =item B This should contain descriptions of each option. This will also -be displayed along with the trivial help if BB_FEATURE_TRIVIAL_HELP +be displayed along with the trivial help if CONFIG_FEATURE_TRIVIAL_HELP is disabled. I =item B @@ -284,4 +284,4 @@ John BEPPU =cut -# $Id: autodocifier.pl,v 1.21 2001/04/17 17:09:34 beppu Exp $ +# $Id: autodocifier.pl,v 1.22 2001/10/24 04:59:20 andersen Exp $ diff --git a/docs/busybox.net/index.html b/docs/busybox.net/index.html index b396b4b16..a0b4e6ccf 100644 --- a/docs/busybox.net/index.html +++ b/docs/busybox.net/index.html @@ -295,7 +295,6 @@ listed in the order I happen to add them to the web page:

Do you use BusyBox? I'd love to know about it and I'd be happy to link to diff --git a/docs/busybox.net/oldnews.html b/docs/busybox.net/oldnews.html index d97bb2684..08a49caf8 100644 --- a/docs/busybox.net/oldnews.html +++ b/docs/busybox.net/oldnews.html @@ -74,12 +74,12 @@

  • Busybox Boot-Floppy Image

    Because you asked for it, we have made available a Busybox boot floppy + "ftp://oss.lineo.com/busybox/busybox.floppy.img"> Busybox boot floppy image. Here's how you use it:

      -
    1. +
    2. Download the image
    3. dd it onto a floppy like so: dd if=busybox.floppy.img @@ -203,13 +203,13 @@ details).

      Also, some exciting infrastructure news! Busybox now has its own - mailing list, + mailing list, publically browsable - CVS tree, + CVS tree, anonymous - CVS access, and + CVS access, and for those that are actively contributing there is even - CVS write access. + CVS write access. I think this will be a huge help to the ongoing development of BusyBox.

      Also, for the curious, there is no 0.44 release. Somehow 0.44 got announced @@ -398,13 +398,10 @@ Freshmeat AppIndex record for BusyBox

      -

    4. Other cool embedded software. +
    5. Cool embedded software.

      -

    6. opensource.lineo.com. -

      - -

    7. Lineo is sponsoring BusyBox development. +
    8. oss.lineo.com.

      @@ -425,8 +422,8 @@ Mail all comments, insults, suggestions and bribes to - Erik Andersen
      - The Busybox logo is copyright 1999,2000, Erik Andersen. + Erik Andersen
      + The Busybox logo is copyright 1999,2000,2001 Erik Andersen.
      diff --git a/docs/new-applet-HOWTO.txt b/docs/new-applet-HOWTO.txt index 1f5c3ebd5..a00dfcc30 100644 --- a/docs/new-applet-HOWTO.txt +++ b/docs/new-applet-HOWTO.txt @@ -109,7 +109,7 @@ order, or else it will break the binary-search lookup algorithm in busybox.c and the Gods of BusyBox smite you. Yea, verily: /* all programs above here are alphabetically "less than" 'mu' */ - #ifdef BB_MU + #ifdef CONFIG_MU APPLET("mu", mu_main, _BB_DIR_USR_BIN, mu_usage) #endif /* all programs below here are alphabetically "greater than" 'mu' */ @@ -117,7 +117,7 @@ and the Gods of BusyBox smite you. Yea, verily: Finally, add a define for your applet to Config.h: - #define BB_MU + #define CONFIG_MU Documentation diff --git a/docs/style-guide.txt b/docs/style-guide.txt index c71f1e609..25c676ca2 100644 --- a/docs/style-guide.txt +++ b/docs/style-guide.txt @@ -252,7 +252,7 @@ files, you can do the following in the busybox directory: If you want to convert all the non-K&R vars in your file all at once, follow these steps: - - In the busybox directory type 'scripts/mk2knr.pl files-to-convert'. This + - In the busybox directory type 'examples/mk2knr.pl files-to-convert'. This does not do the actual conversion, rather, it generates a script called 'convertme.pl' that shows what will be converted, giving you a chance to review the changes beforehand. @@ -269,7 +269,7 @@ these steps: Please be aware of changes that have cascading effects into other files. For example, if you're changing the name of something in, say utility.c, you -should probably run 'scripts/mk2knr.pl utility.c' at first, but when you run +should probably run 'examples/mk2knr.pl utility.c' at first, but when you run the 'convertme.pl' script you should run it on _all_ files like so: './convertme.pl *.[ch]'. @@ -343,7 +343,7 @@ used in the code. ret = my_func(bar, baz); if (!ret) return -1; - #ifdef BB_FEATURE_FUNKY + #ifdef CONFIG_FEATURE_FUNKY maybe_do_funky_stuff(bar, baz); #endif @@ -351,7 +351,7 @@ used in the code. (in .h header file) - #ifdef BB_FEATURE_FUNKY + #ifdef CONFIG_FEATURE_FUNKY static inline void maybe_do_funky_stuff (int bar, int baz) { /* lotsa code in here */ @@ -487,7 +487,7 @@ very limited stack space (e.g., uCLinux). A macro is declared in busybox.h that implements compile-time selection between xmalloc() and stack creation, so you can code the line in question as - RESERVE_BB_BUFFER(buffer, BUFSIZ); + RESERVE_CONFIG_BUFFER(buffer, BUFSIZ); and the right thing will happen, based on your configuration. diff --git a/dos2unix.c b/dos2unix.c deleted file mode 100644 index 8b65d05de..000000000 --- a/dos2unix.c +++ /dev/null @@ -1,194 +0,0 @@ -/* - * dos2unix for BusyBox - * - * dos2unix '\n' convertor 0.5.0 - * based on Unix2Dos 0.9.0 by Peter Hanecak (made 19.2.1997) - * Copyright 1997,.. by Peter Hanecak . - * All rights reserved. - * - * dos2unix filters reading input from stdin and writing output to stdout. - * Without arguments it reverts the format (e.i. if source is in UNIX format, - * output is in DOS format and vice versa). - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * See the COPYING file for license information. - */ - -#include -#include -#include -#include -#include -#include -#include "busybox.h" - -/* We are making a lame pseudo-random string generator here. in - * convert(), each pass through the while loop will add more and more - * stuff into value, which is _supposed_ to wrap. We don't care about - * it being accurate. We care about it being messy, since we then mod - * it by the sizeof(letters) and then use that as an index into letters - * to pick a random letter to add to out temporary file. */ -typedef unsigned long int bb_uint64_t; - -static const char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - -// if fn is NULL then input is stdin and output is stdout -static int convert(char *fn, int ConvType) -{ - int c, fd; - struct timeval tv; - char tempFn[BUFSIZ]; - static bb_uint64_t value=0; - FILE *in = stdin, *out = stdout; - - if (fn != NULL) { - if ((in = wfopen(fn, "rw")) == NULL) { - return -1; - } - strcpy(tempFn, fn); - c = strlen(tempFn); - tempFn[c] = '.'; - while(1) { - if (c >=BUFSIZ) - error_msg_and_die("unique name not found"); - /* Get some semi random stuff to try and make a - * random filename based (and in the same dir as) - * the input file... */ - gettimeofday (&tv, NULL); - value += ((bb_uint64_t) tv.tv_usec << 16) ^ tv.tv_sec ^ getpid (); - tempFn[++c] = letters[value % 62]; - tempFn[c+1] = '\0'; - value /= 62; - - if ((fd = open(tempFn, O_RDWR | O_CREAT | O_EXCL, 0600)) < 0 ) { - continue; - } - out = fdopen(fd, "w+"); - if (!out) { - close(fd); - remove(tempFn); - continue; - } - break; - } - } - - while ((c = fgetc(in)) != EOF) { - if (c == '\r') { - if ((ConvType == CT_UNIX2DOS) && (fn != NULL)) { - // file is alredy in DOS format so it is not necessery to touch it - remove(tempFn); - if (fclose(in) < 0 || fclose(out) < 0) { - perror_msg(NULL); - return -2; - } - return 0; - } - if (!ConvType) - ConvType = CT_DOS2UNIX; - break; - } - if (c == '\n') { - if ((ConvType == CT_DOS2UNIX) && (fn != NULL)) { - // file is alredy in UNIX format so it is not necessery to touch it - remove(tempFn); - if ((fclose(in) < 0) || (fclose(out) < 0)) { - perror_msg(NULL); - return -2; - } - return 0; - } - if (!ConvType) { - ConvType = CT_UNIX2DOS; - } - if (ConvType == CT_UNIX2DOS) { - fputc('\r', out); - } - fputc('\n', out); - break; - } - fputc(c, out); - } - if (c != EOF) - while ((c = fgetc(in)) != EOF) { - if (c == '\r') - continue; - if (c == '\n') { - if (ConvType == CT_UNIX2DOS) - fputc('\r', out); - fputc('\n', out); - continue; - } - fputc(c, out); - } - - if (fn != NULL) { - if (fclose(in) < 0 || fclose(out) < 0) { - perror_msg(NULL); - remove(tempFn); - return -2; - } - - /* Assume they are both on the same filesystem (which - * should be true since we put them into the same directory - * so we _should_ be ok, but you never know... */ - if (rename(tempFn, fn) < 0) { - perror_msg("unable to rename '%s' as '%s'", tempFn, fn); - return -1; - } - } - - return 0; -} - -int dos2unix_main(int argc, char *argv[]) -{ - int ConvType = CT_AUTO; - int o; - - //See if we are supposed to be doing dos2unix or unix2dos - if (argv[0][0]=='d') { - ConvType = CT_DOS2UNIX; - } - if (argv[0][0]=='u') { - ConvType = CT_UNIX2DOS; - } - - // process parameters - while ((o = getopt(argc, argv, "du")) != EOF) { - switch (o) { - case 'd': - ConvType = CT_UNIX2DOS; - break; - case 'u': - ConvType = CT_DOS2UNIX; - break; - default: - show_usage(); - } - } - - if (optind < argc) { - while(optind < argc) - if ((o = convert(argv[optind++], ConvType)) < 0) - break; - } - else - o = convert(NULL, ConvType); - - return o; -} - diff --git a/dpkg.c b/dpkg.c deleted file mode 100644 index bf0dcf3c3..000000000 --- a/dpkg.c +++ /dev/null @@ -1,1509 +0,0 @@ -/* - * Mini dpkg implementation for busybox. - * This is not meant as a replacemnt for dpkg - * - * Written By Glenn McGrath with the help of others - * Copyright (C) 2001 by Glenn McGrath - * - * Started life as a busybox implementation of udpkg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * Known difference between busybox dpkg and the official dpkg that i dont - * consider important, its worth keeping a note of differences anyway, just to - * make it easier to maintain. - * - The first value for the Confflile: field isnt placed on a new line. - * - The .control file is extracted and kept in the info dir. - * - When installing a package the Status: field is placed at the end of the - * section, rather than just after the Package: field. - * - Packages with previously unknown status are inserted at the begining of - * the status file - * - * Bugs that need to be fixed - * - (unknown, please let me know when you find any) - * - */ - -#include -#include -#include -#include -#include "busybox.h" - -/* NOTE: If you vary HASH_PRIME sizes be aware, - * 1) Tweaking these will have a big effect on how much memory this program uses. - * 2) For computational efficiency these hash tables should be at least 20% - * larger than the maximum number of elements stored in it. - * 3) All _HASH_PRIME's must be a prime number or chaos is assured, if your looking - * for a prime, try http://www.utm.edu/research/primes/lists/small/10000.txt - * 4) If you go bigger than 15 bits you may get into trouble (untested) as its - * sometimes cast to an unsigned int, if you go to 16 bit you will overlap - * int's and chaos is assured, 16381 is the max prime for 14 bit field - */ - -/* NAME_HASH_PRIME, Stores package names and versions, - * I estimate it should be at least 50% bigger than PACKAGE_HASH_PRIME, - * as there a lot of duplicate version numbers */ -#define NAME_HASH_PRIME 16381 -char *name_hashtable[NAME_HASH_PRIME + 1]; - -/* PACKAGE_HASH_PRIME, Maximum number of unique packages, - * It must not be smaller than STATUS_HASH_PRIME, - * Currently only packages from status_hashtable are stored in here, but in - * future this may be used to store packages not only from a status file, - * but an available_hashtable, and even multiple packages files. - * Package can be stored more than once if they have different versions. - * e.g. The same package may have different versions in the status file - * and available file */ -#define PACKAGE_HASH_PRIME 10007 -typedef struct edge_s { - unsigned int operator:3; - unsigned int type:4; - unsigned int name:14; - unsigned int version:14; -} edge_t; - -typedef struct common_node_s { - unsigned int name:14; - unsigned int version:14; - unsigned int num_of_edges:14; - edge_t **edge; -} common_node_t; -common_node_t *package_hashtable[PACKAGE_HASH_PRIME + 1]; - -/* Currently it doesnt store packages that have state-status of not-installed - * So it only really has to be the size of the maximum number of packages - * likely to be installed at any one time, so there is a bit of leaway here */ -#define STATUS_HASH_PRIME 8191 -typedef struct status_node_s { - unsigned int package:14; /* has to fit PACKAGE_HASH_PRIME */ - unsigned int status:14; /* has to fit STATUS_HASH_PRIME */ -} status_node_t; -status_node_t *status_hashtable[STATUS_HASH_PRIME + 1]; - -/* Even numbers are for 'extras', like ored dependecies or null */ -enum edge_type_e { - EDGE_NULL = 0, - EDGE_PRE_DEPENDS = 1, - EDGE_OR_PRE_DEPENDS = 2, - EDGE_DEPENDS = 3, - EDGE_OR_DEPENDS = 4, - EDGE_REPLACES = 5, - EDGE_PROVIDES = 7, - EDGE_CONFLICTS = 9, - EDGE_SUGGESTS = 11, - EDGE_RECOMMENDS = 13, - EDGE_ENHANCES = 15 -}; -enum operator_e { - VER_NULL = 0, - VER_EQUAL = 1, - VER_LESS = 2, - VER_LESS_EQUAL = 3, - VER_MORE = 4, - VER_MORE_EQUAL = 5, - VER_ANY = 6 -}; - -enum dpkg_opt_e { - dpkg_opt_purge = 1, - dpkg_opt_remove = 2, - dpkg_opt_unpack = 4, - dpkg_opt_configure = 8, - dpkg_opt_install = 16, - dpkg_opt_package_name = 32, - dpkg_opt_filename = 64, - dpkg_opt_list_installed = 128, - dpkg_opt_force_ignore_depends = 256 -}; - -typedef struct deb_file_s { - char *control_file; - char *filename; - unsigned int package:14; -} deb_file_t; - - -void make_hash(const char *key, unsigned int *start, unsigned int *decrement, const int hash_prime) -{ - unsigned long int hash_num = key[0]; - int len = strlen(key); - int i; - - /* Maybe i should have uses a "proper" hashing algorithm here instead - * of making one up myself, seems to be working ok though. */ - for(i = 1; i < len; i++) { - /* shifts the ascii based value and adds it to previous value - * shift amount is mod 24 because long int is 32 bit and data - * to be shifted is 8, dont want to shift data to where it has - * no effect*/ - hash_num += ((key[i] + key[i-1]) << ((key[i] * i) % 24)); - } - *start = (unsigned int) hash_num % hash_prime; - *decrement = (unsigned int) 1 + (hash_num % (hash_prime - 1)); -} - -/* this adds the key to the hash table */ -int search_name_hashtable(const char *key) -{ - unsigned int probe_address = 0; - unsigned int probe_decrement = 0; -// char *temp; - - make_hash(key, &probe_address, &probe_decrement, NAME_HASH_PRIME); - while(name_hashtable[probe_address] != NULL) { - if (strcmp(name_hashtable[probe_address], key) == 0) { - return(probe_address); - } else { - probe_address -= probe_decrement; - if ((int)probe_address < 0) { - probe_address += NAME_HASH_PRIME; - } - } - } - name_hashtable[probe_address] = xstrdup(key); - return(probe_address); -} - -/* this DOESNT add the key to the hashtable - * TODO make it consistent with search_name_hashtable - */ -unsigned int search_status_hashtable(const char *key) -{ - unsigned int probe_address = 0; - unsigned int probe_decrement = 0; - - make_hash(key, &probe_address, &probe_decrement, STATUS_HASH_PRIME); - while(status_hashtable[probe_address] != NULL) { - if (strcmp(key, name_hashtable[package_hashtable[status_hashtable[probe_address]->package]->name]) == 0) { - break; - } else { - probe_address -= probe_decrement; - if ((int)probe_address < 0) { - probe_address += STATUS_HASH_PRIME; - } - } - } - return(probe_address); -} - -/* Need to rethink version comparison, maybe the official dpkg has something i can use ? */ -int version_compare_part(const char *version1, const char *version2) -{ - int upstream_len1 = 0; - int upstream_len2 = 0; - char *name1_char; - char *name2_char; - int len1 = 0; - int len2 = 0; - int tmp_int; - int ver_num1; - int ver_num2; - int ret; - - if (version1 == NULL) { - version1 = xstrdup(""); - } - if (version2 == NULL) { - version2 = xstrdup(""); - } - upstream_len1 = strlen(version1); - upstream_len2 = strlen(version2); - - while ((len1 < upstream_len1) || (len2 < upstream_len2)) { - /* Compare non-digit section */ - tmp_int = strcspn(&version1[len1], "0123456789"); - name1_char = xstrndup(&version1[len1], tmp_int); - len1 += tmp_int; - tmp_int = strcspn(&version2[len2], "0123456789"); - name2_char = xstrndup(&version2[len2], tmp_int); - len2 += tmp_int; - tmp_int = strcmp(name1_char, name2_char); - free(name1_char); - free(name2_char); - if (tmp_int != 0) { - ret = tmp_int; - goto cleanup_version_compare_part; - } - - /* Compare digits */ - tmp_int = strspn(&version1[len1], "0123456789"); - name1_char = xstrndup(&version1[len1], tmp_int); - len1 += tmp_int; - tmp_int = strspn(&version2[len2], "0123456789"); - name2_char = xstrndup(&version2[len2], tmp_int); - len2 += tmp_int; - ver_num1 = atoi(name1_char); - ver_num2 = atoi(name2_char); - free(name1_char); - free(name2_char); - if (ver_num1 < ver_num2) { - ret = -1; - goto cleanup_version_compare_part; - } - else if (ver_num1 > ver_num2) { - ret = 1; - goto cleanup_version_compare_part; - } - } - ret = 0; -cleanup_version_compare_part: - return(ret); -} - -/* if ver1 < ver2 return -1, - * if ver1 = ver2 return 0, - * if ver1 > ver2 return 1, - */ -int version_compare(const unsigned int ver1, const unsigned int ver2) -{ - char *ch_ver1 = name_hashtable[ver1]; - char *ch_ver2 = name_hashtable[ver2]; - - char epoch1, epoch2; - char *deb_ver1, *deb_ver2; - char *ver1_ptr, *ver2_ptr; - char *upstream_ver1; - char *upstream_ver2; - int result; - - /* Compare epoch */ - if (ch_ver1[1] == ':') { - epoch1 = ch_ver1[0]; - ver1_ptr = strchr(ch_ver1, ':') + 1; - } else { - epoch1 = '0'; - ver1_ptr = ch_ver1; - } - if (ch_ver2[1] == ':') { - epoch2 = ch_ver2[0]; - ver2_ptr = strchr(ch_ver2, ':') + 1; - } else { - epoch2 = '0'; - ver2_ptr = ch_ver2; - } - if (epoch1 < epoch2) { - return(-1); - } - else if (epoch1 > epoch2) { - return(1); - } - - /* Compare upstream version */ - upstream_ver1 = xstrdup(ver1_ptr); - upstream_ver2 = xstrdup(ver2_ptr); - - /* Chop off debian version, and store for later use */ - deb_ver1 = strrchr(upstream_ver1, '-'); - deb_ver2 = strrchr(upstream_ver2, '-'); - if (deb_ver1) { - deb_ver1[0] = '\0'; - deb_ver1++; - } - if (deb_ver2) { - deb_ver2[0] = '\0'; - deb_ver2++; - } - result = version_compare_part(upstream_ver1, upstream_ver2); - - free(upstream_ver1); - free(upstream_ver2); - - if (result != 0) { - return(result); - } - - /* Compare debian versions */ - return(version_compare_part(deb_ver1, deb_ver2)); -} - -int test_version(const unsigned int version1, const unsigned int version2, const unsigned int operator) -{ - const int version_result = version_compare(version1, version2); - switch(operator) { - case (VER_ANY): - return(TRUE); - case (VER_EQUAL): - if (version_result == 0) { - return(TRUE); - } - break; - case (VER_LESS): - if (version_result < 0) { - return(TRUE); - } - break; - case (VER_LESS_EQUAL): - if (version_result <= 0) { - return(TRUE); - } - break; - case (VER_MORE): - if (version_result > 0) { - return(TRUE); - } - break; - case (VER_MORE_EQUAL): - if (version_result >= 0) { - return(TRUE); - } - break; - } - return(FALSE); -} - - -int search_package_hashtable(const unsigned int name, const unsigned int version, const unsigned int operator) -{ - unsigned int probe_address = 0; - unsigned int probe_decrement = 0; - - make_hash(name_hashtable[name], &probe_address, &probe_decrement, PACKAGE_HASH_PRIME); - while(package_hashtable[probe_address] != NULL) { - if (package_hashtable[probe_address]->name == name) { - if (operator == VER_ANY) { - return(probe_address); - } - if (test_version(package_hashtable[probe_address]->version, version, operator)) { - return(probe_address); - } - } - probe_address -= probe_decrement; - if ((int)probe_address < 0) { - probe_address += PACKAGE_HASH_PRIME; - } - } - return(probe_address); -} - -/* - * Create one new node and one new edge for every dependency. - */ -void add_split_dependencies(common_node_t *parent_node, const char *whole_line, unsigned int edge_type) -{ - char *line = xstrdup(whole_line); - char *line2; - char *line_ptr1 = NULL; - char *line_ptr2 = NULL; - char *field; - char *field2; - char *version; - edge_t *edge; - int offset_ch; - int type; - - field = strtok_r(line, ",", &line_ptr1); - do { - line2 = xstrdup(field); - field2 = strtok_r(line2, "|", &line_ptr2); - if ((edge_type == EDGE_DEPENDS) && (strcmp(field, field2) != 0)) { - type = EDGE_OR_DEPENDS; - } - else if ((edge_type == EDGE_PRE_DEPENDS) && (strcmp(field, field2) != 0)) { - type = EDGE_OR_PRE_DEPENDS; - } else { - type = edge_type; - } - - do { - edge = (edge_t *) xmalloc(sizeof(edge_t)); - edge->type = type; - - /* Skip any extra leading spaces */ - field2 += strspn(field2, " "); - - /* Get dependency version info */ - version = strchr(field2, '('); - if (version == NULL) { - edge->operator = VER_ANY; - /* Get the versions hash number, adding it if the number isnt already in there */ - edge->version = search_name_hashtable("ANY"); - } else { - /* Skip leading ' ' or '(' */ - version += strspn(field2, " "); - version += strspn(version, "("); - /* Calculate length of any operator charactors */ - offset_ch = strspn(version, "<=>"); - /* Determine operator */ - if (offset_ch > 0) { - if (strncmp(version, "=", offset_ch) == 0) { - edge->operator = VER_EQUAL; - } - else if (strncmp(version, "<<", offset_ch) == 0) { - edge->operator = VER_LESS; - } - else if (strncmp(version, "<=", offset_ch) == 0) { - edge->operator = VER_LESS_EQUAL; - } - else if (strncmp(version, ">>", offset_ch) == 0) { - edge->operator = VER_MORE; - } - else if (strncmp(version, ">=", offset_ch) == 0) { - edge->operator = VER_MORE_EQUAL; - } else { - error_msg_and_die("Illegal operator\n"); - } - } - /* skip to start of version numbers */ - version += offset_ch; - version += strspn(version, " "); - - /* Truncate version at trailing ' ' or ')' */ - version[strcspn(version, " )")] = '\0'; - /* Get the versions hash number, adding it if the number isnt already in there */ - edge->version = search_name_hashtable(version); - } - - /* Get the dependency name */ - field2[strcspn(field2, " (")] = '\0'; - edge->name = search_name_hashtable(field2); - - /* link the new edge to the current node */ - parent_node->num_of_edges++; - parent_node->edge = xrealloc(parent_node->edge, sizeof(edge_t) * (parent_node->num_of_edges + 1)); - parent_node->edge[parent_node->num_of_edges - 1] = edge; - } while ((field2 = strtok_r(NULL, "|", &line_ptr2)) != NULL); - free(line2); - } while ((field = strtok_r(NULL, ",", &line_ptr1)) != NULL); - free(line); - - return; -} - -void free_package(common_node_t *node) -{ - int i; - if (node != NULL) { - for (i = 0; i < node->num_of_edges; i++) { - if (node->edge[i] != NULL) { - free(node->edge[i]); - } - } - if (node->edge != NULL) { - free(node->edge); - } - if (node != NULL) { - free(node); - } - } -} - -unsigned int fill_package_struct(char *control_buffer) -{ - common_node_t *new_node = (common_node_t *) xcalloc(1, sizeof(common_node_t)); - - char *field_name; - char *field_value; - int field_start = 0; - int num = -1; - int buffer_length = strlen(control_buffer); - - new_node->version = search_name_hashtable("unknown"); - while (field_start < buffer_length) { - field_start += read_package_field(&control_buffer[field_start], - &field_name, &field_value); - - if (field_name == NULL) { - goto fill_package_struct_cleanup; // Oh no, the dreaded goto statement !! - } - - if (strcmp(field_name, "Package") == 0) { - new_node->name = search_name_hashtable(field_value); - } - else if (strcmp(field_name, "Version") == 0) { - new_node->version = search_name_hashtable(field_value); - } - else if (strcmp(field_name, "Pre-Depends") == 0) { - add_split_dependencies(new_node, field_value, EDGE_PRE_DEPENDS); - } - else if (strcmp(field_name, "Depends") == 0) { - add_split_dependencies(new_node, field_value, EDGE_DEPENDS); - } - else if (strcmp(field_name, "Replaces") == 0) { - add_split_dependencies(new_node, field_value, EDGE_REPLACES); - } - else if (strcmp(field_name, "Provides") == 0) { - add_split_dependencies(new_node, field_value, EDGE_PROVIDES); - } - else if (strcmp(field_name, "Conflicts") == 0) { - add_split_dependencies(new_node, field_value, EDGE_CONFLICTS); - } - else if (strcmp(field_name, "Suggests") == 0) { - add_split_dependencies(new_node, field_value, EDGE_SUGGESTS); - } - else if (strcmp(field_name, "Recommends") == 0) { - add_split_dependencies(new_node, field_value, EDGE_RECOMMENDS); - } - else if (strcmp(field_name, "Enhances") == 0) { - add_split_dependencies(new_node, field_value, EDGE_ENHANCES); - } -fill_package_struct_cleanup: - if (field_name) { - free(field_name); - } - if (field_value) { - free(field_value); - } - } - - if (new_node->version == search_name_hashtable("unknown")) { - free_package(new_node); - return(-1); - } - num = search_package_hashtable(new_node->name, new_node->version, VER_EQUAL); - if (package_hashtable[num] == NULL) { - package_hashtable[num] = new_node; - } else { - free_package(new_node); - } - return(num); -} - -/* if num = 1, it returns the want status, 2 returns flag, 3 returns status */ -unsigned int get_status(const unsigned int status_node, const int num) -{ - char *status_string = name_hashtable[status_hashtable[status_node]->status]; - char *state_sub_string; - unsigned int state_sub_num; - int len; - int i; - - /* set tmp_string to point to the start of the word number */ - for (i = 1; i < num; i++) { - /* skip past a word */ - status_string += strcspn(status_string, " "); - /* skip past the seperating spaces */ - status_string += strspn(status_string, " "); - } - len = strcspn(status_string, " \n\0"); - state_sub_string = xstrndup(status_string, len); - state_sub_num = search_name_hashtable(state_sub_string); - free(state_sub_string); - return(state_sub_num); -} - -void set_status(const unsigned int status_node_num, const char *new_value, const int position) -{ - const unsigned int new_value_len = strlen(new_value); - const unsigned int new_value_num = search_name_hashtable(new_value); - unsigned int want = get_status(status_node_num, 1); - unsigned int flag = get_status(status_node_num, 2); - unsigned int status = get_status(status_node_num, 3); - int want_len = strlen(name_hashtable[want]); - int flag_len = strlen(name_hashtable[flag]); - int status_len = strlen(name_hashtable[status]); - char *new_status; - - switch (position) { - case (1): - want = new_value_num; - want_len = new_value_len; - break; - case (2): - flag = new_value_num; - flag_len = new_value_len; - break; - case (3): - status = new_value_num; - status_len = new_value_len; - break; - default: - error_msg_and_die("DEBUG ONLY: this shouldnt happen"); - } - - new_status = (char *) xmalloc(want_len + flag_len + status_len + 3); - sprintf(new_status, "%s %s %s", name_hashtable[want], name_hashtable[flag], name_hashtable[status]); - status_hashtable[status_node_num]->status = search_name_hashtable(new_status); - free(new_status); - return; -} - -void index_status_file(const char *filename) -{ - FILE *status_file; - char *control_buffer; - char *status_line; - status_node_t *status_node = NULL; - unsigned int status_num; - - status_file = xfopen(filename, "r"); - while ((control_buffer = fgets_str(status_file, "\n\n")) != NULL) { - const unsigned int package_num = fill_package_struct(control_buffer); - if (package_num != -1) { - status_node = xmalloc(sizeof(status_node_t)); - /* fill_package_struct doesnt handle the status field */ - status_line = strstr(control_buffer, "Status:"); - if (status_line != NULL) { - status_line += 7; - status_line += strspn(status_line, " \n\t"); - status_line = xstrndup(status_line, strcspn(status_line, "\n\0")); - status_node->status = search_name_hashtable(status_line); - free(status_line); - } - status_node->package = package_num; - status_num = search_status_hashtable(name_hashtable[package_hashtable[status_node->package]->name]); - status_hashtable[status_num] = status_node; - } - free(control_buffer); - } - fclose(status_file); - return; -} - - -char *get_depends_field(common_node_t *package, const int depends_type) -{ - char *depends = NULL; - char *old_sep = (char *)xcalloc(1, 3); - char *new_sep = (char *)xcalloc(1, 3); - int line_size = 0; - int depends_size; - - int i; - - for (i = 0; i < package->num_of_edges; i++) { - if ((package->edge[i]->type == EDGE_OR_PRE_DEPENDS) || - (package->edge[i]->type == EDGE_OR_DEPENDS)) { - } - - if ((package->edge[i]->type == depends_type) || - (package->edge[i]->type == depends_type + 1)) { - /* Check if its the first time through */ - - depends_size = 8 + strlen(name_hashtable[package->edge[i]->name]) - + strlen(name_hashtable[package->edge[i]->version]); - line_size += depends_size; - depends = (char *) xrealloc(depends, line_size + 1); - - /* Check to see if this dependency is the type we are looking for - * +1 to check for 'extra' types, e.g. ored dependecies */ - strcpy(old_sep, new_sep); - if (package->edge[i]->type == depends_type) { - strcpy(new_sep, ", "); - } - else if (package->edge[i]->type == depends_type + 1) { - strcpy(new_sep, "| "); - } - - if (depends_size == line_size) { - strcpy(depends, ""); - } else { - if ((strcmp(old_sep, "| ") == 0) && (strcmp(new_sep, "| ") == 0)) { - strcat(depends, " | "); - } else { - strcat(depends, ", "); - } - } - - strcat(depends, name_hashtable[package->edge[i]->name]); - if (strcmp(name_hashtable[package->edge[i]->version], "NULL") != 0) { - if (package->edge[i]->operator == VER_EQUAL) { - strcat(depends, " (= "); - } - else if (package->edge[i]->operator == VER_LESS) { - strcat(depends, " (<< "); - } - else if (package->edge[i]->operator == VER_LESS_EQUAL) { - strcat(depends, " (<= "); - } - else if (package->edge[i]->operator == VER_MORE) { - strcat(depends, " (>> "); - } - else if (package->edge[i]->operator == VER_MORE_EQUAL) { - strcat(depends, " (>= "); - } else { - strcat(depends, " ("); - } - strcat(depends, name_hashtable[package->edge[i]->version]); - strcat(depends, ")"); - } - } - } - return(depends); -} - -void write_buffer_no_status(FILE *new_status_file, const char *control_buffer) -{ - char *name; - char *value; - int start = 0; - while (1) { - start += read_package_field(&control_buffer[start], &name, &value); - if (name == NULL) { - break; - } - if (strcmp(name, "Status") != 0) { - fprintf(new_status_file, "%s: %s\n", name, value); - } - } - return; -} - -/* This could do with a cleanup */ -void write_status_file(deb_file_t **deb_file) -{ - FILE *old_status_file = xfopen("/var/lib/dpkg/status", "r"); - FILE *new_status_file = xfopen("/var/lib/dpkg/status.udeb", "w"); - char *package_name; - char *status_from_file; - char *control_buffer = NULL; - char *tmp_string; - int status_num; - int field_start = 0; - int write_flag; - int i = 0; - - /* Update previously known packages */ - while ((control_buffer = fgets_str(old_status_file, "\n\n")) != NULL) { - if ((tmp_string = strstr(control_buffer, "Package:")) == NULL) { - continue; - } - - tmp_string += 8; - tmp_string += strspn(tmp_string, " \n\t"); - package_name = xstrndup(tmp_string, strcspn(tmp_string, "\n\0")); - write_flag = FALSE; - tmp_string = strstr(control_buffer, "Status:"); - if (tmp_string != NULL) { - /* Seperate the status value from the control buffer */ - tmp_string += 7; - tmp_string += strspn(tmp_string, " \n\t"); - status_from_file = xstrndup(tmp_string, strcspn(tmp_string, "\n")); - } else { - status_from_file = NULL; - } - - /* Find this package in the status hashtable */ - status_num = search_status_hashtable(package_name); - if (status_hashtable[status_num] != NULL) { - const char *status_from_hashtable = name_hashtable[status_hashtable[status_num]->status]; - if (strcmp(status_from_file, status_from_hashtable) != 0) { - /* New status isnt exactly the same as old status */ - const int state_status = get_status(status_num, 3); - if ((strcmp("installed", name_hashtable[state_status]) == 0) || - (strcmp("unpacked", name_hashtable[state_status]) == 0)) { - /* We need to add the control file from the package */ - i = 0; - while(deb_file[i] != NULL) { - if (strcmp(package_name, name_hashtable[package_hashtable[deb_file[i]->package]->name]) == 0) { - /* Write a status file entry with a modified status */ - /* remove trailing \n's */ - write_buffer_no_status(new_status_file, deb_file[i]->control_file); - set_status(status_num, "ok", 2); - fprintf(new_status_file, "Status: %s\n\n", name_hashtable[status_hashtable[status_num]->status]); - write_flag = TRUE; - break; - } - i++; - } - /* This is temperary, debugging only */ - if (deb_file[i] == NULL) { - error_msg_and_die("ALERT: Couldnt find a control file, your status file may be broken, status may be incorrect for %s", package_name); - } - } - else if (strcmp("not-installed", name_hashtable[state_status]) == 0) { - /* Only write the Package, Status, Priority and Section lines */ - fprintf(new_status_file, "Package: %s\n", package_name); - fprintf(new_status_file, "Status: %s\n", status_from_hashtable); - - while (1) { - char *field_name; - char *field_value; - field_start += read_package_field(&control_buffer[field_start], &field_name, &field_value); - if (field_name == NULL) { - break; - } - if ((strcmp(field_name, "Priority") == 0) || - (strcmp(field_name, "Section") == 0)) { - fprintf(new_status_file, "%s: %s\n", field_name, field_value); - } - } - write_flag = TRUE; - fputs("\n", new_status_file); - } - else if (strcmp("config-files", name_hashtable[state_status]) == 0) { - /* only change the status line */ - while (1) { - char *field_name; - char *field_value; - field_start += read_package_field(&control_buffer[field_start], &field_name, &field_value); - if (field_name == NULL) { - break; - } - /* Setup start point for next field */ - if (strcmp(field_name, "Status") == 0) { - fprintf(new_status_file, "Status: %s\n", status_from_hashtable); - } else { - fprintf(new_status_file, "%s: %s\n", field_name, field_value); - } - } - write_flag = TRUE; - fputs("\n", new_status_file); - } - } - } - /* If the package from the status file wasnt handle above, do it now*/ - if (write_flag == FALSE) { - fprintf(new_status_file, "%s\n\n", control_buffer); - } - - if (status_from_file != NULL) { - free(status_from_file); - } - free(package_name); - free(control_buffer); - } - - /* Write any new packages */ - for(i = 0; deb_file[i] != NULL; i++) { - status_num = search_status_hashtable(name_hashtable[package_hashtable[deb_file[i]->package]->name]); - if (strcmp("reinstreq", name_hashtable[get_status(status_num, 2)]) == 0) { - write_buffer_no_status(new_status_file, deb_file[i]->control_file); - set_status(status_num, "ok", 2); - fprintf(new_status_file, "Status: %s\n\n", name_hashtable[status_hashtable[status_num]->status]); - } - } - fclose(old_status_file); - fclose(new_status_file); - - - /* Create a seperate backfile to dpkg */ - if (rename("/var/lib/dpkg/status", "/var/lib/dpkg/status.udeb.bak") == -1) { - struct stat stat_buf; - if (stat("/var/lib/dpkg/status", &stat_buf) == 0) { - error_msg_and_die("Couldnt create backup status file"); - } - /* Its ok if renaming the status file fails becasue status - * file doesnt exist, maybe we are starting from scratch */ - error_msg("No status file found, creating new one"); - } - - if (rename("/var/lib/dpkg/status.udeb", "/var/lib/dpkg/status") == -1) { - error_msg_and_die("DANGER: Couldnt create status file, you need to manually repair your status file"); - } -} - -int check_deps(deb_file_t **deb_file, int deb_start, int dep_max_count) -{ - int *conflicts = NULL; - int conflicts_num = 0; - int state_status; - int state_flag; - int state_want; - unsigned int status_package_num; - int i = deb_start; - int j, k; - - /* Check for conflicts - * TODO: TEST if conflicts with other packages to be installed - * - * Add install packages and the packages they provide - * to the list of files to check conflicts for - */ - - /* Create array of package numbers to check against - * installed package for conflicts*/ - while (deb_file[i] != NULL) { - const unsigned int package_num = deb_file[i]->package; - conflicts = xrealloc(conflicts, sizeof(int) * (conflicts_num + 1)); - conflicts[conflicts_num] = package_num; - conflicts_num++; - /* add provides to conflicts list */ - for (j = 0; j < package_hashtable[package_num]->num_of_edges; j++) { - if (package_hashtable[package_num]->edge[j]->type == EDGE_PROVIDES) { - const int conflicts_package_num = search_package_hashtable( - package_hashtable[package_num]->edge[j]->name, - package_hashtable[package_num]->edge[j]->version, - package_hashtable[package_num]->edge[j]->operator); - if (package_hashtable[conflicts_package_num] == NULL) { - /* create a new package */ - common_node_t *new_node = (common_node_t *) xmalloc(sizeof(common_node_t)); - new_node->name = package_hashtable[package_num]->edge[j]->name; - new_node->version = package_hashtable[package_num]->edge[j]->version; - new_node->num_of_edges = 0; - new_node->edge = NULL; - package_hashtable[conflicts_package_num] = new_node; - } - conflicts = xrealloc(conflicts, sizeof(int) * (conflicts_num + 1)); - conflicts[conflicts_num] = conflicts_package_num; - conflicts_num++; - } - } - i++; - } - - /* Check conflicts */ - for (i = 0; i < conflicts_num; i++) { - /* Check for conflicts */ - for (j = 0; j < STATUS_HASH_PRIME; j++) { - if (status_hashtable[j] == NULL) { - continue; - } - state_flag = get_status(j, 2); - state_status = get_status(j, 3); - if ((state_status != search_name_hashtable("installed")) - && (state_flag != search_name_hashtable("want-install"))) { - continue; - } - status_package_num = status_hashtable[j]->package; - for (k = 0; k < package_hashtable[status_package_num]->num_of_edges; k++) { - const edge_t *package_edge = package_hashtable[status_package_num]->edge[k]; - if (package_edge->type != EDGE_CONFLICTS) { - continue; - } - if (package_edge->name != package_hashtable[conflicts[i]]->name) { - continue; - } - /* There is a conflict against the package name - * check if version conflict as well */ - if (test_version(package_hashtable[deb_file[i]->package]->version, - package_edge->version, package_edge->operator)) { - error_msg_and_die("Package %s conflict with %s", - name_hashtable[package_hashtable[deb_file[i]->package]->name], - name_hashtable[package_hashtable[status_package_num]->name]); - } - } - } - } - - /* Check dependendcies */ - i = 0; - while (deb_file[i] != NULL) { - const common_node_t *package_node = package_hashtable[deb_file[i]->package]; - int status_num = 0; - - for (j = 0; j < package_hashtable[deb_file[i]->package]->num_of_edges; j++) { - const edge_t *package_edge = package_node->edge[j]; - const unsigned int package_num = search_package_hashtable(package_edge->name, - package_edge->version, package_edge->operator); - - status_num = search_status_hashtable(name_hashtable[package_hashtable[package_num]->name]); - state_status = get_status(status_num, 3); - state_want = get_status(status_num, 1); - switch (package_edge->type) { - case(EDGE_PRE_DEPENDS): - case(EDGE_OR_PRE_DEPENDS): - /* It must be already installed */ - /* NOTE: This is untested, nothing apropriate in my status file */ - if ((package_hashtable[package_num] == NULL) || (state_status != search_name_hashtable("installed"))) { - error_msg_and_die("Package %s pre-depends on %s, but it is not installed", - name_hashtable[package_node->name], - name_hashtable[package_edge->name]); - } - break; - case(EDGE_DEPENDS): - case(EDGE_OR_DEPENDS): - /* It must be already installed, or to be installed */ - if ((package_hashtable[package_num] == NULL) || - ((state_status != search_name_hashtable("installed")) && - (state_want != search_name_hashtable("want_install")))) { - error_msg_and_die("Package %s depends on %s, but it is not installed, or flaged to be installed", - name_hashtable[package_node->name], - name_hashtable[package_edge->name]); - } - break; - } - } - i++; - } - free(conflicts); - return(TRUE); -} - -char **create_list(const char *filename) -{ - FILE *list_stream; - char **file_list = xmalloc(sizeof(char *)); - char *line = NULL; - char *last_char; - int length = 0; - int count = 0; - - /* dont use [xw]fopen here, handle error ourself */ - list_stream = fopen(filename, "r"); - if (list_stream == NULL) { - *file_list = NULL; - return(file_list); - } - while (getline(&line, &length, list_stream) != -1) { - file_list = xrealloc(file_list, sizeof(char *) * (length + 1)); - last_char = last_char_is(line, '\n'); - if (last_char) { - *last_char = '\0'; - } - file_list[count] = xstrdup(line); - count++; - } - fclose(list_stream); - free(line); - - if (count == 0) { - return(NULL); - } else { - file_list[count] = NULL; - return(file_list); - } -} - -/* maybe i should try and hook this into remove_file.c somehow */ -int remove_file_array(char **remove_names, char **exclude_names) -{ - struct stat path_stat; - int match_flag; - int remove_flag = FALSE; - int i,j; - - if (remove_names == NULL) { - return(FALSE); - } - for (i = 0; remove_names[i] != NULL; i++) { - match_flag = FALSE; - if (exclude_names != NULL) { - for (j = 0; exclude_names[j] != 0; j++) { - if (strcmp(remove_names[i], exclude_names[j]) == 0) { - match_flag = TRUE; - break; - } - } - } - if (!match_flag) { - if (lstat(remove_names[i], &path_stat) < 0) { - continue; - } - if (S_ISDIR(path_stat.st_mode)) { - if (rmdir(remove_names[i]) != -1) { - remove_flag = TRUE; - } - } else { - if (unlink(remove_names[i]) != -1) { - remove_flag = TRUE; - } - } - } - } - return(remove_flag); -} - -int run_package_script(const char *package_name, const char *script_type) -{ - struct stat path_stat; - char *script_path; - int result; - - script_path = xmalloc(strlen(package_name) + strlen(script_type) + 21); - sprintf(script_path, "/var/lib/dpkg/info/%s.%s", package_name, script_type); - - /* If the file doesnt exist is isnt a fatal */ - if (lstat(script_path, &path_stat) < 0) { - result = EXIT_SUCCESS; - } else { - result = system(script_path); - } - free(script_path); - return(result); -} - -void all_control_list(char **remove_files, const char *package_name) -{ - const char *all_extensions[11] = {"preinst", "postinst", "prerm", "postrm", - "list", "md5sums", "shlibs", "conffiles", "config", "templates", NULL }; - int i; - - /* Create a list of all /var/lib/dpkg/info/ files */ - for(i = 0; i < 10; i++) { - remove_files[i] = xmalloc(strlen(package_name) + strlen(all_extensions[i]) + 21); - sprintf(remove_files[i], "/var/lib/dpkg/info/%s.%s", package_name, all_extensions[i]); - } - remove_files[10] = NULL; -} - - -/* This function lists information on the installed packages. It loops through - * the status_hashtable to retrieve the info. This results in smaller code than - * scanning the status file. The resulting list, however, is unsorted. - */ -void list_packages(void) -{ - int i; - - printf(" Name Version\n"); - printf("+++-==============-==============\n"); - - /* go through status hash, dereference package hash and finally strings */ - for (i=0; istatus]; - name_str = name_hashtable[package_hashtable[status_hashtable[i]->package]->name]; - vers_str = name_hashtable[package_hashtable[status_hashtable[i]->package]->version]; - - /* get abbreviation for status field 1 */ - s1 = stat_str[0] == 'i' ? 'i' : 'r'; - - /* get abbreviation for status field 2 */ - for (j=0, spccnt=0; stat_str[j] && spccnt<2; j++) { - if (stat_str[j] == ' ') spccnt++; - } - s2 = stat_str[j]; - - /* print out the line formatted like Debian dpkg */ - printf("%c%c %-14s %s\n", s1, s2, name_str, vers_str); - } - } -} - -void remove_package(const unsigned int package_num) -{ - const char *package_name = name_hashtable[package_hashtable[package_num]->name]; - const unsigned int status_num = search_status_hashtable(package_name); - const int package_name_length = strlen(package_name); - char **remove_files; - char **exclude_files; - char list_name[package_name_length + 25]; - char conffile_name[package_name_length + 30]; - int return_value; - - printf("Removing %s ...\n", package_name); - - /* run prerm script */ - return_value = run_package_script(package_name, "prerm"); - if (return_value == -1) { - error_msg_and_die("script failed, prerm failure"); - } - - /* Create a list of files to remove, and a seperate list of those to keep */ - sprintf(list_name, "/var/lib/dpkg/info/%s.list", package_name); - remove_files = create_list(list_name); - - sprintf(conffile_name, "/var/lib/dpkg/info/%s.conffiles", package_name); - exclude_files = create_list(conffile_name); - - /* Some directories cant be removed straight away, so do multiple passes */ - while (remove_file_array(remove_files, exclude_files) == TRUE); - - /* Create a list of all /var/lib/dpkg/info/ files */ - remove_files = xmalloc(11); - all_control_list(remove_files, package_name); - - /* Create a list of files in /var/lib/dpkg/info/.* to keep */ - exclude_files = xmalloc(sizeof(char*) * 3); - exclude_files[0] = xstrdup(conffile_name); - exclude_files[1] = xmalloc(package_name_length + 27); - sprintf(exclude_files[1], "/var/lib/dpkg/info/%s.postrm", package_name); - exclude_files[2] = NULL; - - remove_file_array(remove_files, exclude_files); - - /* rename .conffile to .list */ - rename(conffile_name, list_name); - - /* Change package status */ - set_status(status_num, "deinstall", 1); - set_status(status_num, "config-files", 3); -} - -void purge_package(const unsigned int package_num) -{ - const char *package_name = name_hashtable[package_hashtable[package_num]->name]; - const unsigned int status_num = search_status_hashtable(package_name); - char **remove_files; - char **exclude_files; - char list_name[strlen(package_name) + 25]; - - /* run prerm script */ - if (run_package_script(package_name, "prerm") != 0) { - error_msg_and_die("script failed, prerm failure"); - } - - /* Create a list of files to remove */ - sprintf(list_name, "/var/lib/dpkg/info/%s.list", package_name); - remove_files = create_list(list_name); - - exclude_files = xmalloc(1); - exclude_files[0] = NULL; - - /* Some directories cant be removed straight away, so do multiple passes */ - while (remove_file_array(remove_files, exclude_files) == TRUE); - - /* Create a list of all /var/lib/dpkg/info/ files */ - remove_files = xmalloc(11); - all_control_list(remove_files, package_name); - remove_file_array(remove_files, exclude_files); - - /* run postrm script */ - if (run_package_script(package_name, "postrm") == -1) { - error_msg_and_die("postrm fialure.. set status to what?"); - } - - /* Change package status */ - set_status(status_num, "purge", 1); - set_status(status_num, "not-installed", 3); -} - -void unpack_package(deb_file_t *deb_file) -{ - const char *package_name = name_hashtable[package_hashtable[deb_file->package]->name]; - const unsigned int status_num = search_status_hashtable(package_name); - const unsigned int status_package_num = status_hashtable[status_num]->package; - - FILE *out_stream; - char *info_prefix; - - /* If existing version, remove it first */ - if (strcmp(name_hashtable[get_status(status_num, 3)], "installed") == 0) { - /* Package is already installed, remove old version first */ - printf("Preparing to replace %s %s (using %s) ...\n", package_name, - name_hashtable[package_hashtable[status_package_num]->version], - deb_file->filename); - remove_package(status_package_num); - } else { - printf("Unpacking %s (from %s) ...\n", package_name, deb_file->filename); - } - - /* Extract control.tar.gz to /var/lib/dpkg/info/.filename */ - info_prefix = (char *) xmalloc(sizeof(package_name) + 20 + 4 + 1); - sprintf(info_prefix, "/var/lib/dpkg/info/%s.", package_name); - deb_extract(deb_file->filename, stdout, (extract_quiet | extract_control_tar_gz | extract_all_to_fs | extract_unconditional), info_prefix, NULL); - - /* Run the preinst prior to extracting */ - if (run_package_script(package_name, "preinst") != 0) { - /* when preinst returns exit code != 0 then quit installation process */ - error_msg_and_die("subprocess pre-installation script returned error."); - } - - /* Extract data.tar.gz to the root directory */ - deb_extract(deb_file->filename, stdout, (extract_quiet | extract_data_tar_gz | extract_all_to_fs | extract_unconditional), "/", NULL); - - /* Create the list file */ - strcat(info_prefix, "list"); - out_stream = xfopen(info_prefix, "w"); - deb_extract(deb_file->filename, out_stream, (extract_quiet | extract_data_tar_gz | extract_list), "/", NULL); - fclose(out_stream); - - /* change status */ - set_status(status_num, "install", 1); - set_status(status_num, "unpacked", 3); - - free(info_prefix); -} - -void configure_package(deb_file_t *deb_file) -{ - const char *package_name = name_hashtable[package_hashtable[deb_file->package]->name]; - const char *package_version = name_hashtable[package_hashtable[deb_file->package]->version]; - const int status_num = search_status_hashtable(package_name); - - printf("Setting up %s (%s)\n", package_name, package_version); - - /* Run the postinst script */ - if (run_package_script(package_name, "postinst") != 0) { - /* TODO: handle failure gracefully */ - error_msg_and_die("postrm failure.. set status to what?"); - } - /* Change status to reflect success */ - set_status(status_num, "install", 1); - set_status(status_num, "installed", 3); -} - -extern int dpkg_main(int argc, char **argv) -{ - deb_file_t **deb_file = NULL; - status_node_t *status_node; - char opt = 0; - int package_num; - int dpkg_opt = 0; - int deb_count = 0; - int state_status; - int status_num; - int i; - - while ((opt = getopt(argc, argv, "CF:ilPru")) != -1) { - switch (opt) { - case 'C': // equivalent to --configure in official dpkg - dpkg_opt |= dpkg_opt_configure; - dpkg_opt |= dpkg_opt_package_name; - break; - case 'F': // equivalent to --force in official dpkg - if (strcmp(optarg, "depends") == 0) { - dpkg_opt |= dpkg_opt_force_ignore_depends; - } - case 'i': - dpkg_opt |= dpkg_opt_install; - dpkg_opt |= dpkg_opt_filename; - break; - case 'l': - dpkg_opt |= dpkg_opt_list_installed; - break; - case 'P': - dpkg_opt |= dpkg_opt_purge; - dpkg_opt |= dpkg_opt_package_name; - break; - case 'r': - dpkg_opt |= dpkg_opt_remove; - dpkg_opt |= dpkg_opt_package_name; - break; - case 'u': /* Equivalent to --unpack in official dpkg */ - dpkg_opt |= dpkg_opt_unpack; - dpkg_opt |= dpkg_opt_filename; - break; - default: - show_usage(); - } - } - /* check for non-otion argument if expected */ - if ((dpkg_opt == 0) || ((argc == optind) && !(dpkg_opt && dpkg_opt_list_installed))) { - show_usage(); - } - -/* puts("(Reading database ... xxxxx files and directories installed.)"); */ - index_status_file("/var/lib/dpkg/status"); - - /* if the list action was given print the installed packages and exit */ - if (dpkg_opt & dpkg_opt_list_installed) { - list_packages(); - return(EXIT_SUCCESS); - } - - /* Read arguments and store relevant info in structs */ - deb_file = xmalloc(sizeof(deb_file_t)); - while (optind < argc) { - deb_file[deb_count] = (deb_file_t *) xmalloc(sizeof(deb_file_t)); - if (dpkg_opt & dpkg_opt_filename) { - deb_file[deb_count]->filename = xstrdup(argv[optind]); - deb_file[deb_count]->control_file = deb_extract(argv[optind], stdout, (extract_control_tar_gz | extract_one_to_buffer), NULL, "./control"); - if (deb_file[deb_count]->control_file == NULL) { - error_msg_and_die("Couldnt extract control file"); - } - package_num = fill_package_struct(deb_file[deb_count]->control_file); - - if (package_num == -1) { - error_msg("Invalid control file in %s", argv[optind]); - continue; - } - deb_file[deb_count]->package = (unsigned int) package_num; - /* Add the package to the status hashtable */ - if ((dpkg_opt & dpkg_opt_unpack) || (dpkg_opt & dpkg_opt_install)) { - status_node = (status_node_t *) xmalloc(sizeof(status_node_t)); - status_node->package = deb_file[deb_count]->package; - - /* Try and find a currently installed version of this package */ - status_num = search_status_hashtable(name_hashtable[package_hashtable[deb_file[deb_count]->package]->name]); - /* If no previous entry was found initialise a new entry */ - if ((status_hashtable[status_num] == NULL) || - (status_hashtable[status_num]->status == 0)) { - /* reinstreq isnt changed to "ok" until the package control info - * is written to the status file*/ - status_node->status = search_name_hashtable("install reinstreq not-installed"); - status_hashtable[status_num] = status_node; - } else { - status_hashtable[status_num]->status = search_name_hashtable("install reinstreq installed"); - } - } - } - else if (dpkg_opt & dpkg_opt_package_name) { - deb_file[deb_count]->filename = NULL; - deb_file[deb_count]->control_file = NULL; - deb_file[deb_count]->package = search_package_hashtable( - search_name_hashtable(argv[optind]), - search_name_hashtable("ANY"), VER_ANY); - if (package_hashtable[deb_file[deb_count]->package] == NULL) { - error_msg_and_die("Package %s is uninstalled or unknown\n", argv[optind]); - } - state_status = get_status(search_status_hashtable(name_hashtable[package_hashtable[deb_file[deb_count]->package]->name]), 3); - - /* check package status is "installed" */ - if (dpkg_opt & dpkg_opt_remove) { - if ((strcmp(name_hashtable[state_status], "not-installed") == 0) || - (strcmp(name_hashtable[state_status], "config-files") == 0)) { - error_msg_and_die("%s is already removed.", name_hashtable[package_hashtable[deb_file[deb_count]->package]->name]); - } - } - else if (dpkg_opt & dpkg_opt_purge) { - /* if package status is "conf-files" then its ok */ - if (strcmp(name_hashtable[state_status], "not-installed") == 0) { - error_msg_and_die("%s is already purged.", name_hashtable[package_hashtable[deb_file[deb_count]->package]->name]); - } - } - } - deb_count++; - optind++; - } - deb_file[deb_count] = NULL; - - /* Check that the deb file arguments are installable */ - /* TODO: check dependencies before removing */ - if ((dpkg_opt & dpkg_opt_force_ignore_depends) != dpkg_opt_force_ignore_depends) { - if (!check_deps(deb_file, 0, deb_count)) { - error_msg_and_die("Dependency check failed"); - } - } - - for (i = 0; i < deb_count; i++) { - /* Remove or purge packages */ - if (dpkg_opt & dpkg_opt_remove) { - remove_package(deb_file[i]->package); - } - else if (dpkg_opt & dpkg_opt_purge) { - purge_package(deb_file[i]->package); - } - else if (dpkg_opt & dpkg_opt_unpack) { - unpack_package(deb_file[i]); - } - else if (dpkg_opt & dpkg_opt_install) { - unpack_package(deb_file[i]); - configure_package(deb_file[i]); - } - else if (dpkg_opt & dpkg_opt_configure) { - configure_package(deb_file[i]); - } - } - - write_status_file(deb_file); - - for (i = 0; i < deb_count; i++) { - free(deb_file[i]->control_file); - free(deb_file[i]->filename); - free(deb_file[i]); - } - free(deb_file); - - for (i = 0; i < NAME_HASH_PRIME; i++) { - if (name_hashtable[i] != NULL) { - free(name_hashtable[i]); - } - } - - for (i = 0; i < PACKAGE_HASH_PRIME; i++) { - free_package(package_hashtable[i]); - } - - for (i = 0; i < STATUS_HASH_PRIME; i++) { - if (status_hashtable[i] != NULL) { - free(status_hashtable[i]); - } - } - - return(EXIT_SUCCESS); -} - diff --git a/dpkg_deb.c b/dpkg_deb.c deleted file mode 100644 index a933c6948..000000000 --- a/dpkg_deb.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include -#include -#include -#include "busybox.h" - -extern int dpkg_deb_main(int argc, char **argv) -{ - char *prefix = NULL; - char *filename = NULL; - char *output_buffer = NULL; - int opt = 0; - int arg_type = 0; - int deb_extract_funct = extract_create_leading_dirs | extract_unconditional; - - const int arg_type_prefix = 1; - const int arg_type_field = 2; - const int arg_type_filename = 4; -// const int arg_type_un_ar_gz = 8; - - while ((opt = getopt(argc, argv, "ceftXxI")) != -1) { - switch (opt) { - case 'c': - deb_extract_funct |= extract_data_tar_gz; - deb_extract_funct |= extract_verbose_list; - break; - case 'e': - arg_type = arg_type_prefix; - deb_extract_funct |= extract_control_tar_gz; - deb_extract_funct |= extract_all_to_fs; - break; - case 'f': - arg_type = arg_type_field; - deb_extract_funct |= extract_control_tar_gz; - deb_extract_funct |= extract_one_to_buffer; - filename = xstrdup("./control"); - break; - case 't': /* --fsys-tarfile, i just made up this short name */ - /* Integrate the functionality needed with some code from ar.c */ - error_msg_and_die("Option disabled"); -// arg_type = arg_type_un_ar_gz; - break; - case 'X': - arg_type = arg_type_prefix; - deb_extract_funct |= extract_data_tar_gz; - deb_extract_funct |= extract_all_to_fs; - deb_extract_funct |= extract_list; - case 'x': - arg_type = arg_type_prefix; - deb_extract_funct |= extract_data_tar_gz; - deb_extract_funct |= extract_all_to_fs; - break; - case 'I': - arg_type = arg_type_filename; - deb_extract_funct |= extract_control_tar_gz; - deb_extract_funct |= extract_one_to_buffer; - break; - default: - show_usage(); - } - } - - if (optind == argc) { - show_usage(); - } - - /* Workout where to extract the files */ - if (arg_type == arg_type_prefix) { - /* argument is a dir name */ - if ((optind + 1) == argc ) { - prefix = xstrdup("./DEBIAN/"); - } else { - prefix = (char *) xmalloc(strlen(argv[optind + 1]) + 2); - strcpy(prefix, argv[optind + 1]); - /* Make sure the directory has a trailing '/' */ - if (last_char_is(prefix, '/') == NULL) { - strcat(prefix, "/"); - } - } - mkdir(prefix, 0777); - } - - if (arg_type == arg_type_filename) { - if ((optind + 1) != argc) { - filename = xstrdup(argv[optind + 1]); - } else { - error_msg_and_die("-I currently requires a filename to be specified"); - } - } - - output_buffer = deb_extract(argv[optind], stdout, deb_extract_funct, prefix, filename); - - if ((arg_type == arg_type_filename) && (output_buffer != NULL)) { - puts(output_buffer); - } - else if (arg_type == arg_type_field) { - char *field = NULL; - char *name; - char *value; - int field_start = 0; - - while (1) { - field_start += read_package_field(&output_buffer[field_start], &name, &value); - if (name == NULL) { - break; - } - if (strcmp(name, argv[optind + 1]) == 0) { - puts(value); - } - free(field); - } - } - - return(EXIT_SUCCESS); -} diff --git a/du.c b/du.c deleted file mode 100644 index fb649aee5..000000000 --- a/du.c +++ /dev/null @@ -1,257 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini du implementation for busybox - * - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by John Beppu - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" - - -#ifdef BB_FEATURE_HUMAN_READABLE -static unsigned long disp_hr = KILOBYTE; -#endif - -typedef void (Display) (long, char *); - -static int du_depth = 0; -static int count_hardlinks = 0; - -static Display *print; - -static void print_normal(long size, char *filename) -{ -#ifdef BB_FEATURE_HUMAN_READABLE - printf("%s\t%s\n", make_human_readable_str(size<<10, 1, disp_hr), filename); -#else - printf("%ld\t%s\n", size, filename); -#endif -} - -static void print_summary(long size, char *filename) -{ - if (du_depth == 1) { - print_normal(size, filename); - } -} - -#define HASH_SIZE 311 /* Should be prime */ -#define hash_inode(i) ((i) % HASH_SIZE) - -typedef struct ino_dev_hash_bucket_struct { - struct ino_dev_hash_bucket_struct *next; - ino_t ino; - dev_t dev; - char name[1]; -} ino_dev_hashtable_bucket_t; - -static ino_dev_hashtable_bucket_t *ino_dev_hashtable[HASH_SIZE]; - -/* - * Return 1 if statbuf->st_ino && statbuf->st_dev are recorded in - * `ino_dev_hashtable', else return 0 - * - * If NAME is a non-NULL pointer to a character pointer, and there is - * a match, then set *NAME to the value of the name slot in that - * bucket. - */ -static int is_in_ino_dev_hashtable(const struct stat *statbuf, char **name) -{ - ino_dev_hashtable_bucket_t *bucket; - - bucket = ino_dev_hashtable[hash_inode(statbuf->st_ino)]; - while (bucket != NULL) { - if ((bucket->ino == statbuf->st_ino) && - (bucket->dev == statbuf->st_dev)) - { - if (name) *name = bucket->name; - return 1; - } - bucket = bucket->next; - } - return 0; -} - -/* Add statbuf to statbuf hash table */ -static void add_to_ino_dev_hashtable(const struct stat *statbuf, const char *name) -{ - int i; - size_t s; - ino_dev_hashtable_bucket_t *bucket; - - i = hash_inode(statbuf->st_ino); - s = name ? strlen(name) : 0; - bucket = xmalloc(sizeof(ino_dev_hashtable_bucket_t) + s); - bucket->ino = statbuf->st_ino; - bucket->dev = statbuf->st_dev; - if (name) - strcpy(bucket->name, name); - else - bucket->name[0] = '\0'; - bucket->next = ino_dev_hashtable[i]; - ino_dev_hashtable[i] = bucket; -} - -/* Clear statbuf hash table */ -static void reset_ino_dev_hashtable(void) -{ - int i; - ino_dev_hashtable_bucket_t *bucket; - - for (i = 0; i < HASH_SIZE; i++) { - while (ino_dev_hashtable[i] != NULL) { - bucket = ino_dev_hashtable[i]->next; - free(ino_dev_hashtable[i]); - ino_dev_hashtable[i] = bucket; - } - } -} - -/* tiny recursive du */ -static long du(char *filename) -{ - struct stat statbuf; - long sum; - - if ((lstat(filename, &statbuf)) != 0) { - perror_msg("%s", filename); - return 0; - } - - du_depth++; - sum = (statbuf.st_blocks >> 1); - - /* Don't add in stuff pointed to by symbolic links */ - if (S_ISLNK(statbuf.st_mode)) { - sum = 0L; - if (du_depth == 1) { - } - } - if (S_ISDIR(statbuf.st_mode)) { - DIR *dir; - struct dirent *entry; - char *newfile; - - dir = opendir(filename); - if (!dir) { - du_depth--; - return 0; - } - - newfile = last_char_is(filename, '/'); - if (newfile) - *newfile = '\0'; - - while ((entry = readdir(dir))) { - char *name = entry->d_name; - - if ((strcmp(name, "..") == 0) - || (strcmp(name, ".") == 0)) { - continue; - } - newfile = concat_path_file(filename, name); - sum += du(newfile); - free(newfile); - } - closedir(dir); - print(sum, filename); - } - else if (statbuf.st_nlink > 1 && !count_hardlinks) { - /* Add files with hard links only once */ - if (is_in_ino_dev_hashtable(&statbuf, NULL)) { - sum = 0L; - if (du_depth == 1) - print(sum, filename); - } - else { - add_to_ino_dev_hashtable(&statbuf, NULL); - } - } - du_depth--; - return sum; -} - -int du_main(int argc, char **argv) -{ - int status = EXIT_SUCCESS; - int i; - int c; - - /* default behaviour */ - print = print_normal; - - /* parse argv[] */ - while ((c = getopt(argc, argv, "sl" -#ifdef BB_FEATURE_HUMAN_READABLE -"hm" -#endif -"k")) != EOF) { - switch (c) { - case 's': - print = print_summary; - break; - case 'l': - count_hardlinks = 1; - break; -#ifdef BB_FEATURE_HUMAN_READABLE - case 'h': disp_hr = 0; break; - case 'm': disp_hr = MEGABYTE; break; -#endif - case 'k': break; - default: - show_usage(); - } - } - - /* go through remaining args (if any) */ - if (optind >= argc) { - if (du(".") == 0) - status = EXIT_FAILURE; - } else { - long sum; - - for (i=optind; i < argc; i++) { - sum = du(argv[i]); - if(is_directory(argv[i], FALSE, NULL)==FALSE) { - print_normal(sum, argv[i]); - } - reset_ino_dev_hashtable(); - } - } - - return status; -} - -/* $Id: du.c,v 1.50 2001/06/30 17:54:20 andersen Exp $ */ -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ diff --git a/dumpkmap.c b/dumpkmap.c deleted file mode 100644 index 22652a5e2..000000000 --- a/dumpkmap.c +++ /dev/null @@ -1,95 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini dumpkmap implementation for busybox - * - * Copyright (C) Arne Bernin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" - -/* From */ -struct kbentry { - unsigned char kb_table; - unsigned char kb_index; - unsigned short kb_value; -}; -static const int KDGKBENT = 0x4B46; /* gets one entry in translation table */ - -/* From */ -static const int NR_KEYS = 128; -static const int MAX_NR_KEYMAPS = 256; - -int dumpkmap_main(int argc, char **argv) -{ - struct kbentry ke; - int i, j, fd; - char flags[MAX_NR_KEYMAPS], magic[] = "bkeymap"; - - if (argc>=2 && *argv[1]=='-') { - show_usage(); - } - - fd = open(CURRENT_VC, O_RDWR); - if (fd < 0) { - perror_msg("Error opening " CURRENT_VC); - return EXIT_FAILURE; - } - - write(1, magic, 7); - - for (i=0; i < MAX_NR_KEYMAPS; i++) flags[i]=0; - flags[0]=1; - flags[1]=1; - flags[2]=1; - flags[4]=1; - flags[5]=1; - flags[6]=1; - flags[8]=1; - flags[9]=1; - flags[10]=1; - flags[12]=1; - - /* dump flags */ - for (i=0; i < MAX_NR_KEYMAPS; i++) write(1,&flags[i],1); - - for (i = 0; i < MAX_NR_KEYMAPS; i++) { - if (flags[i] == 1) { - for (j = 0; j < NR_KEYS; j++) { - ke.kb_index = j; - ke.kb_table = i; - if (ioctl(fd, KDGKBENT, &ke) < 0) { - - error_msg("ioctl returned: %s, %s, %s, %xqq", strerror(errno),(char *)&ke.kb_index,(char *)&ke.kb_table,(int)&ke.kb_value); - } - else { - write(1,(void*)&ke.kb_value,2); - } - - } - } - } - close(fd); - return EXIT_SUCCESS; -} diff --git a/dutmp.c b/dutmp.c deleted file mode 100644 index df7f64d30..000000000 --- a/dutmp.c +++ /dev/null @@ -1,64 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * public domain -- Dave 'Kill a Cop' Cinege - * - * dutmp - * Takes utmp formated file on stdin and dumps it's contents - * out in colon delimited fields. Easy to 'cut' for shell based - * versions of 'who', 'last', etc. IP Addr is output in hex, - * little endian on x86. - * - * Modified to support all sorts of libcs by - * Erik Andersen - */ - -#include -#include - -#include -#include -#include -#include -#include "busybox.h" - -extern int dutmp_main(int argc, char **argv) -{ - - int file; - struct utmp ut; - - if (argc<2) { - file = fileno(stdin); - } else if (*argv[1] == '-' ) { - show_usage(); - } else { - file = open(argv[1], O_RDONLY); - if (file < 0) { - perror_msg_and_die(io_error, argv[1]); - } - } - -/* Kludge around the fact that the binary format for utmp has changed. */ -#if __GNU_LIBRARY__ < 5 || defined __UCLIBC__ - /* Linux libc5 */ - while (read(file, (void*)&ut, sizeof(struct utmp))) { - printf("%d|%d|%s|%s|%s|%s|%s|%lx\n", - ut.ut_type, ut.ut_pid, ut.ut_line, - ut.ut_id, ut.ut_user, ut.ut_host, - ctime(&(ut.ut_time)), - (long)ut.ut_addr); - } -#else - /* Glibc, uClibc, etc. */ - while (read(file, (void*)&ut, sizeof(struct utmp))) { - printf("%d|%d|%s|%s|%s|%s|%d|%d|%ld|%ld|%ld|%x\n", - ut.ut_type, ut.ut_pid, ut.ut_line, - ut.ut_id, ut.ut_user, ut.ut_host, - ut.ut_exit.e_termination, ut.ut_exit.e_exit, - ut.ut_session, - ut.ut_tv.tv_sec, ut.ut_tv.tv_usec, - ut.ut_addr); - } -#endif - return EXIT_SUCCESS; -} diff --git a/echo.c b/echo.c deleted file mode 100644 index 31c031528..000000000 --- a/echo.c +++ /dev/null @@ -1,152 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * echo implementation for busybox - * - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Original copyright notice is retained at the end of this file. - */ - -#include -#include -#include -#include "busybox.h" - -extern int -echo_main(int argc, char** argv) -{ - int nflag = 0; - int eflag = 0; - - /* Skip argv[0]. */ - argc--; - argv++; - - while (argc > 0 && *argv[0] == '-') - { - register char *temp; - register int ix; - - /* - * If it appears that we are handling options, then make sure - * that all of the options specified are actually valid. - * Otherwise, the string should just be echoed. - */ - temp = argv[0] + 1; - - for (ix = 0; temp[ix]; ix++) - { - if (strrchr("neE", temp[ix]) == 0) - goto just_echo; - } - - if (!*temp) - goto just_echo; - - /* - * All of the options in temp are valid options to echo. - * Handle them. - */ - while (*temp) - { - if (*temp == 'n') - nflag = 1; - else if (*temp == 'e') - eflag = 1; - else if (*temp == 'E') - eflag = 0; - else - goto just_echo; - - temp++; - } - argc--; - argv++; - } - -just_echo: - while (argc > 0) { - const char *arg = argv[0]; - register int c; - - while ((c = *arg++)) { - - /* Check for escape sequence. */ - if (c == '\\' && eflag && *arg) { - if (*arg == 'c') { - /* '\c' means cancel newline. */ - nflag = 1; - arg++; - continue; - } else { - c = process_escape_sequence(&arg); - } - } - - putchar(c); - } - argc--; - argv++; - if (argc > 0) - putchar(' '); - } - if (!nflag) - putchar('\n'); - fflush(stdout); - - return EXIT_SUCCESS; -} - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. - * - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)echo.c 8.1 (Berkeley) 5/31/93 - */ diff --git a/editors/Makefile b/editors/Makefile new file mode 100644 index 000000000..7d8d96582 --- /dev/null +++ b/editors/Makefile @@ -0,0 +1,36 @@ +# Makefile for busybox +# +# Copyright (C) 1999,2000,2001 by Erik Andersen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +TOPDIR :=.. +L_TARGET := editors.a + +obj-y := +obj-n := +obj- := + +obj-$(CONFIG_SED) += sed.o +obj-$(CONFIG_VI) += vi.o + + +# Hand off to toplevel Rules.mak +include $(TOPDIR)/Rules.mak + +clean: + rm -f $(L_TARGET) *.o core + diff --git a/editors/config.in b/editors/config.in new file mode 100644 index 000000000..6c1d6cebe --- /dev/null +++ b/editors/config.in @@ -0,0 +1,12 @@ +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +mainmenu_option next_comment +comment 'Editors' + +bool 'sed' CONFIG_SED +bool 'vi' CONFIG_VI +endmenu + diff --git a/editors/sed.c b/editors/sed.c index 709fb13a8..10cab7d56 100644 --- a/editors/sed.c +++ b/editors/sed.c @@ -1,8 +1,8 @@ /* * sed.c - very minimalist version of sed * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Mark Whitley , + * Copyright (C) 1999,2000,2001 by Lineo, inc. and Mark Whitley + * Copyright (C) 1999,2000,2001 by Mark Whitley * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -104,7 +104,7 @@ static int ncmds = 0; /* number of sed commands */ /*static char *cur_file = NULL;*/ /* file currently being processed XXX: do I need this? */ -#ifdef BB_FEATURE_CLEAN_UP +#ifdef CONFIG_FEATURE_CLEAN_UP static void destroy_cmd_strs() { if (sed_cmds == NULL) @@ -791,7 +791,7 @@ extern int sed_main(int argc, char **argv) { int opt; -#ifdef BB_FEATURE_CLEAN_UP +#ifdef CONFIG_FEATURE_CLEAN_UP /* destroy command strings on exit */ if (atexit(destroy_cmd_strs) == -1) perror_msg_and_die("atexit"); diff --git a/editors/vi.c b/editors/vi.c index 8d7506d0f..ddc2edc75 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -19,13 +19,13 @@ */ static const char vi_Version[] = - "$Id: vi.c,v 1.15 2001/08/02 05:26:41 andersen Exp $"; + "$Id: vi.c,v 1.16 2001/10/24 04:59:23 andersen Exp $"; /* * To compile for standalone use: * gcc -Wall -Os -s -DSTANDALONE -o vi vi.c * or - * gcc -Wall -Os -s -DSTANDALONE -DBB_FEATURE_VI_CRASHME -o vi vi.c # include testing features + * gcc -Wall -Os -s -DSTANDALONE -DCONFIG_FEATURE_VI_CRASHME -o vi vi.c # include testing features * strip vi */ @@ -48,21 +48,21 @@ static const char vi_Version[] = //---- Feature -------------- Bytes to immplement #ifdef STANDALONE #define vi_main main -#define BB_FEATURE_VI_COLON // 4288 -#define BB_FEATURE_VI_YANKMARK // 1408 -#define BB_FEATURE_VI_SEARCH // 1088 -#define BB_FEATURE_VI_USE_SIGNALS // 1056 -#define BB_FEATURE_VI_DOT_CMD // 576 -#define BB_FEATURE_VI_READONLY // 128 -#define BB_FEATURE_VI_SETOPTS // 576 -#define BB_FEATURE_VI_SET // 224 -#define BB_FEATURE_VI_WIN_RESIZE // 256 WIN_RESIZE +#define CONFIG_FEATURE_VI_COLON // 4288 +#define CONFIG_FEATURE_VI_YANKMARK // 1408 +#define CONFIG_FEATURE_VI_SEARCH // 1088 +#define CONFIG_FEATURE_VI_USE_SIGNALS // 1056 +#define CONFIG_FEATURE_VI_DOT_CMD // 576 +#define CONFIG_FEATURE_VI_READONLY // 128 +#define CONFIG_FEATURE_VI_SETOPTS // 576 +#define CONFIG_FEATURE_VI_SET // 224 +#define CONFIG_FEATURE_VI_WIN_RESIZE // 256 WIN_RESIZE // To test editor using CRASHME: // vi -C filename // To stop testing, wait until all to text[] is deleted, or // Ctrl-Z and kill -9 %1 // while in the editor Ctrl-T will toggle the crashme function on and off. -//#define BB_FEATURE_VI_CRASHME // randomly pick commands to execute +//#define CONFIG_FEATURE_VI_CRASHME // randomly pick commands to execute #endif /* STANDALONE */ #include @@ -161,40 +161,40 @@ static Byte *dot; // where all the action takes place static int tabstop; static struct termios term_orig, term_vi; // remember what the cooked mode was -#ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR +#ifdef CONFIG_FEATURE_VI_OPTIMIZE_CURSOR static int last_row; // where the cursor was last moved to -#endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */ -#ifdef BB_FEATURE_VI_USE_SIGNALS +#endif /* CONFIG_FEATURE_VI_OPTIMIZE_CURSOR */ +#ifdef CONFIG_FEATURE_VI_USE_SIGNALS static jmp_buf restart; // catch_sig() -#endif /* BB_FEATURE_VI_USE_SIGNALS */ -#ifdef BB_FEATURE_VI_WIN_RESIZE +#endif /* CONFIG_FEATURE_VI_USE_SIGNALS */ +#ifdef CONFIG_FEATURE_VI_WIN_RESIZE static struct winsize winsize; // remember the window size -#endif /* BB_FEATURE_VI_WIN_RESIZE */ -#ifdef BB_FEATURE_VI_DOT_CMD +#endif /* CONFIG_FEATURE_VI_WIN_RESIZE */ +#ifdef CONFIG_FEATURE_VI_DOT_CMD static int adding2q; // are we currently adding user input to q static Byte *last_modifying_cmd; // last modifying cmd for "." static Byte *ioq, *ioq_start; // pointer to string for get_one_char to "read" -#endif /* BB_FEATURE_VI_DOT_CMD */ -#if defined(BB_FEATURE_VI_DOT_CMD) || defined(BB_FEATURE_VI_YANKMARK) +#endif /* CONFIG_FEATURE_VI_DOT_CMD */ +#if defined(CONFIG_FEATURE_VI_DOT_CMD) || defined(CONFIG_FEATURE_VI_YANKMARK) static Byte *modifying_cmds; // cmds that modify text[] -#endif /* BB_FEATURE_VI_DOT_CMD || BB_FEATURE_VI_YANKMARK */ -#ifdef BB_FEATURE_VI_READONLY +#endif /* CONFIG_FEATURE_VI_DOT_CMD || CONFIG_FEATURE_VI_YANKMARK */ +#ifdef CONFIG_FEATURE_VI_READONLY static int vi_readonly, readonly; -#endif /* BB_FEATURE_VI_READONLY */ -#ifdef BB_FEATURE_VI_SETOPTS +#endif /* CONFIG_FEATURE_VI_READONLY */ +#ifdef CONFIG_FEATURE_VI_SETOPTS static int autoindent; static int showmatch; static int ignorecase; -#endif /* BB_FEATURE_VI_SETOPTS */ -#ifdef BB_FEATURE_VI_YANKMARK +#endif /* CONFIG_FEATURE_VI_SETOPTS */ +#ifdef CONFIG_FEATURE_VI_YANKMARK static Byte *reg[28]; // named register a-z, "D", and "U" 0-25,26,27 static int YDreg, Ureg; // default delete register and orig line for "U" static Byte *mark[28]; // user marks points somewhere in text[]- a-z and previous context '' static Byte *context_start, *context_end; -#endif /* BB_FEATURE_VI_YANKMARK */ -#ifdef BB_FEATURE_VI_SEARCH +#endif /* CONFIG_FEATURE_VI_YANKMARK */ +#ifdef CONFIG_FEATURE_VI_SEARCH static Byte *last_search_pattern; // last pattern from a '/' or '?' search -#endif /* BB_FEATURE_VI_SEARCH */ +#endif /* CONFIG_FEATURE_VI_SEARCH */ static void edit_file(Byte *); // edit one file @@ -259,59 +259,59 @@ static void redraw(int); // force a full screen refresh static void format_line(Byte*, Byte*, int); static void refresh(int); // update the terminal from screen[] -#ifdef BB_FEATURE_VI_SEARCH +#ifdef CONFIG_FEATURE_VI_SEARCH static Byte *char_search(Byte *, Byte *, int, int); // search for pattern starting at p static int mycmp(Byte *, Byte *, int); // string cmp based in "ignorecase" -#endif /* BB_FEATURE_VI_SEARCH */ -#ifdef BB_FEATURE_VI_COLON +#endif /* CONFIG_FEATURE_VI_SEARCH */ +#ifdef CONFIG_FEATURE_VI_COLON static void Hit_Return(void); static Byte *get_one_address(Byte *, int *); // get colon addr, if present static Byte *get_address(Byte *, int *, int *); // get two colon addrs, if present static void colon(Byte *); // execute the "colon" mode cmds -#endif /* BB_FEATURE_VI_COLON */ +#endif /* CONFIG_FEATURE_VI_COLON */ static Byte *get_input_line(Byte *); // get input line- use "status line" -#ifdef BB_FEATURE_VI_USE_SIGNALS +#ifdef CONFIG_FEATURE_VI_USE_SIGNALS static void winch_sig(int); // catch window size changes static void suspend_sig(int); // catch ctrl-Z static void alarm_sig(int); // catch alarm time-outs static void catch_sig(int); // catch ctrl-C static void core_sig(int); // catch a core dump signal -#endif /* BB_FEATURE_VI_USE_SIGNALS */ -#ifdef BB_FEATURE_VI_DOT_CMD +#endif /* CONFIG_FEATURE_VI_USE_SIGNALS */ +#ifdef CONFIG_FEATURE_VI_DOT_CMD static void start_new_cmd_q(Byte); // new queue for command static void end_cmd_q(); // stop saving input chars -#else /* BB_FEATURE_VI_DOT_CMD */ +#else /* CONFIG_FEATURE_VI_DOT_CMD */ #define end_cmd_q() -#endif /* BB_FEATURE_VI_DOT_CMD */ -#ifdef BB_FEATURE_VI_WIN_RESIZE +#endif /* CONFIG_FEATURE_VI_DOT_CMD */ +#ifdef CONFIG_FEATURE_VI_WIN_RESIZE static void window_size_get(int); // find out what size the window is -#endif /* BB_FEATURE_VI_WIN_RESIZE */ -#ifdef BB_FEATURE_VI_SETOPTS +#endif /* CONFIG_FEATURE_VI_WIN_RESIZE */ +#ifdef CONFIG_FEATURE_VI_SETOPTS static void showmatching(Byte *); // show the matching pair () [] {} -#endif /* BB_FEATURE_VI_SETOPTS */ -#if defined(BB_FEATURE_VI_YANKMARK) || defined(BB_FEATURE_VI_COLON) || defined(BB_FEATURE_VI_CRASHME) +#endif /* CONFIG_FEATURE_VI_SETOPTS */ +#if defined(CONFIG_FEATURE_VI_YANKMARK) || defined(CONFIG_FEATURE_VI_COLON) || defined(CONFIG_FEATURE_VI_CRASHME) static Byte *string_insert(Byte *, Byte *); // insert the string at 'p' -#endif /* BB_FEATURE_VI_YANKMARK || BB_FEATURE_VI_COLON || BB_FEATURE_VI_CRASHME */ -#ifdef BB_FEATURE_VI_YANKMARK +#endif /* CONFIG_FEATURE_VI_YANKMARK || CONFIG_FEATURE_VI_COLON || CONFIG_FEATURE_VI_CRASHME */ +#ifdef CONFIG_FEATURE_VI_YANKMARK static Byte *text_yank(Byte *, Byte *, int); // save copy of "p" into a register static Byte what_reg(void); // what is letter of current YDreg static void check_context(Byte); // remember context for '' command static Byte *swap_context(Byte *); // goto new context for '' command -#endif /* BB_FEATURE_VI_YANKMARK */ -#ifdef BB_FEATURE_VI_CRASHME +#endif /* CONFIG_FEATURE_VI_YANKMARK */ +#ifdef CONFIG_FEATURE_VI_CRASHME static void crash_dummy(); static void crash_test(); static int crashme = 0; -#endif /* BB_FEATURE_VI_CRASHME */ +#endif /* CONFIG_FEATURE_VI_CRASHME */ extern int vi_main(int argc, char **argv) { int c; -#ifdef BB_FEATURE_VI_YANKMARK +#ifdef CONFIG_FEATURE_VI_YANKMARK int i; -#endif /* BB_FEATURE_VI_YANKMARK */ +#endif /* CONFIG_FEATURE_VI_YANKMARK */ CMrc= "\033[%d;%dH"; // Terminal Crusor motion ESC sequence CMup= "\033[A"; // move cursor up one line, same col @@ -321,46 +321,46 @@ extern int vi_main(int argc, char **argv) SOs = "\033[7m"; // Terminal standout mode on SOn = "\033[0m"; // Terminal standout mode off bell= "\007"; // Terminal bell sequence -#ifdef BB_FEATURE_VI_CRASHME +#ifdef CONFIG_FEATURE_VI_CRASHME (void) srand((long) getpid()); -#endif /* BB_FEATURE_VI_CRASHME */ +#endif /* CONFIG_FEATURE_VI_CRASHME */ status_buffer = (Byte *) malloc(200); // hold messages to user -#ifdef BB_FEATURE_VI_READONLY +#ifdef CONFIG_FEATURE_VI_READONLY vi_readonly = readonly = FALSE; if (strncmp(argv[0], "view", 4) == 0) { readonly = TRUE; vi_readonly = TRUE; } -#endif /* BB_FEATURE_VI_READONLY */ -#ifdef BB_FEATURE_VI_SETOPTS +#endif /* CONFIG_FEATURE_VI_READONLY */ +#ifdef CONFIG_FEATURE_VI_SETOPTS autoindent = 1; ignorecase = 1; showmatch = 1; -#endif /* BB_FEATURE_VI_SETOPTS */ -#ifdef BB_FEATURE_VI_YANKMARK +#endif /* CONFIG_FEATURE_VI_SETOPTS */ +#ifdef CONFIG_FEATURE_VI_YANKMARK for (i = 0; i < 28; i++) { reg[i] = 0; } // init the yank regs -#endif /* BB_FEATURE_VI_YANKMARK */ -#ifdef BB_FEATURE_VI_DOT_CMD +#endif /* CONFIG_FEATURE_VI_YANKMARK */ +#ifdef CONFIG_FEATURE_VI_DOT_CMD modifying_cmds = (Byte *) "aAcCdDiIJoOpPrRsxX<>~"; // cmds modifying text[] -#endif /* BB_FEATURE_VI_DOT_CMD */ +#endif /* CONFIG_FEATURE_VI_DOT_CMD */ // 1- process $HOME/.exrc file // 2- process EXINIT variable from environment // 3- process command line args while ((c = getopt(argc, argv, "hCR")) != -1) { switch (c) { -#ifdef BB_FEATURE_VI_CRASHME +#ifdef CONFIG_FEATURE_VI_CRASHME case 'C': crashme = 1; break; -#endif /* BB_FEATURE_VI_CRASHME */ -#ifdef BB_FEATURE_VI_READONLY +#endif /* CONFIG_FEATURE_VI_CRASHME */ +#ifdef CONFIG_FEATURE_VI_READONLY case 'R': // Read-only flag readonly = TRUE; break; -#endif /* BB_FEATURE_VI_READONLY */ +#endif /* CONFIG_FEATURE_VI_READONLY */ //case 'r': // recover flag- ignore- we don't use tmp file //case 'x': // encryption flag- ignore //case 'c': // execute command first @@ -399,21 +399,21 @@ static void edit_file(Byte * fn) char c; int cnt, size, ch; -#ifdef BB_FEATURE_VI_USE_SIGNALS +#ifdef CONFIG_FEATURE_VI_USE_SIGNALS char *msg; int sig; -#endif /* BB_FEATURE_VI_USE_SIGNALS */ -#ifdef BB_FEATURE_VI_YANKMARK +#endif /* CONFIG_FEATURE_VI_USE_SIGNALS */ +#ifdef CONFIG_FEATURE_VI_YANKMARK static Byte *cur_line; -#endif /* BB_FEATURE_VI_YANKMARK */ +#endif /* CONFIG_FEATURE_VI_YANKMARK */ rawmode(); rows = 24; columns = 80; ch= -1; -#ifdef BB_FEATURE_VI_WIN_RESIZE +#ifdef CONFIG_FEATURE_VI_WIN_RESIZE window_size_get(0); -#endif /* BB_FEATURE_VI_WIN_RESIZE */ +#endif /* CONFIG_FEATURE_VI_WIN_RESIZE */ new_screen(rows, columns); // get memory for virtual screen cnt = file_size(fn); // file size @@ -427,14 +427,14 @@ static void edit_file(Byte * fn) (void) char_insert(text, '\n'); // start empty buf with dummy line } file_modified = FALSE; -#ifdef BB_FEATURE_VI_YANKMARK +#ifdef CONFIG_FEATURE_VI_YANKMARK YDreg = 26; // default Yank/Delete reg Ureg = 27; // hold orig line for "U" cmd for (cnt = 0; cnt < 28; cnt++) { mark[cnt] = 0; } // init the marks mark[26] = mark[27] = text; // init "previous context" -#endif /* BB_FEATURE_VI_YANKMARK */ +#endif /* CONFIG_FEATURE_VI_YANKMARK */ err_method = 1; // flash last_forward_char = last_input_char = '\0'; @@ -442,7 +442,7 @@ static void edit_file(Byte * fn) ccol = 0; edit_status(); -#ifdef BB_FEATURE_VI_USE_SIGNALS +#ifdef CONFIG_FEATURE_VI_USE_SIGNALS signal(SIGHUP, catch_sig); signal(SIGINT, catch_sig); signal(SIGALRM, alarm_sig); @@ -481,7 +481,7 @@ static void edit_file(Byte * fn) psbs("-- caught signal %d %s--", sig, msg); screenbegin = dot = text; } -#endif /* BB_FEATURE_VI_USE_SIGNALS */ +#endif /* CONFIG_FEATURE_VI_USE_SIGNALS */ editing = 1; cmd_mode = 0; // 0=command 1=insert 2='R'eplace @@ -489,20 +489,20 @@ static void edit_file(Byte * fn) tabstop = 8; offset = 0; // no horizontal offset c = '\0'; -#ifdef BB_FEATURE_VI_DOT_CMD +#ifdef CONFIG_FEATURE_VI_DOT_CMD if (last_modifying_cmd != 0) free(last_modifying_cmd); if (ioq_start != NULL) free(ioq_start); ioq = ioq_start = last_modifying_cmd = 0; adding2q = 0; -#endif /* BB_FEATURE_VI_DOT_CMD */ +#endif /* CONFIG_FEATURE_VI_DOT_CMD */ redraw(FALSE); // dont force every col re-draw show_status_line(); //------This is the main Vi cmd handling loop ----------------------- while (editing > 0) { -#ifdef BB_FEATURE_VI_CRASHME +#ifdef CONFIG_FEATURE_VI_CRASHME if (crashme > 0) { if ((end - text) > 1) { crash_dummy(); // generate a random command @@ -513,23 +513,23 @@ static void edit_file(Byte * fn) refresh(FALSE); } } -#endif /* BB_FEATURE_VI_CRASHME */ +#endif /* CONFIG_FEATURE_VI_CRASHME */ last_input_char = c = get_one_char(); // get a cmd from user -#ifdef BB_FEATURE_VI_YANKMARK +#ifdef CONFIG_FEATURE_VI_YANKMARK // save a copy of the current line- for the 'U" command if (begin_line(dot) != cur_line) { cur_line = begin_line(dot); text_yank(begin_line(dot), end_line(dot), Ureg); } -#endif /* BB_FEATURE_VI_YANKMARK */ -#ifdef BB_FEATURE_VI_DOT_CMD +#endif /* CONFIG_FEATURE_VI_YANKMARK */ +#ifdef CONFIG_FEATURE_VI_DOT_CMD // These are commands that change text[]. // Remember the input for the "." command if (!adding2q && ioq_start == 0 && strchr((char *) modifying_cmds, c) != NULL) { start_new_cmd_q(c); } -#endif /* BB_FEATURE_VI_DOT_CMD */ +#endif /* CONFIG_FEATURE_VI_DOT_CMD */ do_cmd(c); // execute the user command // // poll to see if there is input already waiting. if we are @@ -540,10 +540,10 @@ static void edit_file(Byte * fn) refresh(FALSE); show_status_line(); } -#ifdef BB_FEATURE_VI_CRASHME +#ifdef CONFIG_FEATURE_VI_CRASHME if (crashme > 0) crash_test(); // test editor variables -#endif /* BB_FEATURE_VI_CRASHME */ +#endif /* CONFIG_FEATURE_VI_CRASHME */ } //------------------------------------------------------------------- @@ -554,7 +554,7 @@ static void edit_file(Byte * fn) static Byte readbuffer[BUFSIZ]; -#ifdef BB_FEATURE_VI_CRASHME +#ifdef CONFIG_FEATURE_VI_CRASHME static int totalcmds = 0; static int Mp = 85; // Movement command Probability static int Np = 90; // Non-movement command Probability @@ -756,7 +756,7 @@ static void crash_test() } return; } -#endif /* BB_FEATURE_VI_CRASHME */ +#endif /* CONFIG_FEATURE_VI_CRASHME */ //--------------------------------------------------------------------- //----- the Ascii Chart ----------------------------------------------- @@ -822,11 +822,11 @@ static void do_cmd(Byte c) //case 0x10: // dle //case 0x11: // dc1 //case 0x13: // dc3 -#ifdef BB_FEATURE_VI_CRASHME +#ifdef CONFIG_FEATURE_VI_CRASHME case 0x14: // dc4 ctrl-T crashme = (crashme == 0) ? 1 : 0; break; -#endif /* BB_FEATURE_VI_CRASHME */ +#endif /* CONFIG_FEATURE_VI_CRASHME */ //case 0x16: // syn //case 0x17: // etb //case 0x18: // can @@ -873,14 +873,14 @@ static void do_cmd(Byte c) case VI_K_PAGEUP: // Cursor Key Page Up dot_scroll(rows - 2, -1); break; -#ifdef BB_FEATURE_VI_USE_SIGNALS +#ifdef CONFIG_FEATURE_VI_USE_SIGNALS case 0x03: // ctrl-C interrupt longjmp(restart, 1); break; case 26: // ctrl-Z suspend suspend_sig(SIGTSTP); break; -#endif /* BB_FEATURE_VI_USE_SIGNALS */ +#endif /* CONFIG_FEATURE_VI_USE_SIGNALS */ case 4: // ctrl-D scroll down half screen dot_scroll((rows - 2) / 2, 1); break; @@ -949,7 +949,7 @@ static void do_cmd(Byte c) } // repeat cnt dot_right(); break; -#ifdef BB_FEATURE_VI_YANKMARK +#ifdef CONFIG_FEATURE_VI_YANKMARK case '"': // "- name a register to use for Delete/Yank c1 = get_one_char(); c1 = tolower(c1); @@ -1031,7 +1031,7 @@ static void do_cmd(Byte c) dot_skip_over_ws(); } break; -#endif /* BB_FEATURE_VI_YANKMARK */ +#endif /* CONFIG_FEATURE_VI_YANKMARK */ case '$': // $- goto end of line case VI_K_END: // Cursor Key End if (cmdcnt-- > 1) { @@ -1080,7 +1080,7 @@ static void do_cmd(Byte c) dot_prev(); dot_skip_over_ws(); break; -#ifdef BB_FEATURE_VI_DOT_CMD +#ifdef CONFIG_FEATURE_VI_DOT_CMD case '.': // .- repeat the last modifying command // Stuff the last_modifying_cmd back into stdin // and let it be re-executed. @@ -1088,8 +1088,8 @@ static void do_cmd(Byte c) ioq = ioq_start = (Byte *) strdup((char *) last_modifying_cmd); } break; -#endif /* BB_FEATURE_VI_DOT_CMD */ -#ifdef BB_FEATURE_VI_SEARCH +#endif /* CONFIG_FEATURE_VI_DOT_CMD */ +#ifdef CONFIG_FEATURE_VI_SEARCH case '?': // /- search for a pattern case '/': // /- search for a pattern buf[0] = c; @@ -1175,7 +1175,7 @@ static void do_cmd(Byte c) dot = next_line(q); // move to next blank line } break; -#endif /* BB_FEATURE_VI_SEARCH */ +#endif /* CONFIG_FEATURE_VI_SEARCH */ case '0': // 0- goto begining of line case '1': // 1- case '2': // 2- @@ -1194,9 +1194,9 @@ static void do_cmd(Byte c) break; case ':': // :- the colon mode commands p = get_input_line((Byte *) ":"); // get input line- use "status line" -#ifdef BB_FEATURE_VI_COLON +#ifdef CONFIG_FEATURE_VI_COLON colon(p); // execute the command -#else /* BB_FEATURE_VI_COLON */ +#else /* CONFIG_FEATURE_VI_COLON */ if (*p == ':') p++; // move past the ':' cnt = strlen((char *) p); @@ -1225,7 +1225,7 @@ static void do_cmd(Byte c) } else { // unrecognised cmd ni((Byte *) p); } -#endif /* BB_FEATURE_VI_COLON */ +#endif /* CONFIG_FEATURE_VI_COLON */ break; case '<': // <- Left shift something case '>': // >- Right shift something @@ -1289,10 +1289,10 @@ static void do_cmd(Byte c) dot = yank_delete(save_dot, dot, 0, YANKDEL); // delete to e-o-l if (c == 'C') goto dc_i; // start inserting -#ifdef BB_FEATURE_VI_DOT_CMD +#ifdef CONFIG_FEATURE_VI_DOT_CMD if (c == 'D') end_cmd_q(); // stop adding to q -#endif /* BB_FEATURE_VI_DOT_CMD */ +#endif /* CONFIG_FEATURE_VI_DOT_CMD */ break; case 'G': // G- goto to a line number (default= E-O-F) dot = end - 1; // assume E-O-F @@ -1396,10 +1396,10 @@ static void do_cmd(Byte c) break; } if (file_modified == TRUE -#ifdef BB_FEATURE_VI_READONLY +#ifdef CONFIG_FEATURE_VI_READONLY && vi_readonly == FALSE && readonly == FALSE -#endif /* BB_FEATURE_VI_READONLY */ +#endif /* CONFIG_FEATURE_VI_READONLY */ ) { cnt = file_write(cfn, text, end - 1); if (cnt == (end - 1 - text + 1)) { @@ -1435,15 +1435,15 @@ static void do_cmd(Byte c) break; case 'c': // c- change something case 'd': // d- delete something -#ifdef BB_FEATURE_VI_YANKMARK +#ifdef CONFIG_FEATURE_VI_YANKMARK case 'y': // y- yank something case 'Y': // Y- Yank a line -#endif /* BB_FEATURE_VI_YANKMARK */ +#endif /* CONFIG_FEATURE_VI_YANKMARK */ yf = YANKDEL; // assume either "c" or "d" -#ifdef BB_FEATURE_VI_YANKMARK +#ifdef CONFIG_FEATURE_VI_YANKMARK if (c == 'y' || c == 'Y') yf = YANKONLY; -#endif /* BB_FEATURE_VI_YANKMARK */ +#endif /* CONFIG_FEATURE_VI_YANKMARK */ c1 = 'y'; if (c != 'Y') c1 = get_one_char(); // get the type of thing to delete @@ -1490,7 +1490,7 @@ static void do_cmd(Byte c) if (c == 'd') { strcpy((char *) buf, "Delete"); } -#ifdef BB_FEATURE_VI_YANKMARK +#ifdef CONFIG_FEATURE_VI_YANKMARK if (c == 'y' || c == 'Y') { strcpy((char *) buf, "Yank"); } @@ -1502,7 +1502,7 @@ static void do_cmd(Byte c) } psb("%s %d lines (%d chars) using [%c]", buf, cnt, strlen((char *) reg[YDreg]), what_reg()); -#endif /* BB_FEATURE_VI_YANKMARK */ +#endif /* CONFIG_FEATURE_VI_YANKMARK */ end_cmd_q(); // stop adding to q } break; @@ -1601,9 +1601,9 @@ static void do_cmd(Byte c) if (dot != end) { dot = bound_dot(dot); // make sure "dot" is valid } -#ifdef BB_FEATURE_VI_YANKMARK +#ifdef CONFIG_FEATURE_VI_YANKMARK check_context(c); // update the current context -#endif /* BB_FEATURE_VI_YANKMARK */ +#endif /* CONFIG_FEATURE_VI_YANKMARK */ if (!isdigit(c)) cmdcnt = 0; // cmd was not a number, reset cmdcnt @@ -1614,25 +1614,25 @@ static void do_cmd(Byte c) } //----- The Colon commands ------------------------------------- -#ifdef BB_FEATURE_VI_COLON +#ifdef CONFIG_FEATURE_VI_COLON static Byte *get_one_address(Byte * p, int *addr) // get colon addr, if present { int st; Byte *q; -#ifdef BB_FEATURE_VI_YANKMARK +#ifdef CONFIG_FEATURE_VI_YANKMARK Byte c; -#endif /* BB_FEATURE_VI_YANKMARK */ -#ifdef BB_FEATURE_VI_SEARCH +#endif /* CONFIG_FEATURE_VI_YANKMARK */ +#ifdef CONFIG_FEATURE_VI_SEARCH Byte *pat, buf[BUFSIZ]; -#endif /* BB_FEATURE_VI_SEARCH */ +#endif /* CONFIG_FEATURE_VI_SEARCH */ *addr = -1; // assume no addr if (*p == '.') { // the current line p++; q = begin_line(dot); *addr = count_lines(text, q); -#ifdef BB_FEATURE_VI_YANKMARK +#ifdef CONFIG_FEATURE_VI_YANKMARK } else if (*p == '\'') { // is this a mark addr p++; c = tolower(*p); @@ -1645,8 +1645,8 @@ static Byte *get_one_address(Byte * p, int *addr) // get colon addr, if present *addr = count_lines(text, q); // count lines } } -#endif /* BB_FEATURE_VI_YANKMARK */ -#ifdef BB_FEATURE_VI_SEARCH +#endif /* CONFIG_FEATURE_VI_YANKMARK */ +#ifdef CONFIG_FEATURE_VI_SEARCH } else if (*p == '/') { // a search pattern q = buf; for (p++; *p; p++) { @@ -1663,7 +1663,7 @@ static Byte *get_one_address(Byte * p, int *addr) // get colon addr, if present *addr = count_lines(text, q); } free(pat); -#endif /* BB_FEATURE_VI_SEARCH */ +#endif /* CONFIG_FEATURE_VI_SEARCH */ } else if (*p == '$') { // the last line in file p++; q = begin_line(end - 1); @@ -1871,7 +1871,7 @@ static void colon(Byte * buf) ch= 1; } file_modified = FALSE; -#ifdef BB_FEATURE_VI_YANKMARK +#ifdef CONFIG_FEATURE_VI_YANKMARK if (Ureg >= 0 && Ureg < 28 && reg[Ureg] != 0) { free(reg[Ureg]); // free orig line reg- for 'U' reg[Ureg]= 0; @@ -1883,18 +1883,18 @@ static void colon(Byte * buf) for (li = 0; li < 28; li++) { mark[li] = 0; } // init the marks -#endif /* BB_FEATURE_VI_YANKMARK */ +#endif /* CONFIG_FEATURE_VI_YANKMARK */ // how many lines in text[]? li = count_lines(text, end - 1); psb("\"%s\"%s" -#ifdef BB_FEATURE_VI_READONLY +#ifdef CONFIG_FEATURE_VI_READONLY "%s" -#endif /* BB_FEATURE_VI_READONLY */ +#endif /* CONFIG_FEATURE_VI_READONLY */ " %dL, %dC", cfn, (sr < 0 ? " [New file]" : ""), -#ifdef BB_FEATURE_VI_READONLY +#ifdef CONFIG_FEATURE_VI_READONLY ((vi_readonly == TRUE || readonly == TRUE) ? " [Read only]" : ""), -#endif /* BB_FEATURE_VI_READONLY */ +#endif /* CONFIG_FEATURE_VI_READONLY */ li, ch); } else if (strncasecmp((char *) cmd, "file", i) == 0) { // what File is this if (b != -1 || e != -1) { @@ -1940,9 +1940,9 @@ static void colon(Byte * buf) if (c > '~') standout_end(); } -#ifdef BB_FEATURE_VI_SET +#ifdef CONFIG_FEATURE_VI_SET vc2: -#endif /* BB_FEATURE_VI_SET */ +#endif /* CONFIG_FEATURE_VI_SET */ Hit_Return(); } else if ((strncasecmp((char *) cmd, "quit", i) == 0) || // Quit (strncasecmp((char *) cmd, "next", i) == 0)) { // edit next file @@ -1982,11 +1982,11 @@ static void colon(Byte * buf) // read after current line- unless user said ":0r foo" if (b != 0) q = next_line(q); -#ifdef BB_FEATURE_VI_READONLY +#ifdef CONFIG_FEATURE_VI_READONLY l= readonly; // remember current files' status #endif ch = file_insert(fn, q, file_size(fn)); -#ifdef BB_FEATURE_VI_READONLY +#ifdef CONFIG_FEATURE_VI_READONLY readonly= l; #endif if (ch < 0) @@ -1994,13 +1994,13 @@ static void colon(Byte * buf) // how many lines in text[]? li = count_lines(q, q + ch - 1); psb("\"%s\"" -#ifdef BB_FEATURE_VI_READONLY +#ifdef CONFIG_FEATURE_VI_READONLY "%s" -#endif /* BB_FEATURE_VI_READONLY */ +#endif /* CONFIG_FEATURE_VI_READONLY */ " %dL, %dC", fn, -#ifdef BB_FEATURE_VI_READONLY +#ifdef CONFIG_FEATURE_VI_READONLY ((vi_readonly == TRUE || readonly == TRUE) ? " [Read only]" : ""), -#endif /* BB_FEATURE_VI_READONLY */ +#endif /* CONFIG_FEATURE_VI_READONLY */ li, ch); if (ch > 0) { // if the insert is before "dot" then we need to update @@ -2016,7 +2016,7 @@ static void colon(Byte * buf) optind = fn_start - 1; editing = 0; } -#ifdef BB_FEATURE_VI_SET +#ifdef CONFIG_FEATURE_VI_SET } else if (strncasecmp((char *) cmd, "set", i) == 0) { // set or clear features i = 0; // offset into args if (strlen((char *) args) == 0) { @@ -2024,7 +2024,7 @@ static void colon(Byte * buf) place_cursor(rows - 1, 0, FALSE); // go to Status line, bottom of screen clear_to_eol(); // clear the line printf("----------------------------------------\r\n"); -#ifdef BB_FEATURE_VI_SETOPTS +#ifdef CONFIG_FEATURE_VI_SETOPTS if (!autoindent) printf("no"); printf("autoindent "); @@ -2038,13 +2038,13 @@ static void colon(Byte * buf) printf("no"); printf("showmatch "); printf("tabstop=%d ", tabstop); -#endif /* BB_FEATURE_VI_SETOPTS */ +#endif /* CONFIG_FEATURE_VI_SETOPTS */ printf("\r\n"); goto vc2; } if (strncasecmp((char *) args, "no", 2) == 0) i = 2; // ":set noautoindent" -#ifdef BB_FEATURE_VI_SETOPTS +#ifdef CONFIG_FEATURE_VI_SETOPTS if (strncasecmp((char *) args + i, "autoindent", 10) == 0 || strncasecmp((char *) args + i, "ai", 2) == 0) { autoindent = (i == 2) ? 0 : 1; @@ -2066,9 +2066,9 @@ static void colon(Byte * buf) if (ch > 0 && ch < columns - 1) tabstop = ch; } -#endif /* BB_FEATURE_VI_SETOPTS */ -#endif /* BB_FEATURE_VI_SET */ -#ifdef BB_FEATURE_VI_SEARCH +#endif /* CONFIG_FEATURE_VI_SETOPTS */ +#endif /* CONFIG_FEATURE_VI_SET */ +#ifdef CONFIG_FEATURE_VI_SEARCH } else if (strncasecmp((char *) cmd, "s", 1) == 0) { // substitute a pattern with a replacement pattern Byte *ls, *F, *R; int gflag; @@ -2115,7 +2115,7 @@ static void colon(Byte * buf) } q = next_line(ls); } -#endif /* BB_FEATURE_VI_SEARCH */ +#endif /* CONFIG_FEATURE_VI_SEARCH */ } else if (strncasecmp((char *) cmd, "version", i) == 0) { // show software version psb("%s", vi_Version); } else if ((strncasecmp((char *) cmd, "write", i) == 0) || // write text to file @@ -2124,12 +2124,12 @@ static void colon(Byte * buf) if (strlen((char *) args) > 0) { fn = args; } -#ifdef BB_FEATURE_VI_READONLY +#ifdef CONFIG_FEATURE_VI_READONLY if ((vi_readonly == TRUE || readonly == TRUE) && useforce == FALSE) { psbs("\"%s\" File is read only", fn); goto vc3; } -#endif /* BB_FEATURE_VI_READONLY */ +#endif /* CONFIG_FEATURE_VI_READONLY */ // how many lines in text[]? li = count_lines(q, r); ch = r - q + 1; @@ -2153,10 +2153,10 @@ static void colon(Byte * buf) if (cmd[1] == 'q' && l == ch) { editing = 0; } -#ifdef BB_FEATURE_VI_READONLY +#ifdef CONFIG_FEATURE_VI_READONLY vc3:; -#endif /* BB_FEATURE_VI_READONLY */ -#ifdef BB_FEATURE_VI_YANKMARK +#endif /* CONFIG_FEATURE_VI_READONLY */ +#ifdef CONFIG_FEATURE_VI_YANKMARK } else if (strncasecmp((char *) cmd, "yank", i) == 0) { // yank lines if (b < 0) { // no addr given- use defaults q = begin_line(dot); // assume .,. for the range @@ -2166,7 +2166,7 @@ static void colon(Byte * buf) li = count_lines(q, r); psb("Yank %d lines (%d chars) into [%c]", li, strlen((char *) reg[YDreg]), what_reg()); -#endif /* BB_FEATURE_VI_YANKMARK */ +#endif /* CONFIG_FEATURE_VI_YANKMARK */ } else { // cmd unknown ni((Byte *) cmd); @@ -2174,7 +2174,7 @@ static void colon(Byte * buf) vc1: dot = bound_dot(dot); // make sure "dot" is valid return; -#ifdef BB_FEATURE_VI_SEARCH +#ifdef CONFIG_FEATURE_VI_SEARCH colon_s_fail: psb(":s expression missing delimiters"); return; @@ -2193,7 +2193,7 @@ static void Hit_Return(void) ; redraw(TRUE); // force redraw all } -#endif /* BB_FEATURE_VI_COLON */ +#endif /* CONFIG_FEATURE_VI_COLON */ //----- Synchronize the cursor to Dot -------------------------- static void sync_cursor(Byte * d, int *row, int *col) @@ -2518,17 +2518,17 @@ static Byte *new_text(int size) return (text); } -#ifdef BB_FEATURE_VI_SEARCH +#ifdef CONFIG_FEATURE_VI_SEARCH static int mycmp(Byte * s1, Byte * s2, int len) { int i; i = strncmp((char *) s1, (char *) s2, len); -#ifdef BB_FEATURE_VI_SETOPTS +#ifdef CONFIG_FEATURE_VI_SETOPTS if (ignorecase) { i = strncasecmp((char *) s1, (char *) s2, len); } -#endif /* BB_FEATURE_VI_SETOPTS */ +#endif /* CONFIG_FEATURE_VI_SETOPTS */ return (i); } @@ -2623,7 +2623,7 @@ static Byte *char_search(Byte * p, Byte * pat, int dir, int range) // search for return (p); #endif /*REGEX_SEARCH */ } -#endif /* BB_FEATURE_VI_SEARCH */ +#endif /* CONFIG_FEATURE_VI_SEARCH */ static Byte *char_insert(Byte * p, Byte c) // insert the char c at 'p' { @@ -2648,7 +2648,7 @@ static Byte *char_insert(Byte * p, Byte c) // insert the char c at 'p' if ((p[-1] != '\n') && (dot>text)) { p--; p = text_hole_delete(p, p); // shrink buffer 1 char -#ifdef BB_FEATURE_VI_DOT_CMD +#ifdef CONFIG_FEATURE_VI_DOT_CMD // also rmove char from last_modifying_cmd if (strlen((char *) last_modifying_cmd) > 0) { Byte *q; @@ -2657,7 +2657,7 @@ static Byte *char_insert(Byte * p, Byte c) // insert the char c at 'p' q[strlen((char *) q) - 1] = '\0'; // erase BS q[strlen((char *) q) - 1] = '\0'; // erase prev char } -#endif /* BB_FEATURE_VI_DOT_CMD */ +#endif /* CONFIG_FEATURE_VI_DOT_CMD */ } } else { // insert a char into text[] @@ -2667,7 +2667,7 @@ static Byte *char_insert(Byte * p, Byte c) // insert the char c at 'p' c = '\n'; // translate \r to \n sp = p; // remember addr of insert p = stupid_insert(p, c); // insert the char -#ifdef BB_FEATURE_VI_SETOPTS +#ifdef CONFIG_FEATURE_VI_SETOPTS if (showmatch && strchr(")]}", *sp) != NULL) { showmatching(sp); } @@ -2679,7 +2679,7 @@ static Byte *char_insert(Byte * p, Byte c) // insert the char c at 'p' p = stupid_insert(p, *q); // insert the char } } -#endif /* BB_FEATURE_VI_SETOPTS */ +#endif /* CONFIG_FEATURE_VI_SETOPTS */ } return (p); } @@ -2844,7 +2844,7 @@ static Byte *find_pair(Byte * p, Byte c) return (q); } -#ifdef BB_FEATURE_VI_SETOPTS +#ifdef CONFIG_FEATURE_VI_SETOPTS // show the matching char of a pair, () [] {} static void showmatching(Byte * p) { @@ -2864,7 +2864,7 @@ static void showmatching(Byte * p) refresh(FALSE); } } -#endif /* BB_FEATURE_VI_SETOPTS */ +#endif /* CONFIG_FEATURE_VI_SETOPTS */ // open a hole in text[] static Byte *text_hole_make(Byte * p, int size) // at "p", make a 'size' byte hole @@ -2951,9 +2951,9 @@ static Byte *yank_delete(Byte * start, Byte * stop, int dist, int yf) } } p = start; -#ifdef BB_FEATURE_VI_YANKMARK +#ifdef CONFIG_FEATURE_VI_YANKMARK text_yank(start, stop, YDreg); -#endif /* BB_FEATURE_VI_YANKMARK */ +#endif /* CONFIG_FEATURE_VI_YANKMARK */ if (yf == YANKDEL) { p = text_hole_delete(start, stop); } // delete lines @@ -2963,33 +2963,33 @@ static Byte *yank_delete(Byte * start, Byte * stop, int dist, int yf) static void show_help(void) { puts("These features are available:" -#ifdef BB_FEATURE_VI_SEARCH +#ifdef CONFIG_FEATURE_VI_SEARCH "\n\tPattern searches with / and ?" -#endif /* BB_FEATURE_VI_SEARCH */ -#ifdef BB_FEATURE_VI_DOT_CMD +#endif /* CONFIG_FEATURE_VI_SEARCH */ +#ifdef CONFIG_FEATURE_VI_DOT_CMD "\n\tLast command repeat with \'.\'" -#endif /* BB_FEATURE_VI_DOT_CMD */ -#ifdef BB_FEATURE_VI_YANKMARK +#endif /* CONFIG_FEATURE_VI_DOT_CMD */ +#ifdef CONFIG_FEATURE_VI_YANKMARK "\n\tLine marking with 'x" "\n\tNamed buffers with \"x" -#endif /* BB_FEATURE_VI_YANKMARK */ -#ifdef BB_FEATURE_VI_READONLY +#endif /* CONFIG_FEATURE_VI_YANKMARK */ +#ifdef CONFIG_FEATURE_VI_READONLY "\n\tReadonly if vi is called as \"view\"" "\n\tReadonly with -R command line arg" -#endif /* BB_FEATURE_VI_READONLY */ -#ifdef BB_FEATURE_VI_SET +#endif /* CONFIG_FEATURE_VI_READONLY */ +#ifdef CONFIG_FEATURE_VI_SET "\n\tSome colon mode commands with \':\'" -#endif /* BB_FEATURE_VI_SET */ -#ifdef BB_FEATURE_VI_SETOPTS +#endif /* CONFIG_FEATURE_VI_SET */ +#ifdef CONFIG_FEATURE_VI_SETOPTS "\n\tSettable options with \":set\"" -#endif /* BB_FEATURE_VI_SETOPTS */ -#ifdef BB_FEATURE_VI_USE_SIGNALS +#endif /* CONFIG_FEATURE_VI_SETOPTS */ +#ifdef CONFIG_FEATURE_VI_USE_SIGNALS "\n\tSignal catching- ^C" "\n\tJob suspend and resume with ^Z" -#endif /* BB_FEATURE_VI_USE_SIGNALS */ -#ifdef BB_FEATURE_VI_WIN_RESIZE +#endif /* CONFIG_FEATURE_VI_USE_SIGNALS */ +#ifdef CONFIG_FEATURE_VI_WIN_RESIZE "\n\tAdapt to window re-sizes" -#endif /* BB_FEATURE_VI_WIN_RESIZE */ +#endif /* CONFIG_FEATURE_VI_WIN_RESIZE */ ); } @@ -3021,7 +3021,7 @@ static void print_literal(Byte * buf, Byte * s) // copy s to buf, convert unprin } } -#ifdef BB_FEATURE_VI_DOT_CMD +#ifdef CONFIG_FEATURE_VI_DOT_CMD static void start_new_cmd_q(Byte c) { // release old cmd @@ -3041,15 +3041,15 @@ static void start_new_cmd_q(Byte c) static void end_cmd_q() { -#ifdef BB_FEATURE_VI_YANKMARK +#ifdef CONFIG_FEATURE_VI_YANKMARK YDreg = 26; // go back to default Yank/Delete reg -#endif /* BB_FEATURE_VI_YANKMARK */ +#endif /* CONFIG_FEATURE_VI_YANKMARK */ adding2q = 0; return; } -#endif /* BB_FEATURE_VI_DOT_CMD */ +#endif /* CONFIG_FEATURE_VI_DOT_CMD */ -#if defined(BB_FEATURE_VI_YANKMARK) || defined(BB_FEATURE_VI_COLON) || defined(BB_FEATURE_VI_CRASHME) +#if defined(CONFIG_FEATURE_VI_YANKMARK) || defined(CONFIG_FEATURE_VI_COLON) || defined(CONFIG_FEATURE_VI_CRASHME) static Byte *string_insert(Byte * p, Byte * s) // insert the string at 'p' { int cnt, i; @@ -3061,14 +3061,14 @@ static Byte *string_insert(Byte * p, Byte * s) // insert the string at 'p' if (*s == '\n') cnt++; } -#ifdef BB_FEATURE_VI_YANKMARK +#ifdef CONFIG_FEATURE_VI_YANKMARK psb("Put %d lines (%d chars) from [%c]", cnt, i, what_reg()); -#endif /* BB_FEATURE_VI_YANKMARK */ +#endif /* CONFIG_FEATURE_VI_YANKMARK */ return (p); } -#endif /* BB_FEATURE_VI_YANKMARK || BB_FEATURE_VI_COLON || BB_FEATURE_VI_CRASHME */ +#endif /* CONFIG_FEATURE_VI_YANKMARK || CONFIG_FEATURE_VI_COLON || CONFIG_FEATURE_VI_CRASHME */ -#ifdef BB_FEATURE_VI_YANKMARK +#ifdef CONFIG_FEATURE_VI_YANKMARK static Byte *text_yank(Byte * p, Byte * q, int dest) // copy text into a register { Byte *t; @@ -3142,7 +3142,7 @@ static Byte *swap_context(Byte * p) // goto new context for '' command make this } return (p); } -#endif /* BB_FEATURE_VI_YANKMARK */ +#endif /* CONFIG_FEATURE_VI_YANKMARK */ static int isblnk(Byte c) // is the char a blank or tab { @@ -3170,7 +3170,7 @@ static void cookmode(void) tcsetattr(0, TCSANOW, &term_orig); } -#ifdef BB_FEATURE_VI_WIN_RESIZE +#ifdef CONFIG_FEATURE_VI_WIN_RESIZE //----- See what the window size currently is -------------------- static void window_size_get(int sig) { @@ -3191,16 +3191,16 @@ static void window_size_get(int sig) rows = (int) winsize.ws_row; columns = (int) winsize.ws_col; } -#endif /* BB_FEATURE_VI_WIN_RESIZE */ +#endif /* CONFIG_FEATURE_VI_WIN_RESIZE */ //----- Come here when we get a window resize signal --------- -#ifdef BB_FEATURE_VI_USE_SIGNALS +#ifdef CONFIG_FEATURE_VI_USE_SIGNALS static void winch_sig(int sig) { signal(SIGWINCH, winch_sig); -#ifdef BB_FEATURE_VI_WIN_RESIZE +#ifdef CONFIG_FEATURE_VI_WIN_RESIZE window_size_get(0); -#endif /* BB_FEATURE_VI_WIN_RESIZE */ +#endif /* CONFIG_FEATURE_VI_WIN_RESIZE */ new_screen(rows, columns); // get memory for virtual screen redraw(TRUE); // re-draw the screen } @@ -3263,7 +3263,7 @@ static void core_sig(int sig) longjmp(restart, sig); } -#endif /* BB_FEATURE_VI_USE_SIGNALS */ +#endif /* CONFIG_FEATURE_VI_USE_SIGNALS */ static int mysleep(int hund) // sleep for 'h' 1/100 seconds { @@ -3396,7 +3396,7 @@ static Byte get_one_char() { static Byte c; -#ifdef BB_FEATURE_VI_DOT_CMD +#ifdef CONFIG_FEATURE_VI_DOT_CMD // ! adding2q && ioq == 0 read() // ! adding2q && ioq != 0 *ioq // adding2q *last_modifying_cmd= read() @@ -3424,9 +3424,9 @@ static Byte get_one_char() last_modifying_cmd[strlen((char *) last_modifying_cmd)] = c; } } -#else /* BB_FEATURE_VI_DOT_CMD */ +#else /* CONFIG_FEATURE_VI_DOT_CMD */ c = readit(); // get the users input -#endif /* BB_FEATURE_VI_DOT_CMD */ +#endif /* CONFIG_FEATURE_VI_DOT_CMD */ return (c); // return the char, where ever it came from } @@ -3489,9 +3489,9 @@ static int file_insert(Byte * fn, Byte * p, int size) int fd, cnt; cnt = -1; -#ifdef BB_FEATURE_VI_READONLY +#ifdef CONFIG_FEATURE_VI_READONLY readonly = FALSE; -#endif /* BB_FEATURE_VI_READONLY */ +#endif /* CONFIG_FEATURE_VI_READONLY */ if (fn == 0 || strlen((char*) fn) <= 0) { psbs("No filename given"); goto fi0; @@ -3511,13 +3511,13 @@ static int file_insert(Byte * fn, Byte * p, int size) } // see if we can open the file -#ifdef BB_FEATURE_VI_READONLY +#ifdef CONFIG_FEATURE_VI_READONLY if (vi_readonly == TRUE) goto fi1; // do not try write-mode #endif fd = open((char *) fn, O_RDWR); // assume read & write if (fd < 0) { // could not open for writing- maybe file is read only -#ifdef BB_FEATURE_VI_READONLY +#ifdef CONFIG_FEATURE_VI_READONLY fi1: #endif fd = open((char *) fn, O_RDONLY); // try read-only @@ -3525,10 +3525,10 @@ static int file_insert(Byte * fn, Byte * p, int size) psbs("\"%s\" %s", fn, "could not open file"); goto fi0; } -#ifdef BB_FEATURE_VI_READONLY +#ifdef CONFIG_FEATURE_VI_READONLY // got the file- read-only readonly = TRUE; -#endif /* BB_FEATURE_VI_READONLY */ +#endif /* CONFIG_FEATURE_VI_READONLY */ } p = text_hole_make(p, size); cnt = read(fd, p, size); @@ -3591,12 +3591,12 @@ static void place_cursor(int row, int col, int opti) char cm1[BUFSIZ]; char *cm; int l; -#ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR +#ifdef CONFIG_FEATURE_VI_OPTIMIZE_CURSOR char cm2[BUFSIZ]; Byte *screenp; // char cm3[BUFSIZ]; int Rrow= last_row; -#endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */ +#endif /* CONFIG_FEATURE_VI_OPTIMIZE_CURSOR */ memset(cm1, '\0', BUFSIZ - 1); // clear the buffer @@ -3610,7 +3610,7 @@ static void place_cursor(int row, int col, int opti) cm= cm1; if (opti == FALSE) goto pc0; -#ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR +#ifdef CONFIG_FEATURE_VI_OPTIMIZE_CURSOR //----- find the minimum # of chars to move cursor ------------- //----- 2. Try moving with discreet chars (Newline, [back]space, ...) memset(cm2, '\0', BUFSIZ - 1); // clear the buffer @@ -3643,7 +3643,7 @@ static void place_cursor(int row, int col, int opti) } /* else if (strlen(cm3) < strlen(cm)) { cm= cm3; } */ -#endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */ +#endif /* CONFIG_FEATURE_VI_OPTIMIZE_CURSOR */ pc0: l= strlen(cm); if (l) write(1, cm, l); // move the cursor @@ -3690,10 +3690,10 @@ static void beep() static void indicate_error(char c) { -#ifdef BB_FEATURE_VI_CRASHME +#ifdef CONFIG_FEATURE_VI_CRASHME if (crashme > 0) return; // generate a random command -#endif /* BB_FEATURE_VI_CRASHME */ +#endif /* CONFIG_FEATURE_VI_CRASHME */ if (err_method == 0) { beep(); } else { @@ -3777,14 +3777,14 @@ static void edit_status(void) // show file status on status line percent = 100; } psb("\"%s\"" -#ifdef BB_FEATURE_VI_READONLY +#ifdef CONFIG_FEATURE_VI_READONLY "%s" -#endif /* BB_FEATURE_VI_READONLY */ +#endif /* CONFIG_FEATURE_VI_READONLY */ "%s line %d of %d --%d%%--", (cfn != 0 ? (char *) cfn : "No file"), -#ifdef BB_FEATURE_VI_READONLY +#ifdef CONFIG_FEATURE_VI_READONLY ((vi_readonly == TRUE || readonly == TRUE) ? " [Read only]" : ""), -#endif /* BB_FEATURE_VI_READONLY */ +#endif /* CONFIG_FEATURE_VI_READONLY */ (file_modified == TRUE ? " [modified]" : ""), cur, tot, percent); } @@ -3847,13 +3847,13 @@ static void refresh(int full_screen) int li, changed; Byte buf[MAX_SCR_COLS]; Byte *tp, *sp; // pointer into text[] and screen[] -#ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR +#ifdef CONFIG_FEATURE_VI_OPTIMIZE_CURSOR int last_li= -2; // last line that changed- for optimizing cursor movement -#endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */ +#endif /* CONFIG_FEATURE_VI_OPTIMIZE_CURSOR */ -#ifdef BB_FEATURE_VI_WIN_RESIZE +#ifdef CONFIG_FEATURE_VI_WIN_RESIZE window_size_get(0); -#endif /* BB_FEATURE_VI_WIN_RESIZE */ +#endif /* CONFIG_FEATURE_VI_WIN_RESIZE */ sync_cursor(dot, &crow, &ccol); // where cursor will be (on "dot") tp = screenbegin; // index into text[] of top line @@ -3916,31 +3916,31 @@ static void refresh(int full_screen) // to handle offsets correctly place_cursor(li, cs, FALSE); } else { -#ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR +#ifdef CONFIG_FEATURE_VI_OPTIMIZE_CURSOR // if this just the next line // try to optimize cursor movement // otherwise, use standard ESC sequence place_cursor(li, cs, li == (last_li+1) ? TRUE : FALSE); last_li= li; -#else /* BB_FEATURE_VI_OPTIMIZE_CURSOR */ +#else /* CONFIG_FEATURE_VI_OPTIMIZE_CURSOR */ place_cursor(li, cs, FALSE); // use standard ESC sequence -#endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */ +#endif /* CONFIG_FEATURE_VI_OPTIMIZE_CURSOR */ } // write line out to terminal write(1, sp+cs, ce-cs+1); -#ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR +#ifdef CONFIG_FEATURE_VI_OPTIMIZE_CURSOR last_row = li; -#endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */ +#endif /* CONFIG_FEATURE_VI_OPTIMIZE_CURSOR */ } } -#ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR +#ifdef CONFIG_FEATURE_VI_OPTIMIZE_CURSOR place_cursor(crow, ccol, (crow == last_row) ? TRUE : FALSE); last_row = crow; #else place_cursor(crow, ccol, FALSE); -#endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */ +#endif /* CONFIG_FEATURE_VI_OPTIMIZE_CURSOR */ if (offset != old_offset) old_offset = offset; diff --git a/env.c b/env.c deleted file mode 100644 index 8bb690b72..000000000 --- a/env.c +++ /dev/null @@ -1,106 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * env implementation for busybox - * - * Copyright (c) 1988, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Original copyright notice is retained at the end of this file. - * - * Modified for BusyBox by Erik Andersen , - */ - -#include -#include -#include -#include -#include -#include "busybox.h" - -extern int env_main(int argc, char** argv) -{ - char **ep, *p; - char *cleanenv[1]; - int ignore_environment = 0; - int ch; - - while ((ch = getopt(argc, argv, "+iu:")) != -1) { - switch(ch) { - case 'i': - ignore_environment = 1; - break; - case 'u': - unsetenv(optarg); - break; - default: - show_usage(); - } - } - if (optind != argc && !strcmp(argv[optind], "-")) { - ignore_environment = 1; - argv++; - } - if (ignore_environment) { - environ = cleanenv; - cleanenv[0] = NULL; - } - for (argv += optind; *argv && (p = strchr(*argv, '=')); ++argv) - if (putenv(*argv) < 0) - perror_msg_and_die("%s", *argv); - if (*argv) { - execvp(*argv, argv); - perror_msg_and_die("%s", *argv); - } - for (ep = environ; *ep; ep++) - puts(*ep); - return 0; -} - -/* - * Copyright (c) 1988, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. - * - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - - diff --git a/examples/inittab b/examples/inittab index 8e7e945b3..45f5a61fe 100644 --- a/examples/inittab +++ b/examples/inittab @@ -1,7 +1,7 @@ # /etc/inittab init(8) configuration for BusyBox # -# Copyright (C) 1999 by Lineo, inc. Written by Erik Andersen -# , +# Copyright (C) 1999 by Lineo, inc. and Erik Andersen +# Copyright (C) 1999,2000,2001 by Erik Andersen # # # Note, BusyBox init doesn't support runlevels. The runlevels field is diff --git a/examples/kernel-patches/devps.patch.9_25_2000 b/examples/kernel-patches/devps.patch.9_25_2000 index d74a26a99..086205cf2 100644 --- a/examples/kernel-patches/devps.patch.9_25_2000 +++ b/examples/kernel-patches/devps.patch.9_25_2000 @@ -44,7 +44,7 @@ diff -urN --exclude=.version --exclude=.config* --exclude=.*depend linux-2.2.18- +/* + * linux/drivers/char/devmtab.c + * -+ * Copyright (C) 2000 Erik Andersen ++ * Copyright (C) 1999,2000,2001 by Erik Andersen + * + * May be copied or modified under the terms of the GNU General Public License. + * See linux/COPYING for more information. @@ -343,7 +343,7 @@ diff -urN --exclude=.version --exclude=.config* --exclude=.*depend linux-2.2.18- +/* + * linux/drivers/char/devps.c + * -+ * Copyright (C) 2000 Erik Andersen ++ * Copyright (C) 1999,2000,2001 by Erik Andersen + * + * May be copied or modified under the terms of the GNU General Public License. + * See linux/COPYING for more information. @@ -900,7 +900,7 @@ diff -urN --exclude=.version --exclude=.config* --exclude=.*depend linux-2.2.18- + * devmtab tester + * + * -+ * Copyright (C) 2000 by Erik Andersen ++ * Copyright (C) 1999,2000,2001 by Erik Andersen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -1020,7 +1020,7 @@ diff -urN --exclude=.version --exclude=.config* --exclude=.*depend linux-2.2.18- + * Mini ps implementation for use with the Linux devps driver + * + * -+ * Copyright (C) 2000 by Erik Andersen ++ * Copyright (C) 1999,2000,2001 by Erik Andersen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -1311,7 +1311,7 @@ diff -urN --exclude=.version --exclude=.config* --exclude=.*depend linux-2.2.18- +/* + * -- + * -+ * Copyright (C) 2000 Erik Andersen ++ * Copyright (C) 1999,2000,2001 by Erik Andersen + * + * May be copied or modified under the terms of the GNU General Public License. + * See linux/COPYING for more information. @@ -1369,7 +1369,7 @@ diff -urN --exclude=.version --exclude=.config* --exclude=.*depend linux-2.2.18- +/* + * -- + * -+ * Copyright (C) 2000 Erik Andersen ++ * Copyright (C) 1999,2000,2001 by Erik Andersen + * + * May be copied or modified under the terms of the GNU General Public License. + * See linux/COPYING for more information. diff --git a/examples/mk2knr.pl b/examples/mk2knr.pl index aaf4963b1..1259b8436 100755 --- a/examples/mk2knr.pl +++ b/examples/mk2knr.pl @@ -3,7 +3,7 @@ # @(#) mk2knr.pl - generates a perl script that converts lexemes to K&R-style # # How to use this script: -# - In the busybox directory type 'scripts/mk2knr.pl files-you-want-to-convert' +# - In the busybox directory type 'examples/mk2knr.pl files-to-convert' # - Review the 'convertme.pl' script generated and remove / edit any of the # substitutions in there (please especially check for false positives) # - Type './convertme.pl same-files-as-before' diff --git a/expr.c b/expr.c deleted file mode 100644 index d6cc82e3e..000000000 --- a/expr.c +++ /dev/null @@ -1,535 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini expr implementation for busybox - * - * based on GNU expr Mike Parker. - * Copyright (C) 86, 1991-1997, 1999 Free Software Foundation, Inc. - * - * Busybox modifications - * Copyright (c) 2000 Edward Betts . - * - * this program is free software; you can redistribute it and/or modify - * it under the terms of the gnu general public license as published by - * the free software foundation; either version 2 of the license, or - * (at your option) any later version. - * - * this program is distributed in the hope that it will be useful, - * but without any warranty; without even the implied warranty of - * merchantability or fitness for a particular purpose. see the gnu - * general public license for more details. - * - * you should have received a copy of the gnu general public license - * along with this program; if not, write to the free software - * foundation, inc., 59 temple place, suite 330, boston, ma 02111-1307 usa - * - */ - -/* This program evaluates expressions. Each token (operator, operand, - * parenthesis) of the expression must be a seperate argument. The - * parser used is a reasonably general one, though any incarnation of - * it is language-specific. It is especially nice for expressions. - * - * No parse tree is needed; a new node is evaluated immediately. - * One function can handle multiple operators all of equal precedence, - * provided they all associate ((x op x) op x). */ - -/* no getopt needed */ - -#include -#include -#include -#include -#include -#include "busybox.h" - - -/* The kinds of value we can have. */ -enum valtype { - integer, - string -}; -typedef enum valtype TYPE; - -/* A value is.... */ -struct valinfo { - TYPE type; /* Which kind. */ - union { /* The value itself. */ - int i; - char *s; - } u; -}; -typedef struct valinfo VALUE; - -/* The arguments given to the program, minus the program name. */ -static char **args; - -static VALUE *docolon (VALUE *sv, VALUE *pv); -static VALUE *eval (void); -static VALUE *int_value (int i); -static VALUE *str_value (char *s); -static int nextarg (char *str); -static int null (VALUE *v); -static int toarith (VALUE *v); -static void freev (VALUE *v); -static void tostring (VALUE *v); - -int expr_main (int argc, char **argv) -{ - VALUE *v; - - if (argc == 1) { - error_msg_and_die("too few arguments"); - } - - args = argv + 1; - - v = eval (); - if (*args) - error_msg_and_die ("syntax error"); - - if (v->type == integer) - printf ("%d\n", v->u.i); - else - puts (v->u.s); - - exit (null (v)); -} - -/* Return a VALUE for I. */ - -static VALUE *int_value (int i) -{ - VALUE *v; - - v = xmalloc (sizeof(VALUE)); - v->type = integer; - v->u.i = i; - return v; -} - -/* Return a VALUE for S. */ - -static VALUE *str_value (char *s) -{ - VALUE *v; - - v = xmalloc (sizeof(VALUE)); - v->type = string; - v->u.s = strdup (s); - return v; -} - -/* Free VALUE V, including structure components. */ - -static void freev (VALUE *v) -{ - if (v->type == string) - free (v->u.s); - free (v); -} - -/* Return nonzero if V is a null-string or zero-number. */ - -static int null (VALUE *v) -{ - switch (v->type) { - case integer: - return v->u.i == 0; - case string: - return v->u.s[0] == '\0' || strcmp (v->u.s, "0") == 0; - default: - abort (); - } -} - -/* Coerce V to a string value (can't fail). */ - -static void tostring (VALUE *v) -{ - char *temp; - - if (v->type == integer) { - temp = xmalloc (4 * (sizeof (int) / sizeof (char))); - sprintf (temp, "%d", v->u.i); - v->u.s = temp; - v->type = string; - } -} - -/* Coerce V to an integer value. Return 1 on success, 0 on failure. */ - -static int toarith (VALUE *v) -{ - int i; - - switch (v->type) { - case integer: - return 1; - case string: - i = 0; - /* Don't interpret the empty string as an integer. */ - if (v->u.s == 0) - return 0; - i = atoi(v->u.s); - free (v->u.s); - v->u.i = i; - v->type = integer; - return 1; - default: - abort (); - } -} - -/* Return nonzero if the next token matches STR exactly. - STR must not be NULL. */ - -static int -nextarg (char *str) -{ - if (*args == NULL) - return 0; - return strcmp (*args, str) == 0; -} - -/* The comparison operator handling functions. */ - -#define cmpf(name, rel) \ -static int name (l, r) VALUE *l; VALUE *r; \ -{ \ - if (l->type == string || r->type == string) { \ - tostring (l); \ - tostring (r); \ - return strcmp (l->u.s, r->u.s) rel 0; \ - } \ - else \ - return l->u.i rel r->u.i; \ -} - cmpf (less_than, <) - cmpf (less_equal, <=) - cmpf (equal, ==) - cmpf (not_equal, !=) - cmpf (greater_equal, >=) - cmpf (greater_than, >) - -#undef cmpf - -/* The arithmetic operator handling functions. */ - -#define arithf(name, op) \ -static \ -int name (l, r) VALUE *l; VALUE *r; \ -{ \ - if (!toarith (l) || !toarith (r)) \ - error_msg_and_die ("non-numeric argument"); \ - return l->u.i op r->u.i; \ -} - -#define arithdivf(name, op) \ -static int name (l, r) VALUE *l; VALUE *r; \ -{ \ - if (!toarith (l) || !toarith (r)) \ - error_msg_and_die ( "non-numeric argument"); \ - if (r->u.i == 0) \ - error_msg_and_die ( "division by zero"); \ - return l->u.i op r->u.i; \ -} - - arithf (plus, +) - arithf (minus, -) - arithf (multiply, *) - arithdivf (divide, /) - arithdivf (mod, %) - -#undef arithf -#undef arithdivf - -/* Do the : operator. - SV is the VALUE for the lhs (the string), - PV is the VALUE for the rhs (the pattern). */ - -static VALUE *docolon (VALUE *sv, VALUE *pv) -{ - VALUE *v; - const char *errmsg; - struct re_pattern_buffer re_buffer; - struct re_registers re_regs; - int len; - - tostring (sv); - tostring (pv); - - if (pv->u.s[0] == '^') { - fprintf (stderr, "\ -warning: unportable BRE: `%s': using `^' as the first character\n\ -of a basic regular expression is not portable; it is being ignored", - pv->u.s); - } - - len = strlen (pv->u.s); - memset (&re_buffer, 0, sizeof (re_buffer)); - memset (&re_regs, 0, sizeof (re_regs)); - re_buffer.allocated = 2 * len; - re_buffer.buffer = (unsigned char *) xmalloc (re_buffer.allocated); - re_buffer.translate = 0; - re_syntax_options = RE_SYNTAX_POSIX_BASIC; - errmsg = re_compile_pattern (pv->u.s, len, &re_buffer); - if (errmsg) { - error_msg_and_die("%s", errmsg); - } - - len = re_match (&re_buffer, sv->u.s, strlen (sv->u.s), 0, &re_regs); - if (len >= 0) { - /* Were \(...\) used? */ - if (re_buffer.re_nsub > 0) { /* was (re_regs.start[1] >= 0) */ - sv->u.s[re_regs.end[1]] = '\0'; - v = str_value (sv->u.s + re_regs.start[1]); - } - else - v = int_value (len); - } - else { - /* Match failed -- return the right kind of null. */ - if (re_buffer.re_nsub > 0) - v = str_value (""); - else - v = int_value (0); - } - free (re_buffer.buffer); - return v; -} - -/* Handle bare operands and ( expr ) syntax. */ - -static VALUE *eval7 (void) -{ - VALUE *v; - - if (!*args) - error_msg_and_die ( "syntax error"); - - if (nextarg ("(")) { - args++; - v = eval (); - if (!nextarg (")")) - error_msg_and_die ( "syntax error"); - args++; - return v; - } - - if (nextarg (")")) - error_msg_and_die ( "syntax error"); - - return str_value (*args++); -} - -/* Handle match, substr, index, length, and quote keywords. */ - -static VALUE *eval6 (void) -{ - VALUE *l, *r, *v, *i1, *i2; - - if (nextarg ("quote")) { - args++; - if (!*args) - error_msg_and_die ( "syntax error"); - return str_value (*args++); - } - else if (nextarg ("length")) { - args++; - r = eval6 (); - tostring (r); - v = int_value (strlen (r->u.s)); - freev (r); - return v; - } - else if (nextarg ("match")) { - args++; - l = eval6 (); - r = eval6 (); - v = docolon (l, r); - freev (l); - freev (r); - return v; - } - else if (nextarg ("index")) { - args++; - l = eval6 (); - r = eval6 (); - tostring (l); - tostring (r); - v = int_value (strcspn (l->u.s, r->u.s) + 1); - if (v->u.i == (int) strlen (l->u.s) + 1) - v->u.i = 0; - freev (l); - freev (r); - return v; - } - else if (nextarg ("substr")) { - args++; - l = eval6 (); - i1 = eval6 (); - i2 = eval6 (); - tostring (l); - if (!toarith (i1) || !toarith (i2) - || i1->u.i > (int) strlen (l->u.s) - || i1->u.i <= 0 || i2->u.i <= 0) - v = str_value (""); - else { - v = xmalloc (sizeof(VALUE)); - v->type = string; - v->u.s = strncpy ((char *) xmalloc (i2->u.i + 1), - l->u.s + i1->u.i - 1, i2->u.i); - v->u.s[i2->u.i] = 0; - } - freev (l); - freev (i1); - freev (i2); - return v; - } - else - return eval7 (); -} - -/* Handle : operator (pattern matching). - Calls docolon to do the real work. */ - -static VALUE *eval5 (void) -{ - VALUE *l, *r, *v; - - l = eval6 (); - while (nextarg (":")) { - args++; - r = eval6 (); - v = docolon (l, r); - freev (l); - freev (r); - l = v; - } - return l; -} - -/* Handle *, /, % operators. */ - -static VALUE *eval4 (void) -{ - VALUE *l, *r; - int (*fxn) (), val; - - l = eval5 (); - while (1) { - if (nextarg ("*")) - fxn = multiply; - else if (nextarg ("/")) - fxn = divide; - else if (nextarg ("%")) - fxn = mod; - else - return l; - args++; - r = eval5 (); - val = (*fxn) (l, r); - freev (l); - freev (r); - l = int_value (val); - } -} - -/* Handle +, - operators. */ - -static VALUE *eval3 (void) -{ - VALUE *l, *r; - int (*fxn) (), val; - - l = eval4 (); - while (1) { - if (nextarg ("+")) - fxn = plus; - else if (nextarg ("-")) - fxn = minus; - else - return l; - args++; - r = eval4 (); - val = (*fxn) (l, r); - freev (l); - freev (r); - l = int_value (val); - } -} - -/* Handle comparisons. */ - -static VALUE *eval2 (void) -{ - VALUE *l, *r; - int (*fxn) (), val; - - l = eval3 (); - while (1) { - if (nextarg ("<")) - fxn = less_than; - else if (nextarg ("<=")) - fxn = less_equal; - else if (nextarg ("=") || nextarg ("==")) - fxn = equal; - else if (nextarg ("!=")) - fxn = not_equal; - else if (nextarg (">=")) - fxn = greater_equal; - else if (nextarg (">")) - fxn = greater_than; - else - return l; - args++; - r = eval3 (); - toarith (l); - toarith (r); - val = (*fxn) (l, r); - freev (l); - freev (r); - l = int_value (val); - } -} - -/* Handle &. */ - -static VALUE *eval1 (void) -{ - VALUE *l, *r; - - l = eval2 (); - while (nextarg ("&")) { - args++; - r = eval2 (); - if (null (l) || null (r)) { - freev (l); - freev (r); - l = int_value (0); - } - else - freev (r); - } - return l; -} - -/* Handle |. */ - -static VALUE *eval (void) -{ - VALUE *l, *r; - - l = eval1 (); - while (nextarg ("|")) { - args++; - r = eval1 (); - if (null (l)) { - freev (l); - l = r; - } - else - freev (r); - } - return l; -} diff --git a/fbset.c b/fbset.c deleted file mode 100644 index 5ccd80e79..000000000 --- a/fbset.c +++ /dev/null @@ -1,424 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini fbset implementation for busybox - * - * Copyright (C) 1999 by Randolph Chung - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * This is a from-scratch implementation of fbset; but the de facto fbset - * implementation was a good reference. fbset (original) is released under - * the GPL, and is (c) 1995-1999 by: - * Geert Uytterhoeven (Geert.Uytterhoeven@cs.kuleuven.ac.be) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" - -#define DEFAULTFBDEV "/dev/fb0" -#define DEFAULTFBMODE "/etc/fb.modes" - -static const int OPT_CHANGE = (1 << 0); -static const int OPT_INFO = (1 << 1); -static const int OPT_READMODE = (1 << 2); - -enum { - CMD_FB = 1, - CMD_DB = 2, - CMD_GEOMETRY = 3, - CMD_TIMING = 4, - CMD_ACCEL = 5, - CMD_HSYNC = 6, - CMD_VSYNC = 7, - CMD_LACED = 8, - CMD_DOUBLE = 9, -/* CMD_XCOMPAT = 10, */ - CMD_ALL = 11, - CMD_INFO = 12, - CMD_CHANGE = 13, - -#ifdef BB_FEATURE_FBSET_FANCY - CMD_XRES = 100, - CMD_YRES = 101, - CMD_VXRES = 102, - CMD_VYRES = 103, - CMD_DEPTH = 104, - CMD_MATCH = 105, - CMD_PIXCLOCK = 106, - CMD_LEFT = 107, - CMD_RIGHT = 108, - CMD_UPPER = 109, - CMD_LOWER = 110, - CMD_HSLEN = 111, - CMD_VSLEN = 112, - CMD_CSYNC = 113, - CMD_GSYNC = 114, - CMD_EXTSYNC = 115, - CMD_BCAST = 116, - CMD_RGBA = 117, - CMD_STEP = 118, - CMD_MOVE = 119, -#endif -}; - -static unsigned int g_options = 0; - -/* Stuff stolen from the kernel's fb.h */ -static const int FBIOGET_VSCREENINFO = 0x4600; -static const int FBIOPUT_VSCREENINFO = 0x4601; -#define __u32 u_int32_t -struct fb_bitfield { - __u32 offset; /* beginning of bitfield */ - __u32 length; /* length of bitfield */ - __u32 msb_right; /* != 0 : Most significant bit is */ - /* right */ -}; -struct fb_var_screeninfo { - __u32 xres; /* visible resolution */ - __u32 yres; - __u32 xres_virtual; /* virtual resolution */ - __u32 yres_virtual; - __u32 xoffset; /* offset from virtual to visible */ - __u32 yoffset; /* resolution */ - - __u32 bits_per_pixel; /* guess what */ - __u32 grayscale; /* != 0 Graylevels instead of colors */ - - struct fb_bitfield red; /* bitfield in fb mem if true color, */ - struct fb_bitfield green; /* else only length is significant */ - struct fb_bitfield blue; - struct fb_bitfield transp; /* transparency */ - - __u32 nonstd; /* != 0 Non standard pixel format */ - - __u32 activate; /* see FB_ACTIVATE_* */ - - __u32 height; /* height of picture in mm */ - __u32 width; /* width of picture in mm */ - - __u32 accel_flags; /* acceleration flags (hints) */ - - /* Timing: All values in pixclocks, except pixclock (of course) */ - __u32 pixclock; /* pixel clock in ps (pico seconds) */ - __u32 left_margin; /* time from sync to picture */ - __u32 right_margin; /* time from picture to sync */ - __u32 upper_margin; /* time from sync to picture */ - __u32 lower_margin; - __u32 hsync_len; /* length of horizontal sync */ - __u32 vsync_len; /* length of vertical sync */ - __u32 sync; /* see FB_SYNC_* */ - __u32 vmode; /* see FB_VMODE_* */ - __u32 reserved[6]; /* Reserved for future compatibility */ -}; - - -static struct cmdoptions_t { - char *name; - unsigned char param_count; - unsigned char code; -} g_cmdoptions[] = { - { - "-fb", 1, CMD_FB}, { - "-db", 1, CMD_DB}, { - "-a", 0, CMD_ALL}, { - "-i", 0, CMD_INFO}, { - "-g", 5, CMD_GEOMETRY}, { - "-t", 7, CMD_TIMING}, { - "-accel", 1, CMD_ACCEL}, { - "-hsync", 1, CMD_HSYNC}, { - "-vsync", 1, CMD_VSYNC}, { - "-laced", 1, CMD_LACED}, { - "-double", 1, CMD_DOUBLE}, { - "-n", 0, CMD_CHANGE}, { -#ifdef BB_FEATURE_FBSET_FANCY - "-all", 0, CMD_ALL}, { - "-xres", 1, CMD_XRES}, { - "-yres", 1, CMD_YRES}, { - "-vxres", 1, CMD_VXRES}, { - "-vyres", 1, CMD_VYRES}, { - "-depth", 1, CMD_DEPTH}, { - "-match", 0, CMD_MATCH}, { - "-geometry", 5, CMD_GEOMETRY}, { - "-pixclock", 1, CMD_PIXCLOCK}, { - "-left", 1, CMD_LEFT}, { - "-right", 1, CMD_RIGHT}, { - "-upper", 1, CMD_UPPER}, { - "-lower", 1, CMD_LOWER}, { - "-hslen", 1, CMD_HSLEN}, { - "-vslen", 1, CMD_VSLEN}, { - "-timings", 7, CMD_TIMING}, { - "-csync", 1, CMD_CSYNC}, { - "-gsync", 1, CMD_GSYNC}, { - "-extsync", 1, CMD_EXTSYNC}, { - "-bcast", 1, CMD_BCAST}, { - "-rgba", 1, CMD_RGBA}, { - "-step", 1, CMD_STEP}, { - "-move", 1, CMD_MOVE}, { -#endif - 0, 0, 0} -}; - -#ifdef BB_FEATURE_FBSET_READMODE -/* taken from linux/fb.h */ -static const int FB_VMODE_INTERLACED = 1; /* interlaced */ -static const int FB_VMODE_DOUBLE = 2; /* double scan */ -static const int FB_SYNC_HOR_HIGH_ACT = 1; /* horizontal sync high active */ -static const int FB_SYNC_VERT_HIGH_ACT = 2; /* vertical sync high active */ -static const int FB_SYNC_EXT = 4; /* external sync */ -static const int FB_SYNC_COMP_HIGH_ACT = 8; /* composite sync high active */ -#endif -static int readmode(struct fb_var_screeninfo *base, const char *fn, - const char *mode) -{ -#ifdef BB_FEATURE_FBSET_READMODE - FILE *f; - char buf[256]; - char *p = buf; - - f = xfopen(fn, "r"); - while (!feof(f)) { - fgets(buf, sizeof(buf), f); - if ((p = strstr(buf, "mode ")) || (p = strstr(buf, "mode\t"))) { - p += 5; - if ((p = strstr(buf, mode))) { - p += strlen(mode); - if (!isspace(*p) && (*p != 0) && (*p != '"') - && (*p != '\r') && (*p != '\n')) - continue; /* almost, but not quite */ - while (!feof(f)) { - fgets(buf, sizeof(buf), f); - - if ((p = strstr(buf, "geometry "))) { - p += 9; - - sscanf(p, "%d %d %d %d %d", - &(base->xres), &(base->yres), - &(base->xres_virtual), &(base->yres_virtual), - &(base->bits_per_pixel)); - } else if ((p = strstr(buf, "timings "))) { - p += 8; - - sscanf(p, "%d %d %d %d %d %d %d", - &(base->pixclock), - &(base->left_margin), &(base->right_margin), - &(base->upper_margin), &(base->lower_margin), - &(base->hsync_len), &(base->vsync_len)); - } else if ((p = strstr(buf, "laced "))) { - p += 6; - - if (strstr(buf, "false")) { - base->vmode &= ~FB_VMODE_INTERLACED; - } else { - base->vmode |= FB_VMODE_INTERLACED; - } - } else if ((p = strstr(buf, "double "))) { - p += 7; - - if (strstr(buf, "false")) { - base->vmode &= ~FB_VMODE_DOUBLE; - } else { - base->vmode |= FB_VMODE_DOUBLE; - } - } else if ((p = strstr(buf, "vsync "))) { - p += 6; - - if (strstr(buf, "low")) { - base->sync &= ~FB_SYNC_VERT_HIGH_ACT; - } else { - base->sync |= FB_SYNC_VERT_HIGH_ACT; - } - } else if ((p = strstr(buf, "hsync "))) { - p += 6; - - if (strstr(buf, "low")) { - base->sync &= ~FB_SYNC_HOR_HIGH_ACT; - } else { - base->sync |= FB_SYNC_HOR_HIGH_ACT; - } - } else if ((p = strstr(buf, "csync "))) { - p += 6; - - if (strstr(buf, "low")) { - base->sync &= ~FB_SYNC_COMP_HIGH_ACT; - } else { - base->sync |= FB_SYNC_COMP_HIGH_ACT; - } - } else if ((p = strstr(buf, "extsync "))) { - p += 8; - - if (strstr(buf, "false")) { - base->sync &= ~FB_SYNC_EXT; - } else { - base->sync |= FB_SYNC_EXT; - } - } - - if (strstr(buf, "endmode")) - return 1; - } - } - } - } -#else - error_msg( "mode reading not compiled in"); -#endif - return 0; -} - -static void setmode(struct fb_var_screeninfo *base, - struct fb_var_screeninfo *set) -{ - if ((int) set->xres > 0) - base->xres = set->xres; - if ((int) set->yres > 0) - base->yres = set->yres; - if ((int) set->xres_virtual > 0) - base->xres_virtual = set->xres_virtual; - if ((int) set->yres_virtual > 0) - base->yres_virtual = set->yres_virtual; - if ((int) set->bits_per_pixel > 0) - base->bits_per_pixel = set->bits_per_pixel; -} - -static void showmode(struct fb_var_screeninfo *v) -{ - double drate = 0, hrate = 0, vrate = 0; - - if (v->pixclock) { - drate = 1e12 / v->pixclock; - hrate = - drate / (v->left_margin + v->xres + v->right_margin + - v->hsync_len); - vrate = - hrate / (v->upper_margin + v->yres + v->lower_margin + - v->vsync_len); - } - printf("\nmode \"%ux%u-%u\"\n", v->xres, v->yres, (int) (vrate + 0.5)); -#ifdef BB_FEATURE_FBSET_FANCY - printf("\t# D: %.3f MHz, H: %.3f kHz, V: %.3f Hz\n", drate / 1e6, - hrate / 1e3, vrate); -#endif - printf("\tgeometry %u %u %u %u %u\n", v->xres, v->yres, - v->xres_virtual, v->yres_virtual, v->bits_per_pixel); - printf("\ttimings %u %u %u %u %u %u %u\n", v->pixclock, v->left_margin, - v->right_margin, v->upper_margin, v->lower_margin, v->hsync_len, - v->vsync_len); - printf("\taccel %s\n", (v->accel_flags > 0 ? "true" : "false")); - printf("\trgba %u/%u,%u/%u,%u/%u,%u/%u\n", v->red.length, - v->red.offset, v->green.length, v->green.offset, v->blue.length, - v->blue.offset, v->transp.length, v->transp.offset); - printf("endmode\n\n"); -} - -#ifdef STANDALONE -int main(int argc, char **argv) -#else -extern int fbset_main(int argc, char **argv) -#endif -{ - struct fb_var_screeninfo var, varset; - int fh, i; - char *fbdev = DEFAULTFBDEV; - char *modefile = DEFAULTFBMODE; - char *thisarg, *mode = NULL; - - memset(&varset, 0xFF, sizeof(varset)); - - /* parse cmd args.... why do they have to make things so difficult? */ - argv++; - argc--; - for (; argc > 0 && (thisarg = *argv); argc--, argv++) { - for (i = 0; g_cmdoptions[i].name; i++) { - if (!strcmp(thisarg, g_cmdoptions[i].name)) { - if (argc - 1 < g_cmdoptions[i].param_count) - show_usage(); - switch (g_cmdoptions[i].code) { - case CMD_FB: - fbdev = argv[1]; - break; - case CMD_DB: - modefile = argv[1]; - break; - case CMD_GEOMETRY: - varset.xres = strtoul(argv[1], 0, 0); - varset.yres = strtoul(argv[2], 0, 0); - varset.xres_virtual = strtoul(argv[3], 0, 0); - varset.yres_virtual = strtoul(argv[4], 0, 0); - varset.bits_per_pixel = strtoul(argv[5], 0, 0); - break; - case CMD_TIMING: - varset.pixclock = strtoul(argv[1], 0, 0); - varset.left_margin = strtoul(argv[2], 0, 0); - varset.right_margin = strtoul(argv[3], 0, 0); - varset.upper_margin = strtoul(argv[4], 0, 0); - varset.lower_margin = strtoul(argv[5], 0, 0); - varset.hsync_len = strtoul(argv[6], 0, 0); - varset.vsync_len = strtoul(argv[7], 0, 0); - break; - case CMD_CHANGE: - g_options |= OPT_CHANGE; - break; -#ifdef BB_FEATURE_FBSET_FANCY - case CMD_XRES: - varset.xres = strtoul(argv[1], 0, 0); - break; - case CMD_YRES: - varset.yres = strtoul(argv[1], 0, 0); - break; -#endif - } - argc -= g_cmdoptions[i].param_count; - argv += g_cmdoptions[i].param_count; - break; - } - } - if (!g_cmdoptions[i].name) { - if (argc == 1) { - mode = *argv; - g_options |= OPT_READMODE; - } else { - show_usage(); - } - } - } - - if ((fh = open(fbdev, O_RDONLY)) < 0) - perror_msg_and_die("fbset(open)"); - if (ioctl(fh, FBIOGET_VSCREENINFO, &var)) - perror_msg_and_die("fbset(ioctl)"); - if (g_options & OPT_READMODE) { - if (!readmode(&var, modefile, mode)) { - error_msg("Unknown video mode `%s'", mode); - return EXIT_FAILURE; - } - } - - setmode(&var, &varset); - if (g_options & OPT_CHANGE) - if (ioctl(fh, FBIOPUT_VSCREENINFO, &var)) - perror_msg_and_die("fbset(ioctl)"); - showmode(&var); - /* Don't close the file, as exiting will take care of that */ - /* close(fh); */ - - return EXIT_SUCCESS; -} diff --git a/fdflush.c b/fdflush.c deleted file mode 100644 index 28f5cb68a..000000000 --- a/fdflush.c +++ /dev/null @@ -1,47 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini fdflush implementation for busybox - * - * - * Copyright (C) 1995, 1996 by Bruce Perens . - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include "busybox.h" - -/* From */ -#define FDFLUSH _IO(2,0x4b) - -extern int fdflush_main(int argc, char **argv) -{ - int fd; - - if (argc <= 1 || **(++argv) == '-') - show_usage(); - - if ((fd = open(*argv, 0)) < 0) - perror_msg_and_die("%s", *argv); - - if (ioctl(fd, FDFLUSH, 0)) - perror_msg_and_die("%s", *argv); - - return EXIT_SUCCESS; -} diff --git a/find.c b/find.c deleted file mode 100644 index e814c97b9..000000000 --- a/find.c +++ /dev/null @@ -1,200 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini find implementation for busybox - * - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , - * Reworked by David Douthitt and - * Matt Kraai . - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" - - -static char *pattern; - -#ifdef BB_FEATURE_FIND_TYPE -static int type_mask = 0; -#endif - -#ifdef BB_FEATURE_FIND_PERM -static char perm_char = 0; -static int perm_mask = 0; -#endif - -#ifdef BB_FEATURE_FIND_MTIME -static char mtime_char; -static int mtime_days; -#endif - -static int fileAction(const char *fileName, struct stat *statbuf, void* junk) -{ - if (pattern != NULL) { - const char *tmp = strrchr(fileName, '/'); - - if (tmp == NULL) - tmp = fileName; - else - tmp++; - if (!(fnmatch(pattern, tmp, FNM_PERIOD) == 0)) - goto no_match; - } -#ifdef BB_FEATURE_FIND_TYPE - if (type_mask != 0) { - if (!((statbuf->st_mode & S_IFMT) == type_mask)) - goto no_match; - } -#endif -#ifdef BB_FEATURE_FIND_PERM - if (perm_mask != 0) { - if (!((isdigit(perm_char) && (statbuf->st_mode & 07777) == perm_mask) || - (perm_char == '-' && (statbuf->st_mode & perm_mask) == perm_mask) || - (perm_char == '+' && (statbuf->st_mode & perm_mask) != 0))) - goto no_match; - } -#endif -#ifdef BB_FEATURE_FIND_MTIME - if (mtime_days != 0) { - time_t file_age = time(NULL) - statbuf->st_mtime; - time_t mtime_secs = mtime_days * 24 * 60 * 60; - if (!((isdigit(mtime_char) && mtime_secs >= file_age && - mtime_secs < file_age + 24 * 60 * 60) || - (mtime_char == '+' && mtime_secs >= file_age) || - (mtime_char == '-' && mtime_secs < file_age))) - goto no_match; - } -#endif - puts(fileName); -no_match: - return (TRUE); -} - -#ifdef BB_FEATURE_FIND_TYPE -static int find_type(char *type) -{ - int mask = 0; - - switch (type[0]) { - case 'b': - mask = S_IFBLK; - break; - case 'c': - mask = S_IFCHR; - break; - case 'd': - mask = S_IFDIR; - break; - case 'p': - mask = S_IFIFO; - break; - case 'f': - mask = S_IFREG; - break; - case 'l': - mask = S_IFLNK; - break; - case 's': - mask = S_IFSOCK; - break; - } - - if (mask == 0 || type[1] != '\0') - error_msg_and_die("invalid argument `%s' to `-type'", type); - - return mask; -} -#endif - -int find_main(int argc, char **argv) -{ - int dereference = FALSE; - int i, firstopt, status = EXIT_SUCCESS; - - for (firstopt = 1; firstopt < argc; firstopt++) { - if (argv[firstopt][0] == '-') - break; - } - - /* Parse any options */ - for (i = firstopt; i < argc; i++) { - if (strcmp(argv[i], "-follow") == 0) - dereference = TRUE; - else if (strcmp(argv[i], "-print") == 0) { - ; - } - else if (strcmp(argv[i], "-name") == 0) { - if (++i == argc) - error_msg_and_die("option `-name' requires an argument"); - pattern = argv[i]; -#ifdef BB_FEATURE_FIND_TYPE - } else if (strcmp(argv[i], "-type") == 0) { - if (++i == argc) - error_msg_and_die("option `-type' requires an argument"); - type_mask = find_type(argv[i]); -#endif -#ifdef BB_FEATURE_FIND_PERM - } else if (strcmp(argv[i], "-perm") == 0) { - char *end; - if (++i == argc) - error_msg_and_die("option `-perm' requires an argument"); - perm_mask = strtol(argv[i], &end, 8); - if (end[0] != '\0') - error_msg_and_die("invalid argument `%s' to `-perm'", argv[i]); - if (perm_mask > 07777) - error_msg_and_die("invalid argument `%s' to `-perm'", argv[i]); - if ((perm_char = argv[i][0]) == '-') - perm_mask = -perm_mask; -#endif -#ifdef BB_FEATURE_FIND_MTIME - } else if (strcmp(argv[i], "-mtime") == 0) { - char *end; - if (++i == argc) - error_msg_and_die("option `-mtime' requires an argument"); - mtime_days = strtol(argv[i], &end, 10); - if (end[0] != '\0') - error_msg_and_die("invalid argument `%s' to `-mtime'", argv[i]); - if ((mtime_char = argv[i][0]) == '-') - mtime_days = -mtime_days; -#endif - } else - show_usage(); - } - - if (firstopt == 1) { - if (recursive_action(".", TRUE, dereference, FALSE, fileAction, - fileAction, NULL) == FALSE) - status = EXIT_FAILURE; - } else { - for (i = 1; i < firstopt; i++) { - if (recursive_action(argv[i], TRUE, dereference, FALSE, fileAction, - fileAction, NULL) == FALSE) - status = EXIT_FAILURE; - } - } - - return status; -} diff --git a/findutils/Makefile b/findutils/Makefile new file mode 100644 index 000000000..ac590ccf4 --- /dev/null +++ b/findutils/Makefile @@ -0,0 +1,39 @@ +# Makefile for busybox +# +# Copyright (C) 1999,2000,2001 by Erik Andersen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +TOPDIR :=.. +L_TARGET := findutils.a + +obj-y := +obj-n := +obj- := + + +obj-$(CONFIG_FIND) += find.o +obj-$(CONFIG_GREP) += grep.o +obj-$(CONFIG_WHICH) += which.o +obj-$(CONFIG_XARGS) += xargs.o + + +# Hand off to toplevel Rules.mak +include $(TOPDIR)/Rules.mak + +clean: + rm -f $(L_TARGET) *.o core + diff --git a/findutils/config.in b/findutils/config.in new file mode 100644 index 000000000..8e41bd50c --- /dev/null +++ b/findutils/config.in @@ -0,0 +1,14 @@ +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +mainmenu_option next_comment +comment 'Finding Utilities' + +bool 'find' CONFIG_FIND +bool 'grep' CONFIG_GREP +bool 'which' CONFIG_WHICH +bool 'xargs' CONFIG_XARGS +endmenu + diff --git a/findutils/find.c b/findutils/find.c index e814c97b9..262213e8b 100644 --- a/findutils/find.c +++ b/findutils/find.c @@ -2,9 +2,9 @@ /* * Mini find implementation for busybox * + * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , * Reworked by David Douthitt and * Matt Kraai . * @@ -37,16 +37,16 @@ static char *pattern; -#ifdef BB_FEATURE_FIND_TYPE +#ifdef CONFIG_FEATURE_FIND_TYPE static int type_mask = 0; #endif -#ifdef BB_FEATURE_FIND_PERM +#ifdef CONFIG_FEATURE_FIND_PERM static char perm_char = 0; static int perm_mask = 0; #endif -#ifdef BB_FEATURE_FIND_MTIME +#ifdef CONFIG_FEATURE_FIND_MTIME static char mtime_char; static int mtime_days; #endif @@ -63,13 +63,13 @@ static int fileAction(const char *fileName, struct stat *statbuf, void* junk) if (!(fnmatch(pattern, tmp, FNM_PERIOD) == 0)) goto no_match; } -#ifdef BB_FEATURE_FIND_TYPE +#ifdef CONFIG_FEATURE_FIND_TYPE if (type_mask != 0) { if (!((statbuf->st_mode & S_IFMT) == type_mask)) goto no_match; } #endif -#ifdef BB_FEATURE_FIND_PERM +#ifdef CONFIG_FEATURE_FIND_PERM if (perm_mask != 0) { if (!((isdigit(perm_char) && (statbuf->st_mode & 07777) == perm_mask) || (perm_char == '-' && (statbuf->st_mode & perm_mask) == perm_mask) || @@ -77,7 +77,7 @@ static int fileAction(const char *fileName, struct stat *statbuf, void* junk) goto no_match; } #endif -#ifdef BB_FEATURE_FIND_MTIME +#ifdef CONFIG_FEATURE_FIND_MTIME if (mtime_days != 0) { time_t file_age = time(NULL) - statbuf->st_mtime; time_t mtime_secs = mtime_days * 24 * 60 * 60; @@ -93,7 +93,7 @@ no_match: return (TRUE); } -#ifdef BB_FEATURE_FIND_TYPE +#ifdef CONFIG_FEATURE_FIND_TYPE static int find_type(char *type) { int mask = 0; @@ -150,13 +150,13 @@ int find_main(int argc, char **argv) if (++i == argc) error_msg_and_die("option `-name' requires an argument"); pattern = argv[i]; -#ifdef BB_FEATURE_FIND_TYPE +#ifdef CONFIG_FEATURE_FIND_TYPE } else if (strcmp(argv[i], "-type") == 0) { if (++i == argc) error_msg_and_die("option `-type' requires an argument"); type_mask = find_type(argv[i]); #endif -#ifdef BB_FEATURE_FIND_PERM +#ifdef CONFIG_FEATURE_FIND_PERM } else if (strcmp(argv[i], "-perm") == 0) { char *end; if (++i == argc) @@ -169,7 +169,7 @@ int find_main(int argc, char **argv) if ((perm_char = argv[i][0]) == '-') perm_mask = -perm_mask; #endif -#ifdef BB_FEATURE_FIND_MTIME +#ifdef CONFIG_FEATURE_FIND_MTIME } else if (strcmp(argv[i], "-mtime") == 0) { char *end; if (++i == argc) diff --git a/findutils/grep.c b/findutils/grep.c index eff7c3ff5..a97a8bbb7 100644 --- a/findutils/grep.c +++ b/findutils/grep.c @@ -1,8 +1,8 @@ /* * Mini grep implementation for busybox using libc regex. * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Mark Whitley , + * Copyright (C) 1999,2000,2001 by Lineo, inc. and Mark Whitley + * Copyright (C) 1999,2000,2001 by Mark Whitley * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -42,13 +42,13 @@ static int invert_search = 0; static int suppress_err_msgs = 0; static int print_files_with_matches = 0; -#ifdef BB_FEATURE_GREP_CONTEXT +#ifdef CONFIG_FEATURE_GREP_CONTEXT extern char *optarg; /* in getopt.h */ static int lines_before = 0; static int lines_after = 0; static char **before_buf = NULL; static int last_line_printed = 0; -#endif /* BB_FEATURE_GREP_CONTEXT */ +#endif /* CONFIG_FEATURE_GREP_CONTEXT */ /* globals used internally */ static regex_t *regexes = NULL; /* growable array of compiled regular expressions */ @@ -59,7 +59,7 @@ static char *cur_file = NULL; /* the current file we are reading */ static void print_line(const char *line, int linenum, char decoration) { -#ifdef BB_FEATURE_GREP_CONTEXT +#ifdef CONFIG_FEATURE_GREP_CONTEXT /* possibly print the little '--' seperator */ if ((lines_before || lines_after) && last_line_printed && last_line_printed < linenum - 1) { @@ -82,11 +82,11 @@ static void grep_file(FILE *file) int linenum = 0; int nmatches = 0; int i; -#ifdef BB_FEATURE_GREP_CONTEXT +#ifdef CONFIG_FEATURE_GREP_CONTEXT int print_n_lines_after = 0; int curpos = 0; /* track where we are in the circular 'before' buffer */ int idx = 0; /* used for iteration through the circular buffer */ -#endif /* BB_FEATURE_GREP_CONTEXT */ +#endif /* CONFIG_FEATURE_GREP_CONTEXT */ while ((line = get_line_from_file(file)) != NULL) { chomp(line); @@ -116,7 +116,7 @@ static void grep_file(FILE *file) /* print the matched line */ if (print_match_counts == 0) { -#ifdef BB_FEATURE_GREP_CONTEXT +#ifdef CONFIG_FEATURE_GREP_CONTEXT int prevpos = (curpos == 0) ? lines_before - 1 : curpos - 1; /* if we were told to print 'before' lines and there is at least @@ -145,11 +145,11 @@ static void grep_file(FILE *file) /* make a note that we need to print 'after' lines */ print_n_lines_after = lines_after; -#endif /* BB_FEATURE_GREP_CONTEXT */ +#endif /* CONFIG_FEATURE_GREP_CONTEXT */ print_line(line, linenum, ':'); } } -#ifdef BB_FEATURE_GREP_CONTEXT +#ifdef CONFIG_FEATURE_GREP_CONTEXT else { /* no match */ /* Add the line to the circular 'before' buffer */ if(lines_before) { @@ -165,7 +165,7 @@ static void grep_file(FILE *file) print_line(line, linenum, '-'); print_n_lines_after--; } -#endif /* BB_FEATURE_GREP_CONTEXT */ +#endif /* CONFIG_FEATURE_GREP_CONTEXT */ } /* for */ free(line); } @@ -215,7 +215,7 @@ static void load_regexes_from_file(const char *filename) } -#ifdef BB_FEATURE_CLEAN_UP +#ifdef CONFIG_FEATURE_CLEAN_UP static void destroy_regexes() { if (regexes == NULL) @@ -233,11 +233,11 @@ static void destroy_regexes() extern int grep_main(int argc, char **argv) { int opt; -#ifdef BB_FEATURE_GREP_CONTEXT +#ifdef CONFIG_FEATURE_GREP_CONTEXT char *junk; #endif -#ifdef BB_FEATURE_CLEAN_UP +#ifdef CONFIG_FEATURE_CLEAN_UP /* destroy command strings on exit */ if (atexit(destroy_regexes) == -1) perror_msg_and_die("atexit"); @@ -245,7 +245,7 @@ extern int grep_main(int argc, char **argv) /* do normal option parsing */ while ((opt = getopt(argc, argv, "iHhlnqvsce:f:" -#ifdef BB_FEATURE_GREP_CONTEXT +#ifdef CONFIG_FEATURE_GREP_CONTEXT "A:B:C:" #endif )) > 0) { @@ -283,7 +283,7 @@ extern int grep_main(int argc, char **argv) case 'f': load_regexes_from_file(optarg); break; -#ifdef BB_FEATURE_GREP_CONTEXT +#ifdef CONFIG_FEATURE_GREP_CONTEXT case 'A': lines_after = strtoul(optarg, &junk, 10); if(*junk != '\0') @@ -301,7 +301,7 @@ extern int grep_main(int argc, char **argv) error_msg_and_die("invalid context length argument"); before_buf = (char **)calloc(lines_before, sizeof(char *)); break; -#endif /* BB_FEATURE_GREP_CONTEXT */ +#endif /* CONFIG_FEATURE_GREP_CONTEXT */ default: show_usage(); } @@ -321,7 +321,7 @@ extern int grep_main(int argc, char **argv) /* sanity checks */ if (print_match_counts || be_quiet || print_files_with_matches) { print_line_num = 0; -#ifdef BB_FEATURE_GREP_CONTEXT +#ifdef CONFIG_FEATURE_GREP_CONTEXT lines_before = 0; lines_after = 0; #endif diff --git a/findutils/which.c b/findutils/which.c index c460ffdd1..eec5fdbfb 100644 --- a/findutils/which.c +++ b/findutils/which.c @@ -2,8 +2,8 @@ /* * Which implementation for busybox * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , + * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/findutils/xargs.c b/findutils/xargs.c index 48adae90a..5d64d0c9f 100644 --- a/findutils/xargs.c +++ b/findutils/xargs.c @@ -1,9 +1,9 @@ /* * Mini xargs implementation for busybox * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , - * Remixed by Mark Whitley , + * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen + * Remixed by Mark Whitley * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -95,7 +95,7 @@ int xargs_main(int argc, char **argv) free(file_to_act_on); } -#ifdef BB_FEATURE_CLEAN_UP +#ifdef CONFIG_FEATURE_CLEAN_UP free(cmd_to_be_executed); #endif diff --git a/free.c b/free.c deleted file mode 100644 index 2e34a972c..000000000 --- a/free.c +++ /dev/null @@ -1,69 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini free implementation for busybox - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* getopt not needed */ - -#include -#include -#include -#include "busybox.h" - -extern 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; - } - 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; - info.totalswap/=info.mem_unit; - info.freeswap/=info.mem_unit; - info.sharedram/=info.mem_unit; - info.bufferram/=info.mem_unit; - - if (argc > 1 && **(argv + 1) == '-') - 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); - - 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); - return EXIT_SUCCESS; -} - - diff --git a/freeramdisk.c b/freeramdisk.c deleted file mode 100644 index aabb5f988..000000000 --- a/freeramdisk.c +++ /dev/null @@ -1,64 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * freeramdisk implementation for busybox - * - * Copyright (C) 2000 and written by Emanuele Caratti - * Adjusted a bit by Erik Andersen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" - - -/* From linux/fs.h */ -#define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */ - -extern int -freeramdisk_main(int argc, char **argv) -{ - FILE *f; - - if (argc != 2 || *argv[1] == '-') { - show_usage(); - } - - f = xfopen(argv[1], "r+"); - - if (ioctl(fileno(f), BLKFLSBUF) < 0) { - perror_msg_and_die("failed ioctl on %s", argv[1]); - } - /* Don't bother closing. Exit does - * that, so we can save a few bytes */ - /* close(f); */ - return EXIT_SUCCESS; -} - -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ - diff --git a/fsck_minix.c b/fsck_minix.c deleted file mode 100644 index 952968d85..000000000 --- a/fsck_minix.c +++ /dev/null @@ -1,1478 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * fsck.c - a file system consistency checker for Linux. - * - * (C) 1991, 1992 Linus Torvalds. This file may be redistributed - * as per the GNU copyleft. - */ - -/* - * 09.11.91 - made the first rudimetary functions - * - * 10.11.91 - updated, does checking, no repairs yet. - * Sent out to the mailing-list for testing. - * - * 14.11.91 - Testing seems to have gone well. Added some - * correction-code, and changed some functions. - * - * 15.11.91 - More correction code. Hopefully it notices most - * cases now, and tries to do something about them. - * - * 16.11.91 - More corrections (thanks to Mika Jalava). Most - * things seem to work now. Yeah, sure. - * - * - * 19.04.92 - Had to start over again from this old version, as a - * kernel bug ate my enhanced fsck in february. - * - * 28.02.93 - added support for different directory entry sizes.. - * - * Sat Mar 6 18:59:42 1993, faith@cs.unc.edu: Output namelen with - * super-block information - * - * Sat Oct 9 11:17:11 1993, faith@cs.unc.edu: make exit status conform - * to that required by fsutil - * - * Mon Jan 3 11:06:52 1994 - Dr. Wettstein (greg%wind.uucp@plains.nodak.edu) - * Added support for file system valid flag. Also - * added program_version variable and output of - * program name and version number when program - * is executed. - * - * 30.10.94 - added support for v2 filesystem - * (Andreas Schwab, schwab@issan.informatik.uni-dortmund.de) - * - * 10.12.94 - added test to prevent checking of mounted fs adapted - * from Theodore Ts'o's (tytso@athena.mit.edu) e2fsck - * program. (Daniel Quinlan, quinlan@yggdrasil.com) - * - * 01.07.96 - Fixed the v2 fs stuff to use the right #defines and such - * for modern libcs (janl@math.uio.no, Nicolai Langfeldt) - * - * 02.07.96 - Added C bit fiddling routines from rmk@ecs.soton.ac.uk - * (Russell King). He made them for ARM. It would seem - * that the ARM is powerful enough to do this in C whereas - * i386 and m64k must use assembly to get it fast >:-) - * This should make minix fsck systemindependent. - * (janl@math.uio.no, Nicolai Langfeldt) - * - * 04.11.96 - Added minor fixes from Andreas Schwab to avoid compiler - * warnings. Added mc68k bitops from - * Joerg Dorchain . - * - * 06.11.96 - Added v2 code submitted by Joerg Dorchain, but written by - * Andreas Schwab. - * - * 1999-02-22 Arkadiusz Mi¶kiewicz - * - added Native Language Support - * - * - * I've had no time to add comments - hopefully the function names - * are comments enough. As with all file system checkers, this assumes - * the file system is quiescent - don't use it on a mounted device - * unless you can be sure nobody is writing to it (and remember that the - * kernel can write to it when it searches for files). - * - * Usuage: fsck [-larvsm] device - * -l for a listing of all the filenames - * -a for automatic repairs (not implemented) - * -r for repairs (interactive) (not implemented) - * -v for verbose (tells how many files) - * -s for super-block info - * -m for minix-like "mode not cleared" warnings - * -f force filesystem check even if filesystem marked as valid - * - * The device may be a block device or a image of one, but this isn't - * enforced (but it's not much fun on a character device :-). - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" - -static const int MINIX_ROOT_INO = 1; -static const int MINIX_LINK_MAX = 250; -static const int MINIX2_LINK_MAX = 65530; - -static const int MINIX_I_MAP_SLOTS = 8; -static const int MINIX_Z_MAP_SLOTS = 64; -static const int MINIX_SUPER_MAGIC = 0x137F; /* original minix fs */ -static const int MINIX_SUPER_MAGIC2 = 0x138F; /* minix fs, 30 char names */ -static const int MINIX2_SUPER_MAGIC = 0x2468; /* minix V2 fs */ -static const int MINIX2_SUPER_MAGIC2 = 0x2478; /* minix V2 fs, 30 char names */ -static const int MINIX_VALID_FS = 0x0001; /* Clean fs. */ -static const int MINIX_ERROR_FS = 0x0002; /* fs has errors. */ - -#define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode))) -#define MINIX2_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix2_inode))) - -static const int MINIX_V1 = 0x0001; /* original minix fs */ -static const int MINIX_V2 = 0x0002; /* minix V2 fs */ - -#define INODE_VERSION(inode) inode->i_sb->u.minix_sb.s_version - -/* - * This is the original minix inode layout on disk. - * Note the 8-bit gid and atime and ctime. - */ -struct minix_inode { - u_int16_t i_mode; - u_int16_t i_uid; - u_int32_t i_size; - u_int32_t i_time; - u_int8_t i_gid; - u_int8_t i_nlinks; - u_int16_t i_zone[9]; -}; - -/* - * The new minix inode has all the time entries, as well as - * long block numbers and a third indirect block (7+1+1+1 - * instead of 7+1+1). Also, some previously 8-bit values are - * now 16-bit. The inode is now 64 bytes instead of 32. - */ -struct minix2_inode { - u_int16_t i_mode; - u_int16_t i_nlinks; - u_int16_t i_uid; - u_int16_t i_gid; - u_int32_t i_size; - u_int32_t i_atime; - u_int32_t i_mtime; - u_int32_t i_ctime; - u_int32_t i_zone[10]; -}; - -/* - * minix super-block data on disk - */ -struct minix_super_block { - u_int16_t s_ninodes; - u_int16_t s_nzones; - u_int16_t s_imap_blocks; - u_int16_t s_zmap_blocks; - u_int16_t s_firstdatazone; - u_int16_t s_log_zone_size; - u_int32_t s_max_size; - u_int16_t s_magic; - u_int16_t s_state; - u_int32_t s_zones; -}; - -struct minix_dir_entry { - u_int16_t inode; - char name[0]; -}; - -#define BLOCK_SIZE_BITS 10 -#define BLOCK_SIZE (1<> 3] & (1<<(i & 7))) != 0; -} -#define inode_in_use(x) (bit(inode_map,(x))) -#define zone_in_use(x) (bit(zone_map,(x)-FIRSTZONE+1)) - -#define mark_inode(x) (setbit(inode_map,(x)),changed=1) -#define unmark_inode(x) (clrbit(inode_map,(x)),changed=1) - -#define mark_zone(x) (setbit(zone_map,(x)-FIRSTZONE+1),changed=1) -#define unmark_zone(x) (clrbit(zone_map,(x)-FIRSTZONE+1),changed=1) - -static void leave(int) __attribute__ ((noreturn)); -static void leave(int status) -{ - if (termios_set) - tcsetattr(0, TCSANOW, &termios); - exit(status); -} - -static void die(const char *str) -{ - error_msg("%s", str); - leave(8); -} - -/* - * This simply goes through the file-name data and prints out the - * current file. - */ -static void print_current_name(void) -{ - int i = 0; - - while (i < name_depth) - printf("/%.*s", namelen, name_list[i++]); - if (i == 0) - printf("/"); -} - -static int ask(const char *string, int def) -{ - int c; - - if (!repair) { - printf("\n"); - errors_uncorrected = 1; - return 0; - } - if (automatic) { - printf("\n"); - if (!def) - errors_uncorrected = 1; - return def; - } - printf(def ? "%s (y/n)? " : "%s (n/y)? ", string); - for (;;) { - fflush(stdout); - if ((c = getchar()) == EOF) { - if (!def) - errors_uncorrected = 1; - return def; - } - c = toupper(c); - if (c == 'Y') { - def = 1; - break; - } else if (c == 'N') { - def = 0; - break; - } else if (c == ' ' || c == '\n') - break; - } - if (def) - printf("y\n"); - else { - printf("n\n"); - errors_uncorrected = 1; - } - return def; -} - -/* - * Make certain that we aren't checking a filesystem that is on a - * mounted partition. Code adapted from e2fsck, Copyright (C) 1993, - * 1994 Theodore Ts'o. Also licensed under GPL. - */ -static void check_mount(void) -{ - FILE *f; - struct mntent *mnt; - int cont; - int fd; - - if ((f = setmntent(MOUNTED, "r")) == NULL) - return; - while ((mnt = getmntent(f)) != NULL) - if (strcmp(device_name, mnt->mnt_fsname) == 0) - break; - endmntent(f); - if (!mnt) - return; - - /* - * If the root is mounted read-only, then /etc/mtab is - * probably not correct; so we won't issue a warning based on - * it. - */ - fd = open(MOUNTED, O_RDWR); - if (fd < 0 && errno == EROFS) - return; - else - close(fd); - - printf("%s is mounted. ", device_name); - if (isatty(0) && isatty(1)) - cont = ask("Do you really want to continue", 0); - else - cont = 0; - if (!cont) { - printf("check aborted.\n"); - exit(0); - } - return; -} - -/* - * check_zone_nr checks to see that *nr is a valid zone nr. If it - * isn't, it will possibly be repaired. Check_zone_nr sets *corrected - * if an error was corrected, and returns the zone (0 for no zone - * or a bad zone-number). - */ -static int check_zone_nr(unsigned short *nr, int *corrected) -{ - if (!*nr) - return 0; - if (*nr < FIRSTZONE) - printf("Zone nr < FIRSTZONE in file `"); - else if (*nr >= ZONES) - printf("Zone nr >= ZONES in file `"); - else - return *nr; - print_current_name(); - printf("'."); - if (ask("Remove block", 1)) { - *nr = 0; - *corrected = 1; - } - return 0; -} - -#ifdef BB_FEATURE_MINIX2 -static int check_zone_nr2(unsigned int *nr, int *corrected) -{ - if (!*nr) - return 0; - if (*nr < FIRSTZONE) - printf("Zone nr < FIRSTZONE in file `"); - else if (*nr >= ZONES) - printf("Zone nr >= ZONES in file `"); - else - return *nr; - print_current_name(); - printf("'."); - if (ask("Remove block", 1)) { - *nr = 0; - *corrected = 1; - } - return 0; -} -#endif - -/* - * read-block reads block nr into the buffer at addr. - */ -static void read_block(unsigned int nr, char *addr) -{ - if (!nr) { - memset(addr, 0, BLOCK_SIZE); - return; - } - if (BLOCK_SIZE * nr != lseek(IN, BLOCK_SIZE * nr, SEEK_SET)) { - printf("Read error: unable to seek to block in file '"); - print_current_name(); - printf("'\n"); - memset(addr, 0, BLOCK_SIZE); - errors_uncorrected = 1; - } else if (BLOCK_SIZE != read(IN, addr, BLOCK_SIZE)) { - printf("Read error: bad block in file '"); - print_current_name(); - printf("'\n"); - memset(addr, 0, BLOCK_SIZE); - errors_uncorrected = 1; - } -} - -/* - * write_block writes block nr to disk. - */ -static void write_block(unsigned int nr, char *addr) -{ - if (!nr) - return; - if (nr < FIRSTZONE || nr >= ZONES) { - printf("Internal error: trying to write bad block\n" - "Write request ignored\n"); - errors_uncorrected = 1; - return; - } - if (BLOCK_SIZE * nr != lseek(IN, BLOCK_SIZE * nr, SEEK_SET)) - die("seek failed in write_block"); - if (BLOCK_SIZE != write(IN, addr, BLOCK_SIZE)) { - printf("Write error: bad block in file '"); - print_current_name(); - printf("'\n"); - errors_uncorrected = 1; - } -} - -/* - * map-block calculates the absolute block nr of a block in a file. - * It sets 'changed' if the inode has needed changing, and re-writes - * any indirect blocks with errors. - */ -static int map_block(struct minix_inode *inode, unsigned int blknr) -{ - unsigned short ind[BLOCK_SIZE >> 1]; - unsigned short dind[BLOCK_SIZE >> 1]; - int blk_chg, block, result; - - if (blknr < 7) - return check_zone_nr(inode->i_zone + blknr, &changed); - blknr -= 7; - if (blknr < 512) { - block = check_zone_nr(inode->i_zone + 7, &changed); - read_block(block, (char *) ind); - blk_chg = 0; - result = check_zone_nr(blknr + ind, &blk_chg); - if (blk_chg) - write_block(block, (char *) ind); - return result; - } - blknr -= 512; - block = check_zone_nr(inode->i_zone + 8, &changed); - read_block(block, (char *) dind); - blk_chg = 0; - result = check_zone_nr(dind + (blknr / 512), &blk_chg); - if (blk_chg) - write_block(block, (char *) dind); - block = result; - read_block(block, (char *) ind); - blk_chg = 0; - result = check_zone_nr(ind + (blknr % 512), &blk_chg); - if (blk_chg) - write_block(block, (char *) ind); - return result; -} - -#ifdef BB_FEATURE_MINIX2 -static int map_block2(struct minix2_inode *inode, unsigned int blknr) -{ - unsigned int ind[BLOCK_SIZE >> 2]; - unsigned int dind[BLOCK_SIZE >> 2]; - unsigned int tind[BLOCK_SIZE >> 2]; - int blk_chg, block, result; - - if (blknr < 7) - return check_zone_nr2(inode->i_zone + blknr, &changed); - blknr -= 7; - if (blknr < 256) { - block = check_zone_nr2(inode->i_zone + 7, &changed); - read_block(block, (char *) ind); - blk_chg = 0; - result = check_zone_nr2(blknr + ind, &blk_chg); - if (blk_chg) - write_block(block, (char *) ind); - return result; - } - blknr -= 256; - if (blknr >= 256 * 256) { - block = check_zone_nr2(inode->i_zone + 8, &changed); - read_block(block, (char *) dind); - blk_chg = 0; - result = check_zone_nr2(dind + blknr / 256, &blk_chg); - if (blk_chg) - write_block(block, (char *) dind); - block = result; - read_block(block, (char *) ind); - blk_chg = 0; - result = check_zone_nr2(ind + blknr % 256, &blk_chg); - if (blk_chg) - write_block(block, (char *) ind); - return result; - } - blknr -= 256 * 256; - block = check_zone_nr2(inode->i_zone + 9, &changed); - read_block(block, (char *) tind); - blk_chg = 0; - result = check_zone_nr2(tind + blknr / (256 * 256), &blk_chg); - if (blk_chg) - write_block(block, (char *) tind); - block = result; - read_block(block, (char *) dind); - blk_chg = 0; - result = check_zone_nr2(dind + (blknr / 256) % 256, &blk_chg); - if (blk_chg) - write_block(block, (char *) dind); - block = result; - read_block(block, (char *) ind); - blk_chg = 0; - result = check_zone_nr2(ind + blknr % 256, &blk_chg); - if (blk_chg) - write_block(block, (char *) ind); - return result; -} -#endif - -static void write_super_block(void) -{ - /* - * Set the state of the filesystem based on whether or not there - * are uncorrected errors. The filesystem valid flag is - * unconditionally set if we get this far. - */ - Super.s_state |= MINIX_VALID_FS; - if (errors_uncorrected) - Super.s_state |= MINIX_ERROR_FS; - else - Super.s_state &= ~MINIX_ERROR_FS; - - if (BLOCK_SIZE != lseek(IN, BLOCK_SIZE, SEEK_SET)) - die("seek failed in write_super_block"); - if (BLOCK_SIZE != write(IN, super_block_buffer, BLOCK_SIZE)) - die("unable to write super-block"); - - return; -} - -static void write_tables(void) -{ - write_super_block(); - - if (IMAPS * BLOCK_SIZE != write(IN, inode_map, IMAPS * BLOCK_SIZE)) - die("Unable to write inode map"); - if (ZMAPS * BLOCK_SIZE != write(IN, zone_map, ZMAPS * BLOCK_SIZE)) - die("Unable to write zone map"); - if (INODE_BUFFER_SIZE != write(IN, inode_buffer, INODE_BUFFER_SIZE)) - die("Unable to write inodes"); -} - -static void get_dirsize(void) -{ - int block; - char blk[BLOCK_SIZE]; - int size; - -#ifdef BB_FEATURE_MINIX2 - if (version2) - block = Inode2[ROOT_INO].i_zone[0]; - else -#endif - block = Inode[ROOT_INO].i_zone[0]; - read_block(block, blk); - for (size = 16; size < BLOCK_SIZE; size <<= 1) { - if (strcmp(blk + size + 2, "..") == 0) { - dirsize = size; - namelen = size - 2; - return; - } - } - /* use defaults */ -} - -static void read_superblock(void) -{ - if (BLOCK_SIZE != lseek(IN, BLOCK_SIZE, SEEK_SET)) - die("seek failed"); - if (BLOCK_SIZE != read(IN, super_block_buffer, BLOCK_SIZE)) - die("unable to read super block"); - if (MAGIC == MINIX_SUPER_MAGIC) { - namelen = 14; - dirsize = 16; - version2 = 0; - } else if (MAGIC == MINIX_SUPER_MAGIC2) { - namelen = 30; - dirsize = 32; - version2 = 0; -#ifdef BB_FEATURE_MINIX2 - } else if (MAGIC == MINIX2_SUPER_MAGIC) { - namelen = 14; - dirsize = 16; - version2 = 1; - } else if (MAGIC == MINIX2_SUPER_MAGIC2) { - namelen = 30; - dirsize = 32; - version2 = 1; -#endif - } else - die("bad magic number in super-block"); - if (ZONESIZE != 0 || BLOCK_SIZE != 1024) - die("Only 1k blocks/zones supported"); - if (IMAPS * BLOCK_SIZE * 8 < INODES + 1) - die("bad s_imap_blocks field in super-block"); - if (ZMAPS * BLOCK_SIZE * 8 < ZONES - FIRSTZONE + 1) - die("bad s_zmap_blocks field in super-block"); -} - -static void read_tables(void) -{ - inode_map = xmalloc(IMAPS * BLOCK_SIZE); - zone_map = xmalloc(ZMAPS * BLOCK_SIZE); - memset(inode_map, 0, sizeof(inode_map)); - memset(zone_map, 0, sizeof(zone_map)); - inode_buffer = xmalloc(INODE_BUFFER_SIZE); - inode_count = xmalloc(INODES + 1); - zone_count = xmalloc(ZONES); - if (IMAPS * BLOCK_SIZE != read(IN, inode_map, IMAPS * BLOCK_SIZE)) - die("Unable to read inode map"); - if (ZMAPS * BLOCK_SIZE != read(IN, zone_map, ZMAPS * BLOCK_SIZE)) - die("Unable to read zone map"); - if (INODE_BUFFER_SIZE != read(IN, inode_buffer, INODE_BUFFER_SIZE)) - die("Unable to read inodes"); - if (NORM_FIRSTZONE != FIRSTZONE) { - printf("Warning: Firstzone != Norm_firstzone\n"); - errors_uncorrected = 1; - } - get_dirsize(); - if (show) { - printf("%ld inodes\n", INODES); - printf("%ld blocks\n", ZONES); - printf("Firstdatazone=%ld (%ld)\n", FIRSTZONE, NORM_FIRSTZONE); - printf("Zonesize=%d\n", BLOCK_SIZE << ZONESIZE); - printf("Maxsize=%ld\n", MAXSIZE); - printf("Filesystem state=%d\n", Super.s_state); - printf("namelen=%d\n\n", namelen); - } -} - -static struct minix_inode *get_inode(unsigned int nr) -{ - struct minix_inode *inode; - - if (!nr || nr > INODES) - return NULL; - total++; - inode = Inode + nr; - if (!inode_count[nr]) { - if (!inode_in_use(nr)) { - printf("Inode %d marked not used, but used for file '", nr); - print_current_name(); - printf("'\n"); - if (repair) { - if (ask("Mark in use", 1)) - mark_inode(nr); - } else { - errors_uncorrected = 1; - } - } - if (S_ISDIR(inode->i_mode)) - directory++; - else if (S_ISREG(inode->i_mode)) - regular++; - else if (S_ISCHR(inode->i_mode)) - chardev++; - else if (S_ISBLK(inode->i_mode)) - blockdev++; - else if (S_ISLNK(inode->i_mode)) - symlinks++; - else if (S_ISSOCK(inode->i_mode)); - else if (S_ISFIFO(inode->i_mode)); - else { - print_current_name(); - printf(" has mode %05o\n", inode->i_mode); - } - - } else - links++; - if (!++inode_count[nr]) { - printf("Warning: inode count too big.\n"); - inode_count[nr]--; - errors_uncorrected = 1; - } - return inode; -} - -#ifdef BB_FEATURE_MINIX2 -static struct minix2_inode *get_inode2(unsigned int nr) -{ - struct minix2_inode *inode; - - if (!nr || nr > INODES) - return NULL; - total++; - inode = Inode2 + nr; - if (!inode_count[nr]) { - if (!inode_in_use(nr)) { - printf("Inode %d marked not used, but used for file '", nr); - print_current_name(); - printf("'\n"); - if (repair) { - if (ask("Mark in use", 1)) - mark_inode(nr); - else - errors_uncorrected = 1; - } - } - if (S_ISDIR(inode->i_mode)) - directory++; - else if (S_ISREG(inode->i_mode)) - regular++; - else if (S_ISCHR(inode->i_mode)) - chardev++; - else if (S_ISBLK(inode->i_mode)) - blockdev++; - else if (S_ISLNK(inode->i_mode)) - symlinks++; - else if (S_ISSOCK(inode->i_mode)); - else if (S_ISFIFO(inode->i_mode)); - else { - print_current_name(); - printf(" has mode %05o\n", inode->i_mode); - } - } else - links++; - if (!++inode_count[nr]) { - printf("Warning: inode count too big.\n"); - inode_count[nr]--; - errors_uncorrected = 1; - } - return inode; -} -#endif - -static void check_root(void) -{ - struct minix_inode *inode = Inode + ROOT_INO; - - if (!inode || !S_ISDIR(inode->i_mode)) - die("root inode isn't a directory"); -} - -#ifdef BB_FEATURE_MINIX2 -static void check_root2(void) -{ - struct minix2_inode *inode = Inode2 + ROOT_INO; - - if (!inode || !S_ISDIR(inode->i_mode)) - die("root inode isn't a directory"); -} -#endif - -static int add_zone(unsigned short *znr, int *corrected) -{ - int result; - int block; - - result = 0; - block = check_zone_nr(znr, corrected); - if (!block) - return 0; - if (zone_count[block]) { - printf("Block has been used before. Now in file `"); - print_current_name(); - printf("'."); - if (ask("Clear", 1)) { - *znr = 0; - block = 0; - *corrected = 1; - } - } - if (!block) - return 0; - if (!zone_in_use(block)) { - printf("Block %d in file `", block); - print_current_name(); - printf("' is marked not in use."); - if (ask("Correct", 1)) - mark_zone(block); - } - if (!++zone_count[block]) - zone_count[block]--; - return block; -} - -#ifdef BB_FEATURE_MINIX2 -static int add_zone2(unsigned int *znr, int *corrected) -{ - int result; - int block; - - result = 0; - block = check_zone_nr2(znr, corrected); - if (!block) - return 0; - if (zone_count[block]) { - printf("Block has been used before. Now in file `"); - print_current_name(); - printf("'."); - if (ask("Clear", 1)) { - *znr = 0; - block = 0; - *corrected = 1; - } - } - if (!block) - return 0; - if (!zone_in_use(block)) { - printf("Block %d in file `", block); - print_current_name(); - printf("' is marked not in use."); - if (ask("Correct", 1)) - mark_zone(block); - } - if (!++zone_count[block]) - zone_count[block]--; - return block; -} -#endif - -static void add_zone_ind(unsigned short *znr, int *corrected) -{ - static char blk[BLOCK_SIZE]; - int i, chg_blk = 0; - int block; - - block = add_zone(znr, corrected); - if (!block) - return; - read_block(block, blk); - for (i = 0; i < (BLOCK_SIZE >> 1); i++) - add_zone(i + (unsigned short *) blk, &chg_blk); - if (chg_blk) - write_block(block, blk); -} - -#ifdef BB_FEATURE_MINIX2 -static void add_zone_ind2(unsigned int *znr, int *corrected) -{ - static char blk[BLOCK_SIZE]; - int i, chg_blk = 0; - int block; - - block = add_zone2(znr, corrected); - if (!block) - return; - read_block(block, blk); - for (i = 0; i < BLOCK_SIZE >> 2; i++) - add_zone2(i + (unsigned int *) blk, &chg_blk); - if (chg_blk) - write_block(block, blk); -} -#endif - -static void add_zone_dind(unsigned short *znr, int *corrected) -{ - static char blk[BLOCK_SIZE]; - int i, blk_chg = 0; - int block; - - block = add_zone(znr, corrected); - if (!block) - return; - read_block(block, blk); - for (i = 0; i < (BLOCK_SIZE >> 1); i++) - add_zone_ind(i + (unsigned short *) blk, &blk_chg); - if (blk_chg) - write_block(block, blk); -} - -#ifdef BB_FEATURE_MINIX2 -static void add_zone_dind2(unsigned int *znr, int *corrected) -{ - static char blk[BLOCK_SIZE]; - int i, blk_chg = 0; - int block; - - block = add_zone2(znr, corrected); - if (!block) - return; - read_block(block, blk); - for (i = 0; i < BLOCK_SIZE >> 2; i++) - add_zone_ind2(i + (unsigned int *) blk, &blk_chg); - if (blk_chg) - write_block(block, blk); -} - -static void add_zone_tind2(unsigned int *znr, int *corrected) -{ - static char blk[BLOCK_SIZE]; - int i, blk_chg = 0; - int block; - - block = add_zone2(znr, corrected); - if (!block) - return; - read_block(block, blk); - for (i = 0; i < BLOCK_SIZE >> 2; i++) - add_zone_dind2(i + (unsigned int *) blk, &blk_chg); - if (blk_chg) - write_block(block, blk); -} -#endif - -static void check_zones(unsigned int i) -{ - struct minix_inode *inode; - - if (!i || i > INODES) - return; - if (inode_count[i] > 1) /* have we counted this file already? */ - return; - inode = Inode + i; - if (!S_ISDIR(inode->i_mode) && !S_ISREG(inode->i_mode) && - !S_ISLNK(inode->i_mode)) return; - for (i = 0; i < 7; i++) - add_zone(i + inode->i_zone, &changed); - add_zone_ind(7 + inode->i_zone, &changed); - add_zone_dind(8 + inode->i_zone, &changed); -} - -#ifdef BB_FEATURE_MINIX2 -static void check_zones2(unsigned int i) -{ - struct minix2_inode *inode; - - if (!i || i > INODES) - return; - if (inode_count[i] > 1) /* have we counted this file already? */ - return; - inode = Inode2 + i; - if (!S_ISDIR(inode->i_mode) && !S_ISREG(inode->i_mode) - && !S_ISLNK(inode->i_mode)) - return; - for (i = 0; i < 7; i++) - add_zone2(i + inode->i_zone, &changed); - add_zone_ind2(7 + inode->i_zone, &changed); - add_zone_dind2(8 + inode->i_zone, &changed); - add_zone_tind2(9 + inode->i_zone, &changed); -} -#endif - -static void check_file(struct minix_inode *dir, unsigned int offset) -{ - static char blk[BLOCK_SIZE]; - struct minix_inode *inode; - int ino; - char *name; - int block; - - block = map_block(dir, offset / BLOCK_SIZE); - read_block(block, blk); - name = blk + (offset % BLOCK_SIZE) + 2; - ino = *(unsigned short *) (name - 2); - if (ino > INODES) { - print_current_name(); - printf(" contains a bad inode number for file '"); - printf("%.*s'.", namelen, name); - if (ask(" Remove", 1)) { - *(unsigned short *) (name - 2) = 0; - write_block(block, blk); - } - ino = 0; - } - if (name_depth < MAX_DEPTH) - strncpy(name_list[name_depth], name, namelen); - name_depth++; - inode = get_inode(ino); - name_depth--; - if (!offset) { - if (!inode || strcmp(".", name)) { - print_current_name(); - printf(": bad directory: '.' isn't first\n"); - errors_uncorrected = 1; - } else - return; - } - if (offset == dirsize) { - if (!inode || strcmp("..", name)) { - print_current_name(); - printf(": bad directory: '..' isn't second\n"); - errors_uncorrected = 1; - } else - return; - } - if (!inode) - return; - if (name_depth < MAX_DEPTH) - strncpy(name_list[name_depth], name, namelen); - name_depth++; - if (list) { - if (verbose) - printf("%6d %07o %3d ", ino, inode->i_mode, inode->i_nlinks); - print_current_name(); - if (S_ISDIR(inode->i_mode)) - printf(":\n"); - else - printf("\n"); - } - check_zones(ino); - if (inode && S_ISDIR(inode->i_mode)) - recursive_check(ino); - name_depth--; - return; -} - -#ifdef BB_FEATURE_MINIX2 -static void check_file2(struct minix2_inode *dir, unsigned int offset) -{ - static char blk[BLOCK_SIZE]; - struct minix2_inode *inode; - int ino; - char *name; - int block; - - block = map_block2(dir, offset / BLOCK_SIZE); - read_block(block, blk); - name = blk + (offset % BLOCK_SIZE) + 2; - ino = *(unsigned short *) (name - 2); - if (ino > INODES) { - print_current_name(); - printf(" contains a bad inode number for file '"); - printf("%.*s'.", namelen, name); - if (ask(" Remove", 1)) { - *(unsigned short *) (name - 2) = 0; - write_block(block, blk); - } - ino = 0; - } - if (name_depth < MAX_DEPTH) - strncpy(name_list[name_depth], name, namelen); - name_depth++; - inode = get_inode2(ino); - name_depth--; - if (!offset) { - if (!inode || strcmp(".", name)) { - print_current_name(); - printf(": bad directory: '.' isn't first\n"); - errors_uncorrected = 1; - } else - return; - } - if (offset == dirsize) { - if (!inode || strcmp("..", name)) { - print_current_name(); - printf(": bad directory: '..' isn't second\n"); - errors_uncorrected = 1; - } else - return; - } - if (!inode) - return; - name_depth++; - if (list) { - if (verbose) - printf("%6d %07o %3d ", ino, inode->i_mode, inode->i_nlinks); - print_current_name(); - if (S_ISDIR(inode->i_mode)) - printf(":\n"); - else - printf("\n"); - } - check_zones2(ino); - if (inode && S_ISDIR(inode->i_mode)) - recursive_check2(ino); - name_depth--; - return; -} -#endif - -static void recursive_check(unsigned int ino) -{ - struct minix_inode *dir; - unsigned int offset; - - dir = Inode + ino; - if (!S_ISDIR(dir->i_mode)) - die("internal error"); - if (dir->i_size < 2 * dirsize) { - print_current_name(); - printf(": bad directory: size<32"); - errors_uncorrected = 1; - } - for (offset = 0; offset < dir->i_size; offset += dirsize) - check_file(dir, offset); -} - -#ifdef BB_FEATURE_MINIX2 -static void recursive_check2(unsigned int ino) -{ - struct minix2_inode *dir; - unsigned int offset; - - dir = Inode2 + ino; - if (!S_ISDIR(dir->i_mode)) - die("internal error"); - if (dir->i_size < 2 * dirsize) { - print_current_name(); - printf(": bad directory: size < 32"); - errors_uncorrected = 1; - } - for (offset = 0; offset < dir->i_size; offset += dirsize) - check_file2(dir, offset); -} -#endif - -static int bad_zone(int i) -{ - char buffer[1024]; - - if (BLOCK_SIZE * i != lseek(IN, BLOCK_SIZE * i, SEEK_SET)) - die("seek failed in bad_zone"); - return (BLOCK_SIZE != read(IN, buffer, BLOCK_SIZE)); -} - -static void check_counts(void) -{ - int i; - - for (i = 1; i <= INODES; i++) { - if (!inode_in_use(i) && Inode[i].i_mode && warn_mode) { - printf("Inode %d mode not cleared.", i); - if (ask("Clear", 1)) { - Inode[i].i_mode = 0; - changed = 1; - } - } - if (!inode_count[i]) { - if (!inode_in_use(i)) - continue; - printf("Inode %d not used, marked used in the bitmap.", i); - if (ask("Clear", 1)) - unmark_inode(i); - continue; - } - if (!inode_in_use(i)) { - printf("Inode %d used, marked unused in the bitmap.", i); - if (ask("Set", 1)) - mark_inode(i); - } - if (Inode[i].i_nlinks != inode_count[i]) { - printf("Inode %d (mode = %07o), i_nlinks=%d, counted=%d.", - i, Inode[i].i_mode, Inode[i].i_nlinks, inode_count[i]); - if (ask("Set i_nlinks to count", 1)) { - Inode[i].i_nlinks = inode_count[i]; - changed = 1; - } - } - } - for (i = FIRSTZONE; i < ZONES; i++) { - if (zone_in_use(i) == zone_count[i]) - continue; - if (!zone_count[i]) { - if (bad_zone(i)) - continue; - printf("Zone %d: marked in use, no file uses it.", i); - if (ask("Unmark", 1)) - unmark_zone(i); - continue; - } - printf("Zone %d: %sin use, counted=%d\n", - i, zone_in_use(i) ? "" : "not ", zone_count[i]); - } -} - -#ifdef BB_FEATURE_MINIX2 -static void check_counts2(void) -{ - int i; - - for (i = 1; i <= INODES; i++) { - if (!inode_in_use(i) && Inode2[i].i_mode && warn_mode) { - printf("Inode %d mode not cleared.", i); - if (ask("Clear", 1)) { - Inode2[i].i_mode = 0; - changed = 1; - } - } - if (!inode_count[i]) { - if (!inode_in_use(i)) - continue; - printf("Inode %d not used, marked used in the bitmap.", i); - if (ask("Clear", 1)) - unmark_inode(i); - continue; - } - if (!inode_in_use(i)) { - printf("Inode %d used, marked unused in the bitmap.", i); - if (ask("Set", 1)) - mark_inode(i); - } - if (Inode2[i].i_nlinks != inode_count[i]) { - printf("Inode %d (mode = %07o), i_nlinks=%d, counted=%d.", - i, Inode2[i].i_mode, Inode2[i].i_nlinks, - inode_count[i]); - if (ask("Set i_nlinks to count", 1)) { - Inode2[i].i_nlinks = inode_count[i]; - changed = 1; - } - } - } - for (i = FIRSTZONE; i < ZONES; i++) { - if (zone_in_use(i) == zone_count[i]) - continue; - if (!zone_count[i]) { - if (bad_zone(i)) - continue; - printf("Zone %d: marked in use, no file uses it.", i); - if (ask("Unmark", 1)) - unmark_zone(i); - continue; - } - printf("Zone %d: %sin use, counted=%d\n", - i, zone_in_use(i) ? "" : "not ", zone_count[i]); - } -} -#endif - -static void check(void) -{ - memset(inode_count, 0, (INODES + 1) * sizeof(*inode_count)); - memset(zone_count, 0, ZONES * sizeof(*zone_count)); - check_zones(ROOT_INO); - recursive_check(ROOT_INO); - check_counts(); -} - -#ifdef BB_FEATURE_MINIX2 -static void check2(void) -{ - memset(inode_count, 0, (INODES + 1) * sizeof(*inode_count)); - memset(zone_count, 0, ZONES * sizeof(*zone_count)); - check_zones2(ROOT_INO); - recursive_check2(ROOT_INO); - check_counts2(); -} -#endif - -/* Wed Feb 9 15:17:06 MST 2000 */ -/* dynamically allocate name_list (instead of making it static) */ -static void alloc_name_list(void) -{ - int i; - - name_list = xmalloc(sizeof(char *) * MAX_DEPTH); - for (i = 0; i < MAX_DEPTH; i++) - name_list[i] = xmalloc(sizeof(char) * BUFSIZ + 1); -} - -#ifdef BB_FEATURE_CLEAN_UP -/* execute this atexit() to deallocate name_list[] */ -/* piptigger was here */ -static void free_name_list(void) -{ - int i; - - if (name_list) { - for (i = 0; i < MAX_DEPTH; i++) { - if (name_list[i]) { - free(name_list[i]); - } - } - free(name_list); - } -} -#endif - -extern int fsck_minix_main(int argc, char **argv) -{ - struct termios tmp; - int count; - int retcode = 0; - - alloc_name_list(); -#ifdef BB_FEATURE_CLEAN_UP - /* Don't bother to free memory. Exit does - * that automagically, so we can save a few bytes */ - atexit(free_name_list); -#endif - - if (INODE_SIZE * MINIX_INODES_PER_BLOCK != BLOCK_SIZE) - die("bad inode size"); -#ifdef BB_FEATURE_MINIX2 - if (INODE_SIZE2 * MINIX2_INODES_PER_BLOCK != BLOCK_SIZE) - die("bad v2 inode size"); -#endif - while (argc-- > 1) { - argv++; - if (argv[0][0] != '-') { - if (device_name) - show_usage(); - else - device_name = argv[0]; - } else - while (*++argv[0]) - switch (argv[0][0]) { - case 'l': - list = 1; - break; - case 'a': - automatic = 1; - repair = 1; - break; - case 'r': - automatic = 0; - repair = 1; - break; - case 'v': - verbose = 1; - break; - case 's': - show = 1; - break; - case 'm': - warn_mode = 1; - break; - case 'f': - force = 1; - break; - default: - show_usage(); - } - } - if (!device_name) - show_usage(); - check_mount(); /* trying to check a mounted filesystem? */ - if (repair && !automatic) { - if (!isatty(0) || !isatty(1)) - die("need terminal for interactive repairs"); - } - IN = open(device_name, repair ? O_RDWR : O_RDONLY); - if (IN < 0){ - fprintf(stderr,"unable to open device '%s'.\n",device_name); - leave(8); - } - for (count = 0; count < 3; count++) - sync(); - read_superblock(); - - /* - * Determine whether or not we should continue with the checking. - * This is based on the status of the filesystem valid and error - * flags and whether or not the -f switch was specified on the - * command line. - */ - printf("%s, %s\n", applet_name, program_version); - if (!(Super.s_state & MINIX_ERROR_FS) && - (Super.s_state & MINIX_VALID_FS) && !force) { - if (repair) - printf("%s is clean, no check.\n", device_name); - return retcode; - } else if (force) - printf("Forcing filesystem check on %s.\n", device_name); - else if (repair) - printf("Filesystem on %s is dirty, needs checking.\n", - device_name); - - read_tables(); - - if (repair && !automatic) { - tcgetattr(0, &termios); - tmp = termios; - tmp.c_lflag &= ~(ICANON | ECHO); - tcsetattr(0, TCSANOW, &tmp); - termios_set = 1; - } -#ifdef BB_FEATURE_MINIX2 - if (version2) { - check_root2(); - check2(); - } else -#endif - { - check_root(); - check(); - } - if (verbose) { - int i, free_cnt; - - for (i = 1, free_cnt = 0; i <= INODES; i++) - if (!inode_in_use(i)) - free_cnt++; - printf("\n%6ld inodes used (%ld%%)\n", (INODES - free_cnt), - 100 * (INODES - free_cnt) / INODES); - for (i = FIRSTZONE, free_cnt = 0; i < ZONES; i++) - if (!zone_in_use(i)) - free_cnt++; - printf("%6ld zones used (%ld%%)\n", (ZONES - free_cnt), - 100 * (ZONES - free_cnt) / ZONES); - printf("\n%6d regular files\n" - "%6d directories\n" - "%6d character device files\n" - "%6d block device files\n" - "%6d links\n" - "%6d symbolic links\n" - "------\n" - "%6d files\n", - regular, directory, chardev, blockdev, - links - 2 * directory + 1, symlinks, - total - 2 * directory + 1); - } - if (changed) { - write_tables(); - printf("----------------------------\n" - "FILE SYSTEM HAS BEEN CHANGED\n" - "----------------------------\n"); - for (count = 0; count < 3; count++) - sync(); - } else if (repair) - write_super_block(); - - if (repair && !automatic) - tcsetattr(0, TCSANOW, &termios); - - if (changed) - retcode += 3; - if (errors_uncorrected) - retcode += 4; - return retcode; -} diff --git a/getopt.c b/getopt.c deleted file mode 100644 index 95ecba6e6..000000000 --- a/getopt.c +++ /dev/null @@ -1,402 +0,0 @@ -/* - * getopt.c - Enhanced implementation of BSD getopt(1) - * Copyright (c) 1997, 1998, 1999, 2000 Frodo Looijaard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * Version 1.0-b4: Tue Sep 23 1997. First public release. - * Version 1.0: Wed Nov 19 1997. - * Bumped up the version number to 1.0 - * Fixed minor typo (CSH instead of TCSH) - * Version 1.0.1: Tue Jun 3 1998 - * Fixed sizeof instead of strlen bug - * Bumped up the version number to 1.0.1 - * Version 1.0.2: Thu Jun 11 1998 (not present) - * Fixed gcc-2.8.1 warnings - * Fixed --version/-V option (not present) - * Version 1.0.5: Tue Jun 22 1999 - * Make -u option work (not present) - * Version 1.0.6: Tue Jun 27 2000 - * No important changes - * Version 1.1.0: Tue Jun 30 2000 - * Added NLS support (partly written by Arkadiusz Mikiewicz - * ) - * Ported to Busybox - Alfred M. Szmidt - * Removed --version/-V and --help/-h in - * Removed prase_error(), using error_msg() from Busybox instead - * Replaced our_malloc with xmalloc and our_realloc with xrealloc - * - */ - -#include -#include -#include -#include -#include -#include - -#include "busybox.h" - -/* NON_OPT is the code that is returned when a non-option is found in '+' - mode */ -static const int NON_OPT = 1; -/* LONG_OPT is the code that is returned when a long option is found. */ -static const int LONG_OPT = 2; - -/* The shells recognized. */ -typedef enum {BASH,TCSH} shell_t; - - -/* Some global variables that tells us how to parse. */ -static shell_t shell=BASH; /* The shell we generate output for. */ -static int quiet_errors=0; /* 0 is not quiet. */ -static int quiet_output=0; /* 0 is not quiet. */ -static int quote=1; /* 1 is do quote. */ -static int alternative=0; /* 0 is getopt_long, 1 is getopt_long_only */ - -/* Function prototypes */ -static const char *normalize(const char *arg); -static int generate_output(char * argv[],int argc,const char *optstr, - const struct option *longopts); -static void add_long_options(char *options); -static void add_longopt(const char *name,int has_arg); -static void set_shell(const char *new_shell); - - -/* - * This function 'normalizes' a single argument: it puts single quotes around - * it and escapes other special characters. If quote is false, it just - * returns its argument. - * Bash only needs special treatment for single quotes; tcsh also recognizes - * exclamation marks within single quotes, and nukes whitespace. - * This function returns a pointer to a buffer that is overwritten by - * each call. - */ -const char *normalize(const char *arg) -{ - static char *BUFFER=NULL; - const char *argptr=arg; - char *bufptr; - - if (BUFFER != NULL) - free(BUFFER); - - if (!quote) { /* Just copy arg */ - BUFFER=xmalloc(strlen(arg)+1); - - strcpy(BUFFER,arg); - return BUFFER; - } - - /* Each character in arg may take upto four characters in the result: - For a quote we need a closing quote, a backslash, a quote and an - opening quote! We need also the global opening and closing quote, - and one extra character for '\0'. */ - BUFFER=xmalloc(strlen(arg)*4+3); - - bufptr=BUFFER; - *bufptr++='\''; - - while (*argptr) { - if (*argptr == '\'') { - /* Quote: replace it with: '\'' */ - *bufptr++='\''; - *bufptr++='\\'; - *bufptr++='\''; - *bufptr++='\''; - } else if (shell==TCSH && *argptr=='!') { - /* Exclamation mark: replace it with: \! */ - *bufptr++='\''; - *bufptr++='\\'; - *bufptr++='!'; - *bufptr++='\''; - } else if (shell==TCSH && *argptr=='\n') { - /* Newline: replace it with: \n */ - *bufptr++='\\'; - *bufptr++='n'; - } else if (shell==TCSH && isspace(*argptr)) { - /* Non-newline whitespace: replace it with \ */ - *bufptr++='\''; - *bufptr++='\\'; - *bufptr++=*argptr; - *bufptr++='\''; - } else - /* Just copy */ - *bufptr++=*argptr; - argptr++; - } - *bufptr++='\''; - *bufptr++='\0'; - return BUFFER; -} - -/* - * Generate the output. argv[0] is the program name (used for reporting errors). - * argv[1..] contains the options to be parsed. argc must be the number of - * elements in argv (ie. 1 if there are no options, only the program name), - * optstr must contain the short options, and longopts the long options. - * Other settings are found in global variables. - */ -int generate_output(char * argv[],int argc,const char *optstr, - const struct option *longopts) -{ - int exit_code = 0; /* We assume everything will be OK */ - int opt; - int longindex; - const char *charptr; - - if (quiet_errors) /* No error reporting from getopt(3) */ - opterr=0; - optind=0; /* Reset getopt(3) */ - - while ((opt = (alternative? - getopt_long_only(argc,argv,optstr,longopts,&longindex): - getopt_long(argc,argv,optstr,longopts,&longindex))) - != EOF) - if (opt == '?' || opt == ':' ) - exit_code = 1; - else if (!quiet_output) { - if (opt == LONG_OPT) { - printf(" --%s",longopts[longindex].name); - if (longopts[longindex].has_arg) - printf(" %s", - normalize(optarg?optarg:"")); - } else if (opt == NON_OPT) - printf(" %s",normalize(optarg)); - else { - printf(" -%c",opt); - charptr = strchr(optstr,opt); - if (charptr != NULL && *++charptr == ':') - printf(" %s", - normalize(optarg?optarg:"")); - } - } - - if (! quiet_output) { - printf(" --"); - while (optind < argc) - printf(" %s",normalize(argv[optind++])); - printf("\n"); - } - return exit_code; -} - -static struct option *long_options=NULL; -static int long_options_length=0; /* Length of array */ -static int long_options_nr=0; /* Nr of used elements in array */ -static const int LONG_OPTIONS_INCR = 10; -#define init_longopt() add_longopt(NULL,0) - -/* Register a long option. The contents of name is copied. */ -void add_longopt(const char *name,int has_arg) -{ - char *tmp; - if (!name) { /* init */ - free(long_options); - long_options=NULL; - long_options_length=0; - long_options_nr=0; - } - - if (long_options_nr == long_options_length) { - long_options_length += LONG_OPTIONS_INCR; - long_options=xrealloc(long_options, - sizeof(struct option) * - long_options_length); - } - - long_options[long_options_nr].name=NULL; - long_options[long_options_nr].has_arg=0; - long_options[long_options_nr].flag=NULL; - long_options[long_options_nr].val=0; - - if (long_options_nr) { /* Not for init! */ - long_options[long_options_nr-1].has_arg=has_arg; - long_options[long_options_nr-1].flag=NULL; - long_options[long_options_nr-1].val=LONG_OPT; - tmp = xmalloc(strlen(name)+1); - strcpy(tmp,name); - long_options[long_options_nr-1].name=tmp; - } - long_options_nr++; -} - - -/* - * Register several long options. options is a string of long options, - * separated by commas or whitespace. - * This nukes options! - */ -void add_long_options(char *options) -{ - int arg_opt, tlen; - char *tokptr=strtok(options,", \t\n"); - while (tokptr) { - arg_opt=no_argument; - tlen=strlen(tokptr); - if (tlen > 0) { - if (tokptr[tlen-1] == ':') { - if (tlen > 1 && tokptr[tlen-2] == ':') { - tokptr[tlen-2]='\0'; - tlen -= 2; - arg_opt=optional_argument; - } else { - tokptr[tlen-1]='\0'; - tlen -= 1; - arg_opt=required_argument; - } - if (tlen == 0) - error_msg("empty long option after -l or --long argument"); - } - add_longopt(tokptr,arg_opt); - } - tokptr=strtok(NULL,", \t\n"); - } -} - -void set_shell(const char *new_shell) -{ - if (!strcmp(new_shell,"bash")) - shell=BASH; - else if (!strcmp(new_shell,"tcsh")) - shell=TCSH; - else if (!strcmp(new_shell,"sh")) - shell=BASH; - else if (!strcmp(new_shell,"csh")) - shell=TCSH; - else - error_msg("unknown shell after -s or --shell argument"); -} - - -/* Exit codes: - * 0) No errors, succesful operation. - * 1) getopt(3) returned an error. - * 2) A problem with parameter parsing for getopt(1). - * 3) Internal error, out of memory - * 4) Returned for -T - */ - -static struct option longopts[]= -{ - {"options",required_argument,NULL,'o'}, - {"longoptions",required_argument,NULL,'l'}, - {"quiet",no_argument,NULL,'q'}, - {"quiet-output",no_argument,NULL,'Q'}, - {"shell",required_argument,NULL,'s'}, - {"test",no_argument,NULL,'T'}, - {"unquoted",no_argument,NULL,'u'}, - {"alternative",no_argument,NULL,'a'}, - {"name",required_argument,NULL,'n'}, - {NULL,0,NULL,0} -}; - -/* Stop scanning as soon as a non-option argument is found! */ -static const char *shortopts="+ao:l:n:qQs:Tu"; - - -int getopt_main(int argc, char *argv[]) -{ - char *optstr=NULL; - char *name=NULL; - int opt; - int compatible=0; - - init_longopt(); - - if (getenv("GETOPT_COMPATIBLE")) - compatible=1; - - if (argc == 1) { - if (compatible) { - /* For some reason, the original getopt gave no error - when there were no arguments. */ - printf(" --\n"); - exit(0); - } else - error_msg_and_die("missing optstring argument"); - } - - if (argv[1][0] != '-' || compatible) { - quote=0; - optstr=xmalloc(strlen(argv[1])+1); - strcpy(optstr,argv[1]+strspn(argv[1],"-+")); - argv[1]=argv[0]; - exit(generate_output(argv+1,argc-1,optstr,long_options)); - } - - while ((opt=getopt_long(argc,argv,shortopts,longopts,NULL)) != EOF) - switch (opt) { - case 'a': - alternative=1; - break; - case 'o': - if (optstr) - free(optstr); - optstr=xmalloc(strlen(optarg)+1); - strcpy(optstr,optarg); - break; - case 'l': - add_long_options(optarg); - break; - case 'n': - if (name) - free(name); - name=xmalloc(strlen(optarg)+1); - strcpy(name,optarg); - break; - case 'q': - quiet_errors=1; - break; - case 'Q': - quiet_output=1; - break; - case 's': - set_shell(optarg); - break; - case 'T': - exit(4); - case 'u': - quote=0; - break; - default: - show_usage(); - } - - if (!optstr) { - if (optind >= argc) - error_msg_and_die("missing optstring argument"); - else { - optstr=xmalloc(strlen(argv[optind])+1); - strcpy(optstr,argv[optind]); - optind++; - } - } - if (name) - argv[optind-1]=name; - else - argv[optind-1]=argv[0]; - exit(generate_output(argv+optind-1,argc-optind+1,optstr,long_options)); -} - -/* - Local Variables: - c-file-style: "linux" - c-basic-offset: 4 - tab-width: 4 - End: -*/ diff --git a/getty.c b/getty.c deleted file mode 100644 index c6d0eb710..000000000 --- a/getty.c +++ /dev/null @@ -1,1232 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* agetty.c - another getty program for Linux. By W. Z. Venema 1989 - Ported to Linux by Peter Orbaek - This program is freely distributable. The entire man-page used to - be here. Now read the real man-page agetty.8 instead. - - -f option added by Eric Rasmussen - 12/28/95 - - 1999-02-22 Arkadiusz Mi¶kiewicz - - added Native Language Support - - 1999-05-05 Thorsten Kranzkowski - - enable hardware flow control before displaying /etc/issue - -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" - -#define _PATH_LOGIN "/bin/login" - -#ifdef linux -#include -#define USE_SYSLOG -#endif - -extern void updwtmp(const char *filename, const struct utmp *ut); - - /* If USE_SYSLOG is undefined all diagnostics go directly to /dev/console. */ -#ifdef USE_SYSLOG -#include -#endif - - - /* - * Some heuristics to find out what environment we are in: if it is not - * System V, assume it is SunOS 4. - */ - -#ifdef LOGIN_PROCESS /* defined in System V utmp.h */ -#define SYSV_STYLE /* select System V style getty */ -#endif - - /* - * Things you may want to modify. - * - * If ISSUE is not defined, agetty will never display the contents of the - * /etc/issue file. You will not want to spit out large "issue" files at the - * wrong baud rate. Relevant for System V only. - * - * You may disagree with the default line-editing etc. characters defined - * below. Note, however, that DEL cannot be used for interrupt generation - * and for line editing at the same time. - */ - -#ifdef SYSV_STYLE -#define ISSUE "/etc/issue" /* displayed before the login prompt */ -#include -#include -#endif - -#define LOGIN " login: " /* login prompt */ - -/* Some shorthands for control characters. */ - -#define CTL(x) (x ^ 0100) /* Assumes ASCII dialect */ -#define CR CTL('M') /* carriage return */ -#define NL CTL('J') /* line feed */ -#define BS CTL('H') /* back space */ -#define DEL CTL('?') /* delete */ - -/* Defaults for line-editing etc. characters; you may want to change this. */ - -#define DEF_ERASE DEL /* default erase character */ -#define DEF_INTR CTL('C') /* default interrupt character */ -#define DEF_QUIT CTL('\\') /* default quit char */ -#define DEF_KILL CTL('U') /* default kill char */ -#define DEF_EOF CTL('D') /* default EOF char */ -#define DEF_EOL 0 -#define DEF_SWITCH 0 /* default switch char */ - - /* - * SunOS 4.1.1 termio is broken. We must use the termios stuff instead, - * because the termio -> termios translation does not clear the termios - * CIBAUD bits. Therefore, the tty driver would sometimes report that input - * baud rate != output baud rate. I did not notice that problem with SunOS - * 4.1. We will use termios where available, and termio otherwise. - */ - -/* linux 0.12 termio is broken too, if we use it c_cc[VERASE] isn't set - properly, but all is well if we use termios?! */ - -#ifdef TCGETS -#undef TCGETA -#undef TCSETA -#undef TCSETAW -#define termio termios -#define TCGETA TCGETS -#define TCSETA TCSETS -#define TCSETAW TCSETSW -#endif - - /* - * This program tries to not use the standard-i/o library. This keeps the - * executable small on systems that do not have shared libraries (System V - * Release <3). - */ -#ifndef BUFSIZ -#define BUFSIZ 1024 -#endif - - /* - * When multiple baud rates are specified on the command line, the first one - * we will try is the first one specified. - */ - -#define FIRST_SPEED 0 - -/* Storage for command-line options. */ - -#define MAX_SPEED 10 /* max. nr. of baud rates */ - -struct options { - int flags; /* toggle switches, see below */ - int timeout; /* time-out period */ - char *login; /* login program */ - char *tty; /* name of tty */ - char *initstring; /* modem init string */ - char *issue; /* alternative issue file */ - int numspeed; /* number of baud rates to try */ - int speeds[MAX_SPEED]; /* baud rates to be tried */ -}; - -#define F_PARSE (1<<0) /* process modem status messages */ -#define F_ISSUE (1<<1) /* display /etc/issue */ -#define F_RTSCTS (1<<2) /* enable RTS/CTS flow control */ -#define F_LOCAL (1<<3) /* force local */ -#define F_INITSTRING (1<<4) /* initstring is set */ -#define F_WAITCRLF (1<<5) /* wait for CR or LF */ -#define F_CUSTISSUE (1<<6) /* give alternative issue file */ -#define F_NOPROMPT (1<<7) /* don't ask for login name! */ - -/* Storage for things detected while the login name was read. */ - -struct chardata { - int erase; /* erase character */ - int kill; /* kill character */ - int eol; /* end-of-line character */ - int parity; /* what parity did we see */ - int capslock; /* upper case without lower case */ -}; - -/* Initial values for the above. */ - -struct chardata init_chardata = { - DEF_ERASE, /* default erase character */ - DEF_KILL, /* default kill character */ - 13, /* default eol char */ - 0, /* space parity */ - 0, /* no capslock */ -}; - -struct Speedtab { - long speed; - int code; -}; - -static struct Speedtab speedtab[] = { - {50, B50}, - {75, B75}, - {110, B110}, - {134, B134}, - {150, B150}, - {200, B200}, - {300, B300}, - {600, B600}, - {1200, B1200}, - {1800, B1800}, - {2400, B2400}, - {4800, B4800}, - {9600, B9600}, -#ifdef B19200 - {19200, B19200}, -#endif -#ifdef B38400 - {38400, B38400}, -#endif -#ifdef EXTA - {19200, EXTA}, -#endif -#ifdef EXTB - {38400, EXTB}, -#endif -#ifdef B57600 - {57600, B57600}, -#endif -#ifdef B115200 - {115200, B115200}, -#endif -#ifdef B230400 - {230400, B230400}, -#endif - {0, 0}, -}; - -void parse_args(int argc, char **argv, struct options *op); -void parse_speeds(struct options *op, char *arg); -void update_utmp(char *line); -void open_tty(char *tty, struct termio *tp, int local); -void termio_init(struct termio *tp, int speed, struct options *op); -void auto_baud(struct termio *tp); -void do_prompt(struct options *op, struct termio *tp); -void next_speed(struct termio *tp, struct options *op); -char *get_logname(struct options *op, struct chardata *cp, - - struct termio *tp); -void termio_final(struct options *op, struct termio *tp, - - struct chardata *cp); -int caps_lock(char *s); -int bcode(char *s); -static void error(const char *fmt, ...); - -/* The following is used for understandable diagnostics. */ - -char *progname; - -/* Fake hostname for ut_host specified on command line. */ -char *fakehost = NULL; - -/* ... */ -#ifdef DEBUGGING -#define debug(s) fprintf(dbf,s); fflush(dbf) -#define DEBUGTERM "/dev/ttyp0" -FILE *dbf; -#else -#define debug(s) /* nothing */ -#endif - -int getty_main(int argc, char **argv) -{ - char *logname = NULL; /* login name, given to /bin/login */ - struct chardata chardata; /* set by get_logname() */ - struct termio termio; /* terminal mode bits */ - static struct options options = { - F_ISSUE, /* show /etc/issue (SYSV_STYLE) */ - 0, /* no timeout */ - _PATH_LOGIN, /* default login program */ - "tty1", /* default tty line */ - "", /* modem init string */ - ISSUE, /* default issue file */ - 0, /* no baud rates known yet */ - }; - - /* The BSD-style init command passes us a useless process name. */ - -#ifdef SYSV_STYLE - progname = argv[0]; -#else - progname = "getty"; -#endif - -#ifdef DEBUGGING - dbf = xfopen(DEBUGTERM, "w"); - - { - int i; - - for (i = 1; i < argc; i++) { - debug(argv[i]); - debug("\n"); - } - } -#endif - - /* Parse command-line arguments. */ - - parse_args(argc, argv, &options); - -#ifdef __linux__ - setsid(); -#endif - - /* Update the utmp file. */ - -#ifdef SYSV_STYLE - update_utmp(options.tty); -#endif - - debug("calling open_tty\n"); - /* Open the tty as standard { input, output, error }. */ - open_tty(options.tty, &termio, options.flags & F_LOCAL); - -#ifdef __linux__ - { - int iv; - - iv = getpid(); - if (ioctl(0, TIOCSPGRP, &iv) < 0) - perror_msg("ioctl() TIOCSPGRP call failed"); - } -#endif - /* Initialize the termio settings (raw mode, eight-bit, blocking i/o). */ - debug("calling termio_init\n"); - termio_init(&termio, options.speeds[FIRST_SPEED], &options); - - /* write the modem init string and DON'T flush the buffers */ - if (options.flags & F_INITSTRING) { - debug("writing init string\n"); - write(1, options.initstring, strlen(options.initstring)); - } - - if (!(options.flags & F_LOCAL)) { - /* go to blocking write mode unless -L is specified */ - fcntl(1, F_SETFL, fcntl(1, F_GETFL, 0) & ~O_NONBLOCK); - } - - /* Optionally detect the baud rate from the modem status message. */ - debug("before autobaud\n"); - if (options.flags & F_PARSE) - auto_baud(&termio); - - /* Set the optional timer. */ - if (options.timeout) - (void) alarm((unsigned) options.timeout); - - /* optionally wait for CR or LF before writing /etc/issue */ - if (options.flags & F_WAITCRLF) { - char ch; - - debug("waiting for cr-lf\n"); - while (read(0, &ch, 1) == 1) { - ch &= 0x7f; /* strip "parity bit" */ -#ifdef DEBUGGING - fprintf(dbf, "read %c\n", ch); -#endif - if (ch == '\n' || ch == '\r') - break; - } - } - - chardata = init_chardata; - if (!(options.flags & F_NOPROMPT)) { - /* Read the login name. */ - debug("reading login name\n"); - /* while ((logname = get_logname(&options, &chardata, &termio)) == 0) */ - while ((logname = get_logname(&options, &chardata, &termio)) == - NULL) next_speed(&termio, &options); - } - - /* Disable timer. */ - - if (options.timeout) - (void) alarm(0); - - /* Finalize the termio settings. */ - - termio_final(&options, &termio, &chardata); - - /* Now the newline character should be properly written. */ - - (void) write(1, "\n", 1); - - /* Let the login program take care of password validation. */ - - (void) execl(options.login, options.login, "--", logname, (char *) 0); - error("%s: can't exec %s: %m", options.tty, options.login); - return (0); /* quiet GCC */ -} - -/* parse-args - parse command-line arguments */ - -void parse_args(argc, argv, op) -int argc; -char **argv; -struct options *op; -{ - extern char *optarg; /* getopt */ - extern int optind; /* getopt */ - int c; - - while (isascii(c = getopt(argc, argv, "I:LH:f:hil:mt:wn"))) { - switch (c) { - case 'I': - if (!(op->initstring = malloc(strlen(optarg)))) { - error("can't malloc initstring"); - break; - } - { - char ch, *p, *q; - int i; - - /* copy optarg into op->initstring decoding \ddd - octal codes into chars */ - q = op->initstring; - p = optarg; - while (*p) { - if (*p == '\\') { /* know \\ means \ */ - p++; - if (*p == '\\') { - ch = '\\'; - p++; - } else { /* handle \000 - \177 */ - ch = 0; - for (i = 1; i <= 3; i++) { - if (*p >= '0' && *p <= '7') { - ch <<= 3; - ch += *p - '0'; - p++; - } else - break; - } - } - *q++ = ch; - } else { - *q++ = *p++; - } - } - *q = '\0'; - } - op->flags |= F_INITSTRING; - break; - - case 'L': /* force local */ - op->flags |= F_LOCAL; - break; - case 'H': /* fake login host */ - fakehost = optarg; - break; - case 'f': /* custom issue file */ - op->flags |= F_CUSTISSUE; - op->issue = optarg; - break; - case 'h': /* enable h/w flow control */ - op->flags |= F_RTSCTS; - break; - case 'i': /* do not show /etc/issue */ - op->flags &= ~F_ISSUE; - break; - case 'l': - op->login = optarg; /* non-default login program */ - break; - case 'm': /* parse modem status message */ - op->flags |= F_PARSE; - break; - case 'n': - op->flags |= F_NOPROMPT; - break; - case 't': /* time out */ - if ((op->timeout = atoi(optarg)) <= 0) - error("bad timeout value: %s", optarg); - break; - case 'w': - op->flags |= F_WAITCRLF; - break; - default: - show_usage(); - } - } - debug("after getopt loop\n"); - if (argc < optind + 2) /* check parameter count */ - show_usage(); - - /* we loosen up a bit and accept both "baudrate tty" and "tty baudrate" */ - if ('0' <= argv[optind][0] && argv[optind][0] <= '9') { - /* a number first, assume it's a speed (BSD style) */ - parse_speeds(op, argv[optind++]); /* baud rate(s) */ - op->tty = argv[optind]; /* tty name */ - } else { - op->tty = argv[optind++]; /* tty name */ - parse_speeds(op, argv[optind]); /* baud rate(s) */ - } - - optind++; - if (argc > optind && argv[optind]) - setenv("TERM", argv[optind], 1); - - debug("exiting parseargs\n"); -} - -/* parse_speeds - parse alternate baud rates */ - -void parse_speeds(op, arg) -struct options *op; -char *arg; -{ - char *strtok(); - char *cp; - - debug("entered parse_speeds\n"); - for (cp = strtok(arg, ","); cp != 0; cp = strtok((char *) 0, ",")) { - if ((op->speeds[op->numspeed++] = bcode(cp)) <= 0) - error("bad speed: %s", cp); - if (op->numspeed > MAX_SPEED) - error("too many alternate speeds"); - } - debug("exiting parsespeeds\n"); -} - -#ifdef SYSV_STYLE - -/* update_utmp - update our utmp entry */ -void update_utmp(line) -char *line; -{ - struct utmp ut; - int mypid = getpid(); - long time(); - long lseek(); -#ifndef __UCLIBC__ - time_t t; - struct utmp *utp; -#endif - -#if ! (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1)) - struct flock lock; -#endif - - /* - * The utmp file holds miscellaneous information about things started by - * /sbin/init and other system-related events. Our purpose is to update - * the utmp entry for the current process, in particular the process type - * and the tty line we are listening to. Return successfully only if the - * utmp file can be opened for update, and if we are able to find our - * entry in the utmp file. - */ - -#ifndef __UCLIBC__ - utmpname(_PATH_UTMP); - setutent(); - while ((utp = getutent()) - && !(utp->ut_type == INIT_PROCESS && utp->ut_pid == mypid)) /* nothing */ - ; - - if (utp) { - memcpy(&ut, utp, sizeof(ut)); - } else { - /* some inits don't initialize utmp... */ - memset(&ut, 0, sizeof(ut)); - strncpy(ut.ut_id, line + 3, sizeof(ut.ut_id)); - } - /*endutent(); */ - - strncpy(ut.ut_user, "LOGIN", sizeof(ut.ut_user)); - strncpy(ut.ut_line, line, sizeof(ut.ut_line)); - if (fakehost) - strncpy(ut.ut_host, fakehost, sizeof(ut.ut_host)); - time(&t); - ut.ut_time = t; - ut.ut_type = LOGIN_PROCESS; - ut.ut_pid = mypid; - - pututline(&ut); - endutent(); - - { - updwtmp(_PATH_WTMP, &ut); - } -#else /* not __linux__ */ - { - int ut_fd; - - if ((ut_fd = open(_PATH_WTMP, 2)) < 0) { - error("%s: open for update: %m"), _PATH_WTMP; - } else { - long ut_size = sizeof(ut); /* avoid nonsense */ - - while (read(ut_fd, (char *) &ut, sizeof(ut)) == sizeof(ut)) { - if (ut.ut_type == INIT_PROCESS && ut.ut_pid == mypid) { - ut.ut_type = LOGIN_PROCESS; - ut.ut_time = time((long *) 0); - (void) strncpy(ut.ut_name, "LOGIN", sizeof(ut.ut_name)); - (void) strncpy(ut.ut_line, line, sizeof(ut.ut_line)); - if (fakehost) - (void) strncpy(ut.ut_host, fakehost, sizeof(ut.ut_host)); - (void) lseek(ut_fd, -ut_size, 1); - (void) write(ut_fd, (char *) &ut, sizeof(ut)); - (void) close(ut_fd); - return; - } - } - error("%s: no utmp entry", line); - } - } -#endif /* __linux__ */ -} - -#endif - -/* open_tty - set up tty as standard { input, output, error } */ -void open_tty(tty, tp, local) -char *tty; -struct termio *tp; -int local; -{ - /* Get rid of the present standard { output, error} if any. */ - - (void) close(1); - (void) close(2); - errno = 0; /* ignore above errors */ - - /* Set up new standard input, unless we are given an already opened port. */ - - if (strcmp(tty, "-")) { - struct stat st; - - /* Sanity checks... */ - - if (chdir("/dev")) - error("/dev: chdir() failed: %m"); - if (stat(tty, &st) < 0) - error("/dev/%s: %m", tty); - if ((st.st_mode & S_IFMT) != S_IFCHR) - error("/dev/%s: not a character device", tty); - - /* Open the tty as standard input. */ - - (void) close(0); - errno = 0; /* ignore close(2) errors */ - - debug("open(2)\n"); - if (open(tty, O_RDWR | O_NONBLOCK, 0) != 0) - error("/dev/%s: cannot open as standard input: %m", tty); - - } else { - - /* - * Standard input should already be connected to an open port. Make - * sure it is open for read/write. - */ - - if ((fcntl(0, F_GETFL, 0) & O_RDWR) != O_RDWR) - error("%s: not open for read/write", tty); - } - - /* Set up standard output and standard error file descriptors. */ - debug("duping\n"); - if (dup(0) != 1 || dup(0) != 2) /* set up stdout and stderr */ - error("%s: dup problem: %m", tty); /* we have a problem */ - - /* - * The following ioctl will fail if stdin is not a tty, but also when - * there is noise on the modem control lines. In the latter case, the - * common course of action is (1) fix your cables (2) give the modem more - * time to properly reset after hanging up. SunOS users can achieve (2) - * by patching the SunOS kernel variable "zsadtrlow" to a larger value; - * 5 seconds seems to be a good value. - */ - - if (ioctl(0, TCGETA, tp) < 0) - error("%s: ioctl: %m", tty); - - /* - * It seems to be a terminal. Set proper protections and ownership. Mode - * 0622 is suitable for SYSV <4 because /bin/login does not change - * protections. SunOS 4 login will change the protections to 0620 (write - * access for group tty) after the login has succeeded. - */ - -#ifdef DEBIAN - { - /* tty to root.dialout 660 */ - struct group *gr; - int id; - - id = (gr = getgrnam("dialout")) ? gr->gr_gid : 0; - chown(tty, 0, id); - chmod(tty, 0660); - - /* vcs,vcsa to root.sys 600 */ - if (!strncmp(tty, "tty", 3) && isdigit(tty[3])) { - char *vcs, *vcsa; - - if (!(vcs = malloc(strlen(tty)))) - error("Can't malloc for vcs"); - if (!(vcsa = malloc(strlen(tty) + 1))) - error("Can't malloc for vcsa"); - strcpy(vcs, "vcs"); - strcpy(vcs + 3, tty + 3); - strcpy(vcsa, "vcsa"); - strcpy(vcsa + 4, tty + 3); - - id = (gr = getgrnam("sys")) ? gr->gr_gid : 0; - chown(vcs, 0, id); - chmod(vcs, 0600); - chown(vcsa, 0, id); - chmod(vcs, 0600); - - free(vcs); - free(vcsa); - } - } -#else - (void) chown(tty, 0, 0); /* root, sys */ - (void) chmod(tty, 0622); /* crw--w--w- */ - errno = 0; /* ignore above errors */ -#endif -} - -/* termio_init - initialize termio settings */ - -char gbuf[1024]; -char area[1024]; - -void termio_init(tp, speed, op) -struct termio *tp; -int speed; -struct options *op; -{ - - /* - * Initial termio settings: 8-bit characters, raw-mode, blocking i/o. - * Special characters are set after we have read the login name; all - * reads will be done in raw mode anyway. Errors will be dealt with - * lateron. - */ -#ifdef __linux__ - /* flush input and output queues, important for modems! */ - (void) ioctl(0, TCFLSH, TCIOFLUSH); -#endif - - tp->c_cflag = CS8 | HUPCL | CREAD | speed; - if (op->flags & F_LOCAL) { - tp->c_cflag |= CLOCAL; - } - - tp->c_iflag = tp->c_lflag = tp->c_oflag = tp->c_line = 0; - tp->c_cc[VMIN] = 1; - tp->c_cc[VTIME] = 0; - - /* Optionally enable hardware flow control */ - -#ifdef CRTSCTS - if (op->flags & F_RTSCTS) - tp->c_cflag |= CRTSCTS; -#endif - - (void) ioctl(0, TCSETA, tp); - - /* go to blocking input even in local mode */ - fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) & ~O_NONBLOCK); - - debug("term_io 2\n"); -} - -/* auto_baud - extract baud rate from modem status message */ -void auto_baud(tp) -struct termio *tp; -{ - int speed; - int vmin; - unsigned iflag; - char buf[BUFSIZ]; - char *bp; - int nread; - - /* - * This works only if the modem produces its status code AFTER raising - * the DCD line, and if the computer is fast enough to set the proper - * baud rate before the message has gone by. We expect a message of the - * following format: - * - * - * - * The number is interpreted as the baud rate of the incoming call. If the - * modem does not tell us the baud rate within one second, we will keep - * using the current baud rate. It is advisable to enable BREAK - * processing (comma-separated list of baud rates) if the processing of - * modem status messages is enabled. - */ - - /* - * Use 7-bit characters, don't block if input queue is empty. Errors will - * be dealt with lateron. - */ - - iflag = tp->c_iflag; - tp->c_iflag |= ISTRIP; /* enable 8th-bit stripping */ - vmin = tp->c_cc[VMIN]; - tp->c_cc[VMIN] = 0; /* don't block if queue empty */ - (void) ioctl(0, TCSETA, tp); - - /* - * Wait for a while, then read everything the modem has said so far and - * try to extract the speed of the dial-in call. - */ - - (void) sleep(1); - if ((nread = read(0, buf, sizeof(buf) - 1)) > 0) { - buf[nread] = '\0'; - for (bp = buf; bp < buf + nread; bp++) { - if (isascii(*bp) && isdigit(*bp)) { - if ((speed = bcode(bp))) { - tp->c_cflag &= ~CBAUD; - tp->c_cflag |= speed; - } - break; - } - } - } - /* Restore terminal settings. Errors will be dealt with lateron. */ - - tp->c_iflag = iflag; - tp->c_cc[VMIN] = vmin; - (void) ioctl(0, TCSETA, tp); -} - -/* do_prompt - show login prompt, optionally preceded by /etc/issue contents */ -void do_prompt(op, tp) -struct options *op; -struct termio *tp; -{ -#ifdef ISSUE - FILE *fd; - int oflag; - int c; - struct utsname uts; - - (void) uname(&uts); -#endif - - (void) write(1, "\r\n", 2); /* start a new line */ -#ifdef ISSUE /* optional: show /etc/issue */ - if ((op->flags & F_ISSUE) && (fd = fopen(op->issue, "r"))) { - oflag = tp->c_oflag; /* save current setting */ - tp->c_oflag |= (ONLCR | OPOST); /* map NL in output to CR-NL */ - (void) ioctl(0, TCSETAW, tp); - - - while ((c = getc(fd)) != EOF) { - if (c == '\\') { - c = getc(fd); - - switch (c) { - case 's': - (void) printf("%s", uts.sysname); - break; - - case 'n': - (void) printf("%s", uts.nodename); - break; - - case 'r': - (void) printf("%s", uts.release); - break; - - case 'v': - (void) printf("%s", uts.version); - break; - - case 'm': - (void) printf("%s", uts.machine); - break; - - case 'o': - { - char domainname[256]; - - getdomainname(domainname, sizeof(domainname)); - domainname[sizeof(domainname) - 1] = '\0'; - printf("%s", domainname); - } - break; - - case 'd': - case 't': - { - char *weekday[] = { "Sun", "Mon", "Tue", "Wed", "Thu", - "Fri", "Sat" - }; - char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", - "Jun", "Jul", "Aug", "Sep", "Oct", - "Nov", "Dec" - }; - time_t now; - struct tm *tm; - - (void) time(&now); - tm = localtime(&now); - - if (c == 'd') - (void) printf("%s %s %d %d", - weekday[tm->tm_wday], - month[tm->tm_mon], tm->tm_mday, - tm->tm_year < - 70 ? tm->tm_year + - 2000 : tm->tm_year + 1900); - else - (void) printf("%02d:%02d:%02d", tm->tm_hour, - tm->tm_min, tm->tm_sec); - - break; - } - - case 'l': - (void) printf("%s", op->tty); - break; - - case 'b': - { - int i; - - for (i = 0; speedtab[i].speed; i++) { - if (speedtab[i].code == (tp->c_cflag & CBAUD)) { - printf("%ld", speedtab[i].speed); - break; - } - } - break; - } - case 'u': - case 'U': - { - int users = 0; - struct utmp *ut; - - setutent(); - while ((ut = getutent())) - if (ut->ut_type == USER_PROCESS) - users++; - endutent(); - printf("%d ", users); - if (c == 'U') - printf((users == 1) ? "user" : "users"); - break; - } - default: - (void) putchar(c); - } - } else - (void) putchar(c); - } - fflush(stdout); - - tp->c_oflag = oflag; /* restore settings */ - (void) ioctl(0, TCSETAW, tp); /* wait till output is gone */ - (void) fclose(fd); - } -#endif -#ifdef __linux__ - { - char hn[MAXHOSTNAMELEN + 1]; - - (void) gethostname(hn, MAXHOSTNAMELEN); - write(1, hn, strlen(hn)); - } -#endif - (void) write(1, LOGIN, sizeof(LOGIN) - 1); /* always show login prompt */ -} - -/* next_speed - select next baud rate */ -void next_speed(tp, op) -struct termio *tp; -struct options *op; -{ - static int baud_index = FIRST_SPEED; /* current speed index */ - - baud_index = (baud_index + 1) % op->numspeed; - tp->c_cflag &= ~CBAUD; - tp->c_cflag |= op->speeds[baud_index]; - (void) ioctl(0, TCSETA, tp); -} - -/* get_logname - get user name, establish parity, speed, erase, kill, eol */ -/* return NULL on failure, logname on success */ -char *get_logname(op, cp, tp) -struct options *op; -struct chardata *cp; -struct termio *tp; -{ - static char logname[BUFSIZ]; - char *bp; - char c; /* input character, full eight bits */ - char ascval; /* low 7 bits of input character */ - int bits; /* # of "1" bits per character */ - int mask; /* mask with 1 bit up */ - static char *erase[] = { /* backspace-space-backspace */ - "\010\040\010", /* space parity */ - "\010\040\010", /* odd parity */ - "\210\240\210", /* even parity */ - "\210\240\210", /* no parity */ - }; - - /* Initialize kill, erase, parity etc. (also after switching speeds). */ - - *cp = init_chardata; - - /* Flush pending input (esp. after parsing or switching the baud rate). */ - - (void) sleep(1); - (void) ioctl(0, TCFLSH, TCIFLUSH); - - /* Prompt for and read a login name. */ - - for (*logname = 0; *logname == 0; /* void */ ) { - - /* Write issue file and prompt, with "parity" bit == 0. */ - - do_prompt(op, tp); - - /* Read name, watch for break, parity, erase, kill, end-of-line. */ - - for (bp = logname, cp->eol = 0; cp->eol == 0; /* void */ ) { - - /* Do not report trivial EINTR/EIO errors. */ - - if (read(0, &c, 1) < 1) { - if (errno == EINTR || errno == EIO) - exit(0); - error("%s: read: %m", op->tty); - } - /* Do BREAK handling elsewhere. */ - - if ((c == 0) && op->numspeed > 1) - /* return (0); */ - return NULL; - - /* Do parity bit handling. */ - - if (c != (ascval = (c & 0177))) { /* "parity" bit on ? */ - for (bits = 1, mask = 1; mask & 0177; mask <<= 1) - if (mask & ascval) - bits++; /* count "1" bits */ - cp->parity |= ((bits & 1) ? 1 : 2); - } - /* Do erase, kill and end-of-line processing. */ - - switch (ascval) { - case CR: - case NL: - *bp = 0; /* terminate logname */ - cp->eol = ascval; /* set end-of-line char */ - break; - case BS: - case DEL: - case '#': - cp->erase = ascval; /* set erase character */ - if (bp > logname) { - (void) write(1, erase[cp->parity], 3); - bp--; - } - break; - case CTL('U'): - case '@': - cp->kill = ascval; /* set kill character */ - while (bp > logname) { - (void) write(1, erase[cp->parity], 3); - bp--; - } - break; - case CTL('D'): - exit(0); - default: - if (!isascii(ascval) || !isprint(ascval)) { - /* ignore garbage characters */ ; - } else if (bp - logname >= sizeof(logname) - 1) { - error("%s: input overrun", op->tty); - } else { - (void) write(1, &c, 1); /* echo the character */ - *bp++ = ascval; /* and store it */ - } - break; - } - } - } - /* Handle names with upper case and no lower case. */ - - if ((cp->capslock = caps_lock(logname))) { - for (bp = logname; *bp; bp++) - if (isupper(*bp)) - *bp = tolower(*bp); /* map name to lower case */ - } - return (logname); -} - -/* termio_final - set the final tty mode bits */ -void termio_final(op, tp, cp) -struct options *op; -struct termio *tp; -struct chardata *cp; -{ - /* General terminal-independent stuff. */ - - tp->c_iflag |= IXON | IXOFF; /* 2-way flow control */ - tp->c_lflag |= ICANON | ISIG | ECHO | ECHOE | ECHOK | ECHOKE; - /* no longer| ECHOCTL | ECHOPRT */ - tp->c_oflag |= OPOST; - /* tp->c_cflag = 0; */ - tp->c_cc[VINTR] = DEF_INTR; /* default interrupt */ - tp->c_cc[VQUIT] = DEF_QUIT; /* default quit */ - tp->c_cc[VEOF] = DEF_EOF; /* default EOF character */ - tp->c_cc[VEOL] = DEF_EOL; -#ifdef __linux__ - tp->c_cc[VSWTC] = DEF_SWITCH; /* default switch character */ -#else - tp->c_cc[VSWTCH] = DEF_SWITCH; /* default switch character */ -#endif - - /* Account for special characters seen in input. */ - - if (cp->eol == CR) { - tp->c_iflag |= ICRNL; /* map CR in input to NL */ - tp->c_oflag |= ONLCR; /* map NL in output to CR-NL */ - } - tp->c_cc[VERASE] = cp->erase; /* set erase character */ - tp->c_cc[VKILL] = cp->kill; /* set kill character */ - - /* Account for the presence or absence of parity bits in input. */ - - switch (cp->parity) { - case 0: /* space (always 0) parity */ - break; - case 1: /* odd parity */ - tp->c_cflag |= PARODD; - /* FALLTHROUGH */ - case 2: /* even parity */ - tp->c_cflag |= PARENB; - tp->c_iflag |= INPCK | ISTRIP; - /* FALLTHROUGH */ - case (1 | 2): /* no parity bit */ - tp->c_cflag &= ~CSIZE; - tp->c_cflag |= CS7; - break; - } - /* Account for upper case without lower case. */ - - if (cp->capslock) { - tp->c_iflag |= IUCLC; - tp->c_lflag |= XCASE; - tp->c_oflag |= OLCUC; - } - /* Optionally enable hardware flow control */ - -#ifdef CRTSCTS - if (op->flags & F_RTSCTS) - tp->c_cflag |= CRTSCTS; -#endif - - /* Finally, make the new settings effective */ - - if (ioctl(0, TCSETA, tp) < 0) - error("%s: ioctl: TCSETA: %m", op->tty); -} - -/* caps_lock - string contains upper case without lower case */ -/* returns 1 if true, 0 if false */ -int caps_lock(s) -char *s; -{ - int capslock; - - for (capslock = 0; *s; s++) { - if (islower(*s)) - return (0); - if (capslock == 0) - capslock = isupper(*s); - } - return (capslock); -} - -/* bcode - convert speed string to speed code; return 0 on failure */ -int bcode(s) -char *s; -{ - struct Speedtab *sp; - long speed = atol(s); - - for (sp = speedtab; sp->speed; sp++) - if (sp->speed == speed) - return (sp->code); - return (0); -} - -/* error - report errors to console or syslog; only understands %s and %m */ - -#define str2cpy(b,s1,s2) strcat(strcpy(b,s1),s2) - -/* - * output error messages - */ -static void error(const char *fmt, ...) -{ - va_list va_alist; - char buf[256], *bp; - -#ifndef USE_SYSLOG - int fd; -#endif - -#ifdef USE_SYSLOG - buf[0] = '\0'; - bp = buf; -#else - strncpy(buf, progname, 256); - strncat(buf, ": ", 256); - buf[255] = 0; - bp = buf + strlen(buf); -#endif - - va_start(va_alist, fmt); - vsnprintf(bp, 256 - strlen(buf), fmt, va_alist); - buf[255] = 0; - va_end(va_alist); - -#ifdef USE_SYSLOG - openlog(progname, LOG_PID, LOG_AUTH); - syslog(LOG_ERR, buf); - closelog(); -#else - strncat(bp, "\r\n", 256 - strlen(buf)); - buf[255] = 0; - if ((fd = open("/dev/console", 1)) >= 0) { - write(fd, buf, strlen(buf)); - close(fd); - } -#endif - (void) sleep((unsigned) 10); /* be kind to init(8) */ - exit(1); -} diff --git a/grep.c b/grep.c deleted file mode 100644 index eff7c3ff5..000000000 --- a/grep.c +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Mini grep implementation for busybox using libc regex. - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Mark Whitley , - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include /* for strerror() */ -#include -#include "busybox.h" - - -extern int optind; /* in unistd.h */ -extern void xregcomp(regex_t *preg, const char *regex, int cflags); /* in busybox.h */ - -/* options */ -static int reflags = REG_NOSUB; -static int print_filename = 0; -static int print_line_num = 0; -static int print_match_counts = 0; -static int be_quiet = 0; -static int invert_search = 0; -static int suppress_err_msgs = 0; -static int print_files_with_matches = 0; - -#ifdef BB_FEATURE_GREP_CONTEXT -extern char *optarg; /* in getopt.h */ -static int lines_before = 0; -static int lines_after = 0; -static char **before_buf = NULL; -static int last_line_printed = 0; -#endif /* BB_FEATURE_GREP_CONTEXT */ - -/* globals used internally */ -static regex_t *regexes = NULL; /* growable array of compiled regular expressions */ -static int nregexes = 0; /* number of elements in above arrary */ -static int matched; /* keeps track of whether we ever matched */ -static char *cur_file = NULL; /* the current file we are reading */ - - -static void print_line(const char *line, int linenum, char decoration) -{ -#ifdef BB_FEATURE_GREP_CONTEXT - /* possibly print the little '--' seperator */ - if ((lines_before || lines_after) && last_line_printed && - last_line_printed < linenum - 1) { - puts("--"); - } - last_line_printed = linenum; -#endif - if (print_filename) - printf("%s%c", cur_file, decoration); - if (print_line_num) - printf("%i%c", linenum, decoration); - puts(line); -} - - -static void grep_file(FILE *file) -{ - char *line = NULL; - int ret; - int linenum = 0; - int nmatches = 0; - int i; -#ifdef BB_FEATURE_GREP_CONTEXT - int print_n_lines_after = 0; - int curpos = 0; /* track where we are in the circular 'before' buffer */ - int idx = 0; /* used for iteration through the circular buffer */ -#endif /* BB_FEATURE_GREP_CONTEXT */ - - while ((line = get_line_from_file(file)) != NULL) { - chomp(line); - linenum++; - - for (i = 0; i < nregexes; i++) { - /* - * test for a postitive-assertion match (regexec returns success (0) - * and the user did not specify invert search), or a negative-assertion - * match (regexec returns failure (REG_NOMATCH) and the user specified - * invert search) - */ - ret = regexec(®exes[i], line, 0, NULL, 0); - if ((ret == 0 && !invert_search) || (ret == REG_NOMATCH && invert_search)) { - - /* if we found a match but were told to be quiet, stop here and - * return success */ - if (be_quiet) - exit(0); - - /* keep track of matches */ - nmatches++; - - /* if we're just printing filenames, we stop after the first match */ - if (print_files_with_matches) - break; - - /* print the matched line */ - if (print_match_counts == 0) { -#ifdef BB_FEATURE_GREP_CONTEXT - int prevpos = (curpos == 0) ? lines_before - 1 : curpos - 1; - - /* if we were told to print 'before' lines and there is at least - * one line in the circular buffer, print them */ - if (lines_before && before_buf[prevpos] != NULL) { - int first_buf_entry_line_num = linenum - lines_before; - - /* advance to the first entry in the circular buffer, and - * figure out the line number is of the first line in the - * buffer */ - idx = curpos; - while (before_buf[idx] == NULL) { - idx = (idx + 1) % lines_before; - first_buf_entry_line_num++; - } - - /* now print each line in the buffer, clearing them as we go */ - while (before_buf[idx] != NULL) { - print_line(before_buf[idx], first_buf_entry_line_num, '-'); - free(before_buf[idx]); - before_buf[idx] = NULL; - idx = (idx + 1) % lines_before; - first_buf_entry_line_num++; - } - } - - /* make a note that we need to print 'after' lines */ - print_n_lines_after = lines_after; -#endif /* BB_FEATURE_GREP_CONTEXT */ - print_line(line, linenum, ':'); - } - } -#ifdef BB_FEATURE_GREP_CONTEXT - else { /* no match */ - /* Add the line to the circular 'before' buffer */ - if(lines_before) { - if(before_buf[curpos]) - free(before_buf[curpos]); - before_buf[curpos] = strdup(line); - curpos = (curpos + 1) % lines_before; - } - } - - /* if we need to print some context lines after the last match, do so */ - if (print_n_lines_after && (last_line_printed != linenum)) { - print_line(line, linenum, '-'); - print_n_lines_after--; - } -#endif /* BB_FEATURE_GREP_CONTEXT */ - } /* for */ - free(line); - } - - - /* special-case file post-processing for options where we don't print line - * matches, just filenames and possibly match counts */ - - /* grep -c: print [filename:]count, even if count is zero */ - if (print_match_counts) { - if (print_filename) - printf("%s:", cur_file); - if (print_files_with_matches && nmatches > 0) - printf("1\n"); - else - printf("%d\n", nmatches); - } - - /* grep -l: print just the filename, but only if we grepped the line in the file */ - if (print_files_with_matches && nmatches > 0) { - puts(cur_file); - } - - - /* remember if we matched */ - if (nmatches != 0) - matched = 1; -} - - -static void add_regex(const char *restr) -{ - regexes = xrealloc(regexes, sizeof(regex_t) * (++nregexes)); - xregcomp(®exes[nregexes-1], restr, reflags); -} - - -static void load_regexes_from_file(const char *filename) -{ - char *line; - FILE *f = xfopen(filename, "r"); - while ((line = get_line_from_file(f)) != NULL) { - chomp(line); - add_regex(line); - free(line); - } -} - - -#ifdef BB_FEATURE_CLEAN_UP -static void destroy_regexes() -{ - if (regexes == NULL) - return; - - /* destroy all the elments in the array */ - while (--nregexes >= 0) { - regfree(®exes[nregexes]); - free(®exes[nregexes]); - } -} -#endif - - -extern int grep_main(int argc, char **argv) -{ - int opt; -#ifdef BB_FEATURE_GREP_CONTEXT - char *junk; -#endif - -#ifdef BB_FEATURE_CLEAN_UP - /* destroy command strings on exit */ - if (atexit(destroy_regexes) == -1) - perror_msg_and_die("atexit"); -#endif - - /* do normal option parsing */ - while ((opt = getopt(argc, argv, "iHhlnqvsce:f:" -#ifdef BB_FEATURE_GREP_CONTEXT -"A:B:C:" -#endif -)) > 0) { - switch (opt) { - case 'i': - reflags |= REG_ICASE; - break; - case 'l': - print_files_with_matches++; - break; - case 'H': - print_filename++; - break; - case 'h': - print_filename--; - break; - case 'n': - print_line_num++; - break; - case 'q': - be_quiet++; - break; - case 'v': - invert_search++; - break; - case 's': - suppress_err_msgs++; - break; - case 'c': - print_match_counts++; - break; - case 'e': - add_regex(optarg); - break; - case 'f': - load_regexes_from_file(optarg); - break; -#ifdef BB_FEATURE_GREP_CONTEXT - case 'A': - lines_after = strtoul(optarg, &junk, 10); - if(*junk != '\0') - error_msg_and_die("invalid context length argument"); - break; - case 'B': - lines_before = strtoul(optarg, &junk, 10); - if(*junk != '\0') - error_msg_and_die("invalid context length argument"); - before_buf = (char **)calloc(lines_before, sizeof(char *)); - break; - case 'C': - lines_after = lines_before = strtoul(optarg, &junk, 10); - if(*junk != '\0') - error_msg_and_die("invalid context length argument"); - before_buf = (char **)calloc(lines_before, sizeof(char *)); - break; -#endif /* BB_FEATURE_GREP_CONTEXT */ - default: - show_usage(); - } - } - - /* if we didn't get a pattern from a -e and no command file was specified, - * argv[optind] should be the pattern. no pattern, no worky */ - if (nregexes == 0) { - if (argv[optind] == NULL) - show_usage(); - else { - add_regex(argv[optind]); - optind++; - } - } - - /* sanity checks */ - if (print_match_counts || be_quiet || print_files_with_matches) { - print_line_num = 0; -#ifdef BB_FEATURE_GREP_CONTEXT - lines_before = 0; - lines_after = 0; -#endif - } - - /* argv[(optind)..(argc-1)] should be names of file to grep through. If - * there is more than one file to grep, we will print the filenames */ - if ((argc-1) - (optind) > 0) - print_filename++; - - /* If no files were specified, or '-' was specified, take input from - * stdin. Otherwise, we grep through all the files specified. */ - if (argv[optind] == NULL || (strcmp(argv[optind], "-") == 0)) { - grep_file(stdin); - } - else { - int i; - FILE *file; - for (i = optind; i < argc; i++) { - cur_file = argv[i]; - file = fopen(cur_file, "r"); - if (file == NULL) { - if (!suppress_err_msgs) - perror_msg("%s", cur_file); - } - else { - grep_file(file); - fclose(file); - } - } - } - - return !matched; /* invert return value 0 = success, 1 = failed */ -} diff --git a/gunzip.c b/gunzip.c deleted file mode 100644 index 430bc630e..000000000 --- a/gunzip.c +++ /dev/null @@ -1,183 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Gzip implementation for busybox - * - * Based on GNU gzip v1.2.4 Copyright (C) 1992-1993 Jean-loup Gailly. - * - * Originally adjusted for busybox by Sven Rudolph - * based on gzip sources - * - * Adjusted further by Erik Andersen , - * to support files as well as stdin/stdout, and to generally behave itself wrt - * command line handling. - * - * General cleanup to better adhere to the style guide and make use of standard - * busybox functions by Glenn McGrath - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface - * Copyright (C) 1992-1993 Jean-loup Gailly - * The unzip code was written and put in the public domain by Mark Adler. - * Portions of the lzw code are derived from the public domain 'compress' - * written by Spencer Thomas, Joe Orost, James Woods, Jim McKie, Steve Davies, - * Ken Turkowski, Dave Mack and Peter Jannesen. - * - * See the license_msg below and the file COPYING for the software license. - * See the file algorithm.doc for the compression algorithms and file formats. - */ - -#if 0 -static char *license_msg[] = { - " Copyright (C) 1992-1993 Jean-loup Gailly", - " This program is free software; you can redistribute it and/or modify", - " it under the terms of the GNU General Public License as published by", - " the Free Software Foundation; either version 2, or (at your option)", - " any later version.", - "", - " This program is distributed in the hope that it will be useful,", - " but WITHOUT ANY WARRANTY; without even the implied warranty of", - " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the", - " GNU General Public License for more details.", - "", - " You should have received a copy of the GNU General Public License", - " along with this program; if not, write to the Free Software", - " Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.", - 0 -}; -#endif - -#include -#include -#include -#include -#include "busybox.h" - -extern int gunzip_main(int argc, char **argv) -{ - FILE *in_file = stdin; - FILE *out_file = NULL; - struct stat stat_buf; - - char *if_name = NULL; - char *of_name = NULL; - char *delete_file_name = NULL; - - const int gunzip_to_stdout = 1; - const int gunzip_force = 2; - const int gunzip_test = 4; - - int flags = 0; - int opt = 0; - int delete_old_file = FALSE; - - /* if called as zcat */ - if (strcmp(applet_name, "zcat") == 0) - flags |= gunzip_to_stdout; - - while ((opt = getopt(argc, argv, "ctfhdq")) != -1) { - switch (opt) { - case 'c': - flags |= gunzip_to_stdout; - break; - case 'f': - flags |= gunzip_force; - break; - case 't': - flags |= gunzip_test; - break; - case 'd': /* Used to convert gzip to gunzip. */ - break; - case 'q': - error_msg("-q option not supported, ignored"); - break; - case 'h': - default: - show_usage(); /* exit's inside usage */ - } - } - - /* Set input filename and number */ - if (argv[optind] == NULL || strcmp(argv[optind], "-") == 0) { - flags |= gunzip_to_stdout; - } else { - if_name = strdup(argv[optind]); - /* Open input file */ - in_file = xfopen(if_name, "r"); - - /* set the buffer size */ - setvbuf(in_file, NULL, _IOFBF, 0x8000); - - /* Get the time stamp on the input file. */ - if (stat(if_name, &stat_buf) < 0) { - error_msg_and_die("Couldn't stat file %s", if_name); - } - } - - /* Check that the input is sane. */ - if (isatty(fileno(in_file)) && (flags & gunzip_force) == 0) - error_msg_and_die("compressed data not read from terminal. Use -f to force it."); - - /* Set output filename and number */ - if (flags & gunzip_test) { - out_file = xfopen("/dev/null", "w"); /* why does test use filenum 2 ? */ - } else if (flags & gunzip_to_stdout) { - out_file = stdout; - } else { - char *extension; - int length = strlen(if_name); - - delete_old_file = TRUE; - extension = strrchr(if_name, '.'); - if (extension && strcmp(extension, ".gz") == 0) { - length -= 3; - } else if (extension && strcmp(extension, ".tgz") == 0) { - length -= 4; - } else { - error_msg_and_die("Invalid extension"); - } - of_name = (char *) xcalloc(sizeof(char), length + 1); - strncpy(of_name, if_name, length); - - /* Open output file */ - out_file = xfopen(of_name, "w"); - - /* Set permissions on the file */ - chmod(of_name, stat_buf.st_mode); - } - - /* do the decompression, and cleanup */ - if (unzip(in_file, out_file) == 0) { - /* Success, remove .gz file */ - delete_file_name = if_name; - } else { - /* remove failed attempt */ - delete_file_name = of_name; - } - - fclose(out_file); - fclose(in_file); - - if (delete_old_file == TRUE) { - if (unlink(delete_file_name) < 0) { - error_msg_and_die("Couldnt remove %s", delete_file_name); - } - } - - free(of_name); - - return(EXIT_SUCCESS); -} diff --git a/gzip.c b/gzip.c deleted file mode 100644 index 5c86c1070..000000000 --- a/gzip.c +++ /dev/null @@ -1,2568 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Gzip implementation for busybox - * - * Based on GNU gzip Copyright (C) 1992-1993 Jean-loup Gailly. - * - * Originally adjusted for busybox by Charles P. Wright - * "this is a stripped down version of gzip I put into busybox, it does - * only standard in to standard out with -9 compression. It also requires - * the zcat module for some important functions." - * - * Adjusted further by Erik Andersen , - * to support files as well as stdin/stdout, and to generally behave itself wrt - * command line handling. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* These defines are very important for BusyBox. Without these, - * huge chunks of ram are pre-allocated making the BusyBox bss - * size Freaking Huge(tm), which is a bad thing.*/ -#define SMALL_MEM -#define DYN_ALLOC - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" - -#define memzero(s, n) memset ((void *)(s), 0, (n)) - -#ifndef RETSIGTYPE -# define RETSIGTYPE void -#endif - -typedef unsigned char uch; -typedef unsigned short ush; -typedef unsigned long ulg; - -/* Return codes from gzip */ -#define OK 0 -#define ERROR 1 -#define WARNING 2 - -/* Compression methods (see algorithm.doc) */ -/* Only STORED and DEFLATED are supported by this BusyBox module */ -#define STORED 0 -/* methods 4 to 7 reserved */ -#define DEFLATED 8 -static int method; /* compression method */ - -/* To save memory for 16 bit systems, some arrays are overlaid between - * the various modules: - * deflate: prev+head window d_buf l_buf outbuf - * unlzw: tab_prefix tab_suffix stack inbuf outbuf - * For compression, input is done in window[]. For decompression, output - * is done in window except for unlzw. - */ - -#ifndef INBUFSIZ -# ifdef SMALL_MEM -# define INBUFSIZ 0x2000 /* input buffer size */ -# else -# define INBUFSIZ 0x8000 /* input buffer size */ -# endif -#endif -#define INBUF_EXTRA 64 /* required by unlzw() */ - -#ifndef OUTBUFSIZ -# ifdef SMALL_MEM -# define OUTBUFSIZ 8192 /* output buffer size */ -# else -# define OUTBUFSIZ 16384 /* output buffer size */ -# endif -#endif -#define OUTBUF_EXTRA 2048 /* required by unlzw() */ - -#ifndef DIST_BUFSIZE -# ifdef SMALL_MEM -# define DIST_BUFSIZE 0x2000 /* buffer for distances, see trees.c */ -# else -# define DIST_BUFSIZE 0x8000 /* buffer for distances, see trees.c */ -# endif -#endif - -#ifdef DYN_ALLOC -# define DECLARE(type, array, size) static type * array -# define ALLOC(type, array, size) { \ - array = (type*)xcalloc((size_t)(((size)+1L)/2), 2*sizeof(type)); \ - } -# define FREE(array) {if (array != NULL) free(array), array=NULL;} -#else -# define DECLARE(type, array, size) static type array[size] -# define ALLOC(type, array, size) -# define FREE(array) -#endif - -#define tab_suffix window -#define tab_prefix prev /* hash link (see deflate.c) */ -#define head (prev+WSIZE) /* hash head (see deflate.c) */ - -static long bytes_in; /* number of input bytes */ - -#define isize bytes_in -/* for compatibility with old zip sources (to be cleaned) */ - -typedef int file_t; /* Do not use stdio */ - -#define NO_FILE (-1) /* in memory compression */ - - -#define PACK_MAGIC "\037\036" /* Magic header for packed files */ -#define GZIP_MAGIC "\037\213" /* Magic header for gzip files, 1F 8B */ -#define OLD_GZIP_MAGIC "\037\236" /* Magic header for gzip 0.5 = freeze 1.x */ -#define LZH_MAGIC "\037\240" /* Magic header for SCO LZH Compress files */ -#define PKZIP_MAGIC "\120\113\003\004" /* Magic header for pkzip files */ - -/* gzip flag byte */ -#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ -#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ -#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ -#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ -#define COMMENT 0x10 /* bit 4 set: file comment present */ -#define RESERVED 0xC0 /* bit 6,7: reserved */ - -/* internal file attribute */ -#define UNKNOWN 0xffff -#define BINARY 0 -#define ASCII 1 - -#ifndef WSIZE -# define WSIZE 0x8000 /* window size--must be a power of two, and */ -#endif /* at least 32K for zip's deflate method */ - -#define MIN_MATCH 3 -#define MAX_MATCH 258 -/* The minimum and maximum match lengths */ - -#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) -/* Minimum amount of lookahead, except at the end of the input file. - * See deflate.c for comments about the MIN_MATCH+1. - */ - -#define MAX_DIST (WSIZE-MIN_LOOKAHEAD) -/* In order to simplify the code, particularly on 16 bit machines, match - * distances are limited to MAX_DIST instead of WSIZE. - */ - -/* put_byte is used for the compressed output */ -#define put_byte(c) {outbuf[outcnt++]=(uch)(c); if (outcnt==OUTBUFSIZ)\ - flush_outbuf();} - -/* Output a 16 bit value, lsb first */ -#define put_short(w) \ -{ if (outcnt < OUTBUFSIZ-2) { \ - outbuf[outcnt++] = (uch) ((w) & 0xff); \ - outbuf[outcnt++] = (uch) ((ush)(w) >> 8); \ - } else { \ - put_short_when_full(w); \ - } \ -} - -/* Output a 32 bit value to the bit stream, lsb first */ -#if 0 -#define put_long(n) { \ - put_short((n) & 0xffff); \ - put_short(((ulg)(n)) >> 16); \ -} -#endif - -#define seekable() 0 /* force sequential output */ -#define translate_eol 0 /* no option -a yet */ - -/* Diagnostic functions */ -#ifdef DEBUG -# define Assert(cond,msg) {if(!(cond)) error_msg(msg);} -# define Trace(x) fprintf x -# define Tracev(x) {if (verbose) fprintf x ;} -# define Tracevv(x) {if (verbose>1) fprintf x ;} -# define Tracec(c,x) {if (verbose && (c)) fprintf x ;} -# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} -#else -# define Assert(cond,msg) -# define Trace(x) -# define Tracev(x) -# define Tracevv(x) -# define Tracec(c,x) -# define Tracecv(c,x) -#endif - -#define WARN(msg) {if (!quiet) fprintf msg ; \ - if (exit_code == OK) exit_code = WARNING;} - -#ifndef MAX_PATH_LEN -# define MAX_PATH_LEN 1024 /* max pathname length */ -#endif - - - /* from zip.c: */ -static int zip (int in, int out); -static int file_read (char *buf, unsigned size); - - /* from gzip.c */ -static RETSIGTYPE abort_gzip (void); - - /* from deflate.c */ -static void lm_init (ush * flags); -static ulg deflate (void); - - /* from trees.c */ -static void ct_init (ush * attr, int *methodp); -static int ct_tally (int dist, int lc); -static ulg flush_block (char *buf, ulg stored_len, int eof); - - /* from bits.c */ -static void bi_init (file_t zipfile); -static void send_bits (int value, int length); -static unsigned bi_reverse (unsigned value, int length); -static void bi_windup (void); -static void copy_block (char *buf, unsigned len, int header); -static int (*read_buf) (char *buf, unsigned size); - - /* from util.c: */ -static void flush_outbuf (void); - -static void put_short_when_full (ush); - - -/* lzw.h -- define the lzw functions. - * Copyright (C) 1992-1993 Jean-loup Gailly. - * This is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License, see the file COPYING. - */ - -#if !defined(OF) && defined(lint) -# include "gzip.h" -#endif - -#ifndef BITS -# define BITS 16 -#endif -#define INIT_BITS 9 /* Initial number of bits per code */ - -#define BIT_MASK 0x1f /* Mask for 'number of compression bits' */ -/* Mask 0x20 is reserved to mean a fourth header byte, and 0x40 is free. - * It's a pity that old uncompress does not check bit 0x20. That makes - * extension of the format actually undesirable because old compress - * would just crash on the new format instead of giving a meaningful - * error message. It does check the number of bits, but it's more - * helpful to say "unsupported format, get a new version" than - * "can only handle 16 bits". - */ - -/* tailor.h -- target dependent definitions - * Copyright (C) 1992-1993 Jean-loup Gailly. - * This is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License, see the file COPYING. - */ - -/* The target dependent definitions should be defined here only. - * The target dependent functions should be defined in tailor.c. - */ - - - /* Common defaults */ - -#ifndef OS_CODE -# define OS_CODE 0x03 /* assume Unix */ -#endif - -#ifndef PATH_SEP -# define PATH_SEP '/' -#endif - -#ifndef OPTIONS_VAR -# define OPTIONS_VAR "GZIP" -#endif - -#ifndef Z_SUFFIX -# define Z_SUFFIX ".gz" -#endif - -#ifdef MAX_EXT_CHARS -# define MAX_SUFFIX MAX_EXT_CHARS -#else -# define MAX_SUFFIX 30 -#endif - - /* global buffers */ - -DECLARE(uch, inbuf, INBUFSIZ + INBUF_EXTRA); -DECLARE(uch, outbuf, OUTBUFSIZ + OUTBUF_EXTRA); -DECLARE(ush, d_buf, DIST_BUFSIZE); -DECLARE(uch, window, 2L * WSIZE); -DECLARE(ush, tab_prefix, 1L << BITS); - -static int crc_table_empty = 1; - -static int foreground; /* set if program run in foreground */ -static int method = DEFLATED; /* compression method */ -static int exit_code = OK; /* program exit code */ -static int part_nb; /* number of parts in .gz file */ -static long time_stamp; /* original time stamp (modification time) */ -static long ifile_size; /* input file size, -1 for devices (debug only) */ -static char z_suffix[MAX_SUFFIX + 1]; /* default suffix (can be set with --suffix) */ -static int z_len; /* strlen(z_suffix) */ - -static char ifname[MAX_PATH_LEN]; /* input file name */ -static char ofname[MAX_PATH_LEN]; /* output file name */ -static int ifd; /* input file descriptor */ -static int ofd; /* output file descriptor */ -static unsigned insize; /* valid bytes in inbuf */ -static unsigned outcnt; /* bytes in output buffer */ - -/* ======================================================================== - * Signal and error handler. - */ -static void abort_gzip() -{ - exit(ERROR); -} - -/* =========================================================================== - * Clear input and output buffers - */ -static void clear_bufs(void) -{ - outcnt = 0; - insize = 0; - bytes_in = 0L; -} - -static void write_error_msg(void) -{ - fprintf(stderr, "\n"); - perror(""); - abort_gzip(); -} - -/* =========================================================================== - * Does the same as write(), but also handles partial pipe writes and checks - * for error return. - */ -static void write_buf(int fd, void *buf, unsigned cnt) -{ - unsigned n; - - while ((n = write(fd, buf, cnt)) != cnt) { - if (n == (unsigned) (-1)) { - write_error_msg(); - } - cnt -= n; - buf = (void *) ((char *) buf + n); - } -} - -/* =========================================================================== - * Run a set of bytes through the crc shift register. If s is a NULL - * pointer, then initialize the crc shift register contents instead. - * Return the current crc in either case. - */ -static ulg updcrc(uch *s, unsigned n) -{ - static ulg crc = (ulg) 0xffffffffL; /* shift register contents */ - register ulg c; /* temporary variable */ - static unsigned long crc_32_tab[256]; - if (crc_table_empty) { - unsigned long csr; /* crc shift register */ - const unsigned long e = 0xedb88320L; /* polynomial exclusive-or pattern */ - int i; /* counter for all possible eight bit values */ - int k; /* byte being shifted into crc apparatus */ - - /* Compute table of CRC's. */ - crc_32_tab[0] = 0x00000000L; - for (i = 1; i < 256; i++) { - csr = i; - /* The idea to initialize the register with the byte instead of - * zero was stolen from Haruhiko Okumura's ar002 - */ - for (k = 8; k; k--) - csr = csr & 1 ? (csr >> 1) ^ e : csr >> 1; - crc_32_tab[i]=csr; - } - } - - if (s == NULL) { - c = 0xffffffffL; - } else { - c = crc; - if (n) - do { - c = crc_32_tab[((int) c ^ (*s++)) & 0xff] ^ (c >> 8); - } while (--n); - } - crc = c; - return c ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */ -} - -/* bits.c -- output variable-length bit strings - * Copyright (C) 1992-1993 Jean-loup Gailly - * This is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License, see the file COPYING. - */ - - -/* - * PURPOSE - * - * Output variable-length bit strings. Compression can be done - * to a file or to memory. (The latter is not supported in this version.) - * - * DISCUSSION - * - * The PKZIP "deflate" file format interprets compressed file data - * as a sequence of bits. Multi-bit strings in the file may cross - * byte boundaries without restriction. - * - * The first bit of each byte is the low-order bit. - * - * The routines in this file allow a variable-length bit value to - * be output right-to-left (useful for literal values). For - * left-to-right output (useful for code strings from the tree routines), - * the bits must have been reversed first with bi_reverse(). - * - * For in-memory compression, the compressed bit stream goes directly - * into the requested output buffer. The input data is read in blocks - * by the mem_read() function. The buffer is limited to 64K on 16 bit - * machines. - * - * INTERFACE - * - * void bi_init (FILE *zipfile) - * Initialize the bit string routines. - * - * void send_bits (int value, int length) - * Write out a bit string, taking the source bits right to - * left. - * - * int bi_reverse (int value, int length) - * Reverse the bits of a bit string, taking the source bits left to - * right and emitting them right to left. - * - * void bi_windup (void) - * Write out any remaining bits in an incomplete byte. - * - * void copy_block(char *buf, unsigned len, int header) - * Copy a stored block to the zip file, storing first the length and - * its one's complement if requested. - * - */ - -/* =========================================================================== - * Local data used by the "bit string" routines. - */ - -static file_t zfile; /* output gzip file */ - -static unsigned short bi_buf; - -/* Output buffer. bits are inserted starting at the bottom (least significant - * bits). - */ - -#define Buf_size (8 * 2*sizeof(char)) -/* Number of bits used within bi_buf. (bi_buf might be implemented on - * more than 16 bits on some systems.) - */ - -static int bi_valid; - -/* Current input function. Set to mem_read for in-memory compression */ - -#ifdef DEBUG -ulg bits_sent; /* bit length of the compressed data */ -#endif - -/* =========================================================================== - * Initialize the bit string routines. - */ -static void bi_init(file_t zipfile) -{ - zfile = zipfile; - bi_buf = 0; - bi_valid = 0; -#ifdef DEBUG - bits_sent = 0L; -#endif - - /* Set the defaults for file compression. They are set by memcompress - * for in-memory compression. - */ - if (zfile != NO_FILE) { - read_buf = file_read; - } -} - -/* =========================================================================== - * Send a value on a given number of bits. - * IN assertion: length <= 16 and value fits in length bits. - */ -static void send_bits(int value, int length) -{ -#ifdef DEBUG - Tracev((stderr, " l %2d v %4x ", length, value)); - Assert(length > 0 && length <= 15, "invalid length"); - bits_sent += (ulg) length; -#endif - /* If not enough room in bi_buf, use (valid) bits from bi_buf and - * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) - * unused bits in value. - */ - if (bi_valid > (int) Buf_size - length) { - bi_buf |= (value << bi_valid); - put_short(bi_buf); - bi_buf = (ush) value >> (Buf_size - bi_valid); - bi_valid += length - Buf_size; - } else { - bi_buf |= value << bi_valid; - bi_valid += length; - } -} - -/* =========================================================================== - * Reverse the first len bits of a code, using straightforward code (a faster - * method would use a table) - * IN assertion: 1 <= len <= 15 - */ -static unsigned bi_reverse(unsigned code, int len) -{ - register unsigned res = 0; - - do { - res |= code & 1; - code >>= 1, res <<= 1; - } while (--len > 0); - return res >> 1; -} - -/* =========================================================================== - * Write out any remaining bits in an incomplete byte. - */ -static void bi_windup() -{ - if (bi_valid > 8) { - put_short(bi_buf); - } else if (bi_valid > 0) { - put_byte(bi_buf); - } - bi_buf = 0; - bi_valid = 0; -#ifdef DEBUG - bits_sent = (bits_sent + 7) & ~7; -#endif -} - -/* =========================================================================== - * Copy a stored block to the zip file, storing first the length and its - * one's complement if requested. - */ -static void copy_block(char *buf, unsigned len, int header) -{ - bi_windup(); /* align on byte boundary */ - - if (header) { - put_short((ush) len); - put_short((ush) ~ len); -#ifdef DEBUG - bits_sent += 2 * 16; -#endif - } -#ifdef DEBUG - bits_sent += (ulg) len << 3; -#endif - while (len--) { - put_byte(*buf++); - } -} - -/* deflate.c -- compress data using the deflation algorithm - * Copyright (C) 1992-1993 Jean-loup Gailly - * This is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License, see the file COPYING. - */ - -/* - * PURPOSE - * - * Identify new text as repetitions of old text within a fixed- - * length sliding window trailing behind the new text. - * - * DISCUSSION - * - * The "deflation" process depends on being able to identify portions - * of the input text which are identical to earlier input (within a - * sliding window trailing behind the input currently being processed). - * - * The most straightforward technique turns out to be the fastest for - * most input files: try all possible matches and select the longest. - * The key feature of this algorithm is that insertions into the string - * dictionary are very simple and thus fast, and deletions are avoided - * completely. Insertions are performed at each input character, whereas - * string matches are performed only when the previous match ends. So it - * is preferable to spend more time in matches to allow very fast string - * insertions and avoid deletions. The matching algorithm for small - * strings is inspired from that of Rabin & Karp. A brute force approach - * is used to find longer strings when a small match has been found. - * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze - * (by Leonid Broukhis). - * A previous version of this file used a more sophisticated algorithm - * (by Fiala and Greene) which is guaranteed to run in linear amortized - * time, but has a larger average cost, uses more memory and is patented. - * However the F&G algorithm may be faster for some highly redundant - * files if the parameter max_chain_length (described below) is too large. - * - * ACKNOWLEDGEMENTS - * - * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and - * I found it in 'freeze' written by Leonid Broukhis. - * Thanks to many info-zippers for bug reports and testing. - * - * REFERENCES - * - * APPNOTE.TXT documentation file in PKZIP 1.93a distribution. - * - * A description of the Rabin and Karp algorithm is given in the book - * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. - * - * Fiala,E.R., and Greene,D.H. - * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 - * - * INTERFACE - * - * void lm_init (int pack_level, ush *flags) - * Initialize the "longest match" routines for a new file - * - * ulg deflate (void) - * Processes a new input file and return its compressed length. Sets - * the compressed length, crc, deflate flags and internal file - * attributes. - */ - - -/* =========================================================================== - * Configuration parameters - */ - -/* Compile with MEDIUM_MEM to reduce the memory requirements or - * with SMALL_MEM to use as little memory as possible. Use BIG_MEM if the - * entire input file can be held in memory (not possible on 16 bit systems). - * Warning: defining these symbols affects HASH_BITS (see below) and thus - * affects the compression ratio. The compressed output - * is still correct, and might even be smaller in some cases. - */ - -#ifdef SMALL_MEM -# define HASH_BITS 13 /* Number of bits used to hash strings */ -#endif -#ifdef MEDIUM_MEM -# define HASH_BITS 14 -#endif -#ifndef HASH_BITS -# define HASH_BITS 15 - /* For portability to 16 bit machines, do not use values above 15. */ -#endif - -/* To save space (see unlzw.c), we overlay prev+head with tab_prefix and - * window with tab_suffix. Check that we can do this: - */ -#if (WSIZE<<1) > (1< BITS-1 -# error cannot overlay head with tab_prefix1 -#endif -#define HASH_SIZE (unsigned)(1<= HASH_BITS - */ - -static unsigned int prev_length; - -/* Length of the best match at previous step. Matches not greater than this - * are discarded. This is used in the lazy match evaluation. - */ - -static unsigned strstart; /* start of string to insert */ -static unsigned match_start; /* start of matching string */ -static int eofile; /* flag set at end of input file */ -static unsigned lookahead; /* number of valid bytes ahead in window */ - -static const unsigned max_chain_length=4096; - -/* To speed up deflation, hash chains are never searched beyond this length. - * A higher limit improves compression ratio but degrades the speed. - */ - -static const unsigned int max_lazy_match=258; - -/* Attempt to find a better match only when the current match is strictly - * smaller than this value. This mechanism is used only for compression - * levels >= 4. - */ -#define max_insert_length max_lazy_match -/* Insert new strings in the hash table only if the match length - * is not greater than this length. This saves time but degrades compression. - * max_insert_length is used only for compression levels <= 3. - */ - -static const unsigned good_match=32; - -/* Use a faster search when the previous match is longer than this */ - - -/* Values for max_lazy_match, good_match and max_chain_length, depending on - * the desired pack level (0..9). The values given below have been tuned to - * exclude worst case performance for pathological files. Better values may be - * found for specific files. - */ - -static const int nice_match=258; /* Stop searching when current match exceeds this */ - -/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 - * For deflate_fast() (levels <= 3) good is ignored and lazy has a different - * meaning. - */ - -#define EQUAL 0 -/* result of memcmp for equal strings */ - -/* =========================================================================== - * Prototypes for local functions. - */ -static void fill_window (void); - -static int longest_match (IPos cur_match); - -#ifdef DEBUG -static void check_match (IPos start, IPos match, int length); -#endif - -/* =========================================================================== - * Update a hash value with the given input byte - * IN assertion: all calls to to UPDATE_HASH are made with consecutive - * input characters, so that a running hash key can be computed from the - * previous key instead of complete recalculation each time. - */ -#define UPDATE_HASH(h,c) (h = (((h)<= 1 - */ - -/* For MSDOS, OS/2 and 386 Unix, an optimized version is in match.asm or - * match.s. The code is functionally equivalent, so you can use the C version - * if desired. - */ -static int longest_match(IPos cur_match) -{ - unsigned chain_length = max_chain_length; /* max hash chain length */ - register uch *scan = window + strstart; /* current string */ - register uch *match; /* matched string */ - register int len; /* length of current match */ - int best_len = prev_length; /* best match length so far */ - IPos limit = - - strstart > (IPos) MAX_DIST ? strstart - (IPos) MAX_DIST : NIL; - /* Stop when cur_match becomes <= limit. To simplify the code, - * we prevent matches with the string of window index 0. - */ - -/* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. - * It is easy to get rid of this optimization if necessary. - */ -#if HASH_BITS < 8 || MAX_MATCH != 258 -# error Code too clever -#endif - register uch *strend = window + strstart + MAX_MATCH; - register uch scan_end1 = scan[best_len - 1]; - register uch scan_end = scan[best_len]; - - /* Do not waste too much time if we already have a good match: */ - if (prev_length >= good_match) { - chain_length >>= 2; - } - Assert(strstart <= window_size - MIN_LOOKAHEAD, - "insufficient lookahead"); - - do { - Assert(cur_match < strstart, "no future"); - match = window + cur_match; - - /* Skip to next match if the match length cannot increase - * or if the match length is less than 2: - */ - if (match[best_len] != scan_end || - match[best_len - 1] != scan_end1 || - *match != *scan || *++match != scan[1]) - continue; - - /* The check at best_len-1 can be removed because it will be made - * again later. (This heuristic is not always a win.) - * It is not necessary to compare scan[2] and match[2] since they - * are always equal when the other bytes match, given that - * the hash keys are equal and that HASH_BITS >= 8. - */ - scan += 2, match++; - - /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. - */ - do { - } while (*++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - scan < strend); - - len = MAX_MATCH - (int) (strend - scan); - scan = strend - MAX_MATCH; - - if (len > best_len) { - match_start = cur_match; - best_len = len; - if (len >= nice_match) - break; - scan_end1 = scan[best_len - 1]; - scan_end = scan[best_len]; - } - } while ((cur_match = prev[cur_match & WMASK]) > limit - && --chain_length != 0); - - return best_len; -} - -#ifdef DEBUG -/* =========================================================================== - * Check that the match at match_start is indeed a match. - */ -static void check_match(IPos start, IPos match, int length) -{ - /* check that the match is indeed a match */ - if (memcmp((char *) window + match, - (char *) window + start, length) != EQUAL) { - fprintf(stderr, - " start %d, match %d, length %d\n", start, match, length); - error_msg("invalid match"); - } - if (verbose > 1) { - fprintf(stderr, "\\[%d,%d]", start - match, length); - do { - putc(window[start++], stderr); - } while (--length != 0); - } -} -#else -# define check_match(start, match, length) -#endif - -/* =========================================================================== - * Fill the window when the lookahead becomes insufficient. - * Updates strstart and lookahead, and sets eofile if end of input file. - * IN assertion: lookahead < MIN_LOOKAHEAD && strstart + lookahead > 0 - * OUT assertions: at least one byte has been read, or eofile is set; - * file reads are performed for at least two bytes (required for the - * translate_eol option). - */ -static void fill_window() -{ - register unsigned n, m; - unsigned more = - - (unsigned) (window_size - (ulg) lookahead - (ulg) strstart); - /* Amount of free space at the end of the window. */ - - /* If the window is almost full and there is insufficient lookahead, - * move the upper half to the lower one to make room in the upper half. - */ - if (more == (unsigned) EOF) { - /* Very unlikely, but possible on 16 bit machine if strstart == 0 - * and lookahead == 1 (input done one byte at time) - */ - more--; - } else if (strstart >= WSIZE + MAX_DIST) { - /* By the IN assertion, the window is not empty so we can't confuse - * more == 0 with more == 64K on a 16 bit machine. - */ - Assert(window_size == (ulg) 2 * WSIZE, "no sliding with BIG_MEM"); - - memcpy((char *) window, (char *) window + WSIZE, (unsigned) WSIZE); - match_start -= WSIZE; - strstart -= WSIZE; /* we now have strstart >= MAX_DIST: */ - - block_start -= (long) WSIZE; - - for (n = 0; n < HASH_SIZE; n++) { - m = head[n]; - head[n] = (Pos) (m >= WSIZE ? m - WSIZE : NIL); - } - for (n = 0; n < WSIZE; n++) { - m = prev[n]; - prev[n] = (Pos) (m >= WSIZE ? m - WSIZE : NIL); - /* If n is not on any hash chain, prev[n] is garbage but - * its value will never be used. - */ - } - more += WSIZE; - } - /* At this point, more >= 2 */ - if (!eofile) { - n = read_buf((char *) window + strstart + lookahead, more); - if (n == 0 || n == (unsigned) EOF) { - eofile = 1; - } else { - lookahead += n; - } - } -} - -/* =========================================================================== - * Flush the current block, with given end-of-file flag. - * IN assertion: strstart is set to the end of the current match. - */ -#define FLUSH_BLOCK(eof) \ - flush_block(block_start >= 0L ? (char*)&window[(unsigned)block_start] : \ - (char*)NULL, (long)strstart - block_start, (eof)) - -/* =========================================================================== - * Same as above, but achieves better compression. We use a lazy - * evaluation for matches: a match is finally adopted only if there is - * no better match at the next window position. - */ -static ulg deflate() -{ - IPos hash_head; /* head of hash chain */ - IPos prev_match; /* previous match */ - int flush; /* set if current block must be flushed */ - int match_available = 0; /* set if previous match exists */ - register unsigned match_length = MIN_MATCH - 1; /* length of best match */ - - /* Process the input block. */ - while (lookahead != 0) { - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - INSERT_STRING(strstart, hash_head); - - /* Find the longest match, discarding those <= prev_length. - */ - prev_length = match_length, prev_match = match_start; - match_length = MIN_MATCH - 1; - - if (hash_head != NIL && prev_length < max_lazy_match && - strstart - hash_head <= MAX_DIST) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - match_length = longest_match(hash_head); - /* longest_match() sets match_start */ - if (match_length > lookahead) - match_length = lookahead; - - /* Ignore a length 3 match if it is too distant: */ - if (match_length == MIN_MATCH - && strstart - match_start > TOO_FAR) { - /* If prev_match is also MIN_MATCH, match_start is garbage - * but we will ignore the current match anyway. - */ - match_length--; - } - } - /* If there was a match at the previous step and the current - * match is not better, output the previous match: - */ - if (prev_length >= MIN_MATCH && match_length <= prev_length) { - - check_match(strstart - 1, prev_match, prev_length); - - flush = - ct_tally(strstart - 1 - prev_match, - prev_length - MIN_MATCH); - - /* Insert in hash table all strings up to the end of the match. - * strstart-1 and strstart are already inserted. - */ - lookahead -= prev_length - 1; - prev_length -= 2; - do { - strstart++; - INSERT_STRING(strstart, hash_head); - /* strstart never exceeds WSIZE-MAX_MATCH, so there are - * always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH - * these bytes are garbage, but it does not matter since the - * next lookahead bytes will always be emitted as literals. - */ - } while (--prev_length != 0); - match_available = 0; - match_length = MIN_MATCH - 1; - strstart++; - if (flush) - FLUSH_BLOCK(0), block_start = strstart; - - } else if (match_available) { - /* If there was no match at the previous position, output a - * single literal. If there was a match but the current match - * is longer, truncate the previous match to a single literal. - */ - Tracevv((stderr, "%c", window[strstart - 1])); - if (ct_tally(0, window[strstart - 1])) { - FLUSH_BLOCK(0), block_start = strstart; - } - strstart++; - lookahead--; - } else { - /* There is no previous match to compare with, wait for - * the next step to decide. - */ - match_available = 1; - strstart++; - lookahead--; - } - Assert(strstart <= isize && lookahead <= isize, "a bit too far"); - - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - while (lookahead < MIN_LOOKAHEAD && !eofile) - fill_window(); - } - if (match_available) - ct_tally(0, window[strstart - 1]); - - return FLUSH_BLOCK(1); /* eof */ -} - -/* gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface - * Copyright (C) 1992-1993 Jean-loup Gailly - * The unzip code was written and put in the public domain by Mark Adler. - * Portions of the lzw code are derived from the public domain 'compress' - * written by Spencer Thomas, Joe Orost, James Woods, Jim McKie, Steve Davies, - * Ken Turkowski, Dave Mack and Peter Jannesen. - * - * See the license_msg below and the file COPYING for the software license. - * See the file algorithm.doc for the compression algorithms and file formats. - */ - -/* Compress files with zip algorithm and 'compress' interface. - * See usage() and help() functions below for all options. - * Outputs: - * file.gz: compressed file with same mode, owner, and utimes - * or stdout with -c option or if stdin used as input. - * If the output file name had to be truncated, the original name is kept - * in the compressed file. - */ - - /* configuration */ - -typedef struct dirent dir_type; - -typedef RETSIGTYPE(*sig_type) (int); - -/* ======================================================================== */ -// int main (argc, argv) -// int argc; -// char **argv; -int gzip_main(int argc, char **argv) -{ - int result; - int inFileNum; - int outFileNum; - struct stat statBuf; - char *delFileName; - int tostdout = 0; - int fromstdin = 0; - int force = 0; - int opt; - - while ((opt = getopt(argc, argv, "cf123456789dq")) != -1) { - switch (opt) { - case 'c': - tostdout = 1; - break; - case 'f': - force = 1; - break; - /* Ignore 1-9 (compression level) options */ - case '1': case '2': case '3': case '4': case '5': - case '6': case '7': case '8': case '9': - break; - case 'q': - break; -#ifdef BB_GUNZIP - case 'd': - optind = 1; - return gunzip_main(argc, argv); -#endif - default: - show_usage(); - } - } - if ((optind == argc) || (strcmp(argv[optind], "-") == 0)) { - fromstdin = 1; - tostdout = 1; - } - - if (isatty(fileno(stdout)) && tostdout==1 && force==0) - error_msg_and_die( "compressed data not written to terminal. Use -f to force it."); - - foreground = signal(SIGINT, SIG_IGN) != SIG_IGN; - if (foreground) { - (void) signal(SIGINT, (sig_type) abort_gzip); - } -#ifdef SIGTERM - if (signal(SIGTERM, SIG_IGN) != SIG_IGN) { - (void) signal(SIGTERM, (sig_type) abort_gzip); - } -#endif -#ifdef SIGHUP - if (signal(SIGHUP, SIG_IGN) != SIG_IGN) { - (void) signal(SIGHUP, (sig_type) abort_gzip); - } -#endif - - strncpy(z_suffix, Z_SUFFIX, sizeof(z_suffix) - 1); - z_len = strlen(z_suffix); - - /* Allocate all global buffers (for DYN_ALLOC option) */ - ALLOC(uch, inbuf, INBUFSIZ + INBUF_EXTRA); - ALLOC(uch, outbuf, OUTBUFSIZ + OUTBUF_EXTRA); - ALLOC(ush, d_buf, DIST_BUFSIZE); - ALLOC(uch, window, 2L * WSIZE); - ALLOC(ush, tab_prefix, 1L << BITS); - - if (fromstdin == 1) { - strcpy(ofname, "stdin"); - - inFileNum = fileno(stdin); - time_stamp = 0; /* time unknown by default */ - ifile_size = -1L; /* convention for unknown size */ - } else { - /* Open up the input file */ - strncpy(ifname, argv[optind], MAX_PATH_LEN); - - /* Open input file */ - inFileNum = open(ifname, O_RDONLY); - if (inFileNum < 0 || stat(ifname, &statBuf) < 0) - perror_msg_and_die("%s", ifname); - /* Get the time stamp on the input file. */ - time_stamp = statBuf.st_ctime; - ifile_size = statBuf.st_size; - } - - - if (tostdout == 1) { - /* And get to work */ - strcpy(ofname, "stdout"); - outFileNum = fileno(stdout); - - clear_bufs(); /* clear input and output buffers */ - part_nb = 0; - - /* Actually do the compression/decompression. */ - zip(inFileNum, outFileNum); - - } else { - - /* And get to work */ - strncpy(ofname, ifname, MAX_PATH_LEN - 4); - strcat(ofname, ".gz"); - - - /* Open output fille */ -#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) - outFileNum = open(ofname, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW); -#else - outFileNum = open(ofname, O_RDWR | O_CREAT | O_EXCL); -#endif - if (outFileNum < 0) - perror_msg_and_die("%s", ofname); - /* Set permissions on the file */ - fchmod(outFileNum, statBuf.st_mode); - - clear_bufs(); /* clear input and output buffers */ - part_nb = 0; - - /* Actually do the compression/decompression. */ - result = zip(inFileNum, outFileNum); - close(outFileNum); - close(inFileNum); - /* Delete the original file */ - if (result == OK) - delFileName = ifname; - else - delFileName = ofname; - - if (unlink(delFileName) < 0) - perror_msg_and_die("%s", delFileName); - } - - return(exit_code); -} - -/* trees.c -- output deflated data using Huffman coding - * Copyright (C) 1992-1993 Jean-loup Gailly - * This is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License, see the file COPYING. - */ - -/* - * PURPOSE - * - * Encode various sets of source values using variable-length - * binary code trees. - * - * DISCUSSION - * - * The PKZIP "deflation" process uses several Huffman trees. The more - * common source values are represented by shorter bit sequences. - * - * Each code tree is stored in the ZIP file in a compressed form - * which is itself a Huffman encoding of the lengths of - * all the code strings (in ascending order by source values). - * The actual code strings are reconstructed from the lengths in - * the UNZIP process, as described in the "application note" - * (APPNOTE.TXT) distributed as part of PKWARE's PKZIP program. - * - * REFERENCES - * - * Lynch, Thomas J. - * Data Compression: Techniques and Applications, pp. 53-55. - * Lifetime Learning Publications, 1985. ISBN 0-534-03418-7. - * - * Storer, James A. - * Data Compression: Methods and Theory, pp. 49-50. - * Computer Science Press, 1988. ISBN 0-7167-8156-5. - * - * Sedgewick, R. - * Algorithms, p290. - * Addison-Wesley, 1983. ISBN 0-201-06672-6. - * - * INTERFACE - * - * void ct_init (ush *attr, int *methodp) - * Allocate the match buffer, initialize the various tables and save - * the location of the internal file attribute (ascii/binary) and - * method (DEFLATE/STORE) - * - * void ct_tally (int dist, int lc); - * Save the match info and tally the frequency counts. - * - * long flush_block (char *buf, ulg stored_len, int eof) - * Determine the best encoding for the current block: dynamic trees, - * static trees or store, and output the encoded block to the zip - * file. Returns the total compressed length for the file so far. - * - */ - -/* =========================================================================== - * Constants - */ - -#define MAX_BITS 15 -/* All codes must not exceed MAX_BITS bits */ - -#define MAX_BL_BITS 7 -/* Bit length codes must not exceed MAX_BL_BITS bits */ - -#define LENGTH_CODES 29 -/* number of length codes, not counting the special END_BLOCK code */ - -#define LITERALS 256 -/* number of literal bytes 0..255 */ - -#define END_BLOCK 256 -/* end of block literal code */ - -#define L_CODES (LITERALS+1+LENGTH_CODES) -/* number of Literal or Length codes, including the END_BLOCK code */ - -#define D_CODES 30 -/* number of distance codes */ - -#define BL_CODES 19 -/* number of codes used to transfer the bit lengths */ - -typedef uch extra_bits_t; - -/* extra bits for each length code */ -static const extra_bits_t extra_lbits[LENGTH_CODES] - = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, - 4, 4, 5, 5, 5, 5, 0 }; - -/* extra bits for each distance code */ -static const extra_bits_t extra_dbits[D_CODES] - = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, - 10, 10, 11, 11, 12, 12, 13, 13 }; - -/* extra bits for each bit length code */ -static const extra_bits_t extra_blbits[BL_CODES] -= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7 }; - -#define STORED_BLOCK 0 -#define STATIC_TREES 1 -#define DYN_TREES 2 -/* The three kinds of block type */ - -#ifndef LIT_BUFSIZE -# ifdef SMALL_MEM -# define LIT_BUFSIZE 0x2000 -# else -# ifdef MEDIUM_MEM -# define LIT_BUFSIZE 0x4000 -# else -# define LIT_BUFSIZE 0x8000 -# endif -# endif -#endif -#ifndef DIST_BUFSIZE -# define DIST_BUFSIZE LIT_BUFSIZE -#endif -/* Sizes of match buffers for literals/lengths and distances. There are - * 4 reasons for limiting LIT_BUFSIZE to 64K: - * - frequencies can be kept in 16 bit counters - * - if compression is not successful for the first block, all input data is - * still in the window so we can still emit a stored block even when input - * comes from standard input. (This can also be done for all blocks if - * LIT_BUFSIZE is not greater than 32K.) - * - if compression is not successful for a file smaller than 64K, we can - * even emit a stored file instead of a stored block (saving 5 bytes). - * - creating new Huffman trees less frequently may not provide fast - * adaptation to changes in the input data statistics. (Take for - * example a binary file with poorly compressible code followed by - * a highly compressible string table.) Smaller buffer sizes give - * fast adaptation but have of course the overhead of transmitting trees - * more frequently. - * - I can't count above 4 - * The current code is general and allows DIST_BUFSIZE < LIT_BUFSIZE (to save - * memory at the expense of compression). Some optimizations would be possible - * if we rely on DIST_BUFSIZE == LIT_BUFSIZE. - */ -#if LIT_BUFSIZE > INBUFSIZ -error cannot overlay l_buf and inbuf -#endif -#define REP_3_6 16 -/* repeat previous bit length 3-6 times (2 bits of repeat count) */ -#define REPZ_3_10 17 -/* repeat a zero length 3-10 times (3 bits of repeat count) */ -#define REPZ_11_138 18 -/* repeat a zero length 11-138 times (7 bits of repeat count) *//* =========================================================================== - * Local data - *//* Data structure describing a single value and its code string. */ typedef struct ct_data { - union { - ush freq; /* frequency count */ - ush code; /* bit string */ - } fc; - union { - ush dad; /* father node in Huffman tree */ - ush len; /* length of bit string */ - } dl; -} ct_data; - -#define Freq fc.freq -#define Code fc.code -#define Dad dl.dad -#define Len dl.len - -#define HEAP_SIZE (2*L_CODES+1) -/* maximum heap size */ - -static ct_data dyn_ltree[HEAP_SIZE]; /* literal and length tree */ -static ct_data dyn_dtree[2 * D_CODES + 1]; /* distance tree */ - -static ct_data static_ltree[L_CODES + 2]; - -/* The static literal tree. Since the bit lengths are imposed, there is no - * need for the L_CODES extra codes used during heap construction. However - * The codes 286 and 287 are needed to build a canonical tree (see ct_init - * below). - */ - -static ct_data static_dtree[D_CODES]; - -/* The static distance tree. (Actually a trivial tree since all codes use - * 5 bits.) - */ - -static ct_data bl_tree[2 * BL_CODES + 1]; - -/* Huffman tree for the bit lengths */ - -typedef struct tree_desc { - ct_data *dyn_tree; /* the dynamic tree */ - ct_data *static_tree; /* corresponding static tree or NULL */ - const extra_bits_t *extra_bits; /* extra bits for each code or NULL */ - int extra_base; /* base index for extra_bits */ - int elems; /* max number of elements in the tree */ - int max_length; /* max bit length for the codes */ - int max_code; /* largest code with non zero frequency */ -} tree_desc; - -static tree_desc l_desc = - { dyn_ltree, static_ltree, extra_lbits, LITERALS + 1, L_CODES, - MAX_BITS, 0 }; - -static tree_desc d_desc = - { dyn_dtree, static_dtree, extra_dbits, 0, D_CODES, MAX_BITS, 0 }; - -static tree_desc bl_desc = - { bl_tree, (ct_data *) 0, extra_blbits, 0, BL_CODES, MAX_BL_BITS, - 0 }; - - -static ush bl_count[MAX_BITS + 1]; - -/* number of codes at each bit length for an optimal tree */ - -static const uch bl_order[BL_CODES] -= { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; - -/* The lengths of the bit length codes are sent in order of decreasing - * probability, to avoid transmitting the lengths for unused bit length codes. - */ - -static int heap[2 * L_CODES + 1]; /* heap used to build the Huffman trees */ -static int heap_len; /* number of elements in the heap */ -static int heap_max; /* element of largest frequency */ - -/* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. - * The same heap array is used to build all trees. - */ - -static uch depth[2 * L_CODES + 1]; - -/* Depth of each subtree used as tie breaker for trees of equal frequency */ - -static uch length_code[MAX_MATCH - MIN_MATCH + 1]; - -/* length code for each normalized match length (0 == MIN_MATCH) */ - -static uch dist_code[512]; - -/* distance codes. The first 256 values correspond to the distances - * 3 .. 258, the last 256 values correspond to the top 8 bits of - * the 15 bit distances. - */ - -static int base_length[LENGTH_CODES]; - -/* First normalized length for each code (0 = MIN_MATCH) */ - -static int base_dist[D_CODES]; - -/* First normalized distance for each code (0 = distance of 1) */ - -#define l_buf inbuf -/* DECLARE(uch, l_buf, LIT_BUFSIZE); buffer for literals or lengths */ - -/* DECLARE(ush, d_buf, DIST_BUFSIZE); buffer for distances */ - -static uch flag_buf[(LIT_BUFSIZE / 8)]; - -/* flag_buf is a bit array distinguishing literals from lengths in - * l_buf, thus indicating the presence or absence of a distance. - */ - -static unsigned last_lit; /* running index in l_buf */ -static unsigned last_dist; /* running index in d_buf */ -static unsigned last_flags; /* running index in flag_buf */ -static uch flags; /* current flags not yet saved in flag_buf */ -static uch flag_bit; /* current bit used in flags */ - -/* bits are filled in flags starting at bit 0 (least significant). - * Note: these flags are overkill in the current code since we don't - * take advantage of DIST_BUFSIZE == LIT_BUFSIZE. - */ - -static ulg opt_len; /* bit length of current block with optimal trees */ -static ulg static_len; /* bit length of current block with static trees */ - -static ulg compressed_len; /* total bit length of compressed file */ - - -static ush *file_type; /* pointer to UNKNOWN, BINARY or ASCII */ -static int *file_method; /* pointer to DEFLATE or STORE */ - -/* =========================================================================== - * Local (static) routines in this file. - */ - -static void init_block (void); -static void pqdownheap (ct_data * tree, int k); -static void gen_bitlen (tree_desc * desc); -static void gen_codes (ct_data * tree, int max_code); -static void build_tree (tree_desc * desc); -static void scan_tree (ct_data * tree, int max_code); -static void send_tree (ct_data * tree, int max_code); -static int build_bl_tree (void); -static void send_all_trees (int lcodes, int dcodes, int blcodes); -static void compress_block (ct_data * ltree, ct_data * dtree); -static void set_file_type (void); - - -#ifndef DEBUG -# define send_code(c, tree) send_bits(tree[c].Code, tree[c].Len) - /* Send a code of the given tree. c and tree must not have side effects */ - -#else /* DEBUG */ -# define send_code(c, tree) \ - { if (verbose>1) fprintf(stderr,"\ncd %3d ",(c)); \ - send_bits(tree[c].Code, tree[c].Len); } -#endif - -#define d_code(dist) \ - ((dist) < 256 ? dist_code[dist] : dist_code[256+((dist)>>7)]) -/* Mapping from a distance to a distance code. dist is the distance - 1 and - * must not have side effects. dist_code[256] and dist_code[257] are never - * used. - */ - -/* the arguments must not have side effects */ - -/* =========================================================================== - * Allocate the match buffer, initialize the various tables and save the - * location of the internal file attribute (ascii/binary) and method - * (DEFLATE/STORE). - */ -static void ct_init(ush *attr, int *methodp) -{ - int n; /* iterates over tree elements */ - int bits; /* bit counter */ - int length; /* length value */ - int code; /* code value */ - int dist; /* distance index */ - - file_type = attr; - file_method = methodp; - compressed_len = 0L; - - if (static_dtree[0].Len != 0) - return; /* ct_init already called */ - - /* Initialize the mapping length (0..255) -> length code (0..28) */ - length = 0; - for (code = 0; code < LENGTH_CODES - 1; code++) { - base_length[code] = length; - for (n = 0; n < (1 << extra_lbits[code]); n++) { - length_code[length++] = (uch) code; - } - } - Assert(length == 256, "ct_init: length != 256"); - /* Note that the length 255 (match length 258) can be represented - * in two different ways: code 284 + 5 bits or code 285, so we - * overwrite length_code[255] to use the best encoding: - */ - length_code[length - 1] = (uch) code; - - /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ - dist = 0; - for (code = 0; code < 16; code++) { - base_dist[code] = dist; - for (n = 0; n < (1 << extra_dbits[code]); n++) { - dist_code[dist++] = (uch) code; - } - } - Assert(dist == 256, "ct_init: dist != 256"); - dist >>= 7; /* from now on, all distances are divided by 128 */ - for (; code < D_CODES; code++) { - base_dist[code] = dist << 7; - for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) { - dist_code[256 + dist++] = (uch) code; - } - } - Assert(dist == 256, "ct_init: 256+dist != 512"); - - /* Construct the codes of the static literal tree */ - for (bits = 0; bits <= MAX_BITS; bits++) - bl_count[bits] = 0; - n = 0; - while (n <= 143) - static_ltree[n++].Len = 8, bl_count[8]++; - while (n <= 255) - static_ltree[n++].Len = 9, bl_count[9]++; - while (n <= 279) - static_ltree[n++].Len = 7, bl_count[7]++; - while (n <= 287) - static_ltree[n++].Len = 8, bl_count[8]++; - /* Codes 286 and 287 do not exist, but we must include them in the - * tree construction to get a canonical Huffman tree (longest code - * all ones) - */ - gen_codes((ct_data *) static_ltree, L_CODES + 1); - - /* The static distance tree is trivial: */ - for (n = 0; n < D_CODES; n++) { - static_dtree[n].Len = 5; - static_dtree[n].Code = bi_reverse(n, 5); - } - - /* Initialize the first block of the first file: */ - init_block(); -} - -/* =========================================================================== - * Initialize a new block. - */ -static void init_block() -{ - int n; /* iterates over tree elements */ - - /* Initialize the trees. */ - for (n = 0; n < L_CODES; n++) - dyn_ltree[n].Freq = 0; - for (n = 0; n < D_CODES; n++) - dyn_dtree[n].Freq = 0; - for (n = 0; n < BL_CODES; n++) - bl_tree[n].Freq = 0; - - dyn_ltree[END_BLOCK].Freq = 1; - opt_len = static_len = 0L; - last_lit = last_dist = last_flags = 0; - flags = 0; - flag_bit = 1; -} - -#define SMALLEST 1 -/* Index within the heap array of least frequent node in the Huffman tree */ - - -/* =========================================================================== - * Remove the smallest element from the heap and recreate the heap with - * one less element. Updates heap and heap_len. - */ -#define pqremove(tree, top) \ -{\ - top = heap[SMALLEST]; \ - heap[SMALLEST] = heap[heap_len--]; \ - pqdownheap(tree, SMALLEST); \ -} - -/* =========================================================================== - * Compares to subtrees, using the tree depth as tie breaker when - * the subtrees have equal frequency. This minimizes the worst case length. - */ -#define smaller(tree, n, m) \ - (tree[n].Freq < tree[m].Freq || \ - (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) - -/* =========================================================================== - * Restore the heap property by moving down the tree starting at node k, - * exchanging a node with the smallest of its two sons if necessary, stopping - * when the heap property is re-established (each father smaller than its - * two sons). - */ -static void pqdownheap(ct_data *tree, int k) -{ - int v = heap[k]; - int j = k << 1; /* left son of k */ - - while (j <= heap_len) { - /* Set j to the smallest of the two sons: */ - if (j < heap_len && smaller(tree, heap[j + 1], heap[j])) - j++; - - /* Exit if v is smaller than both sons */ - if (smaller(tree, v, heap[j])) - break; - - /* Exchange v with the smallest son */ - heap[k] = heap[j]; - k = j; - - /* And continue down the tree, setting j to the left son of k */ - j <<= 1; - } - heap[k] = v; -} - -/* =========================================================================== - * Compute the optimal bit lengths for a tree and update the total bit length - * for the current block. - * IN assertion: the fields freq and dad are set, heap[heap_max] and - * above are the tree nodes sorted by increasing frequency. - * OUT assertions: the field len is set to the optimal bit length, the - * array bl_count contains the frequencies for each bit length. - * The length opt_len is updated; static_len is also updated if stree is - * not null. - */ -static void gen_bitlen(tree_desc *desc) -{ - ct_data *tree = desc->dyn_tree; - const extra_bits_t *extra = desc->extra_bits; - int base = desc->extra_base; - int max_code = desc->max_code; - int max_length = desc->max_length; - ct_data *stree = desc->static_tree; - int h; /* heap index */ - int n, m; /* iterate over the tree elements */ - int bits; /* bit length */ - int xbits; /* extra bits */ - ush f; /* frequency */ - int overflow = 0; /* number of elements with bit length too large */ - - for (bits = 0; bits <= MAX_BITS; bits++) - bl_count[bits] = 0; - - /* In a first pass, compute the optimal bit lengths (which may - * overflow in the case of the bit length tree). - */ - tree[heap[heap_max]].Len = 0; /* root of the heap */ - - for (h = heap_max + 1; h < HEAP_SIZE; h++) { - n = heap[h]; - bits = tree[tree[n].Dad].Len + 1; - if (bits > max_length) - bits = max_length, overflow++; - tree[n].Len = (ush) bits; - /* We overwrite tree[n].Dad which is no longer needed */ - - if (n > max_code) - continue; /* not a leaf node */ - - bl_count[bits]++; - xbits = 0; - if (n >= base) - xbits = extra[n - base]; - f = tree[n].Freq; - opt_len += (ulg) f *(bits + xbits); - - if (stree) - static_len += (ulg) f *(stree[n].Len + xbits); - } - if (overflow == 0) - return; - - Trace((stderr, "\nbit length overflow\n")); - /* This happens for example on obj2 and pic of the Calgary corpus */ - - /* Find the first bit length which could increase: */ - do { - bits = max_length - 1; - while (bl_count[bits] == 0) - bits--; - bl_count[bits]--; /* move one leaf down the tree */ - bl_count[bits + 1] += 2; /* move one overflow item as its brother */ - bl_count[max_length]--; - /* The brother of the overflow item also moves one step up, - * but this does not affect bl_count[max_length] - */ - overflow -= 2; - } while (overflow > 0); - - /* Now recompute all bit lengths, scanning in increasing frequency. - * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all - * lengths instead of fixing only the wrong ones. This idea is taken - * from 'ar' written by Haruhiko Okumura.) - */ - for (bits = max_length; bits != 0; bits--) { - n = bl_count[bits]; - while (n != 0) { - m = heap[--h]; - if (m > max_code) - continue; - if (tree[m].Len != (unsigned) bits) { - Trace( - (stderr, "code %d bits %d->%d\n", m, tree[m].Len, - bits)); - opt_len += - ((long) bits - - (long) tree[m].Len) * (long) tree[m].Freq; - tree[m].Len = (ush) bits; - } - n--; - } - } -} - -/* =========================================================================== - * Generate the codes for a given tree and bit counts (which need not be - * optimal). - * IN assertion: the array bl_count contains the bit length statistics for - * the given tree and the field len is set for all tree elements. - * OUT assertion: the field code is set for all tree elements of non - * zero code length. - */ -static void gen_codes(ct_data *tree, int max_code) -{ - ush next_code[MAX_BITS + 1]; /* next code value for each bit length */ - ush code = 0; /* running code value */ - int bits; /* bit index */ - int n; /* code index */ - - /* The distribution counts are first used to generate the code values - * without bit reversal. - */ - for (bits = 1; bits <= MAX_BITS; bits++) { - next_code[bits] = code = (code + bl_count[bits - 1]) << 1; - } - /* Check that the bit counts in bl_count are consistent. The last code - * must be all ones. - */ - Assert(code + bl_count[MAX_BITS] - 1 == (1 << MAX_BITS) - 1, - "inconsistent bit counts"); - Tracev((stderr, "\ngen_codes: max_code %d ", max_code)); - - for (n = 0; n <= max_code; n++) { - int len = tree[n].Len; - - if (len == 0) - continue; - /* Now reverse the bits */ - tree[n].Code = bi_reverse(next_code[len]++, len); - - Tracec(tree != static_ltree, - (stderr, "\nn %3d %c l %2d c %4x (%x) ", n, - (isgraph(n) ? n : ' '), len, tree[n].Code, - next_code[len] - 1)); - } -} - -/* =========================================================================== - * Construct one Huffman tree and assigns the code bit strings and lengths. - * Update the total bit length for the current block. - * IN assertion: the field freq is set for all tree elements. - * OUT assertions: the fields len and code are set to the optimal bit length - * and corresponding code. The length opt_len is updated; static_len is - * also updated if stree is not null. The field max_code is set. - */ -static void build_tree(tree_desc *desc) -{ - ct_data *tree = desc->dyn_tree; - ct_data *stree = desc->static_tree; - int elems = desc->elems; - int n, m; /* iterate over heap elements */ - int max_code = -1; /* largest code with non zero frequency */ - int node = elems; /* next internal node of the tree */ - - /* Construct the initial heap, with least frequent element in - * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. - * heap[0] is not used. - */ - heap_len = 0, heap_max = HEAP_SIZE; - - for (n = 0; n < elems; n++) { - if (tree[n].Freq != 0) { - heap[++heap_len] = max_code = n; - depth[n] = 0; - } else { - tree[n].Len = 0; - } - } - - /* The pkzip format requires that at least one distance code exists, - * and that at least one bit should be sent even if there is only one - * possible code. So to avoid special checks later on we force at least - * two codes of non zero frequency. - */ - while (heap_len < 2) { - int new = heap[++heap_len] = (max_code < 2 ? ++max_code : 0); - - tree[new].Freq = 1; - depth[new] = 0; - opt_len--; - if (stree) - static_len -= stree[new].Len; - /* new is 0 or 1 so it does not have extra bits */ - } - desc->max_code = max_code; - - /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, - * establish sub-heaps of increasing lengths: - */ - for (n = heap_len / 2; n >= 1; n--) - pqdownheap(tree, n); - - /* Construct the Huffman tree by repeatedly combining the least two - * frequent nodes. - */ - do { - pqremove(tree, n); /* n = node of least frequency */ - m = heap[SMALLEST]; /* m = node of next least frequency */ - - heap[--heap_max] = n; /* keep the nodes sorted by frequency */ - heap[--heap_max] = m; - - /* Create a new node father of n and m */ - tree[node].Freq = tree[n].Freq + tree[m].Freq; - depth[node] = (uch) (MAX(depth[n], depth[m]) + 1); - tree[n].Dad = tree[m].Dad = (ush) node; -#ifdef DUMP_BL_TREE - if (tree == bl_tree) { - fprintf(stderr, "\nnode %d(%d), sons %d(%d) %d(%d)", - node, tree[node].Freq, n, tree[n].Freq, m, - tree[m].Freq); - } -#endif - /* and insert the new node in the heap */ - heap[SMALLEST] = node++; - pqdownheap(tree, SMALLEST); - - } while (heap_len >= 2); - - heap[--heap_max] = heap[SMALLEST]; - - /* At this point, the fields freq and dad are set. We can now - * generate the bit lengths. - */ - gen_bitlen((tree_desc *) desc); - - /* The field len is now set, we can generate the bit codes */ - gen_codes((ct_data *) tree, max_code); -} - -/* =========================================================================== - * Scan a literal or distance tree to determine the frequencies of the codes - * in the bit length tree. Updates opt_len to take into account the repeat - * counts. (The contribution of the bit length codes will be added later - * during the construction of bl_tree.) - */ -static void scan_tree(ct_data *tree, int max_code) -{ - int n; /* iterates over all tree elements */ - int prevlen = -1; /* last emitted length */ - int curlen; /* length of current code */ - int nextlen = tree[0].Len; /* length of next code */ - int count = 0; /* repeat count of the current code */ - int max_count = 7; /* max repeat count */ - int min_count = 4; /* min repeat count */ - - if (nextlen == 0) - max_count = 138, min_count = 3; - tree[max_code + 1].Len = (ush) 0xffff; /* guard */ - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; - nextlen = tree[n + 1].Len; - if (++count < max_count && curlen == nextlen) { - continue; - } else if (count < min_count) { - bl_tree[curlen].Freq += count; - } else if (curlen != 0) { - if (curlen != prevlen) - bl_tree[curlen].Freq++; - bl_tree[REP_3_6].Freq++; - } else if (count <= 10) { - bl_tree[REPZ_3_10].Freq++; - } else { - bl_tree[REPZ_11_138].Freq++; - } - count = 0; - prevlen = curlen; - if (nextlen == 0) { - max_count = 138, min_count = 3; - } else if (curlen == nextlen) { - max_count = 6, min_count = 3; - } else { - max_count = 7, min_count = 4; - } - } -} - -/* =========================================================================== - * Send a literal or distance tree in compressed form, using the codes in - * bl_tree. - */ -static void send_tree(ct_data *tree, int max_code) -{ - int n; /* iterates over all tree elements */ - int prevlen = -1; /* last emitted length */ - int curlen; /* length of current code */ - int nextlen = tree[0].Len; /* length of next code */ - int count = 0; /* repeat count of the current code */ - int max_count = 7; /* max repeat count */ - int min_count = 4; /* min repeat count */ - -/* tree[max_code+1].Len = -1; *//* guard already set */ - if (nextlen == 0) - max_count = 138, min_count = 3; - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; - nextlen = tree[n + 1].Len; - if (++count < max_count && curlen == nextlen) { - continue; - } else if (count < min_count) { - do { - send_code(curlen, bl_tree); - } while (--count != 0); - - } else if (curlen != 0) { - if (curlen != prevlen) { - send_code(curlen, bl_tree); - count--; - } - Assert(count >= 3 && count <= 6, " 3_6?"); - send_code(REP_3_6, bl_tree); - send_bits(count - 3, 2); - - } else if (count <= 10) { - send_code(REPZ_3_10, bl_tree); - send_bits(count - 3, 3); - - } else { - send_code(REPZ_11_138, bl_tree); - send_bits(count - 11, 7); - } - count = 0; - prevlen = curlen; - if (nextlen == 0) { - max_count = 138, min_count = 3; - } else if (curlen == nextlen) { - max_count = 6, min_count = 3; - } else { - max_count = 7, min_count = 4; - } - } -} - -/* =========================================================================== - * Construct the Huffman tree for the bit lengths and return the index in - * bl_order of the last bit length code to send. - */ -static const int build_bl_tree() -{ - int max_blindex; /* index of last bit length code of non zero freq */ - - /* Determine the bit length frequencies for literal and distance trees */ - scan_tree((ct_data *) dyn_ltree, l_desc.max_code); - scan_tree((ct_data *) dyn_dtree, d_desc.max_code); - - /* Build the bit length tree: */ - build_tree((tree_desc *) (&bl_desc)); - /* opt_len now includes the length of the tree representations, except - * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. - */ - - /* Determine the number of bit length codes to send. The pkzip format - * requires that at least 4 bit length codes be sent. (appnote.txt says - * 3 but the actual value used is 4.) - */ - for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) { - if (bl_tree[bl_order[max_blindex]].Len != 0) - break; - } - /* Update opt_len to include the bit length tree and counts */ - opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4; - Tracev( - (stderr, "\ndyn trees: dyn %ld, stat %ld", opt_len, - static_len)); - - return max_blindex; -} - -/* =========================================================================== - * Send the header for a block using dynamic Huffman trees: the counts, the - * lengths of the bit length codes, the literal tree and the distance tree. - * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. - */ -static void send_all_trees(int lcodes, int dcodes, int blcodes) -{ - int rank; /* index in bl_order */ - - Assert(lcodes >= 257 && dcodes >= 1 - && blcodes >= 4, "not enough codes"); - Assert(lcodes <= L_CODES && dcodes <= D_CODES - && blcodes <= BL_CODES, "too many codes"); - Tracev((stderr, "\nbl counts: ")); - send_bits(lcodes - 257, 5); /* not +255 as stated in appnote.txt */ - send_bits(dcodes - 1, 5); - send_bits(blcodes - 4, 4); /* not -3 as stated in appnote.txt */ - for (rank = 0; rank < blcodes; rank++) { - Tracev((stderr, "\nbl code %2d ", bl_order[rank])); - send_bits(bl_tree[bl_order[rank]].Len, 3); - } - Tracev((stderr, "\nbl tree: sent %ld", bits_sent)); - - send_tree((ct_data *) dyn_ltree, lcodes - 1); /* send the literal tree */ - Tracev((stderr, "\nlit tree: sent %ld", bits_sent)); - - send_tree((ct_data *) dyn_dtree, dcodes - 1); /* send the distance tree */ - Tracev((stderr, "\ndist tree: sent %ld", bits_sent)); -} - -/* =========================================================================== - * Determine the best encoding for the current block: dynamic trees, static - * trees or store, and output the encoded block to the zip file. This function - * returns the total compressed length for the file so far. - */ -static ulg flush_block(char *buf, ulg stored_len, int eof) -{ - ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ - int max_blindex; /* index of last bit length code of non zero freq */ - - flag_buf[last_flags] = flags; /* Save the flags for the last 8 items */ - - /* Check if the file is ascii or binary */ - if (*file_type == (ush) UNKNOWN) - set_file_type(); - - /* Construct the literal and distance trees */ - build_tree((tree_desc *) (&l_desc)); - Tracev((stderr, "\nlit data: dyn %ld, stat %ld", opt_len, static_len)); - - build_tree((tree_desc *) (&d_desc)); - Tracev( - (stderr, "\ndist data: dyn %ld, stat %ld", opt_len, - static_len)); - /* At this point, opt_len and static_len are the total bit lengths of - * the compressed block data, excluding the tree representations. - */ - - /* Build the bit length tree for the above two trees, and get the index - * in bl_order of the last bit length code to send. - */ - max_blindex = build_bl_tree(); - - /* Determine the best encoding. Compute first the block length in bytes */ - opt_lenb = (opt_len + 3 + 7) >> 3; - static_lenb = (static_len + 3 + 7) >> 3; - - Trace( - (stderr, - "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u dist %u ", - opt_lenb, opt_len, static_lenb, static_len, stored_len, - last_lit, last_dist)); - - if (static_lenb <= opt_lenb) - opt_lenb = static_lenb; - - /* If compression failed and this is the first and last block, - * and if the zip file can be seeked (to rewrite the local header), - * the whole file is transformed into a stored file: - */ - if (stored_len <= opt_lenb && eof && compressed_len == 0L - && seekable()) { - /* Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there: */ - if (buf == (char *) 0) - error_msg("block vanished"); - - copy_block(buf, (unsigned) stored_len, 0); /* without header */ - compressed_len = stored_len << 3; - *file_method = STORED; - - } else if (stored_len + 4 <= opt_lenb && buf != (char *) 0) { - /* 4: two words for the lengths */ - /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. - * Otherwise we can't have processed more than WSIZE input bytes since - * the last block flush, because compression would have been - * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to - * transform a block into a stored block. - */ - send_bits((STORED_BLOCK << 1) + eof, 3); /* send block type */ - compressed_len = (compressed_len + 3 + 7) & ~7L; - compressed_len += (stored_len + 4) << 3; - - copy_block(buf, (unsigned) stored_len, 1); /* with header */ - - } else if (static_lenb == opt_lenb) { - send_bits((STATIC_TREES << 1) + eof, 3); - compress_block((ct_data *) static_ltree, - (ct_data *) static_dtree); - compressed_len += 3 + static_len; - } else { - send_bits((DYN_TREES << 1) + eof, 3); - send_all_trees(l_desc.max_code + 1, d_desc.max_code + 1, - max_blindex + 1); - compress_block((ct_data *) dyn_ltree, - (ct_data *) dyn_dtree); - compressed_len += 3 + opt_len; - } - Assert(compressed_len == bits_sent, "bad compressed size"); - init_block(); - - if (eof) { - bi_windup(); - compressed_len += 7; /* align on byte boundary */ - } - Tracev((stderr, "\ncomprlen %lu(%lu) ", compressed_len >> 3, - compressed_len - 7 * eof)); - - return compressed_len >> 3; -} - -/* =========================================================================== - * Save the match info and tally the frequency counts. Return true if - * the current block must be flushed. - */ -static int ct_tally(int dist, int lc) -{ - l_buf[last_lit++] = (uch) lc; - if (dist == 0) { - /* lc is the unmatched char */ - dyn_ltree[lc].Freq++; - } else { - /* Here, lc is the match length - MIN_MATCH */ - dist--; /* dist = match distance - 1 */ - Assert((ush) dist < (ush) MAX_DIST && - (ush) lc <= (ush) (MAX_MATCH - MIN_MATCH) && - (ush) d_code(dist) < (ush) D_CODES, "ct_tally: bad match"); - - dyn_ltree[length_code[lc] + LITERALS + 1].Freq++; - dyn_dtree[d_code(dist)].Freq++; - - d_buf[last_dist++] = (ush) dist; - flags |= flag_bit; - } - flag_bit <<= 1; - - /* Output the flags if they fill a byte: */ - if ((last_lit & 7) == 0) { - flag_buf[last_flags++] = flags; - flags = 0, flag_bit = 1; - } - /* Try to guess if it is profitable to stop the current block here */ - if ((last_lit & 0xfff) == 0) { - /* Compute an upper bound for the compressed length */ - ulg out_length = (ulg) last_lit * 8L; - ulg in_length = (ulg) strstart - block_start; - int dcode; - - for (dcode = 0; dcode < D_CODES; dcode++) { - out_length += - (ulg) dyn_dtree[dcode].Freq * (5L + extra_dbits[dcode]); - } - out_length >>= 3; - Trace( - (stderr, - "\nlast_lit %u, last_dist %u, in %ld, out ~%ld(%ld%%) ", - last_lit, last_dist, in_length, out_length, - 100L - out_length * 100L / in_length)); - if (last_dist < last_lit / 2 && out_length < in_length / 2) - return 1; - } - return (last_lit == LIT_BUFSIZE - 1 || last_dist == DIST_BUFSIZE); - /* We avoid equality with LIT_BUFSIZE because of wraparound at 64K - * on 16 bit machines and because stored blocks are restricted to - * 64K-1 bytes. - */ -} - -/* =========================================================================== - * Send the block data compressed using the given Huffman trees - */ -static void compress_block(ct_data *ltree, ct_data *dtree) -{ - unsigned dist; /* distance of matched string */ - int lc; /* match length or unmatched char (if dist == 0) */ - unsigned lx = 0; /* running index in l_buf */ - unsigned dx = 0; /* running index in d_buf */ - unsigned fx = 0; /* running index in flag_buf */ - uch flag = 0; /* current flags */ - unsigned code; /* the code to send */ - int extra; /* number of extra bits to send */ - - if (last_lit != 0) - do { - if ((lx & 7) == 0) - flag = flag_buf[fx++]; - lc = l_buf[lx++]; - if ((flag & 1) == 0) { - send_code(lc, ltree); /* send a literal byte */ - Tracecv(isgraph(lc), (stderr, " '%c' ", lc)); - } else { - /* Here, lc is the match length - MIN_MATCH */ - code = length_code[lc]; - send_code(code + LITERALS + 1, ltree); /* send the length code */ - extra = extra_lbits[code]; - if (extra != 0) { - lc -= base_length[code]; - send_bits(lc, extra); /* send the extra length bits */ - } - dist = d_buf[dx++]; - /* Here, dist is the match distance - 1 */ - code = d_code(dist); - Assert(code < D_CODES, "bad d_code"); - - send_code(code, dtree); /* send the distance code */ - extra = extra_dbits[code]; - if (extra != 0) { - dist -= base_dist[code]; - send_bits(dist, extra); /* send the extra distance bits */ - } - } /* literal or match pair ? */ - flag >>= 1; - } while (lx < last_lit); - - send_code(END_BLOCK, ltree); -} - -/* =========================================================================== - * Set the file type to ASCII or BINARY, using a crude approximation: - * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. - * IN assertion: the fields freq of dyn_ltree are set and the total of all - * frequencies does not exceed 64K (to fit in an int on 16 bit machines). - */ -static void set_file_type() -{ - int n = 0; - unsigned ascii_freq = 0; - unsigned bin_freq = 0; - - while (n < 7) - bin_freq += dyn_ltree[n++].Freq; - while (n < 128) - ascii_freq += dyn_ltree[n++].Freq; - while (n < LITERALS) - bin_freq += dyn_ltree[n++].Freq; - *file_type = bin_freq > (ascii_freq >> 2) ? BINARY : ASCII; - if (*file_type == BINARY && translate_eol) { - error_msg("-l used on binary file"); - } -} - -/* zip.c -- compress files to the gzip or pkzip format - * Copyright (C) 1992-1993 Jean-loup Gailly - * This is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License, see the file COPYING. - */ - - -static ulg crc; /* crc on uncompressed file data */ -static long header_bytes; /* number of bytes in gzip header */ - -static void put_short_when_full(ush w) -{ - put_byte((uch)((w) & 0xff)); - put_byte((uch)((ush)(w) >> 8)); -} - -static void put_short_function(ush n) -{ - put_short(n); -} - -static void put_long(ulg n) -{ - put_short_function((n) & 0xffff); - put_short_function(((ulg)(n)) >> 16); -} - -/* put_header_byte is used for the compressed output - * - for the initial 4 bytes that can't overflow the buffer. - */ -#define put_header_byte(c) {outbuf[outcnt++]=(uch)(c);} - -/* =========================================================================== - * Deflate in to out. - * IN assertions: the input and output buffers are cleared. - * The variables time_stamp and save_orig_name are initialized. - */ -static int zip(int in, int out) -{ - uch my_flags = 0; /* general purpose bit flags */ - ush attr = 0; /* ascii/binary flag */ - ush deflate_flags = 0; /* pkzip -es, -en or -ex equivalent */ - - ifd = in; - ofd = out; - outcnt = 0; - - /* Write the header to the gzip file. See algorithm.doc for the format */ - - - method = DEFLATED; - put_header_byte(GZIP_MAGIC[0]); /* magic header */ - put_header_byte(GZIP_MAGIC[1]); - put_header_byte(DEFLATED); /* compression method */ - - put_header_byte(my_flags); /* general flags */ - put_long(time_stamp); - - /* Write deflated file to zip file */ - crc = updcrc(0, 0); - - bi_init(out); - ct_init(&attr, &method); - lm_init(&deflate_flags); - - put_byte((uch) deflate_flags); /* extra flags */ - put_byte(OS_CODE); /* OS identifier */ - - header_bytes = (long) outcnt; - - (void) deflate(); - - /* Write the crc and uncompressed size */ - put_long(crc); - put_long(isize); - header_bytes += 2 * sizeof(long); - - flush_outbuf(); - return OK; -} - - -/* =========================================================================== - * Read a new buffer from the current input file, perform end-of-line - * translation, and update the crc and input file size. - * IN assertion: size >= 2 (for end-of-line translation) - */ -static int file_read(char *buf, unsigned size) -{ - unsigned len; - - Assert(insize == 0, "inbuf not empty"); - - len = read(ifd, buf, size); - if (len == (unsigned) (-1) || len == 0) - return (int) len; - - crc = updcrc((uch *) buf, len); - isize += (ulg) len; - return (int) len; -} - -/* =========================================================================== - * Write the output buffer outbuf[0..outcnt-1] and update bytes_out. - * (used for the compressed data only) - */ -static void flush_outbuf() -{ - if (outcnt == 0) - return; - - write_buf(ofd, (char *) outbuf, outcnt); - outcnt = 0; -} diff --git a/halt.c b/halt.c deleted file mode 100644 index d66e28d0e..000000000 --- a/halt.c +++ /dev/null @@ -1,41 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini halt implementation for busybox - * - * - * Copyright (C) 1995, 1996 by Bruce Perens . - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include "busybox.h" -#include - -extern int halt_main(int argc, char **argv) -{ -#ifdef BB_FEATURE_LINUXRC - /* don't assume init's pid == 1 */ - pid_t *pid = find_pid_by_name("init"); - if (!pid || *pid<=0) { - pid = find_pid_by_name("linuxrc"); - if (!pid || *pid<=0) - error_msg_and_die("no process killed"); - } - return(kill(*pid, SIGUSR1)); -#else - return(kill(1, SIGUSR1)); -#endif -} diff --git a/head.c b/head.c deleted file mode 100644 index 688c250b1..000000000 --- a/head.c +++ /dev/null @@ -1,97 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini head implementation for busybox - * - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by John Beppu - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include "busybox.h" - -static int head(int len, FILE *fp) -{ - int i; - char *input; - - for (i = 0; i < len; i++) { - if ((input = get_line_from_file(fp)) == NULL) - break; - fputs(input, stdout); - free(input); - } - return 0; -} - -/* BusyBoxed head(1) */ -int head_main(int argc, char **argv) -{ - FILE *fp; - int need_headers, opt, len = 10, status = EXIT_SUCCESS; - - /* parse argv[] */ - while ((opt = getopt(argc, argv, "n:")) > 0) { - switch (opt) { - case 'n': - len = atoi(optarg); - if (len >= 1) - break; - /* fallthrough */ - default: - show_usage(); - } - } - - /* get rest of argv[] or stdin if nothing's left */ - if (argv[optind] == NULL) { - head(len, stdin); - return status; - } - - need_headers = optind != (argc - 1); - while (argv[optind]) { - if (strcmp(argv[optind], "-") == 0) { - fp = stdin; - argv[optind] = "standard input"; - } else { - if ((fp = wfopen(argv[optind], "r")) == NULL) - status = EXIT_FAILURE; - } - if (fp) { - if (need_headers) { - printf("==> %s <==\n", argv[optind]); - } - head(len, fp); - if (ferror(fp)) { - perror_msg("%s", argv[optind]); - status = EXIT_FAILURE; - } - if (optind < argc - 1) - putchar('\n'); - if (fp != stdin) - fclose(fp); - } - optind++; - } - - return status; -} diff --git a/hostid.c b/hostid.c deleted file mode 100644 index 68a2cc659..000000000 --- a/hostid.c +++ /dev/null @@ -1,32 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini hostid implementation for busybox - * - * Copyright (C) 2000 Edward Betts . - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include "busybox.h" - -extern int hostid_main(int argc, char **argv) -{ - printf("%lx\n", gethostid()); - return EXIT_SUCCESS; -} diff --git a/hostname.c b/hostname.c deleted file mode 100644 index d87851509..000000000 --- a/hostname.c +++ /dev/null @@ -1,128 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * $Id: hostname.c,v 1.30 2001/06/26 02:06:08 bug1 Exp $ - * Mini hostname implementation for busybox - * - * Copyright (C) 1999 by Randolph Chung - * - * adjusted by Erik Andersen to remove - * use of long options and GNU getopt. Improved the usage info. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" - -static void do_sethostname(char *s, int isfile) -{ - FILE *f; - char buf[255]; - - if (!s) - return; - if (!isfile) { - if (sethostname(s, strlen(s)) < 0) { - if (errno == EPERM) - error_msg_and_die("you must be root to change the hostname"); - else - perror_msg_and_die("sethostname"); - } - } else { - f = xfopen(s, "r"); - fgets(buf, 255, f); -#ifdef BB_FEATURE_CLEAN_UP - fclose(f); -#endif - chomp(buf); - do_sethostname(buf, 0); - } -} - -int hostname_main(int argc, char **argv) -{ - int opt_short = 0; - int opt_domain = 0; - int opt_ip = 0; - struct hostent *h; - char *filename = NULL; - char buf[255]; - char *s = NULL; - - if (argc < 1) - show_usage(); - - while (--argc > 0 && **(++argv) == '-') { - while (*(++(*argv))) { - switch (**argv) { - case 's': - opt_short = 1; - break; - case 'i': - opt_ip = 1; - break; - case 'd': - opt_domain = 1; - break; - case 'F': - if (--argc == 0) { - show_usage(); - } - filename = *(++argv); - break; - case '-': - if (strcmp(++(*argv), "file") || --argc ==0 ) { - show_usage(); - } - filename = *(++argv); - break; - default: - show_usage(); - } - if (filename != NULL) - break; - } - } - - if (argc >= 1) { - do_sethostname(*argv, 0); - } else if (filename != NULL) { - do_sethostname(filename, 1); - } else { - gethostname(buf, 255); - if (opt_short) { - s = strchr(buf, '.'); - if (!s) - s = buf; - *s = 0; - puts(buf); - } else if (opt_domain) { - s = strchr(buf, '.'); - puts(s ? s + 1 : ""); - } else if (opt_ip) { - h = xgethostbyname(buf); - puts(inet_ntoa(*(struct in_addr *) (h->h_addr))); - } else { - puts(buf); - } - } - return(0); -} diff --git a/hush.c b/hush.c deleted file mode 100644 index cb0e6e980..000000000 --- a/hush.c +++ /dev/null @@ -1,2695 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * sh.c -- a prototype Bourne shell grammar parser - * Intended to follow the original Thompson and Ritchie - * "small and simple is beautiful" philosophy, which - * incidentally is a good match to today's BusyBox. - * - * Copyright (C) 2000,2001 Larry Doolittle - * - * Credits: - * The parser routines proper are all original material, first - * written Dec 2000 and Jan 2001 by Larry Doolittle. - * The execution engine, the builtins, and much of the underlying - * support has been adapted from busybox-0.49pre's lash, - * which is Copyright (C) 2000 by Lineo, Inc., and - * written by Erik Andersen , . - * That, in turn, is based in part on ladsh.c, by Michael K. Johnson and - * Erik W. Troan, which they placed in the public domain. I don't know - * how much of the Johnson/Troan code has survived the repeated rewrites. - * Other credits: - * simple_itoa() was lifted from boa-0.93.15 - * b_addchr() derived from similar w_addchar function in glibc-2.2 - * setup_redirect(), redirect_opt_num(), and big chunks of main() - * and many builtins derived from contributions by Erik Andersen - * miscellaneous bugfixes from Matt Kraai - * - * There are two big (and related) architecture differences between - * this parser and the lash parser. One is that this version is - * actually designed from the ground up to understand nearly all - * of the Bourne grammar. The second, consequential change is that - * the parser and input reader have been turned inside out. Now, - * the parser is in control, and asks for input as needed. The old - * way had the input reader in control, and it asked for parsing to - * take place as needed. The new way makes it much easier to properly - * handle the recursion implicit in the various substitutions, especially - * across continuation lines. - * - * Bash grammar not implemented: (how many of these were in original sh?) - * $@ (those sure look like weird quoting rules) - * $_ - * ! negation operator for pipes - * &> and >& redirection of stdout+stderr - * Brace Expansion - * Tilde Expansion - * fancy forms of Parameter Expansion - * aliases - * Arithmetic Expansion - * <(list) and >(list) Process Substitution - * reserved words: case, esac, select, function - * Here Documents ( << word ) - * Functions - * Major bugs: - * job handling woefully incomplete and buggy - * reserved word execution woefully incomplete and buggy - * to-do: - * port selected bugfixes from post-0.49 busybox lash - done? - * finish implementing reserved words: for, while, until, do, done - * change { and } from special chars to reserved words - * builtins: break, continue, eval, return, set, trap, ulimit - * test magic exec - * handle children going into background - * clean up recognition of null pipes - * check setting of global_argc and global_argv - * control-C handling, probably with longjmp - * follow IFS rules more precisely, including update semantics - * figure out what to do with backslash-newline - * explain why we use signal instead of sigaction - * propagate syntax errors, die on resource errors? - * continuation lines, both explicit and implicit - done? - * memory leak finding and plugging - done? - * more testing, especially quoting rules and redirection - * document how quoting rules not precisely followed for variable assignments - * maybe change map[] to use 2-bit entries - * (eventually) remove all the printf's - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include /* isalpha, isdigit */ -#include /* getpid */ -#include /* getenv, atoi */ -#include /* strchr */ -#include /* popen etc. */ -#include /* glob, of course */ -#include /* va_list */ -#include -#include -#include /* should be pretty obvious */ - -#include /* ulimit */ -#include -#include -#include - -/* #include */ -/* #define DEBUG_SHELL */ - -#ifdef BB_VER -#include "busybox.h" -#include "cmdedit.h" -#else -#define applet_name "hush" -#include "standalone.h" -#define hush_main main -#undef BB_FEATURE_SH_FANCY_PROMPT -#endif - -typedef enum { - REDIRECT_INPUT = 1, - REDIRECT_OVERWRITE = 2, - REDIRECT_APPEND = 3, - REDIRECT_HEREIS = 4, - REDIRECT_IO = 5 -} redir_type; - -/* The descrip member of this structure is only used to make debugging - * output pretty */ -struct {int mode; int default_fd; char *descrip;} redir_table[] = { - { 0, 0, "()" }, - { O_RDONLY, 0, "<" }, - { O_CREAT|O_TRUNC|O_WRONLY, 1, ">" }, - { O_CREAT|O_APPEND|O_WRONLY, 1, ">>" }, - { O_RDONLY, -1, "<<" }, - { O_RDWR, 1, "<>" } -}; - -typedef enum { - PIPE_SEQ = 1, - PIPE_AND = 2, - PIPE_OR = 3, - PIPE_BG = 4, -} pipe_style; - -/* might eventually control execution */ -typedef enum { - RES_NONE = 0, - RES_IF = 1, - RES_THEN = 2, - RES_ELIF = 3, - RES_ELSE = 4, - RES_FI = 5, - RES_FOR = 6, - RES_WHILE = 7, - RES_UNTIL = 8, - RES_DO = 9, - RES_DONE = 10, - RES_XXXX = 11, - RES_SNTX = 12 -} reserved_style; -#define FLAG_END (1<, but protected with __USE_GNU */ - -/* "globals" within this file */ -static char *ifs; -static char map[256]; -static int fake_mode; -static int interactive; -static struct close_me *close_me_head; -static const char *cwd; -static struct pipe *job_list; -static unsigned int last_bg_pid; -static unsigned int last_jobid; -static unsigned int shell_terminal; -static char *PS1; -static char *PS2; -struct variables shell_ver = { "HUSH_VERSION", "0.01", 1, 1, 0 }; -struct variables *top_vars = &shell_ver; - - -#define B_CHUNK (100) -#define B_NOSPAC 1 - -typedef struct { - char *data; - int length; - int maxlen; - int quote; - int nonnull; -} o_string; -#define NULL_O_STRING {NULL,0,0,0,0} -/* used for initialization: - o_string foo = NULL_O_STRING; */ - -/* I can almost use ordinary FILE *. Is open_memstream() universally - * available? Where is it documented? */ -struct in_str { - const char *p; - char peek_buf[2]; - int __promptme; - int promptmode; - FILE *file; - int (*get) (struct in_str *); - int (*peek) (struct in_str *); -}; -#define b_getch(input) ((input)->get(input)) -#define b_peek(input) ((input)->peek(input)) - -#define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n" - -struct built_in_command { - char *cmd; /* name */ - char *descr; /* description */ - int (*function) (struct child_prog *); /* function ptr */ -}; - -/* belongs in busybox.h */ -static inline int max(int a, int b) { - return (a>b)?a:b; -} - -/* This should be in utility.c */ -#ifdef DEBUG_SHELL -static void debug_printf(const char *format, ...) -{ - va_list args; - va_start(args, format); - vfprintf(stderr, format, args); - va_end(args); -} -#else -static inline void debug_printf(const char *format, ...) { } -#endif -#define final_printf debug_printf - -static void __syntax(char *file, int line) { - error_msg("syntax error %s:%d", file, line); -} -#define syntax() __syntax(__FILE__, __LINE__) - -/* Index of subroutines: */ -/* function prototypes for builtins */ -static int builtin_cd(struct child_prog *child); -static int builtin_env(struct child_prog *child); -static int builtin_exec(struct child_prog *child); -static int builtin_exit(struct child_prog *child); -static int builtin_export(struct child_prog *child); -static int builtin_fg_bg(struct child_prog *child); -static int builtin_help(struct child_prog *child); -static int builtin_jobs(struct child_prog *child); -static int builtin_pwd(struct child_prog *child); -static int builtin_read(struct child_prog *child); -static int builtin_set(struct child_prog *child); -static int builtin_shift(struct child_prog *child); -static int builtin_source(struct child_prog *child); -static int builtin_umask(struct child_prog *child); -static int builtin_unset(struct child_prog *child); -static int builtin_not_written(struct child_prog *child); -/* o_string manipulation: */ -static int b_check_space(o_string *o, int len); -static int b_addchr(o_string *o, int ch); -static void b_reset(o_string *o); -static int b_addqchr(o_string *o, int ch, int quote); -static int b_adduint(o_string *o, unsigned int i); -/* in_str manipulations: */ -static int static_get(struct in_str *i); -static int static_peek(struct in_str *i); -static int file_get(struct in_str *i); -static int file_peek(struct in_str *i); -static void setup_file_in_str(struct in_str *i, FILE *f); -static void setup_string_in_str(struct in_str *i, const char *s); -/* close_me manipulations: */ -static void mark_open(int fd); -static void mark_closed(int fd); -static void close_all(); -/* "run" the final data structures: */ -static char *indenter(int i); -static int free_pipe_list(struct pipe *head, int indent); -static int free_pipe(struct pipe *pi, int indent); -/* really run the final data structures: */ -static int setup_redirects(struct child_prog *prog, int squirrel[]); -static int run_list_real(struct pipe *pi); -static void pseudo_exec(struct child_prog *child) __attribute__ ((noreturn)); -static int run_pipe_real(struct pipe *pi); -/* extended glob support: */ -static int globhack(const char *src, int flags, glob_t *pglob); -static int glob_needed(const char *s); -static int xglob(o_string *dest, int flags, glob_t *pglob); -/* variable assignment: */ -static int is_assignment(const char *s); -/* data structure manipulation: */ -static int setup_redirect(struct p_context *ctx, int fd, redir_type style, struct in_str *input); -static void initialize_context(struct p_context *ctx); -static int done_word(o_string *dest, struct p_context *ctx); -static int done_command(struct p_context *ctx); -static int done_pipe(struct p_context *ctx, pipe_style type); -/* primary string parsing: */ -static int redirect_dup_num(struct in_str *input); -static int redirect_opt_num(o_string *o); -static int process_command_subs(o_string *dest, struct p_context *ctx, struct in_str *input, int subst_end); -static int parse_group(o_string *dest, struct p_context *ctx, struct in_str *input, int ch); -static void lookup_param(o_string *dest, struct p_context *ctx, o_string *src); -static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *input); -static int parse_string(o_string *dest, struct p_context *ctx, const char *src); -static int parse_stream(o_string *dest, struct p_context *ctx, struct in_str *input0, int end_trigger); -/* setup: */ -static int parse_stream_outer(struct in_str *inp); -static int parse_string_outer(const char *s); -static int parse_file_outer(FILE *f); -/* job management: */ -static int checkjobs(struct pipe* fg_pipe); -static void insert_bg_job(struct pipe *pi); -static void remove_bg_job(struct pipe *pi); -/* local variable support */ -static char *get_local_var(const char *var); -static void unset_local_var(const char *name); -static int set_local_var(const char *s, int flg_export); - -/* Table of built-in functions. They can be forked or not, depending on - * context: within pipes, they fork. As simple commands, they do not. - * When used in non-forking context, they can change global variables - * in the parent shell process. If forked, of course they can not. - * For example, 'unset foo | whatever' will parse and run, but foo will - * still be set at the end. */ -static struct built_in_command bltins[] = { - {"bg", "Resume a job in the background", builtin_fg_bg}, - {"break", "Exit for, while or until loop", builtin_not_written}, - {"cd", "Change working directory", builtin_cd}, - {"continue", "Continue for, while or until loop", builtin_not_written}, - {"env", "Print all environment variables", builtin_env}, - {"eval", "Construct and run shell command", builtin_not_written}, - {"exec", "Exec command, replacing this shell with the exec'd process", - builtin_exec}, - {"exit", "Exit from shell()", builtin_exit}, - {"export", "Set environment variable", builtin_export}, - {"fg", "Bring job into the foreground", builtin_fg_bg}, - {"jobs", "Lists the active jobs", builtin_jobs}, - {"pwd", "Print current directory", builtin_pwd}, - {"read", "Input environment variable", builtin_read}, - {"return", "Return from a function", builtin_not_written}, - {"set", "Set/unset shell local variables", builtin_set}, - {"shift", "Shift positional parameters", builtin_shift}, - {"trap", "Trap signals", builtin_not_written}, - {"ulimit","Controls resource limits", builtin_not_written}, - {"umask","Sets file creation mask", builtin_umask}, - {"unset", "Unset environment variable", builtin_unset}, - {".", "Source-in and run commands in a file", builtin_source}, - {"help", "List shell built-in commands", builtin_help}, - {NULL, NULL, NULL} -}; - -static const char *set_cwd(void) -{ - if(cwd==unknown) - cwd = NULL; /* xgetcwd(arg) called free(arg) */ - cwd = xgetcwd((char *)cwd); - if (!cwd) - cwd = unknown; - return cwd; -} - - -/* built-in 'cd ' handler */ -static int builtin_cd(struct child_prog *child) -{ - char *newdir; - if (child->argv[1] == NULL) - newdir = getenv("HOME"); - else - newdir = child->argv[1]; - if (chdir(newdir)) { - printf("cd: %s: %s\n", newdir, strerror(errno)); - return EXIT_FAILURE; - } - set_cwd(); - return EXIT_SUCCESS; -} - -/* built-in 'env' handler */ -static int builtin_env(struct child_prog *dummy) -{ - char **e = environ; - if (e == NULL) return EXIT_FAILURE; - for (; *e; e++) { - puts(*e); - } - return EXIT_SUCCESS; -} - -/* built-in 'exec' handler */ -static int builtin_exec(struct child_prog *child) -{ - if (child->argv[1] == NULL) - return EXIT_SUCCESS; /* Really? */ - child->argv++; - pseudo_exec(child); - /* never returns */ -} - -/* built-in 'exit' handler */ -static int builtin_exit(struct child_prog *child) -{ - if (child->argv[1] == NULL) - exit(last_return_code); - exit (atoi(child->argv[1])); -} - -/* built-in 'export VAR=value' handler */ -static int builtin_export(struct child_prog *child) -{ - int res = 0; - char *name = child->argv[1]; - - if (name == NULL) { - return (builtin_env(child)); - } - - name = strdup(name); - - if(name) { - char *value = strchr(name, '='); - - if (!value) { - char *tmp; - /* They are exporting something without an =VALUE */ - - value = get_local_var(name); - if (value) { - size_t ln = strlen(name); - - tmp = realloc(name, ln+strlen(value)+2); - if(tmp==NULL) - res = -1; - else { - sprintf(tmp+ln, "=%s", value); - name = tmp; - } - } else { - /* bash does not return an error when trying to export - * an undefined variable. Do likewise. */ - res = 1; - } - } - } - if (res<0) - perror_msg("export"); - else if(res==0) - res = set_local_var(name, 1); - else - res = 0; - free(name); - return res; -} - -/* built-in 'fg' and 'bg' handler */ -static int builtin_fg_bg(struct child_prog *child) -{ - int i, jobnum; - struct pipe *pi=NULL; - - if (!interactive) - return EXIT_FAILURE; - /* If they gave us no args, assume they want the last backgrounded task */ - if (!child->argv[1]) { - for (pi = job_list; pi; pi = pi->next) { - if (pi->jobid == last_jobid) { - break; - } - } - if (!pi) { - error_msg("%s: no current job", child->argv[0]); - return EXIT_FAILURE; - } - } else { - if (sscanf(child->argv[1], "%%%d", &jobnum) != 1) { - error_msg("%s: bad argument '%s'", child->argv[0], child->argv[1]); - return EXIT_FAILURE; - } - for (pi = job_list; pi; pi = pi->next) { - if (pi->jobid == jobnum) { - break; - } - } - if (!pi) { - error_msg("%s: %d: no such job", child->argv[0], jobnum); - return EXIT_FAILURE; - } - } - - if (*child->argv[0] == 'f') { - /* Put the job into the foreground. */ - tcsetpgrp(shell_terminal, pi->pgrp); - } - - /* Restart the processes in the job */ - for (i = 0; i < pi->num_progs; i++) - pi->progs[i].is_stopped = 0; - - if ( (i=kill(- pi->pgrp, SIGCONT)) < 0) { - if (i == ESRCH) { - remove_bg_job(pi); - } else { - perror_msg("kill (SIGCONT)"); - } - } - - pi->stopped_progs = 0; - return EXIT_SUCCESS; -} - -/* built-in 'help' handler */ -static int builtin_help(struct child_prog *dummy) -{ - struct built_in_command *x; - - printf("\nBuilt-in commands:\n"); - printf("-------------------\n"); - for (x = bltins; x->cmd; x++) { - if (x->descr==NULL) - continue; - printf("%s\t%s\n", x->cmd, x->descr); - } - printf("\n\n"); - return EXIT_SUCCESS; -} - -/* built-in 'jobs' handler */ -static int builtin_jobs(struct child_prog *child) -{ - struct pipe *job; - char *status_string; - - for (job = job_list; job; job = job->next) { - if (job->running_progs == job->stopped_progs) - status_string = "Stopped"; - else - status_string = "Running"; - - printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->text); - } - return EXIT_SUCCESS; -} - - -/* built-in 'pwd' handler */ -static int builtin_pwd(struct child_prog *dummy) -{ - puts(set_cwd()); - return EXIT_SUCCESS; -} - -/* built-in 'read VAR' handler */ -static int builtin_read(struct child_prog *child) -{ - int res; - - if (child->argv[1]) { - char string[BUFSIZ]; - char *var = 0; - - string[0] = 0; /* In case stdin has only EOF */ - /* read string */ - fgets(string, sizeof(string), stdin); - chomp(string); - var = malloc(strlen(child->argv[1])+strlen(string)+2); - if(var) { - sprintf(var, "%s=%s", child->argv[1], string); - res = set_local_var(var, 0); - } else - res = -1; - if (res) - fprintf(stderr, "read: %m\n"); - free(var); /* So not move up to avoid breaking errno */ - return res; - } else { - do res=getchar(); while(res!='\n' && res!=EOF); - return 0; - } -} - -/* built-in 'set VAR=value' handler */ -static int builtin_set(struct child_prog *child) -{ - char *temp = child->argv[1]; - struct variables *e; - - if (temp == NULL) - for(e = top_vars; e; e=e->next) - printf("%s=%s\n", e->name, e->value); - else - set_local_var(temp, 0); - - return EXIT_SUCCESS; -} - - -/* Built-in 'shift' handler */ -static int builtin_shift(struct child_prog *child) -{ - int n=1; - if (child->argv[1]) { - n=atoi(child->argv[1]); - } - if (n>=0 && nargv[1] == NULL) - return EXIT_FAILURE; - - /* XXX search through $PATH is missing */ - input = fopen(child->argv[1], "r"); - if (!input) { - error_msg("Couldn't open file '%s'", child->argv[1]); - return EXIT_FAILURE; - } - - /* Now run the file */ - /* XXX argv and argc are broken; need to save old global_argv - * (pointer only is OK!) on this stack frame, - * set global_argv=child->argv+1, recurse, and restore. */ - mark_open(fileno(input)); - status = parse_file_outer(input); - mark_closed(fileno(input)); - fclose(input); - return (status); -} - -static int builtin_umask(struct child_prog *child) -{ - mode_t new_umask; - const char *arg = child->argv[1]; - char *end; - if (arg) { - new_umask=strtoul(arg, &end, 8); - if (*end!='\0' || end == arg) { - return EXIT_FAILURE; - } - } else { - printf("%.3o\n", (unsigned int) (new_umask=umask(0))); - } - umask(new_umask); - return EXIT_SUCCESS; -} - -/* built-in 'unset VAR' handler */ -static int builtin_unset(struct child_prog *child) -{ - /* bash returned already true */ - unset_local_var(child->argv[1]); - return EXIT_SUCCESS; -} - -static int builtin_not_written(struct child_prog *child) -{ - printf("builtin_%s not written\n",child->argv[0]); - return EXIT_FAILURE; -} - -static int b_check_space(o_string *o, int len) -{ - /* It would be easy to drop a more restrictive policy - * in here, such as setting a maximum string length */ - if (o->length + len > o->maxlen) { - char *old_data = o->data; - /* assert (data == NULL || o->maxlen != 0); */ - o->maxlen += max(2*len, B_CHUNK); - o->data = realloc(o->data, 1 + o->maxlen); - if (o->data == NULL) { - free(old_data); - } - } - return o->data == NULL; -} - -static int b_addchr(o_string *o, int ch) -{ - debug_printf("b_addchr: %c %d %p\n", ch, o->length, o); - if (b_check_space(o, 1)) return B_NOSPAC; - o->data[o->length] = ch; - o->length++; - o->data[o->length] = '\0'; - return 0; -} - -static void b_reset(o_string *o) -{ - o->length = 0; - o->nonnull = 0; - if (o->data != NULL) *o->data = '\0'; -} - -static void b_free(o_string *o) -{ - b_reset(o); - if (o->data != NULL) free(o->data); - o->data = NULL; - o->maxlen = 0; -} - -/* My analysis of quoting semantics tells me that state information - * is associated with a destination, not a source. - */ -static int b_addqchr(o_string *o, int ch, int quote) -{ - if (quote && strchr("*?[\\",ch)) { - int rc; - rc = b_addchr(o, '\\'); - if (rc) return rc; - } - return b_addchr(o, ch); -} - -/* belongs in utility.c */ -char *simple_itoa(unsigned int i) -{ - /* 21 digits plus null terminator, good for 64-bit or smaller ints */ - static char local[22]; - char *p = &local[21]; - *p-- = '\0'; - do { - *p-- = '0' + i % 10; - i /= 10; - } while (i > 0); - return p + 1; -} - -static int b_adduint(o_string *o, unsigned int i) -{ - int r; - char *p = simple_itoa(i); - /* no escape checking necessary */ - do r=b_addchr(o, *p++); while (r==0 && *p); - return r; -} - -static int static_get(struct in_str *i) -{ - int ch=*i->p++; - if (ch=='\0') return EOF; - return ch; -} - -static int static_peek(struct in_str *i) -{ - return *i->p; -} - -static inline void cmdedit_set_initial_prompt(void) -{ -#ifndef BB_FEATURE_SH_FANCY_PROMPT - PS1 = NULL; -#else - PS1 = getenv("PS1"); - if(PS1==0) - PS1 = "\\w \\$ "; -#endif -} - -static inline void setup_prompt_string(int promptmode, char **prompt_str) -{ - debug_printf("setup_prompt_string %d ",promptmode); -#ifndef BB_FEATURE_SH_FANCY_PROMPT - /* Set up the prompt */ - if (promptmode == 1) { - if (PS1) - free(PS1); - PS1=xmalloc(strlen(cwd)+4); - sprintf(PS1, "%s %s", cwd, ( geteuid() != 0 ) ? "$ ":"# "); - *prompt_str = PS1; - } else { - *prompt_str = PS2; - } -#else - *prompt_str = (promptmode==1)? PS1 : PS2; -#endif - debug_printf("result %s\n",*prompt_str); -} - -static void get_user_input(struct in_str *i) -{ - char *prompt_str; - static char the_command[BUFSIZ]; - - setup_prompt_string(i->promptmode, &prompt_str); -#ifdef BB_FEATURE_COMMAND_EDITING - /* - ** enable command line editing only while a command line - ** is actually being read; otherwise, we'll end up bequeathing - ** atexit() handlers and other unwanted stuff to our - ** child processes (rob@sysgo.de) - */ - cmdedit_read_input(prompt_str, the_command); -#else - fputs(prompt_str, stdout); - fflush(stdout); - the_command[0]=fgetc(i->file); - the_command[1]='\0'; -#endif - fflush(stdout); - i->p = the_command; -} - -/* This is the magic location that prints prompts - * and gets data back from the user */ -static int file_get(struct in_str *i) -{ - int ch; - - ch = 0; - /* If there is data waiting, eat it up */ - if (i->p && *i->p) { - ch=*i->p++; - } else { - /* need to double check i->file because we might be doing something - * more complicated by now, like sourcing or substituting. */ - if (i->__promptme && interactive && i->file == stdin) { - while(! i->p || (interactive && strlen(i->p)==0) ) { - get_user_input(i); - } - i->promptmode=2; - i->__promptme = 0; - if (i->p && *i->p) { - ch=*i->p++; - } - } else { - ch = fgetc(i->file); - } - - debug_printf("b_getch: got a %d\n", ch); - } - if (ch == '\n') i->__promptme=1; - return ch; -} - -/* All the callers guarantee this routine will never be - * used right after a newline, so prompting is not needed. - */ -static int file_peek(struct in_str *i) -{ - if (i->p && *i->p) { - return *i->p; - } else { - i->peek_buf[0] = fgetc(i->file); - i->peek_buf[1] = '\0'; - i->p = i->peek_buf; - debug_printf("b_peek: got a %d\n", *i->p); - return *i->p; - } -} - -static void setup_file_in_str(struct in_str *i, FILE *f) -{ - i->peek = file_peek; - i->get = file_get; - i->__promptme=1; - i->promptmode=1; - i->file = f; - i->p = NULL; -} - -static void setup_string_in_str(struct in_str *i, const char *s) -{ - i->peek = static_peek; - i->get = static_get; - i->__promptme=1; - i->promptmode=1; - i->p = s; -} - -static void mark_open(int fd) -{ - struct close_me *new = xmalloc(sizeof(struct close_me)); - new->fd = fd; - new->next = close_me_head; - close_me_head = new; -} - -static void mark_closed(int fd) -{ - struct close_me *tmp; - if (close_me_head == NULL || close_me_head->fd != fd) - error_msg_and_die("corrupt close_me"); - tmp = close_me_head; - close_me_head = close_me_head->next; - free(tmp); -} - -static void close_all() -{ - struct close_me *c; - for (c=close_me_head; c; c=c->next) { - close(c->fd); - } - close_me_head = NULL; -} - -/* squirrel != NULL means we squirrel away copies of stdin, stdout, - * and stderr if they are redirected. */ -static int setup_redirects(struct child_prog *prog, int squirrel[]) -{ - int openfd, mode; - struct redir_struct *redir; - - for (redir=prog->redirects; redir; redir=redir->next) { - if (redir->dup == -1 && redir->word.gl_pathv == NULL) { - /* something went wrong in the parse. Pretend it didn't happen */ - continue; - } - if (redir->dup == -1) { - mode=redir_table[redir->type].mode; - openfd = open(redir->word.gl_pathv[0], mode, 0666); - if (openfd < 0) { - /* this could get lost if stderr has been redirected, but - bash and ash both lose it as well (though zsh doesn't!) */ - perror_msg("error opening %s", redir->word.gl_pathv[0]); - return 1; - } - } else { - openfd = redir->dup; - } - - if (openfd != redir->fd) { - if (squirrel && redir->fd < 3) { - squirrel[redir->fd] = dup(redir->fd); - } - if (openfd == -3) { - close(openfd); - } else { - dup2(openfd, redir->fd); - if (redir->dup == -1) - close (openfd); - } - } - } - return 0; -} - -static void restore_redirects(int squirrel[]) -{ - int i, fd; - for (i=0; i<3; i++) { - fd = squirrel[i]; - if (fd != -1) { - /* No error checking. I sure wouldn't know what - * to do with an error if I found one! */ - dup2(fd, i); - close(fd); - } - } -} - -/* never returns */ -/* XXX no exit() here. If you don't exec, use _exit instead. - * The at_exit handlers apparently confuse the calling process, - * in particular stdin handling. Not sure why? */ -static void pseudo_exec(struct child_prog *child) -{ - int i, rcode; - struct built_in_command *x; - if (child->argv) { - for (i=0; is_assignment(child->argv[i]); i++) { - debug_printf("pid %d environment modification: %s\n",getpid(),child->argv[i]); - putenv(strdup(child->argv[i])); - } - child->argv+=i; /* XXX this hack isn't so horrible, since we are about - to exit, and therefore don't need to keep data - structures consistent for free() use. */ - /* If a variable is assigned in a forest, and nobody listens, - * was it ever really set? - */ - if (child->argv[0] == NULL) { - _exit(EXIT_SUCCESS); - } - - /* - * Check if the command matches any of the builtins. - * Depending on context, this might be redundant. But it's - * easier to waste a few CPU cycles than it is to figure out - * if this is one of those cases. - */ - for (x = bltins; x->cmd; x++) { - if (strcmp(child->argv[0], x->cmd) == 0 ) { - debug_printf("builtin exec %s\n", child->argv[0]); - rcode = x->function(child); - fflush(stdout); - _exit(rcode); - } - } - - /* Check if the command matches any busybox internal commands - * ("applets") here. - * FIXME: This feature is not 100% safe, since - * BusyBox is not fully reentrant, so we have no guarantee the things - * from the .bss are still zeroed, or that things from .data are still - * at their defaults. We could exec ourself from /proc/self/exe, but I - * really dislike relying on /proc for things. We could exec ourself - * from global_argv[0], but if we are in a chroot, we may not be able - * to find ourself... */ -#ifdef BB_FEATURE_SH_STANDALONE_SHELL - { - int argc_l; - char** argv_l=child->argv; - char *name = child->argv[0]; - -#ifdef BB_FEATURE_SH_APPLETS_ALWAYS_WIN - /* Following discussions from November 2000 on the busybox mailing - * list, the default configuration, (without - * get_last_path_component()) lets the user force use of an - * external command by specifying the full (with slashes) filename. - * If you enable BB_FEATURE_SH_APPLETS_ALWAYS_WIN, then applets - * _aways_ override external commands, so if you want to run - * /bin/cat, it will use BusyBox cat even if /bin/cat exists on the - * filesystem and is _not_ busybox. Some systems may want this, - * most do not. */ - name = get_last_path_component(name); -#endif - /* Count argc for use in a second... */ - for(argc_l=0;*argv_l!=NULL; argv_l++, argc_l++); - optind = 1; - debug_printf("running applet %s\n", name); - run_applet_by_name(name, argc_l, child->argv); - } -#endif - debug_printf("exec of %s\n",child->argv[0]); - execvp(child->argv[0],child->argv); - perror_msg("couldn't exec: %s",child->argv[0]); - _exit(1); - } else if (child->group) { - debug_printf("runtime nesting to group\n"); - interactive=0; /* crucial!!!! */ - rcode = run_list_real(child->group); - /* OK to leak memory by not calling free_pipe_list, - * since this process is about to exit */ - _exit(rcode); - } else { - /* Can happen. See what bash does with ">foo" by itself. */ - debug_printf("trying to pseudo_exec null command\n"); - _exit(EXIT_SUCCESS); - } -} - -static void insert_bg_job(struct pipe *pi) -{ - struct pipe *thejob; - - /* Linear search for the ID of the job to use */ - pi->jobid = 1; - for (thejob = job_list; thejob; thejob = thejob->next) - if (thejob->jobid >= pi->jobid) - pi->jobid = thejob->jobid + 1; - - /* add thejob to the list of running jobs */ - if (!job_list) { - thejob = job_list = xmalloc(sizeof(*thejob)); - } else { - for (thejob = job_list; thejob->next; thejob = thejob->next) /* nothing */; - thejob->next = xmalloc(sizeof(*thejob)); - thejob = thejob->next; - } - - /* physically copy the struct job */ - memcpy(thejob, pi, sizeof(struct pipe)); - thejob->next = NULL; - thejob->running_progs = thejob->num_progs; - thejob->stopped_progs = 0; - thejob->text = xmalloc(BUFSIZ); /* cmdedit buffer size */ - - //if (pi->progs[0] && pi->progs[0].argv && pi->progs[0].argv[0]) - { - char *bar=thejob->text; - char **foo=pi->progs[0].argv; - while(foo && *foo) { - bar += sprintf(bar, "%s ", *foo++); - } - } - - /* we don't wait for background thejobs to return -- append it - to the list of backgrounded thejobs and leave it alone */ - printf("[%d] %d\n", thejob->jobid, thejob->progs[0].pid); - last_bg_pid = thejob->progs[0].pid; - last_jobid = thejob->jobid; -} - -/* remove a backgrounded job */ -static void remove_bg_job(struct pipe *pi) -{ - struct pipe *prev_pipe; - - if (pi == job_list) { - job_list = pi->next; - } else { - prev_pipe = job_list; - while (prev_pipe->next != pi) - prev_pipe = prev_pipe->next; - prev_pipe->next = pi->next; - } - if (job_list) - last_jobid = job_list->jobid; - else - last_jobid = 0; - - pi->stopped_progs = 0; - free_pipe(pi, 0); - free(pi); -} - -/* Checks to see if any processes have exited -- if they - have, figure out why and see if a job has completed */ -static int checkjobs(struct pipe* fg_pipe) -{ - int attributes; - int status; - int prognum = 0; - struct pipe *pi; - pid_t childpid; - - attributes = WUNTRACED; - if (fg_pipe==NULL) { - attributes |= WNOHANG; - } - - while ((childpid = waitpid(-1, &status, attributes)) > 0) { - if (fg_pipe) { - int i, rcode = 0; - for (i=0; i < fg_pipe->num_progs; i++) { - if (fg_pipe->progs[i].pid == childpid) { - if (i==fg_pipe->num_progs-1) - rcode=WEXITSTATUS(status); - (fg_pipe->num_progs)--; - return(rcode); - } - } - } - - for (pi = job_list; pi; pi = pi->next) { - prognum = 0; - while (prognum < pi->num_progs && pi->progs[prognum].pid != childpid) { - prognum++; - } - if (prognum < pi->num_progs) - break; - } - - if(pi==NULL) { - debug_printf("checkjobs: pid %d was not in our list!\n", childpid); - continue; - } - - if (WIFEXITED(status) || WIFSIGNALED(status)) { - /* child exited */ - pi->running_progs--; - pi->progs[prognum].pid = 0; - - if (!pi->running_progs) { - printf(JOB_STATUS_FORMAT, pi->jobid, "Done", pi->text); - remove_bg_job(pi); - } - } else { - /* child stopped */ - pi->stopped_progs++; - pi->progs[prognum].is_stopped = 1; - -#if 0 - /* Printing this stuff is a pain, since it tends to - * overwrite the prompt an inconveinient moments. So - * don't do that. */ - if (pi->stopped_progs == pi->num_progs) { - printf("\n"JOB_STATUS_FORMAT, pi->jobid, "Stopped", pi->text); - } -#endif - } - } - - if (childpid == -1 && errno != ECHILD) - perror_msg("waitpid"); - - /* move the shell to the foreground */ - //if (interactive && tcsetpgrp(shell_terminal, getpgid(0))) - // perror_msg("tcsetpgrp-2"); - return -1; -} - -/* Figure out our controlling tty, checking in order stderr, - * stdin, and stdout. If check_pgrp is set, also check that - * we belong to the foreground process group associated with - * that tty. The value of shell_terminal is needed in order to call - * tcsetpgrp(shell_terminal, ...); */ -void controlling_tty(int check_pgrp) -{ - pid_t curpgrp; - - if ((curpgrp = tcgetpgrp(shell_terminal = 2)) < 0 - && (curpgrp = tcgetpgrp(shell_terminal = 0)) < 0 - && (curpgrp = tcgetpgrp(shell_terminal = 1)) < 0) - goto shell_terminal_error; - - if (check_pgrp && curpgrp != getpgid(0)) - goto shell_terminal_error; - - return; - -shell_terminal_error: - shell_terminal = -1; - return; -} - -/* run_pipe_real() starts all the jobs, but doesn't wait for anything - * to finish. See checkjobs(). - * - * return code is normally -1, when the caller has to wait for children - * to finish to determine the exit status of the pipe. If the pipe - * is a simple builtin command, however, the action is done by the - * time run_pipe_real returns, and the exit code is provided as the - * return value. - * - * The input of the pipe is always stdin, the output is always - * stdout. The outpipe[] mechanism in BusyBox-0.48 lash is bogus, - * because it tries to avoid running the command substitution in - * subshell, when that is in fact necessary. The subshell process - * now has its stdout directed to the input of the appropriate pipe, - * so this routine is noticeably simpler. - */ -static int run_pipe_real(struct pipe *pi) -{ - int i; - int nextin, nextout; - int pipefds[2]; /* pipefds[0] is for reading */ - struct child_prog *child; - struct built_in_command *x; - - nextin = 0; - pi->pgrp = -1; - - /* Check if this is a simple builtin (not part of a pipe). - * Builtins within pipes have to fork anyway, and are handled in - * pseudo_exec. "echo foo | read bar" doesn't work on bash, either. - */ - if (pi->num_progs == 1) child = & (pi->progs[0]); - if (pi->num_progs == 1 && child->group && child->subshell == 0) { - int squirrel[] = {-1, -1, -1}; - int rcode; - debug_printf("non-subshell grouping\n"); - setup_redirects(child, squirrel); - /* XXX could we merge code with following builtin case, - * by creating a pseudo builtin that calls run_list_real? */ - rcode = run_list_real(child->group); - restore_redirects(squirrel); - return rcode; - } else if (pi->num_progs == 1 && pi->progs[0].argv != NULL) { - for (i=0; is_assignment(child->argv[i]); i++) { /* nothing */ } - if (i!=0 && child->argv[i]==NULL) { - /* assignments, but no command: set the local environment */ - for (i=0; child->argv[i]!=NULL; i++) { - - /* Ok, this case is tricky. We have to decide if this is a - * local variable, or an already exported variable. If it is - * already exported, we have to export the new value. If it is - * not exported, we need only set this as a local variable. - * This junk is all to decide whether or not to export this - * variable. */ - int export_me=0; - char *name, *value; - name = xstrdup(child->argv[i]); - debug_printf("Local environment set: %s\n", name); - value = strchr(name, '='); - if (value) - *value=0; - if ( get_local_var(name)) { - export_me=1; - } - free(name); - set_local_var(child->argv[i], export_me); - } - return EXIT_SUCCESS; /* don't worry about errors in set_local_var() yet */ - } - for (x = bltins; x->cmd; x++) { - if (strcmp(child->argv[i], x->cmd) == 0 ) { - int squirrel[] = {-1, -1, -1}; - int rcode; - if (x->function == builtin_exec && child->argv[i+1]==NULL) { - debug_printf("magic exec\n"); - setup_redirects(child,NULL); - return EXIT_SUCCESS; - } - debug_printf("builtin inline %s\n", child->argv[0]); - /* XXX setup_redirects acts on file descriptors, not FILEs. - * This is perfect for work that comes after exec(). - * Is it really safe for inline use? Experimentally, - * things seem to work with glibc. */ - setup_redirects(child, squirrel); - for (i=0; is_assignment(child->argv[i]); i++) { - putenv(strdup(child->argv[i])); - } - child->argv+=i; /* XXX horrible hack */ - rcode = x->function(child); - child->argv-=i; /* XXX restore hack so free() can work right */ - restore_redirects(squirrel); - return rcode; - } - } - } - - for (i = 0; i < pi->num_progs; i++) { - child = & (pi->progs[i]); - - /* pipes are inserted between pairs of commands */ - if ((i + 1) < pi->num_progs) { - if (pipe(pipefds)<0) perror_msg_and_die("pipe"); - nextout = pipefds[1]; - } else { - nextout=1; - pipefds[0] = -1; - } - - /* XXX test for failed fork()? */ - if (!(child->pid = fork())) { - /* Set the handling for job control signals back to the default. */ - signal(SIGINT, SIG_DFL); - signal(SIGQUIT, SIG_DFL); - signal(SIGTERM, SIG_DFL); - signal(SIGTSTP, SIG_DFL); - signal(SIGTTIN, SIG_DFL); - signal(SIGTTOU, SIG_DFL); - signal(SIGCHLD, SIG_DFL); - - close_all(); - - if (nextin != 0) { - dup2(nextin, 0); - close(nextin); - } - if (nextout != 1) { - dup2(nextout, 1); - close(nextout); - } - if (pipefds[0]!=-1) { - close(pipefds[0]); /* opposite end of our output pipe */ - } - - /* Like bash, explicit redirects override pipes, - * and the pipe fd is available for dup'ing. */ - setup_redirects(child,NULL); - - if (interactive && pi->followup!=PIPE_BG) { - /* If we (the child) win the race, put ourselves in the process - * group whose leader is the first process in this pipe. */ - if (pi->pgrp < 0) { - pi->pgrp = getpid(); - } - if (setpgid(0, pi->pgrp) == 0) { - tcsetpgrp(2, pi->pgrp); - } - } - - pseudo_exec(child); - } - - - /* put our child in the process group whose leader is the - first process in this pipe */ - if (pi->pgrp < 0) { - pi->pgrp = child->pid; - } - /* Don't check for errors. The child may be dead already, - * in which case setpgid returns error code EACCES. */ - setpgid(child->pid, pi->pgrp); - - if (nextin != 0) - close(nextin); - if (nextout != 1) - close(nextout); - - /* If there isn't another process, nextin is garbage - but it doesn't matter */ - nextin = pipefds[0]; - } - return -1; -} - -static int run_list_real(struct pipe *pi) -{ - int rcode=0; - int if_code=0, next_if_code=0; /* need double-buffer to handle elif */ - reserved_style rmode, skip_more_in_this_rmode=RES_XXXX; - for (;pi;pi=pi->next) { - rmode = pi->r_mode; - debug_printf("rmode=%d if_code=%d next_if_code=%d skip_more=%d\n", rmode, if_code, next_if_code, skip_more_in_this_rmode); - if (rmode == skip_more_in_this_rmode) continue; - skip_more_in_this_rmode = RES_XXXX; - if (rmode == RES_THEN || rmode == RES_ELSE) if_code = next_if_code; - if (rmode == RES_THEN && if_code) continue; - if (rmode == RES_ELSE && !if_code) continue; - if (rmode == RES_ELIF && !if_code) continue; - if (pi->num_progs == 0) continue; - rcode = run_pipe_real(pi); - debug_printf("run_pipe_real returned %d\n",rcode); - if (rcode!=-1) { - /* We only ran a builtin: rcode was set by the return value - * of run_pipe_real(), and we don't need to wait for anything. */ - } else if (pi->followup==PIPE_BG) { - /* XXX check bash's behavior with nontrivial pipes */ - /* XXX compute jobid */ - /* XXX what does bash do with attempts to background builtins? */ - insert_bg_job(pi); - rcode = EXIT_SUCCESS; - } else { - if (interactive) { - /* move the new process group into the foreground */ - if (tcsetpgrp(shell_terminal, pi->pgrp) && errno != ENOTTY) - perror_msg("tcsetpgrp-3"); - rcode = checkjobs(pi); - /* move the shell to the foreground */ - if (tcsetpgrp(shell_terminal, getpgid(0)) && errno != ENOTTY) - perror_msg("tcsetpgrp-4"); - } else { - rcode = checkjobs(pi); - } - debug_printf("checkjobs returned %d\n",rcode); - } - last_return_code=rcode; - if ( rmode == RES_IF || rmode == RES_ELIF ) - next_if_code=rcode; /* can be overwritten a number of times */ - if ( (rcode==EXIT_SUCCESS && pi->followup==PIPE_OR) || - (rcode!=EXIT_SUCCESS && pi->followup==PIPE_AND) ) - skip_more_in_this_rmode=rmode; - checkjobs(NULL); - } - return rcode; -} - -/* broken, of course, but OK for testing */ -static char *indenter(int i) -{ - static char blanks[]=" "; - return &blanks[sizeof(blanks)-i-1]; -} - -/* return code is the exit status of the pipe */ -static int free_pipe(struct pipe *pi, int indent) -{ - char **p; - struct child_prog *child; - struct redir_struct *r, *rnext; - int a, i, ret_code=0; - char *ind = indenter(indent); - - if (pi->stopped_progs > 0) - return ret_code; - final_printf("%s run pipe: (pid %d)\n",ind,getpid()); - for (i=0; inum_progs; i++) { - child = &pi->progs[i]; - final_printf("%s command %d:\n",ind,i); - if (child->argv) { - for (a=0,p=child->argv; *p; a++,p++) { - final_printf("%s argv[%d] = %s\n",ind,a,*p); - } - globfree(&child->glob_result); - child->argv=NULL; - } else if (child->group) { - final_printf("%s begin group (subshell:%d)\n",ind, child->subshell); - ret_code = free_pipe_list(child->group,indent+3); - final_printf("%s end group\n",ind); - } else { - final_printf("%s (nil)\n",ind); - } - for (r=child->redirects; r; r=rnext) { - final_printf("%s redirect %d%s", ind, r->fd, redir_table[r->type].descrip); - if (r->dup == -1) { - /* guard against the case >$FOO, where foo is unset or blank */ - if (r->word.gl_pathv) { - final_printf(" %s\n", *r->word.gl_pathv); - globfree(&r->word); - } - } else { - final_printf("&%d\n", r->dup); - } - rnext=r->next; - free(r); - } - child->redirects=NULL; - } - free(pi->progs); /* children are an array, they get freed all at once */ - pi->progs=NULL; - return ret_code; -} - -static int free_pipe_list(struct pipe *head, int indent) -{ - int rcode=0; /* if list has no members */ - struct pipe *pi, *next; - char *ind = indenter(indent); - for (pi=head; pi; pi=next) { - final_printf("%s pipe reserved mode %d\n", ind, pi->r_mode); - rcode = free_pipe(pi, indent); - final_printf("%s pipe followup code %d\n", ind, pi->followup); - next=pi->next; - pi->next=NULL; - free(pi); - } - return rcode; -} - -/* Select which version we will use */ -static int run_list(struct pipe *pi) -{ - int rcode=0; - if (fake_mode==0) { - rcode = run_list_real(pi); - } - /* free_pipe_list has the side effect of clearing memory - * In the long run that function can be merged with run_list_real, - * but doing that now would hobble the debugging effort. */ - free_pipe_list(pi,0); - return rcode; -} - -/* The API for glob is arguably broken. This routine pushes a non-matching - * string into the output structure, removing non-backslashed backslashes. - * If someone can prove me wrong, by performing this function within the - * original glob(3) api, feel free to rewrite this routine into oblivion. - * Return code (0 vs. GLOB_NOSPACE) matches glob(3). - * XXX broken if the last character is '\\', check that before calling. - */ -static int globhack(const char *src, int flags, glob_t *pglob) -{ - int cnt=0, pathc; - const char *s; - char *dest; - for (cnt=1, s=src; s && *s; s++) { - if (*s == '\\') s++; - cnt++; - } - dest = malloc(cnt); - if (!dest) return GLOB_NOSPACE; - if (!(flags & GLOB_APPEND)) { - pglob->gl_pathv=NULL; - pglob->gl_pathc=0; - pglob->gl_offs=0; - pglob->gl_offs=0; - } - pathc = ++pglob->gl_pathc; - pglob->gl_pathv = realloc(pglob->gl_pathv, (pathc+1)*sizeof(*pglob->gl_pathv)); - if (pglob->gl_pathv == NULL) return GLOB_NOSPACE; - pglob->gl_pathv[pathc-1]=dest; - pglob->gl_pathv[pathc]=NULL; - for (s=src; s && *s; s++, dest++) { - if (*s == '\\') s++; - *dest = *s; - } - *dest='\0'; - return 0; -} - -/* XXX broken if the last character is '\\', check that before calling */ -static int glob_needed(const char *s) -{ - for (; *s; s++) { - if (*s == '\\') s++; - if (strchr("*[?",*s)) return 1; - } - return 0; -} - -#if 0 -static void globprint(glob_t *pglob) -{ - int i; - debug_printf("glob_t at %p:\n", pglob); - debug_printf(" gl_pathc=%d gl_pathv=%p gl_offs=%d gl_flags=%d\n", - pglob->gl_pathc, pglob->gl_pathv, pglob->gl_offs, pglob->gl_flags); - for (i=0; igl_pathc; i++) - debug_printf("pglob->gl_pathv[%d] = %p = %s\n", i, - pglob->gl_pathv[i], pglob->gl_pathv[i]); -} -#endif - -static int xglob(o_string *dest, int flags, glob_t *pglob) -{ - int gr; - - /* short-circuit for null word */ - /* we can code this better when the debug_printf's are gone */ - if (dest->length == 0) { - if (dest->nonnull) { - /* bash man page calls this an "explicit" null */ - gr = globhack(dest->data, flags, pglob); - debug_printf("globhack returned %d\n",gr); - } else { - return 0; - } - } else if (glob_needed(dest->data)) { - gr = glob(dest->data, flags, NULL, pglob); - debug_printf("glob returned %d\n",gr); - if (gr == GLOB_NOMATCH) { - /* quote removal, or more accurately, backslash removal */ - gr = globhack(dest->data, flags, pglob); - debug_printf("globhack returned %d\n",gr); - } - } else { - gr = globhack(dest->data, flags, pglob); - debug_printf("globhack returned %d\n",gr); - } - if (gr == GLOB_NOSPACE) - error_msg_and_die("out of memory during glob"); - if (gr != 0) { /* GLOB_ABORTED ? */ - error_msg("glob(3) error %d",gr); - } - /* globprint(glob_target); */ - return gr; -} - -/* This is used to get/check local shell variables */ -static char *get_local_var(const char *s) -{ - struct variables *cur; - - if (!s) - return NULL; - for (cur = top_vars; cur; cur=cur->next) - if(strcmp(cur->name, s)==0) - return cur->value; - return NULL; -} - -/* This is used to set local shell variables - flg_export==0 if only local (not exporting) variable - flg_export==1 if "new" exporting environ - flg_export>1 if current startup environ (not call putenv()) */ -static int set_local_var(const char *s, int flg_export) -{ - char *name, *value; - int result=0; - struct variables *cur; - - name=strdup(s); - - /* Assume when we enter this function that we are already in - * NAME=VALUE format. So the first order of business is to - * split 's' on the '=' into 'name' and 'value' */ - value = strchr(name, '='); - if (value==0 && ++value==0) { - free(name); - return -1; - } - *value++ = 0; - - for(cur = top_vars; cur; cur = cur->next) { - if(strcmp(cur->name, name)==0) - break; - } - - if(cur) { - if(strcmp(cur->value, value)==0) { - if(flg_export>0 && cur->flg_export==0) - cur->flg_export=flg_export; - else - result++; - } else { - if(cur->flg_read_only) { - error_msg("%s: readonly variable", name); - result = -1; - } else { - if(flg_export>0 || cur->flg_export>1) - cur->flg_export=1; - free(cur->value); - - cur->value = strdup(value); - } - } - } else { - cur = malloc(sizeof(struct variables)); - if(!cur) { - result = -1; - } else { - cur->name = strdup(name); - if(cur->name == 0) { - free(cur); - result = -1; - } else { - struct variables *bottom = top_vars; - cur->value = strdup(value); - cur->next = 0; - cur->flg_export = flg_export; - cur->flg_read_only = 0; - while(bottom->next) bottom=bottom->next; - bottom->next = cur; - } - } - } - - if(result==0 && cur->flg_export==1) { - *(value-1) = '='; - result = putenv(name); - } else { - free(name); - if(result>0) /* equivalent to previous set */ - result = 0; - } - return result; -} - -static void unset_local_var(const char *name) -{ - struct variables *cur; - - if (name) { - for (cur = top_vars; cur; cur=cur->next) { - if(strcmp(cur->name, name)==0) - break; - } - if(cur!=0) { - struct variables *next = top_vars; - if(cur->flg_read_only) { - error_msg("%s: readonly variable", name); - return; - } else { - if(cur->flg_export) - unsetenv(cur->name); - free(cur->name); - free(cur->value); - while (next->next != cur) - next = next->next; - next->next = cur->next; - } - free(cur); - } - } -} - -static int is_assignment(const char *s) -{ - if (s==NULL || !isalpha(*s)) return 0; - ++s; - while(isalnum(*s) || *s=='_') ++s; - return *s=='='; -} - -/* the src parameter allows us to peek forward to a possible &n syntax - * for file descriptor duplication, e.g., "2>&1". - * Return code is 0 normally, 1 if a syntax error is detected in src. - * Resource errors (in xmalloc) cause the process to exit */ -static int setup_redirect(struct p_context *ctx, int fd, redir_type style, - struct in_str *input) -{ - struct child_prog *child=ctx->child; - struct redir_struct *redir = child->redirects; - struct redir_struct *last_redir=NULL; - - /* Create a new redir_struct and drop it onto the end of the linked list */ - while(redir) { - last_redir=redir; - redir=redir->next; - } - redir = xmalloc(sizeof(struct redir_struct)); - redir->next=NULL; - redir->word.gl_pathv=NULL; - if (last_redir) { - last_redir->next=redir; - } else { - child->redirects=redir; - } - - redir->type=style; - redir->fd= (fd==-1) ? redir_table[style].default_fd : fd ; - - debug_printf("Redirect type %d%s\n", redir->fd, redir_table[style].descrip); - - /* Check for a '2>&1' type redirect */ - redir->dup = redirect_dup_num(input); - if (redir->dup == -2) return 1; /* syntax error */ - if (redir->dup != -1) { - /* Erik had a check here that the file descriptor in question - * is legit; I postpone that to "run time" - * A "-" representation of "close me" shows up as a -3 here */ - debug_printf("Duplicating redirect '%d>&%d'\n", redir->fd, redir->dup); - } else { - /* We do _not_ try to open the file that src points to, - * since we need to return and let src be expanded first. - * Set ctx->pending_redirect, so we know what to do at the - * end of the next parsed word. - */ - ctx->pending_redirect = redir; - } - return 0; -} - -struct pipe *new_pipe(void) { - struct pipe *pi; - pi = xmalloc(sizeof(struct pipe)); - pi->num_progs = 0; - pi->progs = NULL; - pi->next = NULL; - pi->followup = 0; /* invalid */ - return pi; -} - -static void initialize_context(struct p_context *ctx) -{ - ctx->pipe=NULL; - ctx->pending_redirect=NULL; - ctx->child=NULL; - ctx->list_head=new_pipe(); - ctx->pipe=ctx->list_head; - ctx->w=RES_NONE; - ctx->stack=NULL; - done_command(ctx); /* creates the memory for working child */ -} - -/* normal return is 0 - * if a reserved word is found, and processed, return 1 - * should handle if, then, elif, else, fi, for, while, until, do, done. - * case, function, and select are obnoxious, save those for later. - */ -int reserved_word(o_string *dest, struct p_context *ctx) -{ - struct reserved_combo { - char *literal; - int code; - long flag; - }; - /* Mostly a list of accepted follow-up reserved words. - * FLAG_END means we are done with the sequence, and are ready - * to turn the compound list into a command. - * FLAG_START means the word must start a new compound list. - */ - static struct reserved_combo reserved_list[] = { - { "if", RES_IF, FLAG_THEN | FLAG_START }, - { "then", RES_THEN, FLAG_ELIF | FLAG_ELSE | FLAG_FI }, - { "elif", RES_ELIF, FLAG_THEN }, - { "else", RES_ELSE, FLAG_FI }, - { "fi", RES_FI, FLAG_END }, - { "for", RES_FOR, FLAG_DO | FLAG_START }, - { "while", RES_WHILE, FLAG_DO | FLAG_START }, - { "until", RES_UNTIL, FLAG_DO | FLAG_START }, - { "do", RES_DO, FLAG_DONE }, - { "done", RES_DONE, FLAG_END } - }; - struct reserved_combo *r; - for (r=reserved_list; -#define NRES sizeof(reserved_list)/sizeof(struct reserved_combo) - rdata, r->literal) == 0) { - debug_printf("found reserved word %s, code %d\n",r->literal,r->code); - if (r->flag & FLAG_START) { - struct p_context *new = xmalloc(sizeof(struct p_context)); - debug_printf("push stack\n"); - *new = *ctx; /* physical copy */ - initialize_context(ctx); - ctx->stack=new; - } else if ( ctx->w == RES_NONE || ! (ctx->old_flag & (1<code))) { - syntax(); - ctx->w = RES_SNTX; - b_reset (dest); - return 1; - } - ctx->w=r->code; - ctx->old_flag = r->flag; - if (ctx->old_flag & FLAG_END) { - struct p_context *old; - debug_printf("pop stack\n"); - old = ctx->stack; - old->child->group = ctx->list_head; - old->child->subshell = 0; - *ctx = *old; /* physical copy */ - free(old); - } - b_reset (dest); - return 1; - } - } - return 0; -} - -/* normal return is 0. - * Syntax or xglob errors return 1. */ -static int done_word(o_string *dest, struct p_context *ctx) -{ - struct child_prog *child=ctx->child; - glob_t *glob_target; - int gr, flags = 0; - - debug_printf("done_word: %s %p\n", dest->data, child); - if (dest->length == 0 && !dest->nonnull) { - debug_printf(" true null, ignored\n"); - return 0; - } - if (ctx->pending_redirect) { - glob_target = &ctx->pending_redirect->word; - } else { - if (child->group) { - syntax(); - return 1; /* syntax error, groups and arglists don't mix */ - } - if (!child->argv) { - debug_printf("checking %s for reserved-ness\n",dest->data); - if (reserved_word(dest,ctx)) return ctx->w==RES_SNTX; - } - glob_target = &child->glob_result; - if (child->argv) flags |= GLOB_APPEND; - } - gr = xglob(dest, flags, glob_target); - if (gr != 0) return 1; - - b_reset(dest); - if (ctx->pending_redirect) { - ctx->pending_redirect=NULL; - if (glob_target->gl_pathc != 1) { - error_msg("ambiguous redirect"); - return 1; - } - } else { - child->argv = glob_target->gl_pathv; - } - return 0; -} - -/* The only possible error here is out of memory, in which case - * xmalloc exits. */ -static int done_command(struct p_context *ctx) -{ - /* The child is really already in the pipe structure, so - * advance the pipe counter and make a new, null child. - * Only real trickiness here is that the uncommitted - * child structure, to which ctx->child points, is not - * counted in pi->num_progs. */ - struct pipe *pi=ctx->pipe; - struct child_prog *prog=ctx->child; - - if (prog && prog->group == NULL - && prog->argv == NULL - && prog->redirects == NULL) { - debug_printf("done_command: skipping null command\n"); - return 0; - } else if (prog) { - pi->num_progs++; - debug_printf("done_command: num_progs incremented to %d\n",pi->num_progs); - } else { - debug_printf("done_command: initializing\n"); - } - pi->progs = xrealloc(pi->progs, sizeof(*pi->progs) * (pi->num_progs+1)); - - prog = pi->progs + pi->num_progs; - prog->redirects = NULL; - prog->argv = NULL; - prog->is_stopped = 0; - prog->group = NULL; - prog->glob_result.gl_pathv = NULL; - prog->family = pi; - - ctx->child=prog; - /* but ctx->pipe and ctx->list_head remain unchanged */ - return 0; -} - -static int done_pipe(struct p_context *ctx, pipe_style type) -{ - struct pipe *new_p; - done_command(ctx); /* implicit closure of previous command */ - debug_printf("done_pipe, type %d\n", type); - ctx->pipe->followup = type; - ctx->pipe->r_mode = ctx->w; - new_p=new_pipe(); - ctx->pipe->next = new_p; - ctx->pipe = new_p; - ctx->child = NULL; - done_command(ctx); /* set up new pipe to accept commands */ - return 0; -} - -/* peek ahead in the in_str to find out if we have a "&n" construct, - * as in "2>&1", that represents duplicating a file descriptor. - * returns either -2 (syntax error), -1 (no &), or the number found. - */ -static int redirect_dup_num(struct in_str *input) -{ - int ch, d=0, ok=0; - ch = b_peek(input); - if (ch != '&') return -1; - - b_getch(input); /* get the & */ - ch=b_peek(input); - if (ch == '-') { - b_getch(input); - return -3; /* "-" represents "close me" */ - } - while (isdigit(ch)) { - d = d*10+(ch-'0'); - ok=1; - b_getch(input); - ch = b_peek(input); - } - if (ok) return d; - - error_msg("ambiguous redirect"); - return -2; -} - -/* If a redirect is immediately preceded by a number, that number is - * supposed to tell which file descriptor to redirect. This routine - * looks for such preceding numbers. In an ideal world this routine - * needs to handle all the following classes of redirects... - * echo 2>foo # redirects fd 2 to file "foo", nothing passed to echo - * echo 49>foo # redirects fd 49 to file "foo", nothing passed to echo - * echo -2>foo # redirects fd 1 to file "foo", "-2" passed to echo - * echo 49x>foo # redirects fd 1 to file "foo", "49x" passed to echo - * A -1 output from this program means no valid number was found, so the - * caller should use the appropriate default for this redirection. - */ -static int redirect_opt_num(o_string *o) -{ - int num; - - if (o->length==0) return -1; - for(num=0; numlength; num++) { - if (!isdigit(*(o->data+num))) { - return -1; - } - } - /* reuse num (and save an int) */ - num=atoi(o->data); - b_reset(o); - return num; -} - -FILE *generate_stream_from_list(struct pipe *head) -{ - FILE *pf; -#if 1 - int pid, channel[2]; - if (pipe(channel)<0) perror_msg_and_die("pipe"); - pid=fork(); - if (pid<0) { - perror_msg_and_die("fork"); - } else if (pid==0) { - close(channel[0]); - if (channel[1] != 1) { - dup2(channel[1],1); - close(channel[1]); - } -#if 0 -#define SURROGATE "surrogate response" - write(1,SURROGATE,sizeof(SURROGATE)); - _exit(run_list(head)); -#else - _exit(run_list_real(head)); /* leaks memory */ -#endif - } - debug_printf("forked child %d\n",pid); - close(channel[1]); - pf = fdopen(channel[0],"r"); - debug_printf("pipe on FILE *%p\n",pf); -#else - free_pipe_list(head,0); - pf=popen("echo surrogate response","r"); - debug_printf("started fake pipe on FILE *%p\n",pf); -#endif - return pf; -} - -/* this version hacked for testing purposes */ -/* return code is exit status of the process that is run. */ -static int process_command_subs(o_string *dest, struct p_context *ctx, struct in_str *input, int subst_end) -{ - int retcode; - o_string result=NULL_O_STRING; - struct p_context inner; - FILE *p; - struct in_str pipe_str; - initialize_context(&inner); - - /* recursion to generate command */ - retcode = parse_stream(&result, &inner, input, subst_end); - if (retcode != 0) return retcode; /* syntax error or EOF */ - done_word(&result, &inner); - done_pipe(&inner, PIPE_SEQ); - b_free(&result); - - p=generate_stream_from_list(inner.list_head); - if (p==NULL) return 1; - mark_open(fileno(p)); - setup_file_in_str(&pipe_str, p); - - /* now send results of command back into original context */ - retcode = parse_stream(dest, ctx, &pipe_str, '\0'); - /* XXX In case of a syntax error, should we try to kill the child? - * That would be tough to do right, so just read until EOF. */ - if (retcode == 1) { - while (b_getch(&pipe_str)!=EOF) { /* discard */ }; - } - - debug_printf("done reading from pipe, pclose()ing\n"); - /* This is the step that wait()s for the child. Should be pretty - * safe, since we just read an EOF from its stdout. We could try - * to better, by using wait(), and keeping track of background jobs - * at the same time. That would be a lot of work, and contrary - * to the KISS philosophy of this program. */ - mark_closed(fileno(p)); - retcode=pclose(p); - free_pipe_list(inner.list_head,0); - debug_printf("pclosed, retcode=%d\n",retcode); - /* XXX this process fails to trim a single trailing newline */ - return retcode; -} - -static int parse_group(o_string *dest, struct p_context *ctx, - struct in_str *input, int ch) -{ - int rcode, endch=0; - struct p_context sub; - struct child_prog *child = ctx->child; - if (child->argv) { - syntax(); - return 1; /* syntax error, groups and arglists don't mix */ - } - initialize_context(&sub); - switch(ch) { - case '(': endch=')'; child->subshell=1; break; - case '{': endch='}'; break; - default: syntax(); /* really logic error */ - } - rcode=parse_stream(dest,&sub,input,endch); - done_word(dest,&sub); /* finish off the final word in the subcontext */ - done_pipe(&sub, PIPE_SEQ); /* and the final command there, too */ - child->group = sub.list_head; - return rcode; - /* child remains "open", available for possible redirects */ -} - -/* basically useful version until someone wants to get fancier, - * see the bash man page under "Parameter Expansion" */ -static void lookup_param(o_string *dest, struct p_context *ctx, o_string *src) -{ - const char *p=NULL; - if (src->data) { - p = getenv(src->data); - if (!p) - p = get_local_var(src->data); - } - if (p) parse_string(dest, ctx, p); /* recursion */ - b_free(src); -} - -/* return code: 0 for OK, 1 for syntax error */ -static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *input) -{ - int i, advance=0; - o_string alt=NULL_O_STRING; - char sep[]=" "; - int ch = input->peek(input); /* first character after the $ */ - debug_printf("handle_dollar: ch=%c\n",ch); - if (isalpha(ch)) { - while(ch=b_peek(input),isalnum(ch) || ch=='_') { - b_getch(input); - b_addchr(&alt,ch); - } - lookup_param(dest, ctx, &alt); - } else if (isdigit(ch)) { - i = ch-'0'; /* XXX is $0 special? */ - if (i 0) b_adduint(dest, last_bg_pid); - advance = 1; - break; - case '?': - b_adduint(dest,last_return_code); - advance = 1; - break; - case '#': - b_adduint(dest,global_argc ? global_argc-1 : 0); - advance = 1; - break; - case '{': - b_getch(input); - /* XXX maybe someone will try to escape the '}' */ - while(ch=b_getch(input),ch!=EOF && ch!='}') { - b_addchr(&alt,ch); - } - if (ch != '}') { - syntax(); - return 1; - } - lookup_param(dest, ctx, &alt); - break; - case '(': - b_getch(input); - process_command_subs(dest, ctx, input, ')'); - break; - case '*': - sep[0]=ifs[0]; - for (i=1; iquote); - } - /* Eat the character if the flag was set. If the compiler - * is smart enough, we could substitute "b_getch(input);" - * for all the "advance = 1;" above, and also end up with - * a nice size-optimized program. Hah! That'll be the day. - */ - if (advance) b_getch(input); - return 0; -} - -int parse_string(o_string *dest, struct p_context *ctx, const char *src) -{ - struct in_str foo; - setup_string_in_str(&foo, src); - return parse_stream(dest, ctx, &foo, '\0'); -} - -/* return code is 0 for normal exit, 1 for syntax error */ -int parse_stream(o_string *dest, struct p_context *ctx, - struct in_str *input, int end_trigger) -{ - unsigned int ch, m; - int redir_fd; - redir_type redir_style; - int next; - - /* Only double-quote state is handled in the state variable dest->quote. - * A single-quote triggers a bypass of the main loop until its mate is - * found. When recursing, quote state is passed in via dest->quote. */ - - debug_printf("parse_stream, end_trigger=%d\n",end_trigger); - while ((ch=b_getch(input))!=EOF) { - m = map[ch]; - next = (ch == '\n') ? 0 : b_peek(input); - debug_printf("parse_stream: ch=%c (%d) m=%d quote=%d\n", - ch,ch,m,dest->quote); - if (m==0 || ((m==1 || m==2) && dest->quote)) { - b_addqchr(dest, ch, dest->quote); - } else { - if (m==2) { /* unquoted IFS */ - done_word(dest, ctx); - /* If we aren't performing a substitution, treat a newline as a - * command separator. */ - if (end_trigger != '\0' && ch=='\n') - done_pipe(ctx,PIPE_SEQ); - } - if (ch == end_trigger && !dest->quote && ctx->w==RES_NONE) { - debug_printf("leaving parse_stream (triggered)\n"); - return 0; - } -#if 0 - if (ch=='\n') { - /* Yahoo! Time to run with it! */ - done_pipe(ctx,PIPE_SEQ); - run_list(ctx->list_head); - initialize_context(ctx); - } -#endif - if (m!=2) switch (ch) { - case '#': - if (dest->length == 0 && !dest->quote) { - while(ch=b_peek(input),ch!=EOF && ch!='\n') { b_getch(input); } - } else { - b_addqchr(dest, ch, dest->quote); - } - break; - case '\\': - if (next == EOF) { - syntax(); - return 1; - } - b_addqchr(dest, '\\', dest->quote); - b_addqchr(dest, b_getch(input), dest->quote); - break; - case '$': - if (handle_dollar(dest, ctx, input)!=0) return 1; - break; - case '\'': - dest->nonnull = 1; - while(ch=b_getch(input),ch!=EOF && ch!='\'') { - b_addchr(dest,ch); - } - if (ch==EOF) { - syntax(); - return 1; - } - break; - case '"': - dest->nonnull = 1; - dest->quote = !dest->quote; - break; - case '`': - process_command_subs(dest, ctx, input, '`'); - break; - case '>': - redir_fd = redirect_opt_num(dest); - done_word(dest, ctx); - redir_style=REDIRECT_OVERWRITE; - if (next == '>') { - redir_style=REDIRECT_APPEND; - b_getch(input); - } else if (next == '(') { - syntax(); /* until we support >(list) Process Substitution */ - return 1; - } - setup_redirect(ctx, redir_fd, redir_style, input); - break; - case '<': - redir_fd = redirect_opt_num(dest); - done_word(dest, ctx); - redir_style=REDIRECT_INPUT; - if (next == '<') { - redir_style=REDIRECT_HEREIS; - b_getch(input); - } else if (next == '>') { - redir_style=REDIRECT_IO; - b_getch(input); - } else if (next == '(') { - syntax(); /* until we support <(list) Process Substitution */ - return 1; - } - setup_redirect(ctx, redir_fd, redir_style, input); - break; - case ';': - done_word(dest, ctx); - done_pipe(ctx,PIPE_SEQ); - break; - case '&': - done_word(dest, ctx); - if (next=='&') { - b_getch(input); - done_pipe(ctx,PIPE_AND); - } else { - done_pipe(ctx,PIPE_BG); - } - break; - case '|': - done_word(dest, ctx); - if (next=='|') { - b_getch(input); - done_pipe(ctx,PIPE_OR); - } else { - /* we could pick up a file descriptor choice here - * with redirect_opt_num(), but bash doesn't do it. - * "echo foo 2| cat" yields "foo 2". */ - done_command(ctx); - } - break; - case '(': - case '{': - if (parse_group(dest, ctx, input, ch)!=0) return 1; - break; - case ')': - case '}': - syntax(); /* Proper use of this character caught by end_trigger */ - return 1; - break; - default: - syntax(); /* this is really an internal logic error */ - return 1; - } - } - } - /* complain if quote? No, maybe we just finished a command substitution - * that was quoted. Example: - * $ echo "`cat foo` plus more" - * and we just got the EOF generated by the subshell that ran "cat foo" - * The only real complaint is if we got an EOF when end_trigger != '\0', - * that is, we were really supposed to get end_trigger, and never got - * one before the EOF. Can't use the standard "syntax error" return code, - * so that parse_stream_outer can distinguish the EOF and exit smoothly. */ - debug_printf("leaving parse_stream (EOF)\n"); - if (end_trigger != '\0') return -1; - return 0; -} - -void mapset(const unsigned char *set, int code) -{ - const unsigned char *s; - for (s=set; *s; s++) map[*s] = code; -} - -void update_ifs_map(void) -{ - /* char *ifs and char map[256] are both globals. */ - ifs = getenv("IFS"); - if (ifs == NULL) ifs=" \t\n"; - /* Precompute a list of 'flow through' behavior so it can be treated - * quickly up front. Computation is necessary because of IFS. - * Special case handling of IFS == " \t\n" is not implemented. - * The map[] array only really needs two bits each, and on most machines - * that would be faster because of the reduced L1 cache footprint. - */ - memset(map,0,sizeof(map)); /* most characters flow through always */ - mapset("\\$'\"`", 3); /* never flow through */ - mapset("<>;&|(){}#", 1); /* flow through if quoted */ - mapset(ifs, 2); /* also flow through if quoted */ -} - -/* most recursion does not come through here, the exeception is - * from builtin_source() */ -int parse_stream_outer(struct in_str *inp) -{ - - struct p_context ctx; - o_string temp=NULL_O_STRING; - int rcode; - do { - initialize_context(&ctx); - update_ifs_map(); - inp->promptmode=1; - rcode = parse_stream(&temp, &ctx, inp, '\n'); - done_word(&temp, &ctx); - done_pipe(&ctx,PIPE_SEQ); - run_list(ctx.list_head); - b_free(&temp); - } while (rcode != -1); /* loop on syntax errors, return on EOF */ - return 0; -} - -static int parse_string_outer(const char *s) -{ - struct in_str input; - setup_string_in_str(&input, s); - return parse_stream_outer(&input); -} - -static int parse_file_outer(FILE *f) -{ - int rcode; - struct in_str input; - setup_file_in_str(&input, f); - rcode = parse_stream_outer(&input); - return rcode; -} - -/* Make sure we have a controlling tty. If we get started under a job - * aware app (like bash for example), make sure we are now in charge so - * we don't fight over who gets the foreground */ -static void setup_job_control() -{ - static pid_t shell_pgrp; - /* Loop until we are in the foreground. */ - while (tcgetpgrp (shell_terminal) != (shell_pgrp = getpgrp ())) - kill (- shell_pgrp, SIGTTIN); - - /* Ignore interactive and job-control signals. */ - signal(SIGINT, SIG_IGN); - signal(SIGQUIT, SIG_IGN); - signal(SIGTERM, SIG_IGN); - signal(SIGTSTP, SIG_IGN); - signal(SIGTTIN, SIG_IGN); - signal(SIGTTOU, SIG_IGN); - signal(SIGCHLD, SIG_IGN); - - /* Put ourselves in our own process group. */ - setsid(); - shell_pgrp = getpid (); - setpgid (shell_pgrp, shell_pgrp); - - /* Grab control of the terminal. */ - tcsetpgrp(shell_terminal, shell_pgrp); -} - -int hush_main(int argc, char **argv) -{ - int opt; - FILE *input; - char **e = environ; - - /* XXX what should these be while sourcing /etc/profile? */ - global_argc = argc; - global_argv = argv; - - /* (re?) initialize globals. Sometimes hush_main() ends up calling - * hush_main(), therefore we cannot rely on the BSS to zero out this - * stuff. Reset these to 0 every time. */ - ifs = NULL; - /* map[] is taken care of with call to update_ifs_map() */ - fake_mode = 0; - interactive = 0; - close_me_head = NULL; - last_bg_pid = 0; - job_list = NULL; - last_jobid = 0; - - /* Initialize some more globals to non-zero values */ - set_cwd(); -#ifdef BB_FEATURE_COMMAND_EDITING - cmdedit_set_initial_prompt(); -#else - PS1 = NULL; -#endif - PS2 = "> "; - - /* initialize our shell local variables with the values - * currently living in the environment */ - if (e) { - for (; *e; e++) - set_local_var(*e, 2); /* without call putenv() */ - } - - last_return_code=EXIT_SUCCESS; - - - if (argv[0] && argv[0][0] == '-') { - debug_printf("\nsourcing /etc/profile\n"); - if ((input = fopen("/etc/profile", "r")) != NULL) { - mark_open(fileno(input)); - parse_file_outer(input); - mark_closed(fileno(input)); - fclose(input); - } - } - input=stdin; - - while ((opt = getopt(argc, argv, "c:xif")) > 0) { - switch (opt) { - case 'c': - { - global_argv = argv+optind; - global_argc = argc-optind; - opt = parse_string_outer(optarg); - goto final_return; - } - break; - case 'i': - interactive++; - break; - case 'f': - fake_mode++; - break; - default: -#ifndef BB_VER - fprintf(stderr, "Usage: sh [FILE]...\n" - " or: sh -c command [args]...\n\n"); - exit(EXIT_FAILURE); -#else - show_usage(); -#endif - } - } - /* A shell is interactive if the `-i' flag was given, or if all of - * the following conditions are met: - * no -c command - * no arguments remaining or the -s flag given - * standard input is a terminal - * standard output is a terminal - * Refer to Posix.2, the description of the `sh' utility. */ - if (argv[optind]==NULL && input==stdin && - isatty(fileno(stdin)) && isatty(fileno(stdout))) { - interactive++; - } - - debug_printf("\ninteractive=%d\n", interactive); - if (interactive) { - /* Looks like they want an interactive shell */ -#ifndef BB_FEATURE_SH_EXTRA_QUIET - printf( "\n\n" BB_BANNER " hush - the humble shell v0.01 (testing)\n"); - printf( "Enter 'help' for a list of built-in commands.\n\n"); -#endif - setup_job_control(); - } - - if (argv[optind]==NULL) { - opt=parse_file_outer(stdin); - goto final_return; - } - - debug_printf("\nrunning script '%s'\n", argv[optind]); - global_argv = argv+optind; - global_argc = argc-optind; - input = xfopen(argv[optind], "r"); - opt = parse_file_outer(input); - -#ifdef BB_FEATURE_CLEAN_UP - fclose(input); - if (cwd && cwd != unknown) - free((char*)cwd); - { - struct variables *cur, *tmp; - for(cur = top_vars; cur; cur = tmp) { - tmp = cur->next; - if (!cur->flg_read_only) { - free(cur->name); - free(cur->value); - free(cur); - } - } - } -#endif - -final_return: - return(opt?opt:last_return_code); -} diff --git a/id.c b/id.c deleted file mode 100644 index 85b288c0c..000000000 --- a/id.c +++ /dev/null @@ -1,97 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini id implementation for busybox - * - * Copyright (C) 2000 by Randolph Chung - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include "busybox.h" -#include -#include -#include -#include -#include - -extern int id_main(int argc, char **argv) -{ - int no_user = 0, no_group = 0, print_real = 0; - int name_not_number = 0; - char user[9], group[9]; - long gid; - long pwnam, grnam; - int opt; - - gid = 0; - - while ((opt = getopt(argc, argv, "ugrn")) > 0) { - switch (opt) { - case 'u': - no_group++; - break; - case 'g': - no_user++; - break; - case 'r': - print_real++; - break; - case 'n': - name_not_number++; - break; - default: - show_usage(); - } - } - - if (no_user && no_group) show_usage(); - - if (argv[optind] == NULL) { - if (print_real) { - my_getpwuid(user, getuid()); - my_getgrgid(group, getgid()); - } else { - my_getpwuid(user, geteuid()); - my_getgrgid(group, getegid()); - } - } else { - strncpy(user, argv[optind], 8); - user[8] = '\0'; - gid = my_getpwnamegid(user); - my_getgrgid(group, gid); - } - - pwnam=my_getpwnam(user); - grnam=my_getgrnam(group); - - if (no_group) { - if(name_not_number && user) - puts(user); - else - printf("%ld\n", pwnam); - } else if (no_user) { - if(name_not_number && group) - puts(group); - else - printf("%ld\n", grnam); - } else { - printf("uid=%ld(%s) gid=%ld(%s)\n", pwnam, user, grnam, group); - } - return(0); -} - - -/* END CODE */ diff --git a/ifconfig.c b/ifconfig.c deleted file mode 100644 index c77ea04b1..000000000 --- a/ifconfig.c +++ /dev/null @@ -1,492 +0,0 @@ -/* ifconfig - * - * Similar to the standard Unix ifconfig, but with only the necessary - * parts for AF_INET, and without any printing of if info (for now). - * - * Bjorn Wesen, Axis Communications AB - * - * - * Authors of the original ifconfig was: - * Fred N. van Kempen, - * - * This program is free software; you can redistribute it - * and/or modify it under the terms of the GNU General - * Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * $Id: ifconfig.c,v 1.12 2001/08/10 06:02:23 mjn3 Exp $ - * - */ - -/* - * Heavily modified by Manuel Novoa III Mar 6, 2001 - * - * From initial port to busybox, removed most of the redundancy by - * converting to a table-driven approach. Added several (optional) - * args missing from initial port. - * - * Still missing: media, tunnel. - */ - -#include -#include -#include // strcmp and friends -#include // isdigit and friends -#include /* offsetof */ -#include -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" - -#ifdef BB_FEATURE_IFCONFIG_SLIP -#include -#endif - -/* I don't know if this is needed for busybox or not. Anyone? */ -#define QUESTIONABLE_ALIAS_CASE - - -/* Defines for glibc2.0 users. */ -#ifndef SIOCSIFTXQLEN -#define SIOCSIFTXQLEN 0x8943 -#define SIOCGIFTXQLEN 0x8942 -#endif - -/* ifr_qlen is ifru_ivalue, but it isn't present in 2.0 kernel headers */ -#ifndef ifr_qlen -#define ifr_qlen ifr_ifru.ifru_mtu -#endif - -#ifndef IFF_DYNAMIC -#define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses */ -#endif - -/* - * Here are the bit masks for the "flags" member of struct options below. - * N_ signifies no arg prefix; M_ signifies arg prefixed by '-'. - * CLR clears the flag; SET sets the flag; ARG signifies (optional) arg. - */ -#define N_CLR 0x01 -#define M_CLR 0x02 -#define N_SET 0x04 -#define M_SET 0x08 -#define N_ARG 0x10 -#define M_ARG 0x20 - -#define M_MASK (M_CLR | M_SET | M_ARG) -#define N_MASK (N_CLR | N_SET | N_ARG) -#define SET_MASK (N_SET | M_SET) -#define CLR_MASK (N_CLR | M_CLR) -#define SET_CLR_MASK (SET_MASK | CLR_MASK) -#define ARG_MASK (M_ARG | N_ARG) - -/* - * Here are the bit masks for the "arg_flags" member of struct options below. - */ - -/* - * cast type: - * 00 int - * 01 char * - * 02 HOST_COPY in_ether - * 03 HOST_COPY INET_resolve - */ -#define A_CAST_TYPE 0x03 -/* - * map type: - * 00 not a map type (mem_start, io_addr, irq) - * 04 memstart (unsigned long) - * 08 io_addr (unsigned short) - * 0C irq (unsigned char) - */ -#define A_MAP_TYPE 0x0C -#define A_ARG_REQ 0x10 /* Set if an arg is required. */ -#define A_NETMASK 0x20 /* Set if netmask (check for multiple sets). */ -#define A_SET_AFTER 0x40 /* Set a flag at the end. */ -#define A_COLON_CHK 0x80 /* Is this needed? See below. */ - -/* - * These defines are for dealing with the A_CAST_TYPE field. - */ -#define A_CAST_CHAR_PTR 0x01 -#define A_CAST_RESOLVE 0x01 -#define A_CAST_HOST_COPY 0x02 -#define A_CAST_HOST_COPY_IN_ETHER A_CAST_HOST_COPY -#define A_CAST_HOST_COPY_RESOLVE (A_CAST_HOST_COPY | A_CAST_RESOLVE) - -/* - * These defines are for dealing with the A_MAP_TYPE field. - */ -#define A_MAP_ULONG 0x04 /* memstart */ -#define A_MAP_USHORT 0x08 /* io_addr */ -#define A_MAP_UCHAR 0x0C /* irq */ - -/* - * Define the bit masks signifying which operations to perform for each arg. - */ - -#define ARG_METRIC (A_ARG_REQ /*| A_CAST_INT*/) -#define ARG_MTU (A_ARG_REQ /*| A_CAST_INT*/) -#define ARG_TXQUEUELEN (A_ARG_REQ /*| A_CAST_INT*/) -#define ARG_MEM_START (A_ARG_REQ | A_MAP_ULONG) -#define ARG_IO_ADDR (A_ARG_REQ | A_MAP_USHORT) -#define ARG_IRQ (A_ARG_REQ | A_MAP_UCHAR) -#define ARG_DSTADDR (A_ARG_REQ | A_CAST_HOST_COPY_RESOLVE) -#define ARG_NETMASK (A_ARG_REQ | A_CAST_HOST_COPY_RESOLVE | A_NETMASK) -#define ARG_BROADCAST (A_ARG_REQ | A_CAST_HOST_COPY_RESOLVE | A_SET_AFTER) -#define ARG_HW (A_ARG_REQ | A_CAST_HOST_COPY_IN_ETHER) -#define ARG_POINTOPOINT (A_CAST_HOST_COPY_RESOLVE | A_SET_AFTER) -#define ARG_KEEPALIVE (A_ARG_REQ | A_CAST_CHAR_PTR) -#define ARG_OUTFILL (A_ARG_REQ | A_CAST_CHAR_PTR) -#define ARG_HOSTNAME (A_CAST_HOST_COPY_RESOLVE | A_SET_AFTER | A_COLON_CHK) - - -/* - * Set up the tables. Warning! They must have corresponding order! - */ - -struct arg1opt { - const char *name; - unsigned short selector; - unsigned short ifr_offset; -}; - -struct options { - const char *name; - const unsigned char flags; - const unsigned char arg_flags; - const unsigned short selector; -}; - -#define ifreq_offsetof(x) offsetof(struct ifreq, x) - -static const struct arg1opt Arg1Opt[] = { - {"SIOCSIFMETRIC", SIOCSIFMETRIC, ifreq_offsetof(ifr_metric)}, - {"SIOCSIFMTU", SIOCSIFMTU, ifreq_offsetof(ifr_mtu)}, - {"SIOCSIFTXQLEN", SIOCSIFTXQLEN, ifreq_offsetof(ifr_qlen)}, - {"SIOCSIFDSTADDR", SIOCSIFDSTADDR, ifreq_offsetof(ifr_dstaddr)}, - {"SIOCSIFNETMASK", SIOCSIFNETMASK, ifreq_offsetof(ifr_netmask)}, - {"SIOCSIFBRDADDR", SIOCSIFBRDADDR, ifreq_offsetof(ifr_broadaddr)}, -#ifdef BB_FEATURE_IFCONFIG_HW - {"SIOCSIFHWADDR", SIOCSIFHWADDR, ifreq_offsetof(ifr_hwaddr)}, -#endif - {"SIOCSIFDSTADDR", SIOCSIFDSTADDR, ifreq_offsetof(ifr_dstaddr)}, -#ifdef SIOCSKEEPALIVE - {"SIOCSKEEPALIVE", SIOCSKEEPALIVE, ifreq_offsetof(ifr_data)}, -#endif -#ifdef SIOCSOUTFILL - {"SIOCSOUTFILL", SIOCSOUTFILL, ifreq_offsetof(ifr_data)}, -#endif -#ifdef BB_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ - {"SIOCSIFMAP", SIOCSIFMAP, ifreq_offsetof(ifr_map.mem_start)}, - {"SIOCSIFMAP", SIOCSIFMAP, ifreq_offsetof(ifr_map.base_addr)}, - {"SIOCSIFMAP", SIOCSIFMAP, ifreq_offsetof(ifr_map.irq)}, -#endif - /* Last entry if for unmatched (possibly hostname) arg. */ - {"SIOCSIFADDR", SIOCSIFADDR, ifreq_offsetof(ifr_addr)}, -}; - -static const struct options OptArray[] = { - {"metric", N_ARG, ARG_METRIC, 0}, - {"mtu", N_ARG, ARG_MTU, 0}, - {"txqueuelen", N_ARG, ARG_TXQUEUELEN, 0}, - {"dstaddr", N_ARG, ARG_DSTADDR, 0}, - {"netmask", N_ARG, ARG_NETMASK, 0}, - {"broadcast", N_ARG | M_CLR, ARG_BROADCAST, IFF_BROADCAST}, -#ifdef BB_FEATURE_IFCONFIG_HW - {"hw", N_ARG, ARG_HW, 0}, -#endif - {"pointopoint", N_ARG | M_CLR, ARG_POINTOPOINT, IFF_POINTOPOINT}, -#ifdef SIOCSKEEPALIVE - {"keepalive", N_ARG, ARG_KEEPALIVE, 0}, -#endif -#ifdef SIOCSOUTFILL - {"outfill", N_ARG, ARG_OUTFILL, 0}, -#endif -#ifdef BB_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ - {"mem_start", N_ARG, ARG_MEM_START, 0}, - {"io_addr", N_ARG, ARG_IO_ADDR, 0}, - {"irq", N_ARG, ARG_IRQ, 0}, -#endif - {"arp", N_CLR | M_SET, 0, IFF_NOARP}, - {"trailers", N_CLR | M_SET, 0, IFF_NOTRAILERS}, - {"promisc", N_SET | M_CLR, 0, IFF_PROMISC}, - {"multicast", N_SET | M_CLR, 0, IFF_MULTICAST}, - {"allmulti", N_SET | M_CLR, 0, IFF_ALLMULTI}, - {"dynamic", N_SET | M_CLR, 0, IFF_DYNAMIC}, - {"up", N_SET , 0, (IFF_UP | IFF_RUNNING)}, - {"down", N_CLR , 0, IFF_UP}, - { NULL, 0, ARG_HOSTNAME, (IFF_UP | IFF_RUNNING)} -}; - -/* - * A couple of prototypes. - */ - -#ifdef BB_FEATURE_IFCONFIG_HW -static int in_ether(char *bufp, struct sockaddr *sap); -#endif - -#ifdef BB_FEATURE_IFCONFIG_STATUS -extern int interface_opt_a; -extern int display_interfaces(char *ifname); -#endif - -/* - * Our main function. - */ - -int ifconfig_main(int argc, char **argv) -{ - struct ifreq ifr; - struct sockaddr_in sai; -#ifdef BB_FEATURE_IFCONFIG_HW - struct sockaddr sa; -#endif - const struct arg1opt *a1op; - const struct options *op; - int sockfd; /* socket fd we use to manipulate stuff with */ - int goterr; - int selector; - char *p; - char host[128]; - unsigned char mask; - unsigned char did_flags; - - goterr = 0; - did_flags = 0; - - /* skip argv[0] */ - ++argv; - --argc; - -#ifdef BB_FEATURE_IFCONFIG_STATUS - if ((argc > 0) && (strcmp(*argv,"-a") == 0)) { - interface_opt_a = 1; - --argc; - ++argv; - } -#endif - - if(argc <= 1) { -#ifdef BB_FEATURE_IFCONFIG_STATUS - return display_interfaces(argc ? *argv : NULL); -#else - error_msg_and_die( "ifconfig was not compiled with interface status display support."); -#endif - } - - /* Create a channel to the NET kernel. */ - if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - perror_msg_and_die("socket"); - } - - /* get interface name */ - safe_strncpy(ifr.ifr_name, *argv, IFNAMSIZ); - - /* Process the remaining arguments. */ - while (*++argv != (char *) NULL) { - p = *argv; - mask = N_MASK; - if (*p == '-') { /* If the arg starts with '-'... */ - ++p; /* advance past it and */ - mask = M_MASK; /* set the appropriate mask. */ - } - for (op = OptArray ; op->name ; op++) { /* Find table entry. */ - if (strcmp(p,op->name) == 0) { /* If name matches... */ - if ((mask &= op->flags)) { /* set the mask and go. */ - goto FOUND_ARG;; - } - /* If we get here, there was a valid arg with an */ - /* invalid '-' prefix. */ - ++goterr; - goto LOOP; - } - } - - /* We fell through, so treat as possible hostname. */ - a1op = Arg1Opt + (sizeof(Arg1Opt) / sizeof(Arg1Opt[0])) - 1; - mask = op->arg_flags; - goto HOSTNAME; - - FOUND_ARG: - if (mask & ARG_MASK) { - mask = op->arg_flags; - a1op = Arg1Opt + (op - OptArray); - if (mask & A_NETMASK & did_flags) { - show_usage(); - } - if (*++argv == NULL) { - if (mask & A_ARG_REQ) { - show_usage(); - } else { - --argv; - mask &= A_SET_AFTER; /* just for broadcast */ - } - } else { /* got an arg so process it */ - HOSTNAME: - did_flags |= (mask & A_NETMASK); - if (mask & A_CAST_HOST_COPY) { -#ifdef BB_FEATURE_IFCONFIG_HW - if (mask & A_CAST_RESOLVE) { -#endif - safe_strncpy(host, *argv, (sizeof host)); - sai.sin_family = AF_INET; - sai.sin_port = 0; - if (!strcmp(host, "default")) { - /* Default is special, meaning 0.0.0.0. */ - sai.sin_addr.s_addr = INADDR_ANY; - } else if (inet_aton(host, &sai.sin_addr) == 0) { - /* It's not a dotted quad. */ - ++goterr; - continue; - } - p = (char *) &sai; -#ifdef BB_FEATURE_IFCONFIG_HW - } else { /* A_CAST_HOST_COPY_IN_ETHER */ - /* This is the "hw" arg case. */ - if (strcmp("ether", *argv) || (*++argv == NULL)) { - show_usage(); - } - safe_strncpy(host, *argv, (sizeof host)); - if (in_ether(host, &sa)) { - fprintf(stderr, "invalid hw-addr %s\n", host); - ++goterr; - continue; - } - p = (char *) &sa; - } -#endif - memcpy((((char *)(&ifr)) + a1op->ifr_offset), - p, sizeof(struct sockaddr)); - } else { - unsigned int i = strtoul(*argv,NULL,0); - p = ((char *)(&ifr)) + a1op->ifr_offset; -#ifdef BB_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ - if (mask & A_MAP_TYPE) { - if (ioctl(sockfd, SIOCGIFMAP, &ifr) < 0) { - ++goterr; - continue; - } - if ((mask & A_MAP_UCHAR) == A_MAP_UCHAR) { - *((unsigned char *) p) = i; - } else if (mask & A_MAP_USHORT) { - *((unsigned short *) p) = i; - } else { - *((unsigned long *) p) = i; - } - } else -#endif - if (mask & A_CAST_CHAR_PTR) { - *((caddr_t *) p) = (caddr_t) i; - } else { /* A_CAST_INT */ - *((int *) p) = i; - } - } - - if (ioctl(sockfd, a1op->selector, &ifr) < 0) { - perror(a1op->name); - ++goterr; - continue; - } - -#ifdef QUESTIONABLE_ALIAS_CASE - if (mask & A_COLON_CHK) { - /* - * Don't do the set_flag() if the address is an alias with - * a - at the end, since it's deleted already! - Roman - * - * Should really use regex.h here, not sure though how well - * it'll go with the cross-platform support etc. - */ - char *ptr; - short int found_colon = 0; - for (ptr = ifr.ifr_name; *ptr; ptr++ ) { - if (*ptr == ':') { - found_colon++; - } - } - - if (found_colon && *(ptr - 1) == '-') { - continue; - } - } -#endif - } - if (!(mask & A_SET_AFTER)) { - continue; - } - mask = N_SET; - } - - if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) { - perror("SIOCGIFFLAGS"); - ++goterr; - } else { - selector = op->selector; - if (mask & SET_MASK) { - ifr.ifr_flags |= selector; - } else { - ifr.ifr_flags &= ~selector; - } - if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) { - perror("SIOCSIFFLAGS"); - ++goterr; - } - } - LOOP: - } /* end of while-loop */ - - return goterr; -} - -#ifdef BB_FEATURE_IFCONFIG_HW -/* Input an Ethernet address and convert to binary. */ -static int -in_ether(char *bufp, struct sockaddr *sap) -{ - unsigned char *ptr; - int i, j; - unsigned char val; - unsigned char c; - - sap->sa_family = ARPHRD_ETHER; - ptr = sap->sa_data; - - for (i = 0 ; i < ETH_ALEN ; i++) { - val = 0; - - /* We might get a semicolon here - not required. */ - if (i && (*bufp == ':')) { - bufp++; - } - - for (j=0 ; j<2 ; j++) { - c = *bufp; - if (c >= '0' && c <= '9') { - c -= '0'; - } else if (c >= 'a' && c <= 'f') { - c -= ('a' - 10); - } else if (c >= 'A' && c <= 'F') { - c -= ('A' - 10); - } else if (j && (c == ':' || c == 0)) { - break; - } else { - return -1; - } - ++bufp; - val <<= 4; - val += c; - } - *ptr++ = val; - } - - return (int) (*bufp); /* Error if we don't end at end of string. */ -} -#endif diff --git a/include/applets.h b/include/applets.h index 5ecfe3cba..35dd947fe 100644 --- a/include/applets.h +++ b/include/applets.h @@ -21,7 +21,7 @@ #define APPLET_ODDNAME(a,b,c,d) extern int b(int argc, char **argv); extern const char usage_messages[]; #elif defined(MAKE_USAGE) - #ifdef BB_FEATURE_VERBOSE_USAGE + #ifdef CONFIG_FEATURE_VERBOSE_USAGE #define APPLET(a,b,c) a##_trivial_usage "\n\n" a##_full_usage "\0" #define APPLET_NOUSAGE(a,b,c) "\0" #define APPLET_ODDNAME(a,b,c,d) d##_trivial_usage "\n\n" d##_full_usage "\0" @@ -43,452 +43,452 @@ -#ifdef BB_TEST +#ifdef CONFIG_TEST APPLET_NOUSAGE("[", test_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_ADDGROUP +#ifdef CONFIG_ADDGROUP APPLET(addgroup, addgroup_main, _BB_DIR_BIN) #endif -#ifdef BB_ADDUSER +#ifdef CONFIG_ADDUSER APPLET(adduser, adduser_main, _BB_DIR_BIN) #endif -#ifdef BB_ADJTIMEX +#ifdef CONFIG_ADJTIMEX APPLET(adjtimex, adjtimex_main, _BB_DIR_SBIN) #endif -#ifdef BB_AR +#ifdef CONFIG_AR APPLET(ar, ar_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_ASH +#ifdef CONFIG_ASH APPLET_NOUSAGE("ash", ash_main, _BB_DIR_BIN) #endif -#ifdef BB_BASENAME +#ifdef CONFIG_BASENAME APPLET(basename, basename_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_BUNZIP2 +#ifdef CONFIG_BUNZIP2 APPLET(bunzip2, bunzip2_main, _BB_DIR_USR_BIN) #endif APPLET_NOUSAGE("busybox", busybox_main, _BB_DIR_BIN) -#ifdef BB_CAT +#ifdef CONFIG_CAT APPLET(cat, cat_main, _BB_DIR_BIN) #endif -#ifdef BB_CHGRP +#ifdef CONFIG_CHGRP APPLET(chgrp, chgrp_main, _BB_DIR_BIN) #endif -#ifdef BB_CHMOD +#ifdef CONFIG_CHMOD APPLET(chmod, chmod_main, _BB_DIR_BIN) #endif -#ifdef BB_CHOWN +#ifdef CONFIG_CHOWN APPLET(chown, chown_main, _BB_DIR_BIN) #endif -#ifdef BB_CHROOT +#ifdef CONFIG_CHROOT APPLET(chroot, chroot_main, _BB_DIR_USR_SBIN) #endif -#ifdef BB_CHVT +#ifdef CONFIG_CHVT APPLET(chvt, chvt_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_CLEAR +#ifdef CONFIG_CLEAR APPLET(clear, clear_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_CMP +#ifdef CONFIG_CMP APPLET(cmp, cmp_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_CP +#ifdef CONFIG_CP APPLET(cp, cp_main, _BB_DIR_BIN) #endif -#ifdef BB_CPIO +#ifdef CONFIG_CPIO APPLET(cpio, cpio_main, _BB_DIR_BIN) #endif -#ifdef BB_CUT +#ifdef CONFIG_CUT APPLET(cut, cut_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_DATE +#ifdef CONFIG_DATE APPLET(date, date_main, _BB_DIR_BIN) #endif -#ifdef BB_DC +#ifdef CONFIG_DC APPLET(dc, dc_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_DD +#ifdef CONFIG_DD APPLET(dd, dd_main, _BB_DIR_BIN) #endif -#ifdef BB_DEALLOCVT +#ifdef CONFIG_DEALLOCVT APPLET(deallocvt, deallocvt_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_DELGROUP +#ifdef CONFIG_DELGROUP APPLET(delgroup, delgroup_main, _BB_DIR_BIN) #endif -#ifdef BB_DELUSER +#ifdef CONFIG_DELUSER APPLET(deluser, deluser_main, _BB_DIR_BIN) #endif -#ifdef BB_DF +#ifdef CONFIG_DF APPLET(df, df_main, _BB_DIR_BIN) #endif -#ifdef BB_DIRNAME +#ifdef CONFIG_DIRNAME APPLET(dirname, dirname_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_DMESG +#ifdef CONFIG_DMESG APPLET(dmesg, dmesg_main, _BB_DIR_BIN) #endif -#ifdef BB_DOS2UNIX +#ifdef CONFIG_DOS2UNIX APPLET(dos2unix, dos2unix_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_DPKG +#ifdef CONFIG_DPKG APPLET(dpkg, dpkg_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_DPKG_DEB +#ifdef CONFIG_DPKG_DEB APPLET_ODDNAME("dpkg-deb", dpkg_deb_main, _BB_DIR_USR_BIN, dpkg_deb) #endif -#ifdef BB_DU +#ifdef CONFIG_DU APPLET(du, du_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_DUMPKMAP +#ifdef CONFIG_DUMPKMAP APPLET(dumpkmap, dumpkmap_main, _BB_DIR_BIN) #endif -#ifdef BB_DUTMP +#ifdef CONFIG_DUTMP APPLET(dutmp, dutmp_main, _BB_DIR_USR_SBIN) #endif -#ifdef BB_ECHO +#ifdef CONFIG_ECHO APPLET(echo, echo_main, _BB_DIR_BIN) #endif -#if defined(BB_FEATURE_GREP_EGREP_ALIAS) && defined(BB_GREP) +#if defined(CONFIG_FEATURE_GREP_EGREP_ALIAS) && defined(CONFIG_GREP) APPLET_NOUSAGE("egrep", grep_main, _BB_DIR_BIN) #endif -#ifdef BB_ENV +#ifdef CONFIG_ENV APPLET(env, env_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_EXPR +#ifdef CONFIG_EXPR APPLET(expr, expr_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_TRUE_FALSE +#ifdef CONFIG_TRUE_FALSE APPLET(false, false_main, _BB_DIR_BIN) #endif -#ifdef BB_FBSET +#ifdef CONFIG_FBSET APPLET(fbset, fbset_main, _BB_DIR_USR_SBIN) #endif -#ifdef BB_FDFLUSH +#ifdef CONFIG_FDFLUSH APPLET(fdflush, fdflush_main, _BB_DIR_BIN) #endif -#ifdef BB_FIND +#ifdef CONFIG_FIND APPLET(find, find_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_FREE +#ifdef CONFIG_FREE APPLET(free, free_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_FREERAMDISK +#ifdef CONFIG_FREERAMDISK APPLET(freeramdisk, freeramdisk_main, _BB_DIR_SBIN) #endif -#ifdef BB_FSCK_MINIX +#ifdef CONFIG_FSCK_MINIX APPLET_ODDNAME("fsck.minix", fsck_minix_main, _BB_DIR_SBIN, fsck_minix) #endif -#ifdef BB_GETOPT +#ifdef CONFIG_GETOPT APPLET(getopt, getopt_main, _BB_DIR_BIN) #endif -#ifdef BB_GETTY +#ifdef CONFIG_GETTY APPLET(getty, getty_main, _BB_DIR_SBIN) #endif -#ifdef BB_GREP +#ifdef CONFIG_GREP APPLET(grep, grep_main, _BB_DIR_BIN) #endif -#ifdef BB_GUNZIP +#ifdef CONFIG_GUNZIP APPLET(gunzip, gunzip_main, _BB_DIR_BIN) #endif -#ifdef BB_GZIP +#ifdef CONFIG_GZIP APPLET(gzip, gzip_main, _BB_DIR_BIN) #endif -#ifdef BB_HALT +#ifdef CONFIG_HALT APPLET(halt, halt_main, _BB_DIR_SBIN) #endif -#ifdef BB_HEAD +#ifdef CONFIG_HEAD APPLET(head, head_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_HOSTID +#ifdef CONFIG_HOSTID APPLET(hostid, hostid_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_HOSTNAME +#ifdef CONFIG_HOSTNAME APPLET(hostname, hostname_main, _BB_DIR_BIN) #endif -#ifdef BB_HUSH +#ifdef CONFIG_HUSH APPLET_NOUSAGE("hush", hush_main, _BB_DIR_BIN) #endif -#ifdef BB_ID +#ifdef CONFIG_ID APPLET(id, id_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_IFCONFIG +#ifdef CONFIG_IFCONFIG APPLET(ifconfig, ifconfig_main, _BB_DIR_SBIN) #endif -#ifdef BB_INIT +#ifdef CONFIG_INIT APPLET(init, init_main, _BB_DIR_SBIN) #endif -#ifdef BB_INSMOD +#ifdef CONFIG_INSMOD APPLET(insmod, insmod_main, _BB_DIR_SBIN) #endif -#ifdef BB_KILL +#ifdef CONFIG_KILL APPLET(kill, kill_main, _BB_DIR_BIN) #endif -#ifdef BB_KILLALL +#ifdef CONFIG_KILLALL APPLET(killall, kill_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_KLOGD +#ifdef CONFIG_KLOGD APPLET(klogd, klogd_main, _BB_DIR_SBIN) #endif -#ifdef BB_LASH +#ifdef CONFIG_LASH APPLET(lash, lash_main, _BB_DIR_BIN) #endif -#ifdef BB_LENGTH +#ifdef CONFIG_LENGTH APPLET(length, length_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_FEATURE_LINUXRC +#ifdef CONFIG_FEATURE_INITRD APPLET_NOUSAGE("linuxrc", init_main, _BB_DIR_ROOT) #endif -#ifdef BB_LN +#ifdef CONFIG_LN APPLET(ln, ln_main, _BB_DIR_BIN) #endif -#ifdef BB_LOADACM +#ifdef CONFIG_LOADACM APPLET(loadacm, loadacm_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_LOADFONT +#ifdef CONFIG_LOADFONT APPLET(loadfont, loadfont_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_LOADKMAP +#ifdef CONFIG_LOADKMAP APPLET(loadkmap, loadkmap_main, _BB_DIR_SBIN) #endif -#ifdef BB_LOGGER +#ifdef CONFIG_LOGGER APPLET(logger, logger_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_LOGNAME +#ifdef CONFIG_LOGNAME APPLET(logname, logname_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_LOGREAD +#ifdef CONFIG_LOGREAD APPLET(logread, logread_main, _BB_DIR_SBIN) #endif -#ifdef BB_LS +#ifdef CONFIG_LS APPLET(ls, ls_main, _BB_DIR_BIN) #endif -#ifdef BB_LSMOD +#ifdef CONFIG_LSMOD APPLET(lsmod, lsmod_main, _BB_DIR_SBIN) #endif -#ifdef BB_MAKEDEVS +#ifdef CONFIG_MAKEDEVS APPLET(makedevs, makedevs_main, _BB_DIR_SBIN) #endif -#ifdef BB_MD5SUM +#ifdef CONFIG_MD5SUM APPLET(md5sum, md5sum_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_MKDIR +#ifdef CONFIG_MKDIR APPLET(mkdir, mkdir_main, _BB_DIR_BIN) #endif -#ifdef BB_MKFIFO +#ifdef CONFIG_MKFIFO APPLET(mkfifo, mkfifo_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_MKFS_MINIX +#ifdef CONFIG_MKFS_MINIX APPLET_ODDNAME("mkfs.minix", mkfs_minix_main, _BB_DIR_SBIN, mkfs_minix) #endif -#ifdef BB_MKNOD +#ifdef CONFIG_MKNOD APPLET(mknod, mknod_main, _BB_DIR_BIN) #endif -#ifdef BB_MKSWAP +#ifdef CONFIG_MKSWAP APPLET(mkswap, mkswap_main, _BB_DIR_SBIN) #endif -#ifdef BB_MKTEMP +#ifdef CONFIG_MKTEMP APPLET(mktemp, mktemp_main, _BB_DIR_BIN) #endif -#ifdef BB_MODPROBE +#ifdef CONFIG_MODPROBE APPLET(modprobe, modprobe_main, _BB_DIR_SBIN) #endif -#ifdef BB_MORE +#ifdef CONFIG_MORE APPLET(more, more_main, _BB_DIR_BIN) #endif -#ifdef BB_MOUNT +#ifdef CONFIG_MOUNT APPLET(mount, mount_main, _BB_DIR_BIN) #endif -#ifdef BB_MSH +#ifdef CONFIG_MSH APPLET_NOUSAGE("msh", msh_main, _BB_DIR_BIN) #endif -#ifdef BB_MT +#ifdef CONFIG_MT APPLET(mt, mt_main, _BB_DIR_BIN) #endif -#ifdef BB_MV +#ifdef CONFIG_MV APPLET(mv, mv_main, _BB_DIR_BIN) #endif -#ifdef BB_NC +#ifdef CONFIG_NC APPLET(nc, nc_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_NSLOOKUP +#ifdef CONFIG_NSLOOKUP APPLET(nslookup, nslookup_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_PIDOF +#ifdef CONFIG_PIDOF APPLET(pidof, pidof_main, _BB_DIR_BIN) #endif -#ifdef BB_PING +#ifdef CONFIG_PING APPLET(ping, ping_main, _BB_DIR_BIN) #endif -#ifdef BB_PIVOT_ROOT +#ifdef CONFIG_PIVOT_ROOT APPLET(pivot_root, pivot_root_main, _BB_DIR_SBIN) #endif -#ifdef BB_POWEROFF +#ifdef CONFIG_POWEROFF APPLET(poweroff, poweroff_main, _BB_DIR_SBIN) #endif -#ifdef BB_PRINTF +#ifdef CONFIG_PRINTF APPLET(printf, printf_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_PS +#ifdef CONFIG_PS APPLET(ps, ps_main, _BB_DIR_BIN) #endif -#ifdef BB_PWD +#ifdef CONFIG_PWD APPLET(pwd, pwd_main, _BB_DIR_BIN) #endif -#ifdef BB_RDATE +#ifdef CONFIG_RDATE APPLET(rdate, rdate_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_READLINK +#ifdef CONFIG_READLINK APPLET(readlink, readlink_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_REBOOT +#ifdef CONFIG_REBOOT APPLET(reboot, reboot_main, _BB_DIR_SBIN) #endif -#ifdef BB_RENICE +#ifdef CONFIG_RENICE APPLET(renice, renice_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_RESET +#ifdef CONFIG_RESET APPLET(reset, reset_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_RM +#ifdef CONFIG_RM APPLET(rm, rm_main, _BB_DIR_BIN) #endif -#ifdef BB_RMDIR +#ifdef CONFIG_RMDIR APPLET(rmdir, rmdir_main, _BB_DIR_BIN) #endif -#ifdef BB_RMMOD +#ifdef CONFIG_RMMOD APPLET(rmmod, rmmod_main, _BB_DIR_SBIN) #endif -#ifdef BB_ROUTE +#ifdef CONFIG_ROUTE APPLET(route, route_main, _BB_DIR_SBIN) #endif -#ifdef BB_RPM2CPIO +#ifdef CONFIG_RPM2CPIO APPLET(rpm2cpio, rpm2cpio_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_SED +#ifdef CONFIG_SED APPLET(sed, sed_main, _BB_DIR_BIN) #endif -#ifdef BB_SETKEYCODES +#ifdef CONFIG_SETKEYCODES APPLET(setkeycodes, setkeycodes_main, _BB_DIR_USR_BIN) #endif -#if defined(BB_FEATURE_SH_IS_ASH) && defined(BB_ASH) +#if defined(CONFIG_FEATURE_SH_IS_ASH) && defined(CONFIG_ASH) APPLET_NOUSAGE("sh", ash_main, _BB_DIR_BIN) -#elif defined(BB_FEATURE_SH_IS_HUSH) && defined(BB_HUSH) +#elif defined(CONFIG_FEATURE_SH_IS_HUSH) && defined(CONFIG_HUSH) APPLET_NOUSAGE("sh", hush_main, _BB_DIR_BIN) -#elif defined(BB_FEATURE_SH_IS_LASH) && defined(BB_LASH) +#elif defined(CONFIG_FEATURE_SH_IS_LASH) && defined(CONFIG_LASH) APPLET_NOUSAGE("sh", lash_main, _BB_DIR_BIN) -#elif defined(BB_FEATURE_SH_IS_MSH) && defined(BB_MSH) +#elif defined(CONFIG_FEATURE_SH_IS_MSH) && defined(CONFIG_MSH) APPLET_NOUSAGE("sh", msh_main, _BB_DIR_BIN) #endif -#ifdef BB_SLEEP +#ifdef CONFIG_SLEEP APPLET(sleep, sleep_main, _BB_DIR_BIN) #endif -#ifdef BB_SORT +#ifdef CONFIG_SORT APPLET(sort, sort_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_START_STOP_DAEMON +#ifdef CONFIG_START_STOP_DAEMON APPLET_ODDNAME("start-stop-daemon", start_stop_daemon_main, _BB_DIR_SBIN, start_stop_daemon) #endif -#ifdef BB_STTY +#ifdef CONFIG_STTY APPLET(stty, stty_main, _BB_DIR_BIN) #endif -#ifdef BB_SWAPONOFF +#ifdef CONFIG_SWAPONOFF APPLET(swapoff, swap_on_off_main, _BB_DIR_SBIN) #endif -#ifdef BB_SWAPONOFF +#ifdef CONFIG_SWAPONOFF APPLET(swapon, swap_on_off_main, _BB_DIR_SBIN) #endif -#ifdef BB_SYNC +#ifdef CONFIG_SYNC APPLET(sync, sync_main, _BB_DIR_BIN) #endif -#ifdef BB_SYSLOGD +#ifdef CONFIG_SYSLOGD APPLET(syslogd, syslogd_main, _BB_DIR_SBIN) #endif -#ifdef BB_TAIL +#ifdef CONFIG_TAIL APPLET(tail, tail_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_TAR +#ifdef CONFIG_TAR APPLET(tar, tar_main, _BB_DIR_BIN) #endif -#ifdef BB_TEE +#ifdef CONFIG_TEE APPLET(tee, tee_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_TELNET +#ifdef CONFIG_TELNET APPLET(telnet, telnet_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_TEST +#ifdef CONFIG_TEST APPLET(test, test_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_TFTP +#ifdef CONFIG_TFTP APPLET(tftp, tftp_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_TOUCH +#ifdef CONFIG_TOUCH APPLET(touch, touch_main, _BB_DIR_BIN) #endif -#ifdef BB_TR +#ifdef CONFIG_TR APPLET(tr, tr_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_TRACEROUTE +#ifdef CONFIG_TRACEROUTE APPLET(traceroute, traceroute_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_TRUE_FALSE +#ifdef CONFIG_TRUE_FALSE APPLET(true, true_main, _BB_DIR_BIN) #endif -#ifdef BB_TTY +#ifdef CONFIG_TTY APPLET(tty, tty_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_UMOUNT +#ifdef CONFIG_UMOUNT APPLET(umount, umount_main, _BB_DIR_BIN) #endif -#ifdef BB_UNAME +#ifdef CONFIG_UNAME APPLET(uname, uname_main, _BB_DIR_BIN) #endif -#ifdef BB_UNIQ +#ifdef CONFIG_UNIQ APPLET(uniq, uniq_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_UNIX2DOS +#ifdef CONFIG_UNIX2DOS APPLET(unix2dos, dos2unix_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_UPDATE +#ifdef CONFIG_UPDATE APPLET(update, update_main, _BB_DIR_SBIN) #endif -#ifdef BB_UPTIME +#ifdef CONFIG_UPTIME APPLET(uptime, uptime_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_USLEEP +#ifdef CONFIG_USLEEP APPLET(usleep, usleep_main, _BB_DIR_BIN) #endif -#ifdef BB_UUDECODE +#ifdef CONFIG_UUDECODE APPLET(uudecode, uudecode_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_UUENCODE +#ifdef CONFIG_UUENCODE APPLET(uuencode, uuencode_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_VI +#ifdef CONFIG_VI APPLET(vi, vi_main, _BB_DIR_BIN) #endif -#ifdef BB_WATCHDOG +#ifdef CONFIG_WATCHDOG APPLET(watchdog, watchdog_main, _BB_DIR_SBIN) #endif -#ifdef BB_WC +#ifdef CONFIG_WC APPLET(wc, wc_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_WGET +#ifdef CONFIG_WGET APPLET(wget, wget_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_WHICH +#ifdef CONFIG_WHICH APPLET(which, which_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_WHOAMI +#ifdef CONFIG_WHOAMI APPLET(whoami, whoami_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_XARGS +#ifdef CONFIG_XARGS APPLET(xargs, xargs_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_YES +#ifdef CONFIG_YES APPLET(yes, yes_main, _BB_DIR_USR_BIN) #endif -#ifdef BB_GUNZIP +#ifdef CONFIG_GUNZIP APPLET(zcat, gunzip_main, _BB_DIR_BIN) #endif diff --git a/include/busybox.h b/include/busybox.h index f79dac8c8..87cebc3d1 100644 --- a/include/busybox.h +++ b/include/busybox.h @@ -24,7 +24,7 @@ #ifndef _BB_INTERNAL_H_ #define _BB_INTERNAL_H_ 1 -#include "Config.h" +#include "config.h" #include #include @@ -34,7 +34,7 @@ #define BB_BANNER "BusyBox v" BB_VER " (" BB_BT ")" #ifdef DMALLOC -#include "dmalloc.h" +#include #endif #include @@ -66,19 +66,19 @@ extern const struct BB_applet applets[]; #include "applets.h" #undef PROTOTYPES -#ifdef BB_FEATURE_BUFFERS_GO_ON_STACK -#define RESERVE_BB_BUFFER(buffer,len) char buffer[len] -#define RESERVE_BB_UBUFFER(buffer,len) unsigned char buffer[len] -#define RELEASE_BB_BUFFER(buffer) ((void)0) +#ifdef CONFIG_FEATURE_BUFFERS_GO_ON_STACK +#define RESERVE_CONFIG_BUFFER(buffer,len) char buffer[len] +#define RESERVE_CONFIG_UBUFFER(buffer,len) unsigned char buffer[len] +#define RELEASE_CONFIG_BUFFER(buffer) ((void)0) #else -#ifdef BB_FEATURE_BUFFERS_GO_IN_BSS -#define RESERVE_BB_BUFFER(buffer,len) static char buffer[len] -#define RESERVE_BB_UBUFFER(buffer,len) static unsigned char buffer[len] -#define RELEASE_BB_BUFFER(buffer) ((void)0) +#ifdef CONFIG_FEATURE_BUFFERS_GO_IN_BSS +#define RESERVE_CONFIG_BUFFER(buffer,len) static char buffer[len] +#define RESERVE_CONFIG_UBUFFER(buffer,len) static unsigned char buffer[len] +#define RELEASE_CONFIG_BUFFER(buffer) ((void)0) #else -#define RESERVE_BB_BUFFER(buffer,len) char *buffer=xmalloc(len) -#define RESERVE_BB_UBUFFER(buffer,len) unsigned char *buffer=xmalloc(len) -#define RELEASE_BB_BUFFER(buffer) free (buffer) +#define RESERVE_CONFIG_BUFFER(buffer,len) char *buffer=xmalloc(len) +#define RESERVE_CONFIG_UBUFFER(buffer,len) unsigned char *buffer=xmalloc(len) +#define RELEASE_CONFIG_BUFFER(buffer) free (buffer) #endif #endif @@ -99,7 +99,7 @@ extern const struct BB_applet applets[]; /* Pull in the utility routines from libbb */ -#include "libbb/libbb.h" +#include "libbb.h" diff --git a/include/grp.h b/include/grp.h index 87d4115ce..191c2d4e5 100644 --- a/include/grp.h +++ b/include/grp.h @@ -1,5 +1,5 @@ -#ifndef __BB_GRP_H -#define __BB_GRP_H +#ifndef __CONFIG_GRP_H +#define __CONFIG_GRP_H #if defined USE_SYSTEM_PWD_GRP #include @@ -33,5 +33,5 @@ extern int initgroups __P ((__const char * user, gid_t gid)); extern struct group * __getgrent __P ((int grp_fd)); #endif /* USE_SYSTEM_PWD_GRP */ -#endif /* __BB_GRP_H */ +#endif /* __CONFIG_GRP_H */ diff --git a/include/libbb.h b/include/libbb.h index 3ef0278f8..8b84077d8 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -21,8 +21,8 @@ * Permission has been granted to redistribute this code under the GPL. * */ -#ifndef __LIBBB_H__ -#define __LIBBB_H__ 1 +#ifndef __LIBCONFIG_H__ +#define __LIBCONFIG_H__ 1 #include #include @@ -32,15 +32,11 @@ #include #ifdef DMALLOC -#include "dmalloc.h" +#include #endif #include -#ifndef _BB_INTERNAL_H_ -#include "../busybox.h" -#endif - #if (__GNU_LIBRARY__ < 5) && (!defined __dietlibc__) /* libc5 doesn't define socklen_t */ typedef unsigned int socklen_t; @@ -295,7 +291,7 @@ extern const char * const name_longer_than_foo; extern const char * const unknown; extern const char * const can_not_create_raw_socket; -#ifdef BB_FEATURE_DEVFS +#ifdef CONFIG_FEATURE_DEVFS # define CURRENT_VC "/dev/vc/0" # define VC_1 "/dev/vc/1" # define VC_2 "/dev/vc/2" @@ -323,4 +319,4 @@ extern const char * const can_not_create_raw_socket; #define CURRENT_TTY "/dev/tty" #define CONSOLE_DEV "/dev/console" -#endif /* __LIBBB_H__ */ +#endif /* __LIBCONFIG_H__ */ diff --git a/include/pwd.h b/include/pwd.h index e603a96e3..2fd0ab06e 100644 --- a/include/pwd.h +++ b/include/pwd.h @@ -1,5 +1,5 @@ -#ifndef __BB_PWD_H -#define __BB_PWD_H +#ifndef __CONFIG_PWD_H +#define __CONFIG_PWD_H #if defined USE_SYSTEM_PWD_GRP #include @@ -36,5 +36,5 @@ extern struct passwd * getpwnam __P ((__const char *)); extern struct passwd * __getpwent __P ((__const int passwd_fd)); #endif /* USE_SYSTEM_PWD_GRP */ -#endif /* __BB_PWD_H */ +#endif /* __CONFIG_PWD_H */ diff --git a/include/usage.h b/include/usage.h index 5e514274a..1de29666e 100644 --- a/include/usage.h +++ b/include/usage.h @@ -247,7 +247,7 @@ #define deluser_full_usage \ "Deletes user USER from the system" -#ifdef BB_FEATURE_HUMAN_READABLE +#ifdef CONFIG_FEATURE_HUMAN_READABLE #define USAGE_HUMAN_READABLE(a) a #define USAGE_NOT_HUMAN_READABLE(a) #else @@ -464,17 +464,17 @@ #define fdflush_full_usage \ "Forces floppy disk drive to detect disk change" -#ifdef BB_FEATURE_FIND_TYPE +#ifdef CONFIG_FEATURE_FIND_TYPE #define USAGE_FIND_TYPE(a) a #else #define USAGE_FIND_TYPE(a) #endif -#ifdef BB_FEATURE_FIND_PERM +#ifdef CONFIG_FEATURE_FIND_PERM #define USAGE_FIND_PERM(a) a #else #define USAGE_FIND_PERM(a) #endif -#ifdef BB_FEATURE_FIND_MTIME +#ifdef CONFIG_FEATURE_FIND_MTIME #define USAGE_FIND_MTIME(a) a #else #define USAGE_FIND_MTIME(a) @@ -678,22 +678,22 @@ "$ id\n" \ "uid=1000(andersen) gid=1000(andersen)\n" -#ifdef BB_FEATURE_IFCONFIG_SLIP +#ifdef CONFIG_FEATURE_IFCONFIG_SLIP #define USAGE_SIOCSKEEPALIVE(a) a #else #define USAGE_SIOCSKEEPALIVE(a) #endif -#ifdef BB_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ +#ifdef CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ #define USAGE_IFCONFIG_MII(a) a #else #define USAGE_IFCONFIG_MII(a) #endif -#ifdef BB_FEATURE_IFCONFIG_HW +#ifdef CONFIG_FEATURE_IFCONFIG_HW #define USAGE_IFCONFIG_HW(a) a #else #define USAGE_IFCONFIG_HW(a) #endif -#ifdef BB_FEATURE_IFCONFIG_STATUS +#ifdef CONFIG_FEATURE_IFCONFIG_STATUS #define USAGE_IFCONFIG_OPT_A(a) a #else #define USAGE_IFCONFIG_OPT_A(a) @@ -950,32 +950,32 @@ #define logread_full_usage \ "Shows the messages from syslogd (using circular buffer)." -#ifdef BB_FEATURE_LS_TIMESTAMPS +#ifdef CONFIG_FEATURE_LS_TIMESTAMPS #define USAGE_LS_TIMESTAMPS(a) a #else #define USAGE_LS_TIMESTAMPS(a) #endif -#ifdef BB_FEATURE_LS_FILETYPES +#ifdef CONFIG_FEATURE_LS_FILETYPES #define USAGE_LS_FILETYPES(a) a #else #define USAGE_LS_FILETYPES(a) #endif -#ifdef BB_FEATURE_LS_FOLLOWLINKS +#ifdef CONFIG_FEATURE_LS_FOLLOWLINKS #define USAGE_LS_FOLLOWLINKS(a) a #else #define USAGE_LS_FOLLOWLINKS(a) #endif -#ifdef BB_FEATURE_LS_RECURSIVE +#ifdef CONFIG_FEATURE_LS_RECURSIVE #define USAGE_LS_RECURSIVE(a) a #else #define USAGE_LS_RECURSIVE(a) #endif -#ifdef BB_FEATURE_LS_SORTFILES +#ifdef CONFIG_FEATURE_LS_SORTFILES #define USAGE_LS_SORTFILES(a) a #else #define USAGE_LS_SORTFILES(a) #endif -#ifdef BB_FEATURE_AUTOWIDTH +#ifdef CONFIG_FEATURE_AUTOWIDTH #define USAGE_AUTOWIDTH(a) a #else #define USAGE_AUTOWIDTH(a) @@ -1145,12 +1145,12 @@ #define more_example_usage \ "$ dmesg | more\n" -#ifdef BB_FEATURE_MOUNT_LOOP +#ifdef CONFIG_FEATURE_MOUNT_LOOP #define USAGE_MOUNT_LOOP(a) a #else #define USAGE_MOUNT_LOOP(a) #endif -#ifdef BB_FEATURE_MTAB_SUPPORT +#ifdef CONFIG_FEATURE_MTAB_SUPPORT #define USAGE_MTAB(a) a #else #define USAGE_MTAB(a) @@ -1245,7 +1245,7 @@ "$ pidof init\n" \ "1\n" -#ifndef BB_FEATURE_FANCY_PING +#ifndef CONFIG_FEATURE_FANCY_PING #define ping_trivial_usage "host" #define ping_full_usage "Send ICMP ECHO_REQUEST packets to network hosts" #else @@ -1431,12 +1431,12 @@ "[2 second delay results]\n" -#ifdef BB_FEATURE_SORT_UNIQUE +#ifdef CONFIG_FEATURE_SORT_UNIQUE #define USAGE_SORT_UNIQUE(a) a #else #define USAGE_SORT_UNIQUE(a) #endif -#ifdef BB_FEATURE_SORT_REVERSE +#ifdef CONFIG_FEATURE_SORT_REVERSE #define USAGE_SORT_REVERSE(a) a #else #define USAGE_SORT_REVERSE(a) @@ -1503,7 +1503,7 @@ "Write all buffered filesystem blocks to disk." -#ifdef BB_FEATURE_REMOTE_LOG +#ifdef CONFIG_FEATURE_REMOTE_LOG #define USAGE_REMOTE_LOG(a) a #else #define USAGE_REMOTE_LOG(a) @@ -1525,7 +1525,7 @@ "$ syslogd -R 192.168.1.1:601\n" -#ifndef BB_FEATURE_FANCY_TAIL +#ifndef CONFIG_FEATURE_FANCY_TAIL #define USAGE_UNSIMPLE_TAIL(a) #else #define USAGE_UNSIMPLE_TAIL(a) a @@ -1550,12 +1550,12 @@ "$ tail -n 1 /etc/resolv.conf\n" \ "nameserver 10.0.0.1\n" -#ifdef BB_FEATURE_TAR_CREATE +#ifdef CONFIG_FEATURE_TAR_CREATE #define USAGE_TAR_CREATE(a) a #else #define USAGE_TAR_CREATE(a) #endif -#ifdef BB_FEATURE_TAR_EXCLUDE +#ifdef CONFIG_FEATURE_TAR_EXCLUDE #define USAGE_TAR_EXCLUDE(a) a #else #define USAGE_TAR_EXCLUDE(a) @@ -1619,17 +1619,17 @@ "$ echo $?\n" \ "1\n" -#ifdef BB_FEATURE_TFTP_GET +#ifdef CONFIG_FEATURE_TFTP_GET #define USAGE_TFTP_GET(a) a #else #define USAGE_TFTP_GET(a) #endif -#ifdef BB_FEATURE_TFTP_PUT +#ifdef CONFIG_FEATURE_TFTP_PUT #define USAGE_TFTP_PUT(a) a #else #define USAGE_TFTP_PUT(a) #endif -#ifdef BB_FEATURE_TFTP_BLOCKSIZE +#ifdef CONFIG_FEATURE_TFTP_BLOCKSIZE #define USAGE_TFTP_BS(a) a #else #define USAGE_TFTP_BS(a) @@ -1719,7 +1719,7 @@ "$ tty\n" \ "/dev/tty2\n" -#ifdef BB_FEATURE_MOUNT_FORCE +#ifdef CONFIG_FEATURE_MOUNT_FORCE #define USAGE_MOUNT_FORCE(a) a #else #define USAGE_MOUNT_FORCE(a) diff --git a/init.c b/init.c deleted file mode 100644 index 068e1df16..000000000 --- a/init.c +++ /dev/null @@ -1,1045 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini init implementation for busybox - * - * - * Copyright (C) 1995, 1996 by Bruce Perens . - * Adjusted by so many folks, it's impossible to keep track. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* Turn this on to disable all the dangerous - rebooting stuff when debugging. -#define DEBUG_INIT -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" -#ifdef BB_SYSLOGD -# include -#endif - - -/* From */ -struct vt_stat { - unsigned short v_active; /* active vt */ - unsigned short v_signal; /* signal to send */ - unsigned short v_state; /* vt bitmask */ -}; -static const int VT_GETSTATE = 0x5603; /* get global vt state info */ - -/* From */ -struct serial_struct { - int type; - int line; - int port; - int irq; - int flags; - int xmit_fifo_size; - int custom_divisor; - int baud_base; - unsigned short close_delay; - char reserved_char[2]; - int hub6; - unsigned short closing_wait; /* time to wait before closing */ - unsigned short closing_wait2; /* no longer used... */ - int reserved[4]; -}; - - - -#ifndef RB_HALT_SYSTEM -static const int RB_HALT_SYSTEM = 0xcdef0123; -static const int RB_ENABLE_CAD = 0x89abcdef; -static const int RB_DISABLE_CAD = 0; -#define RB_POWER_OFF 0x4321fedc -static const int RB_AUTOBOOT = 0x01234567; -#endif - -#if (__GNU_LIBRARY__ > 5) || defined(__dietlibc__) - #include - #define init_reboot(magic) reboot(magic) -#else - #define init_reboot(magic) reboot(0xfee1dead, 672274793, magic) -#endif - -#ifndef _PATH_STDPATH -#define _PATH_STDPATH "/usr/bin:/bin:/usr/sbin:/sbin" -#endif - - -#if defined BB_FEATURE_INIT_COREDUMPS -/* - * When a file named CORE_ENABLE_FLAG_FILE exists, setrlimit is called - * before processes are spawned to set core file size as unlimited. - * This is for debugging only. Don't use this is production, unless - * you want core dumps lying about.... - */ -#define CORE_ENABLE_FLAG_FILE "/.init_enable_core" -#include -#include -#endif - -#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) - -#if __GNU_LIBRARY__ > 5 - #include -#else - extern int bdflush (int func, long int data); -#endif - - -#define SHELL "/bin/sh" /* Default shell */ -#define LOGIN_SHELL "-" SHELL /* Default login shell */ -#define INITTAB "/etc/inittab" /* inittab file location */ -#ifndef INIT_SCRIPT -#define INIT_SCRIPT "/etc/init.d/rcS" /* Default sysinit script. */ -#endif - -#define MAXENV 16 /* Number of env. vars */ -//static const int MAXENV = 16; /* Number of env. vars */ -static const int LOG = 0x1; -static const int CONSOLE = 0x2; - -/* Allowed init action types */ -typedef enum { - SYSINIT = 1, - RESPAWN, - ASKFIRST, - WAIT, - ONCE, - CTRLALTDEL, - SHUTDOWN -} initActionEnum; - -/* A mapping between "inittab" action name strings and action type codes. */ -typedef struct initActionType { - const char *name; - initActionEnum action; -} initActionType; - -static const struct initActionType actions[] = { - {"sysinit", SYSINIT}, - {"respawn", RESPAWN}, - {"askfirst", ASKFIRST}, - {"wait", WAIT}, - {"once", ONCE}, - {"ctrlaltdel", CTRLALTDEL}, - {"shutdown", SHUTDOWN}, - {0, 0} -}; - -/* Set up a linked list of initActions, to be read from inittab */ -typedef struct initActionTag initAction; -struct initActionTag { - pid_t pid; - char process[256]; - char console[256]; - initAction *nextPtr; - initActionEnum action; -}; -static initAction *initActionList = NULL; - - -static char *secondConsole = VC_2; -static char *thirdConsole = VC_3; -static char *fourthConsole = VC_4; -static char *log = VC_5; -static int kernelVersion = 0; -static char termType[32] = "TERM=linux"; -static char console[32] = _PATH_CONSOLE; - -static void delete_initAction(initAction * action); - -static void loop_forever(void) -{ - while (1) - sleep (1); -} - -/* Print a message to the specified device. - * Device may be bitwise-or'd from LOG | CONSOLE */ -static void message(int device, char *fmt, ...) - __attribute__ ((format (printf, 2, 3))); -static void message(int device, char *fmt, ...) -{ - va_list arguments; - int fd; - -#ifdef BB_SYSLOGD - - /* Log the message to syslogd */ - if (device & LOG) { - char msg[1024]; - - va_start(arguments, fmt); - vsnprintf(msg, sizeof(msg), fmt, arguments); - va_end(arguments); - syslog_msg(LOG_USER, LOG_USER|LOG_INFO, msg); - } -#else - static int log_fd = -1; - - /* Take full control of the log tty, and never close it. - * It's mine, all mine! Muhahahaha! */ - if (log_fd < 0) { - if (log == NULL) { - /* don't even try to log, because there is no such console */ - log_fd = -2; - /* log to main console instead */ - device = CONSOLE; - } else if ((log_fd = device_open(log, O_RDWR|O_NDELAY)) < 0) { - log_fd = -2; - fprintf(stderr, "Bummer, can't write to log on %s!\r\n", log); - log = NULL; - device = CONSOLE; - } - } - if ((device & LOG) && (log_fd >= 0)) { - va_start(arguments, fmt); - vdprintf(log_fd, fmt, arguments); - va_end(arguments); - } -#endif - - if (device & CONSOLE) { - /* Always send console messages to /dev/console so people will see them. */ - if ( - (fd = - device_open(_PATH_CONSOLE, - O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0) { - va_start(arguments, fmt); - vdprintf(fd, fmt, arguments); - va_end(arguments); - close(fd); - } else { - fprintf(stderr, "Bummer, can't print: "); - va_start(arguments, fmt); - vfprintf(stderr, fmt, arguments); - va_end(arguments); - } - } -} - -/* Set terminal settings to reasonable defaults */ -static void set_term(int fd) -{ - struct termios tty; - - tcgetattr(fd, &tty); - - /* set control chars */ - tty.c_cc[VINTR] = 3; /* C-c */ - tty.c_cc[VQUIT] = 28; /* C-\ */ - tty.c_cc[VERASE] = 127; /* C-? */ - tty.c_cc[VKILL] = 21; /* C-u */ - tty.c_cc[VEOF] = 4; /* C-d */ - tty.c_cc[VSTART] = 17; /* C-q */ - tty.c_cc[VSTOP] = 19; /* C-s */ - tty.c_cc[VSUSP] = 26; /* C-z */ - - /* use line dicipline 0 */ - tty.c_line = 0; - - /* Make it be sane */ - tty.c_cflag &= CBAUD|CBAUDEX|CSIZE|CSTOPB|PARENB|PARODD; - tty.c_cflag |= CREAD|HUPCL|CLOCAL; - - - /* input modes */ - tty.c_iflag = ICRNL | IXON | IXOFF; - - /* output modes */ - tty.c_oflag = OPOST | ONLCR; - - /* local modes */ - tty.c_lflag = - ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN; - - tcsetattr(fd, TCSANOW, &tty); -} - -/* How much memory does this machine have? - Units are kBytes to avoid overflow on 4GB machines */ -static int check_free_memory(void) -{ - struct sysinfo info; - unsigned int result, u, s=10; - - if (sysinfo(&info) != 0) { - perror_msg("Error checking free memory"); - return -1; - } - - /* Kernels 2.0.x and 2.2.x return info.mem_unit==0 with values in bytes. - * Kernels 2.4.0 return info.mem_unit in bytes. */ - u = info.mem_unit; - if (u==0) u=1; - while ( (u&1) == 0 && s > 0 ) { u>>=1; s--; } - result = (info.totalram>>s) + (info.totalswap>>s); - result = result*u; - if (result < 0) result = INT_MAX; - return result; -} - -static void console_init(void) -{ - int fd; - int tried_devcons = 0; - int tried_vtprimary = 0; - struct vt_stat vt; - struct serial_struct sr; - char *s; - - if ((s = getenv("TERM")) != NULL) { - snprintf(termType, sizeof(termType) - 1, "TERM=%s", s); - } - - if ((s = getenv("CONSOLE")) != NULL) { - safe_strncpy(console, s, sizeof(console)); - } -#if #cpu(sparc) - /* sparc kernel supports console=tty[ab] parameter which is also - * passed to init, so catch it here */ - else if ((s = getenv("console")) != NULL) { - /* remap tty[ab] to /dev/ttyS[01] */ - if (strcmp(s, "ttya") == 0) - safe_strncpy(console, SC_0, sizeof(console)); - else if (strcmp(s, "ttyb") == 0) - safe_strncpy(console, SC_1, sizeof(console)); - } -#endif - else { - /* 2.2 kernels: identify the real console backend and try to use it */ - if (ioctl(0, TIOCGSERIAL, &sr) == 0) { - /* this is a serial console */ - snprintf(console, sizeof(console) - 1, SC_FORMAT, sr.line); - } else if (ioctl(0, VT_GETSTATE, &vt) == 0) { - /* this is linux virtual tty */ - snprintf(console, sizeof(console) - 1, VC_FORMAT, vt.v_active); - } else { - safe_strncpy(console, _PATH_CONSOLE, sizeof(console)); - tried_devcons++; - } - } - - while ((fd = open(console, O_RDONLY | O_NONBLOCK)) < 0) { - /* Can't open selected console -- try /dev/console */ - if (!tried_devcons) { - tried_devcons++; - safe_strncpy(console, _PATH_CONSOLE, sizeof(console)); - continue; - } - /* Can't open selected console -- try vt1 */ - if (!tried_vtprimary) { - tried_vtprimary++; - safe_strncpy(console, VC_1, sizeof(console)); - continue; - } - break; - } - if (fd < 0) { - /* Perhaps we should panic here? */ - safe_strncpy(console, "/dev/null", sizeof(console)); - } else { - /* check for serial console and disable logging to tty5 & running a - * shell to tty2-4 */ - if (ioctl(0, TIOCGSERIAL, &sr) == 0) { - log = NULL; - secondConsole = NULL; - thirdConsole = NULL; - fourthConsole = NULL; - /* Force the TERM setting to vt102 for serial console -- - * iff TERM is set to linux (the default) */ - if (strcmp( termType, "TERM=linux" ) == 0) - safe_strncpy(termType, "TERM=vt102", sizeof(termType)); - message(LOG | CONSOLE, - "serial console detected. Disabling virtual terminals.\r\n"); - } - close(fd); - } - message(LOG, "console=%s\n", console); -} - -static void fixup_argv(int argc, char **argv, char *new_argv0) -{ - int len; - /* Fix up argv[0] to be certain we claim to be init */ - len = strlen(argv[0]); - memset(argv[0], 0, len); - strncpy(argv[0], new_argv0, len); - - /* Wipe argv[1]-argv[N] so they don't clutter the ps listing */ - len = 1; - while (argc > len) { - memset(argv[len], 0, strlen(argv[len])); - len++; - } -} - - -static pid_t run(char *command, char *terminal, int get_enter) -{ - int i, j; - int fd; - pid_t pid; - char *tmpCmd, *s; - char *cmd[255], *cmdpath; - char buf[255]; - struct stat sb; - static const char press_enter[] = - -#ifdef CUSTOMIZED_BANNER -#include CUSTOMIZED_BANNER -#endif - - "\nPlease press Enter to activate this console. "; - char *environment[MAXENV+1] = { - termType, - "HOME=/", - "PATH=/usr/bin:/bin:/usr/sbin:/sbin", - "SHELL=" SHELL, - "USER=root", - NULL - }; - - /* inherit environment to the child, merging our values -andy */ - for (i=0; environ[i]; i++) { - for (j=0; environment[j]; j++) { - s = strchr(environment[j], '='); - if (!strncmp(environ[i], environment[j], s - environment[j])) - break; - } - if (!environment[j]) { - environment[j++] = environ[i]; - environment[j] = NULL; - } - } - - if ((pid = fork()) == 0) { - /* Clean up */ - ioctl(0, TIOCNOTTY, 0); - close(0); - close(1); - close(2); - setsid(); - - /* Reset signal handlers set for parent process */ - signal(SIGUSR1, SIG_DFL); - signal(SIGUSR2, SIG_DFL); - signal(SIGINT, SIG_DFL); - signal(SIGTERM, SIG_DFL); - signal(SIGHUP, SIG_DFL); - - if ((fd = device_open(terminal, O_RDWR)) < 0) { - if (stat(terminal, &sb) != 0) { - message(LOG | CONSOLE, "device '%s' does not exist.\n", - terminal); - exit(1); - } - message(LOG | CONSOLE, "Bummer, can't open %s\r\n", terminal); - exit(1); - } - dup2(fd, 0); - dup2(fd, 1); - dup2(fd, 2); - ioctl(0, TIOCSCTTY, 1); - tcsetpgrp(0, getpgrp()); - set_term(0); - - /* See if any special /bin/sh requiring characters are present */ - if (strpbrk(command, "~`!$^&*()=|\\{}[];\"'<>?") != NULL) { - cmd[0] = SHELL; - cmd[1] = "-c"; - strcpy(buf, "exec "); - strncat(buf, command, sizeof(buf) - strlen(buf) - 1); - cmd[2] = buf; - cmd[3] = NULL; - } else { - /* Convert command (char*) into cmd (char**, one word per string) */ - for (tmpCmd = command, i = 0; - (tmpCmd = strsep(&command, " \t")) != NULL;) { - if (*tmpCmd != '\0') { - cmd[i] = tmpCmd; - tmpCmd++; - i++; - } - } - cmd[i] = NULL; - } - - cmdpath = cmd[0]; - - /* - Interactive shells want to see a dash in argv[0]. This - typically is handled by login, argv will be setup this - way if a dash appears at the front of the command path - (like "-/bin/sh"). - */ - - if (*cmdpath == '-') { - - /* skip over the dash */ - ++cmdpath; - - /* find the last component in the command pathname */ - s = get_last_path_component(cmdpath); - - /* make a new argv[0] */ - if ((cmd[0] = malloc(strlen(s)+2)) == NULL) { - message(LOG | CONSOLE, "malloc failed"); - cmd[0] = cmdpath; - } else { - cmd[0][0] = '-'; - strcpy(cmd[0]+1, s); - } - } - - if (get_enter == TRUE) { - /* - * Save memory by not exec-ing anything large (like a shell) - * before the user wants it. This is critical if swap is not - * enabled and the system has low memory. Generally this will - * be run on the second virtual console, and the first will - * be allowed to start a shell or whatever an init script - * specifies. - */ -#ifdef DEBUG_INIT - message(LOG, "Waiting for enter to start '%s' (pid %d, console %s)\r\n", - cmd[0], getpid(), terminal); -#endif - write(fileno(stdout), press_enter, sizeof(press_enter) - 1); - getc(stdin); - } - -#ifdef DEBUG_INIT - /* Log the process name and args */ - message(LOG, "Starting pid %d, console %s: '%s'\r\n", - getpid(), terminal, command); -#endif - -#if defined BB_FEATURE_INIT_COREDUMPS - if (stat (CORE_ENABLE_FLAG_FILE, &sb) == 0) { - struct rlimit limit; - limit.rlim_cur = RLIM_INFINITY; - limit.rlim_max = RLIM_INFINITY; - setrlimit(RLIMIT_CORE, &limit); - } -#endif - - /* Now run it. The new program will take over this PID, - * so nothing further in init.c should be run. */ - execve(cmdpath, cmd, environment); - - /* We're still here? Some error happened. */ - message(LOG | CONSOLE, "Bummer, could not run '%s': %s\n", cmdpath, - strerror(errno)); - exit(-1); - } - return pid; -} - -static int waitfor(char *command, char *terminal, int get_enter) -{ - int status, wpid; - int pid = run(command, terminal, get_enter); - - while (1) { - wpid = wait(&status); - if (wpid > 0 && wpid != pid) { - continue; - } - if (wpid == pid) - break; - } - return wpid; -} - -/* Make sure there is enough memory to do something useful. * - * Calls "swapon -a" if needed so be sure /etc/fstab is present... */ -static void check_memory(void) -{ - struct stat statBuf; - - if (check_free_memory() > 1000) - return; - - if (stat("/etc/fstab", &statBuf) == 0) { - /* swapon -a requires /proc typically */ - waitfor("mount proc /proc -t proc", console, FALSE); - /* Try to turn on swap */ - waitfor("swapon -a", console, FALSE); - if (check_free_memory() < 1000) - goto goodnight; - } else - goto goodnight; - return; - - goodnight: - message(CONSOLE, - "Sorry, your computer does not have enough memory.\r\n"); - loop_forever(); -} - -/* Run all commands to be run right before halt/reboot */ -static void run_actions(initActionEnum action) -{ - initAction *a, *tmp; - for (a = initActionList; a; a = tmp) { - tmp = a->nextPtr; - if (a->action == action) { - waitfor(a->process, a->console, FALSE); - delete_initAction(a); - } - } -} - - -#ifndef DEBUG_INIT -static void shutdown_system(void) -{ - - /* first disable our SIGHUP signal */ - signal(SIGHUP, SIG_DFL); - - /* Allow Ctrl-Alt-Del to reboot system. */ - init_reboot(RB_ENABLE_CAD); - - message(CONSOLE|LOG, "\r\nThe system is going down NOW !!\r\n"); - sync(); - - /* Send signals to every process _except_ pid 1 */ - message(CONSOLE|LOG, "Sending SIGTERM to all processes.\r\n"); - kill(-1, SIGTERM); - sleep(1); - sync(); - - message(CONSOLE|LOG, "Sending SIGKILL to all processes.\r\n"); - kill(-1, SIGKILL); - sleep(1); - - /* run everything to be run at "shutdown" */ - run_actions(SHUTDOWN); - - sync(); - if (kernelVersion > 0 && kernelVersion <= KERNEL_VERSION(2,2,11)) { - /* bdflush, kupdate not needed for kernels >2.2.11 */ - bdflush(1, 0); - sync(); - } -} - -static void halt_signal(int sig) -{ - shutdown_system(); - message(CONSOLE|LOG, - "The system is halted. Press %s or turn off power\r\n", - (secondConsole == NULL) /* serial console */ - ? "Reset" : "CTRL-ALT-DEL"); - sync(); - - /* allow time for last message to reach serial console */ - sleep(2); - - if (sig == SIGUSR2 && kernelVersion >= KERNEL_VERSION(2,2,0)) - init_reboot(RB_POWER_OFF); - else - init_reboot(RB_HALT_SYSTEM); - - loop_forever(); -} - -static void reboot_signal(int sig) -{ - shutdown_system(); - message(CONSOLE|LOG, "Please stand by while rebooting the system.\r\n"); - sync(); - - /* allow time for last message to reach serial console */ - sleep(2); - - init_reboot(RB_AUTOBOOT); - - loop_forever(); -} - -static void ctrlaltdel_signal(int sig) -{ - run_actions(CTRLALTDEL); -} - -#endif /* ! DEBUG_INIT */ - -static void new_initAction(initActionEnum action, char *process, char *cons) -{ - initAction *newAction; -#ifdef BB_FEATURE_INIT_NORMAL_ORDER - initAction *a; -#endif - - if (*cons == '\0') - cons = console; - - /* If BusyBox detects that a serial console is in use, - * then entries not refering to the console or null devices will _not_ be run. - * The exception to this rule is the null device. - */ - if (secondConsole == NULL && strcmp(cons, console) - && strcmp(cons, "/dev/null")) - return; - if (strcmp(cons, "/dev/null") == 0 && action == ASKFIRST) - return; - - newAction = calloc((size_t) (1), sizeof(initAction)); - if (!newAction) { - message(LOG | CONSOLE, "Memory allocation failure\n"); - loop_forever(); - } -#ifdef BB_FEATURE_INIT_NORMAL_ORDER - for (a = initActionList; a && a->nextPtr; a = a->nextPtr) ; - if (a) { - a->nextPtr = newAction; - } else { - initActionList = newAction; - } -#else - newAction->nextPtr = initActionList; - initActionList = newAction; -#endif - strncpy(newAction->process, process, 255); - newAction->action = action; - strncpy(newAction->console, cons, 255); - newAction->pid = 0; -// message(LOG|CONSOLE, "process='%s' action='%d' console='%s'\n", -// newAction->process, newAction->action, newAction->console); -} - -static void delete_initAction(initAction * action) -{ - initAction *a, *b = NULL; - - for (a = initActionList; a; b = a, a = a->nextPtr) { - if (a == action) { - if (b == NULL) { - initActionList = a->nextPtr; - } else { - b->nextPtr = a->nextPtr; - } - free(a); - break; - } - } -} - -/* NOTE that if BB_FEATURE_USE_INITTAB is NOT defined, - * then parse_inittab() simply adds in some default - * actions(i.e., runs INIT_SCRIPT and then starts a pair - * of "askfirst" shells). If BB_FEATURE_USE_INITTAB - * _is_ defined, but /etc/inittab is missing, this - * results in the same set of default behaviors. - * */ -static void parse_inittab(void) -{ -#ifdef BB_FEATURE_USE_INITTAB - FILE *file; - char buf[256], lineAsRead[256], tmpConsole[256]; - char *id, *runlev, *action, *process, *eol; - const struct initActionType *a = actions; - int foundIt; - - - file = fopen(INITTAB, "r"); - if (file == NULL) { - /* No inittab file -- set up some default behavior */ -#endif - /* Reboot on Ctrl-Alt-Del */ - new_initAction(CTRLALTDEL, "/sbin/reboot", console); -#ifdef BB_FEATURE_INIT_NORMAL_ORDER - /* Umount all filesystems on halt/reboot */ - new_initAction(SHUTDOWN, "/bin/umount -a -r", console); - /* Swapoff on halt/reboot */ - new_initAction(SHUTDOWN, "/sbin/swapoff -a", console); -#else - /* Swapoff on halt/reboot */ - new_initAction(SHUTDOWN, "/sbin/swapoff -a", console); - /* Umount all filesystems on halt/reboot */ - new_initAction(SHUTDOWN, "/bin/umount -a -r", console); -#endif - /* Askfirst shell on tty1 */ - new_initAction(ASKFIRST, LOGIN_SHELL, console); - /* Askfirst shell on tty2 */ - if (secondConsole != NULL) - new_initAction(ASKFIRST, LOGIN_SHELL, secondConsole); - /* Askfirst shell on tty3 */ - if (thirdConsole != NULL) - new_initAction(ASKFIRST, LOGIN_SHELL, thirdConsole); - /* Askfirst shell on tty4 */ - if (fourthConsole != NULL) - new_initAction(ASKFIRST, LOGIN_SHELL, fourthConsole); - /* sysinit */ - new_initAction(SYSINIT, INIT_SCRIPT, console); - - return; -#ifdef BB_FEATURE_USE_INITTAB - } - - while (fgets(buf, 255, file) != NULL) { - foundIt = FALSE; - /* Skip leading spaces */ - for (id = buf; *id == ' ' || *id == '\t'; id++); - - /* Skip the line if it's a comment */ - if (*id == '#' || *id == '\n') - continue; - - /* Trim the trailing \n */ - eol = strrchr(id, '\n'); - if (eol != NULL) - *eol = '\0'; - - /* Keep a copy around for posterity's sake (and error msgs) */ - strcpy(lineAsRead, buf); - - /* Separate the ID field from the runlevels */ - runlev = strchr(id, ':'); - if (runlev == NULL || *(runlev + 1) == '\0') { - message(LOG | CONSOLE, "Bad inittab entry: %s\n", lineAsRead); - continue; - } else { - *runlev = '\0'; - ++runlev; - } - - /* Separate the runlevels from the action */ - action = strchr(runlev, ':'); - if (action == NULL || *(action + 1) == '\0') { - message(LOG | CONSOLE, "Bad inittab entry: %s\n", lineAsRead); - continue; - } else { - *action = '\0'; - ++action; - } - - /* Separate the action from the process */ - process = strchr(action, ':'); - if (process == NULL || *(process + 1) == '\0') { - message(LOG | CONSOLE, "Bad inittab entry: %s\n", lineAsRead); - continue; - } else { - *process = '\0'; - ++process; - } - - /* Ok, now process it */ - a = actions; - while (a->name != 0) { - if (strcmp(a->name, action) == 0) { - if (*id != '\0') { - strcpy(tmpConsole, "/dev/"); - strncat(tmpConsole, id, 200); - id = tmpConsole; - } - new_initAction(a->action, process, id); - foundIt = TRUE; - } - a++; - } - if (foundIt == TRUE) - continue; - else { - /* Choke on an unknown action */ - message(LOG | CONSOLE, "Bad inittab entry: %s\n", lineAsRead); - } - } - return; -#endif /* BB_FEATURE_USE_INITTAB */ -} - - - -extern int init_main(int argc, char **argv) -{ - initAction *a, *tmp; - pid_t wpid; - int status; - -#ifndef DEBUG_INIT - /* Expect to be invoked as init with PID=1 or be invoked as linuxrc */ - if (getpid() != 1 -#ifdef BB_FEATURE_LINUXRC - && strstr(applet_name, "linuxrc") == NULL -#endif - ) - { - show_usage(); - } - /* Set up sig handlers -- be sure to - * clear all of these in run() */ - signal(SIGUSR1, halt_signal); - signal(SIGUSR2, halt_signal); - signal(SIGINT, ctrlaltdel_signal); - signal(SIGTERM, reboot_signal); - - /* Turn off rebooting via CTL-ALT-DEL -- we get a - * SIGINT on CAD so we can shut things down gracefully... */ - init_reboot(RB_DISABLE_CAD); -#endif - - /* Figure out what kernel this is running */ - kernelVersion = get_kernel_revision(); - - /* Figure out where the default console should be */ - console_init(); - - /* Close whatever files are open, and reset the console. */ - close(0); - close(1); - close(2); - set_term(0); - chdir("/"); - setsid(); - - /* Make sure PATH is set to something sane */ - putenv("PATH="_PATH_STDPATH); - - /* Hello world */ -#ifndef DEBUG_INIT - message( -#if ! defined BB_FEATURE_EXTRA_QUIET - CONSOLE| -#endif - LOG, - "init started: %s\r\n", full_version); -#else - message( -#if ! defined BB_FEATURE_EXTRA_QUIET - CONSOLE| -#endif - LOG, - "init(%d) started: %s\r\n", getpid(), full_version); -#endif - - - /* Make sure there is enough memory to do something useful. */ - check_memory(); - - /* Check if we are supposed to be in single user mode */ - if (argc > 1 && (!strcmp(argv[1], "single") || - !strcmp(argv[1], "-s") || !strcmp(argv[1], "1"))) { - /* Ask first then start a shell on tty2-4 */ - if (secondConsole != NULL) - new_initAction(ASKFIRST, LOGIN_SHELL, secondConsole); - if (thirdConsole != NULL) - new_initAction(ASKFIRST, LOGIN_SHELL, thirdConsole); - if (fourthConsole != NULL) - new_initAction(ASKFIRST, LOGIN_SHELL, fourthConsole); - /* Start a shell on tty1 */ - new_initAction(RESPAWN, LOGIN_SHELL, console); - } else { - /* Not in single user mode -- see what inittab says */ - - /* NOTE that if BB_FEATURE_USE_INITTAB is NOT defined, - * then parse_inittab() simply adds in some default - * actions(i.e., runs INIT_SCRIPT and then starts a pair - * of "askfirst" shells */ - parse_inittab(); - } - - /* Make the command line just say "init" -- thats all, nothing else */ - fixup_argv(argc, argv, "init"); - - /* Now run everything that needs to be run */ - - /* First run the sysinit command */ - run_actions(SYSINIT); - /* Next run anything that wants to block */ - run_actions(WAIT); - /* Next run anything to be run only once */ - for (a = initActionList; a; a = tmp) { - tmp = a->nextPtr; - if (a->action == ONCE) { - run(a->process, a->console, FALSE); - /* Now remove the "once" entry from the list */ - delete_initAction(a); - } - } - /* If there is nothing else to do, stop */ - if (initActionList == NULL) { - message(LOG | CONSOLE, - "No more tasks for init -- sleeping forever.\n"); - loop_forever(); - } - - /* Now run the looping stuff for the rest of forever */ - while (1) { - for (a = initActionList; a; a = a->nextPtr) { - /* Only run stuff with pid==0. If they have - * a pid, that means they are still running */ - if (a->pid == 0) { - switch (a->action) { - case RESPAWN: - /* run the respawn stuff */ - a->pid = run(a->process, a->console, FALSE); - break; - case ASKFIRST: - /* run the askfirst stuff */ - a->pid = run(a->process, a->console, TRUE); - break; - /* silence the compiler's incessant whining */ - default: - break; - } - } - } - /* Wait for a child process to exit */ - wpid = wait(&status); - if (wpid > 0) { - /* Find out who died and clean up their corpse */ - for (a = initActionList; a; a = a->nextPtr) { - if (a->pid == wpid) { - a->pid = 0; - message(LOG, - "Process '%s' (pid %d) exited. Scheduling it for restart.\n", - a->process, wpid); - } - } - } - sleep(1); - } -} - -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ diff --git a/init/Makefile b/init/Makefile new file mode 100644 index 000000000..472fb02b1 --- /dev/null +++ b/init/Makefile @@ -0,0 +1,39 @@ +# Makefile for busybox +# +# Copyright (C) 1999,2000,2001 by Erik Andersen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +TOPDIR :=.. +L_TARGET := init.a + +obj-y := +obj-n := +obj- := + +obj-$(CONFIG_HALT) += halt.o +obj-$(CONFIG_INIT) += init.o +obj-$(CONFIG_POWEROFF) += poweroff.o +obj-$(CONFIG_REBOOT) += reboot.o +obj-$(CONFIG_START_STOP_DAEMON) += start_stop_daemon.o + + +# Hand off to toplevel Rules.mak +include $(TOPDIR)/Rules.mak + +clean: + rm -f $(L_TARGET) *.o core + diff --git a/init/config.in b/init/config.in new file mode 100644 index 000000000..1d4760c2c --- /dev/null +++ b/init/config.in @@ -0,0 +1,25 @@ +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +mainmenu_option next_comment +comment 'Init Utilities' + + +bool 'init' CONFIG_INIT +if [ "$CONFIG_INIT" = "y" ]; then + bool ' Support reading an inittab file?' CONFIG_FEATURE_USE_INITTAB + bool ' Support running init from within an initrd?' CONFIG_FEATURE_INITRD + bool ' Support dumping core for child processes (debugging only)?' CONFIG_FEATURE_INIT_COREDUMPS + bool ' Should init be _extra_ quiet on boot?' CONFIG_FEATURE_EXTRA_QUIET + + # Some more apps that are meaningless without BusyBox running as init + bool 'halt' CONFIG_HALT + bool 'poweroff' CONFIG_POWEROFF + bool 'reboot' CONFIG_REBOOT + bool 'start-stop-daemon' CONFIG_START_STOP_DAEMON +fi + +endmenu + diff --git a/init/halt.c b/init/halt.c index d66e28d0e..307c1022d 100644 --- a/init/halt.c +++ b/init/halt.c @@ -26,7 +26,7 @@ extern int halt_main(int argc, char **argv) { -#ifdef BB_FEATURE_LINUXRC +#ifdef CONFIG_FEATURE_INITRD /* don't assume init's pid == 1 */ pid_t *pid = find_pid_by_name("init"); if (!pid || *pid<=0) { diff --git a/init/init.c b/init/init.c index 068e1df16..b6eaa46ea 100644 --- a/init/init.c +++ b/init/init.c @@ -43,7 +43,7 @@ #include #include #include "busybox.h" -#ifdef BB_SYSLOGD +#ifdef CONFIG_SYSLOGD # include #endif @@ -96,7 +96,7 @@ static const int RB_AUTOBOOT = 0x01234567; #endif -#if defined BB_FEATURE_INIT_COREDUMPS +#if defined CONFIG_FEATURE_INIT_COREDUMPS /* * When a file named CORE_ENABLE_FLAG_FILE exists, setrlimit is called * before processes are spawned to set core file size as unlimited. @@ -194,7 +194,7 @@ static void message(int device, char *fmt, ...) va_list arguments; int fd; -#ifdef BB_SYSLOGD +#ifdef CONFIG_SYSLOGD /* Log the message to syslogd */ if (device & LOG) { @@ -546,7 +546,7 @@ static pid_t run(char *command, char *terminal, int get_enter) getpid(), terminal, command); #endif -#if defined BB_FEATURE_INIT_COREDUMPS +#if defined CONFIG_FEATURE_INIT_COREDUMPS if (stat (CORE_ENABLE_FLAG_FILE, &sb) == 0) { struct rlimit limit; limit.rlim_cur = RLIM_INFINITY; @@ -701,7 +701,7 @@ static void ctrlaltdel_signal(int sig) static void new_initAction(initActionEnum action, char *process, char *cons) { initAction *newAction; -#ifdef BB_FEATURE_INIT_NORMAL_ORDER +#ifdef CONFIG_FEATURE_INIT_NORMAL_ORDER initAction *a; #endif @@ -723,7 +723,7 @@ static void new_initAction(initActionEnum action, char *process, char *cons) message(LOG | CONSOLE, "Memory allocation failure\n"); loop_forever(); } -#ifdef BB_FEATURE_INIT_NORMAL_ORDER +#ifdef CONFIG_FEATURE_INIT_NORMAL_ORDER for (a = initActionList; a && a->nextPtr; a = a->nextPtr) ; if (a) { a->nextPtr = newAction; @@ -759,16 +759,16 @@ static void delete_initAction(initAction * action) } } -/* NOTE that if BB_FEATURE_USE_INITTAB is NOT defined, +/* NOTE that if CONFIG_FEATURE_USE_INITTAB is NOT defined, * then parse_inittab() simply adds in some default * actions(i.e., runs INIT_SCRIPT and then starts a pair - * of "askfirst" shells). If BB_FEATURE_USE_INITTAB + * of "askfirst" shells). If CONFIG_FEATURE_USE_INITTAB * _is_ defined, but /etc/inittab is missing, this * results in the same set of default behaviors. * */ static void parse_inittab(void) { -#ifdef BB_FEATURE_USE_INITTAB +#ifdef CONFIG_FEATURE_USE_INITTAB FILE *file; char buf[256], lineAsRead[256], tmpConsole[256]; char *id, *runlev, *action, *process, *eol; @@ -782,7 +782,7 @@ static void parse_inittab(void) #endif /* Reboot on Ctrl-Alt-Del */ new_initAction(CTRLALTDEL, "/sbin/reboot", console); -#ifdef BB_FEATURE_INIT_NORMAL_ORDER +#ifdef CONFIG_FEATURE_INIT_NORMAL_ORDER /* Umount all filesystems on halt/reboot */ new_initAction(SHUTDOWN, "/bin/umount -a -r", console); /* Swapoff on halt/reboot */ @@ -808,7 +808,7 @@ static void parse_inittab(void) new_initAction(SYSINIT, INIT_SCRIPT, console); return; -#ifdef BB_FEATURE_USE_INITTAB +#ifdef CONFIG_FEATURE_USE_INITTAB } while (fgets(buf, 255, file) != NULL) { @@ -880,7 +880,7 @@ static void parse_inittab(void) } } return; -#endif /* BB_FEATURE_USE_INITTAB */ +#endif /* CONFIG_FEATURE_USE_INITTAB */ } @@ -894,7 +894,7 @@ extern int init_main(int argc, char **argv) #ifndef DEBUG_INIT /* Expect to be invoked as init with PID=1 or be invoked as linuxrc */ if (getpid() != 1 -#ifdef BB_FEATURE_LINUXRC +#ifdef CONFIG_FEATURE_INITRD && strstr(applet_name, "linuxrc") == NULL #endif ) @@ -933,14 +933,14 @@ extern int init_main(int argc, char **argv) /* Hello world */ #ifndef DEBUG_INIT message( -#if ! defined BB_FEATURE_EXTRA_QUIET +#if ! defined CONFIG_FEATURE_EXTRA_QUIET CONSOLE| #endif LOG, "init started: %s\r\n", full_version); #else message( -#if ! defined BB_FEATURE_EXTRA_QUIET +#if ! defined CONFIG_FEATURE_EXTRA_QUIET CONSOLE| #endif LOG, @@ -966,7 +966,7 @@ extern int init_main(int argc, char **argv) } else { /* Not in single user mode -- see what inittab says */ - /* NOTE that if BB_FEATURE_USE_INITTAB is NOT defined, + /* NOTE that if CONFIG_FEATURE_USE_INITTAB is NOT defined, * then parse_inittab() simply adds in some default * actions(i.e., runs INIT_SCRIPT and then starts a pair * of "askfirst" shells */ diff --git a/init/poweroff.c b/init/poweroff.c index db20a4572..cec2d6ddd 100644 --- a/init/poweroff.c +++ b/init/poweroff.c @@ -26,7 +26,7 @@ extern int poweroff_main(int argc, char **argv) { -#ifdef BB_FEATURE_LINUXRC +#ifdef CONFIG_FEATURE_INITRD /* don't assume init's pid == 1 */ pid_t *pid = find_pid_by_name("init"); if (!pid || *pid<=0) { diff --git a/init/reboot.c b/init/reboot.c index 35afd74ff..a13d42492 100644 --- a/init/reboot.c +++ b/init/reboot.c @@ -26,7 +26,7 @@ extern int reboot_main(int argc, char **argv) { -#ifdef BB_FEATURE_LINUXRC +#ifdef CONFIG_FEATURE_INITRD /* don't assume init's pid == 1 */ pid_t *pid = find_pid_by_name("init"); if (!pid || *pid<=0) { diff --git a/insmod.c b/insmod.c deleted file mode 100644 index 6b81ca754..000000000 --- a/insmod.c +++ /dev/null @@ -1,3485 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini insmod implementation for busybox - * - * This version of insmod supports x86, ARM, SH3/4, powerpc, m68k, - * and MIPS. - * - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen - * and Ron Alder - * - * Modified by Bryan Rittmeyer to support SH4 - * and (theoretically) SH3. I have only tested SH4 in little endian mode. - * - * Modified by Alcove, Julien Gaulmin and - * Nicolas Ferre to support ARM7TDMI. Only - * very minor changes required to also work with StrongArm and presumably - * all ARM based systems. - * - * Magnus Damm added PowerPC support 20-Feb-2001. - * PowerPC specific code stolen from modutils-2.3.16, - * written by Paul Mackerras, Copyright 1996, 1997 Linux International. - * I've only tested the code on mpc8xx platforms in big-endian mode. - * Did some cleanup and added BB_USE_xxx_ENTRIES... - * - * Quinn Jensen added MIPS support 23-Feb-2001. - * based on modutils-2.4.2 - * MIPS specific support for Elf loading and relocation. - * Copyright 1996, 1997 Linux International. - * Contributed by Ralf Baechle - * - * Based almost entirely on the Linux modutils-2.3.11 implementation. - * Copyright 1996, 1997 Linux International. - * New implementation contributed by Richard Henderson - * Based on original work by Bjorn Ekwall - * Restructured (and partly rewritten) by: - * Björn Ekwall February 1999 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" - -#ifdef BB_FEATURE_NEW_MODULE_INTERFACE -# undef BB_FEATURE_OLD_MODULE_INTERFACE -# define new_sys_init_module init_module -#else -# define old_sys_init_module init_module -#endif - -#ifdef BB_FEATURE_INSMOD_LOADINKMEM -#define LOADBITS 0 -#else -#define LOADBITS 1 -#endif - -#if defined(__powerpc__) -#define BB_USE_PLT_ENTRIES -#define BB_PLT_ENTRY_SIZE 16 -#endif - -#if defined(__arm__) -#define BB_USE_PLT_ENTRIES -#define BB_PLT_ENTRY_SIZE 8 -#define BB_USE_GOT_ENTRIES -#define BB_GOT_ENTRY_SIZE 8 -#endif - -#if defined(__sh__) -#define BB_USE_GOT_ENTRIES -#define BB_GOT_ENTRY_SIZE 4 -#endif - -#if defined(__i386__) -#define BB_USE_GOT_ENTRIES -#define BB_GOT_ENTRY_SIZE 4 -#endif - -#if defined(__mips__) -// neither used -#endif - -//---------------------------------------------------------------------------- -//--------modutils module.h, lines 45-242 -//---------------------------------------------------------------------------- - -/* Definitions for the Linux module syscall interface. - Copyright 1996, 1997 Linux International. - - Contributed by Richard Henderson - - This file is part of the Linux modutils. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - - -#ifndef MODUTILS_MODULE_H -static const int MODUTILS_MODULE_H = 1; - -#ident "$Id: insmod.c,v 1.73 2001/08/22 05:41:57 andersen Exp $" - -/* This file contains the structures used by the 2.0 and 2.1 kernels. - We do not use the kernel headers directly because we do not wish - to be dependant on a particular kernel version to compile insmod. */ - - -/*======================================================================*/ -/* The structures used by Linux 2.0. */ - -/* The symbol format used by get_kernel_syms(2). */ -struct old_kernel_sym -{ - unsigned long value; - char name[60]; -}; - -struct old_module_ref -{ - unsigned long module; /* kernel addresses */ - unsigned long next; -}; - -struct old_module_symbol -{ - unsigned long addr; - unsigned long name; -}; - -struct old_symbol_table -{ - int size; /* total, including string table!!! */ - int n_symbols; - int n_refs; - struct old_module_symbol symbol[0]; /* actual size defined by n_symbols */ - struct old_module_ref ref[0]; /* actual size defined by n_refs */ -}; - -struct old_mod_routines -{ - unsigned long init; - unsigned long cleanup; -}; - -struct old_module -{ - unsigned long next; - unsigned long ref; /* the list of modules that refer to me */ - unsigned long symtab; - unsigned long name; - int size; /* size of module in pages */ - unsigned long addr; /* address of module */ - int state; - unsigned long cleanup; /* cleanup routine */ -}; - -/* Sent to init_module(2) or'ed into the code size parameter. */ -static const int OLD_MOD_AUTOCLEAN = 0x40000000; /* big enough, but no sign problems... */ - -int get_kernel_syms(struct old_kernel_sym *); -int old_sys_init_module(const char *name, char *code, unsigned codesize, - struct old_mod_routines *, struct old_symbol_table *); - -/*======================================================================*/ -/* For sizeof() which are related to the module platform and not to the - environment isnmod is running in, use sizeof_xx instead of sizeof(xx). */ - -#define tgt_sizeof_char sizeof(char) -#define tgt_sizeof_short sizeof(short) -#define tgt_sizeof_int sizeof(int) -#define tgt_sizeof_long sizeof(long) -#define tgt_sizeof_char_p sizeof(char *) -#define tgt_sizeof_void_p sizeof(void *) -#define tgt_long long - -#if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64) -#undef tgt_sizeof_long -#undef tgt_sizeof_char_p -#undef tgt_sizeof_void_p -#undef tgt_long -static const int tgt_sizeof_long = 8; -static const int tgt_sizeof_char_p = 8; -static const int tgt_sizeof_void_p = 8; -#define tgt_long long long -#endif - -/*======================================================================*/ -/* The structures used in Linux 2.1. */ - -/* Note: new_module_symbol does not use tgt_long intentionally */ -struct new_module_symbol -{ - unsigned long value; - unsigned long name; -}; - -struct new_module_persist; - -struct new_module_ref -{ - unsigned tgt_long dep; /* kernel addresses */ - unsigned tgt_long ref; - unsigned tgt_long next_ref; -}; - -struct new_module -{ - unsigned tgt_long size_of_struct; /* == sizeof(module) */ - unsigned tgt_long next; - unsigned tgt_long name; - unsigned tgt_long size; - - tgt_long usecount; - unsigned tgt_long flags; /* AUTOCLEAN et al */ - - unsigned nsyms; - unsigned ndeps; - - unsigned tgt_long syms; - unsigned tgt_long deps; - unsigned tgt_long refs; - unsigned tgt_long init; - unsigned tgt_long cleanup; - unsigned tgt_long ex_table_start; - unsigned tgt_long ex_table_end; -#ifdef __alpha__ - unsigned tgt_long gp; -#endif - /* Everything after here is extension. */ - unsigned tgt_long persist_start; - unsigned tgt_long persist_end; - unsigned tgt_long can_unload; - unsigned tgt_long runsize; -#ifdef BB_FEATURE_NEW_MODULE_INTERFACE - const char *kallsyms_start; /* All symbols for kernel debugging */ - const char *kallsyms_end; - const char *archdata_start; /* arch specific data for module */ - const char *archdata_end; - const char *kernel_data; /* Reserved for kernel internal use */ -#endif -}; - -#define ARCHDATA_SEC_NAME "__archdata" -#define KALLSYMS_SEC_NAME "__kallsyms" - - -struct new_module_info -{ - unsigned long addr; - unsigned long size; - unsigned long flags; - long usecount; -}; - -/* Bits of module.flags. */ -static const int NEW_MOD_RUNNING = 1; -static const int NEW_MOD_DELETED = 2; -static const int NEW_MOD_AUTOCLEAN = 4; -static const int NEW_MOD_VISITED = 8; -static const int NEW_MOD_USED_ONCE = 16; - -int new_sys_init_module(const char *name, const struct new_module *); -int query_module(const char *name, int which, void *buf, size_t bufsize, - size_t *ret); - -/* Values for query_module's which. */ - -static const int QM_MODULES = 1; -static const int QM_DEPS = 2; -static const int QM_REFS = 3; -static const int QM_SYMBOLS = 4; -static const int QM_INFO = 5; - -/*======================================================================*/ -/* The system calls unchanged between 2.0 and 2.1. */ - -unsigned long create_module(const char *, size_t); -int delete_module(const char *); - - -#endif /* module.h */ - -//---------------------------------------------------------------------------- -//--------end of modutils module.h -//---------------------------------------------------------------------------- - - - -//---------------------------------------------------------------------------- -//--------modutils obj.h, lines 253-462 -//---------------------------------------------------------------------------- - -/* Elf object file loading and relocation routines. - Copyright 1996, 1997 Linux International. - - Contributed by Richard Henderson - - This file is part of the Linux modutils. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - - -#ifndef MODUTILS_OBJ_H -static const int MODUTILS_OBJ_H = 1; - -#ident "$Id: insmod.c,v 1.73 2001/08/22 05:41:57 andersen Exp $" - -/* The relocatable object is manipulated using elfin types. */ - -#include -#include - - -/* Machine-specific elf macros for i386 et al. */ - -/* the SH changes have only been tested on the SH4 in =little endian= mode */ -/* I'm not sure about big endian, so let's warn: */ - -#if (defined(__SH4__) || defined(__SH3__)) && defined(__BIG_ENDIAN__) -#error insmod.c may require changes for use on big endian SH4/SH3 -#endif - -/* it may or may not work on the SH1/SH2... So let's error on those - also */ -#if (defined(__sh__) && (!(defined(__SH3__) || defined(__SH4__)))) -#error insmod.c may require changes for non-SH3/SH4 use -#endif - -#define ELFCLASSM ELFCLASS32 - -#if (defined(__mc68000__)) -#define ELFDATAM ELFDATA2MSB -#endif - - - -#if defined(__sh__) - -#define MATCH_MACHINE(x) (x == EM_SH) -#define SHT_RELM SHT_RELA -#define Elf32_RelM Elf32_Rela -#define ELFDATAM ELFDATA2LSB - -#elif defined(__arm__) - -#define MATCH_MACHINE(x) (x == EM_ARM) -#define SHT_RELM SHT_REL -#define Elf32_RelM Elf32_Rel -#define ELFDATAM ELFDATA2LSB - -#elif defined(__powerpc__) - -#define MATCH_MACHINE(x) (x == EM_PPC) -#define SHT_RELM SHT_RELA -#define Elf32_RelM Elf32_Rela -#define ELFDATAM ELFDATA2MSB - -#elif defined(__mips__) - -/* Account for ELF spec changes. */ -#ifndef EM_MIPS_RS3_LE -#ifdef EM_MIPS_RS4_BE -#define EM_MIPS_RS3_LE EM_MIPS_RS4_BE -#else -#define EM_MIPS_RS3_LE 10 -#endif -#endif /* !EM_MIPS_RS3_LE */ - -#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE) -#define SHT_RELM SHT_REL -#define Elf32_RelM Elf32_Rel -#ifdef __MIPSEB__ -#define ELFDATAM ELFDATA2MSB -#endif -#ifdef __MIPSEL__ -#define ELFDATAM ELFDATA2LSB -#endif - -#elif defined(__i386__) - -/* presumably we can use these for anything but the SH and ARM*/ -/* this is the previous behavior, but it does result in - insmod.c being broken on anything except i386 */ -#ifndef EM_486 -#define MATCH_MACHINE(x) (x == EM_386) -#else -#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486) -#endif - -#define SHT_RELM SHT_REL -#define Elf32_RelM Elf32_Rel -#define ELFDATAM ELFDATA2LSB - -#elif defined(__mc68000__) - -#define MATCH_MACHINE(x) (x == EM_68K) -#define SHT_RELM SHT_RELA -#define Elf32_RelM Elf32_Rela - -#else -#error Sorry, but insmod.c does not yet support this architecture... -#endif - -#ifndef ElfW -# if ELFCLASSM == ELFCLASS32 -# define ElfW(x) Elf32_ ## x -# define ELFW(x) ELF32_ ## x -# else -# define ElfW(x) Elf64_ ## x -# define ELFW(x) ELF64_ ## x -# endif -#endif - -/* For some reason this is missing from libc5. */ -#ifndef ELF32_ST_INFO -# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) -#endif - -#ifndef ELF64_ST_INFO -# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) -#endif - -struct obj_string_patch; -struct obj_symbol_patch; - -struct obj_section -{ - ElfW(Shdr) header; - const char *name; - char *contents; - struct obj_section *load_next; - int idx; -}; - -struct obj_symbol -{ - struct obj_symbol *next; /* hash table link */ - const char *name; - unsigned long value; - unsigned long size; - int secidx; /* the defining section index/module */ - int info; - int ksymidx; /* for export to the kernel symtab */ - int referenced; /* actually used in the link */ -}; - -/* Hardcode the hash table size. We shouldn't be needing so many - symbols that we begin to degrade performance, and we get a big win - by giving the compiler a constant divisor. */ - -#define HASH_BUCKETS 521 - -struct obj_file -{ - ElfW(Ehdr) header; - ElfW(Addr) baseaddr; - struct obj_section **sections; - struct obj_section *load_order; - struct obj_section **load_order_search_start; - struct obj_string_patch *string_patches; - struct obj_symbol_patch *symbol_patches; - int (*symbol_cmp)(const char *, const char *); - unsigned long (*symbol_hash)(const char *); - unsigned long local_symtab_size; - struct obj_symbol **local_symtab; - struct obj_symbol *symtab[HASH_BUCKETS]; -}; - -enum obj_reloc -{ - obj_reloc_ok, - obj_reloc_overflow, - obj_reloc_dangerous, - obj_reloc_unhandled -}; - -struct obj_string_patch -{ - struct obj_string_patch *next; - int reloc_secidx; - ElfW(Addr) reloc_offset; - ElfW(Addr) string_offset; -}; - -struct obj_symbol_patch -{ - struct obj_symbol_patch *next; - int reloc_secidx; - ElfW(Addr) reloc_offset; - struct obj_symbol *sym; -}; - - -/* Generic object manipulation routines. */ - -static unsigned long obj_elf_hash(const char *); - -static unsigned long obj_elf_hash_n(const char *, unsigned long len); - -static struct obj_symbol *obj_find_symbol (struct obj_file *f, - const char *name); - -static ElfW(Addr) obj_symbol_final_value(struct obj_file *f, - struct obj_symbol *sym); - -#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING -static void obj_set_symbol_compare(struct obj_file *f, - int (*cmp)(const char *, const char *), - unsigned long (*hash)(const char *)); -#endif - -static struct obj_section *obj_find_section (struct obj_file *f, - const char *name); - -static void obj_insert_section_load_order (struct obj_file *f, - struct obj_section *sec); - -static struct obj_section *obj_create_alloced_section (struct obj_file *f, - const char *name, - unsigned long align, - unsigned long size); - -static struct obj_section *obj_create_alloced_section_first (struct obj_file *f, - const char *name, - unsigned long align, - unsigned long size); - -static void *obj_extend_section (struct obj_section *sec, unsigned long more); - -static int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, - const char *string); - -static int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, - struct obj_symbol *sym); - -static int obj_check_undefineds(struct obj_file *f); - -static void obj_allocate_commons(struct obj_file *f); - -static unsigned long obj_load_size (struct obj_file *f); - -static int obj_relocate (struct obj_file *f, ElfW(Addr) base); - -static struct obj_file *obj_load(FILE *f, int loadprogbits); - -static int obj_create_image (struct obj_file *f, char *image); - -/* Architecture specific manipulation routines. */ - -static struct obj_file *arch_new_file (void); - -static struct obj_section *arch_new_section (void); - -static struct obj_symbol *arch_new_symbol (void); - -static enum obj_reloc arch_apply_relocation (struct obj_file *f, - struct obj_section *targsec, - struct obj_section *symsec, - struct obj_symbol *sym, - ElfW(RelM) *rel, ElfW(Addr) value); - -static int arch_create_got (struct obj_file *f); - -static int arch_init_module (struct obj_file *f, struct new_module *); - -#endif /* obj.h */ -//---------------------------------------------------------------------------- -//--------end of modutils obj.h -//---------------------------------------------------------------------------- - - - - - -#define _PATH_MODULES "/lib/modules" -static const int STRVERSIONLEN = 32; - -/*======================================================================*/ - -static int flag_force_load = 0; -static int flag_autoclean = 0; -static int flag_verbose = 0; -static int flag_export = 1; - - -/*======================================================================*/ - -/* previously, these were named i386_* but since we could be - compiling for the sh, I've renamed them to the more general - arch_* These structures are the same between the x86 and SH, - and we can't support anything else right now anyway. In the - future maybe they should be #if defined'd */ - -/* Done ;-) */ - - - -#if defined(BB_USE_PLT_ENTRIES) -struct arch_plt_entry -{ - int offset; - int allocated:1; - int inited:1; /* has been set up */ -}; -#endif - -#if defined(BB_USE_GOT_ENTRIES) -struct arch_got_entry { - int offset; - unsigned offset_done:1; - unsigned reloc_done:1; -}; -#endif - -#if defined(__mips__) -struct mips_hi16 -{ - struct mips_hi16 *next; - Elf32_Addr *addr; - Elf32_Addr value; -}; -#endif - -struct arch_file { - struct obj_file root; -#if defined(BB_USE_PLT_ENTRIES) - struct obj_section *plt; -#endif -#if defined(BB_USE_GOT_ENTRIES) - struct obj_section *got; -#endif -#if defined(__mips__) - struct mips_hi16 *mips_hi16_list; -#endif -}; - -struct arch_symbol { - struct obj_symbol root; -#if defined(BB_USE_PLT_ENTRIES) - struct arch_plt_entry pltent; -#endif -#if defined(BB_USE_GOT_ENTRIES) - struct arch_got_entry gotent; -#endif -}; - - -struct external_module { - const char *name; - ElfW(Addr) addr; - int used; - size_t nsyms; - struct new_module_symbol *syms; -}; - -static struct new_module_symbol *ksyms; -static size_t nksyms; - -static struct external_module *ext_modules; -static int n_ext_modules; -static int n_ext_modules_used; -extern int delete_module(const char *); - -static char m_filename[FILENAME_MAX + 1]; -static char m_fullName[FILENAME_MAX + 1]; - - - -/*======================================================================*/ - - -static int check_module_name_match(const char *filename, struct stat *statbuf, - void *userdata) -{ - char *fullname = (char *) userdata; - - if (fullname[0] == '\0') - return (FALSE); - else { - char *tmp, *tmp1 = strdup(filename); - tmp = get_last_path_component(tmp1); - if (strcmp(tmp, fullname) == 0) { - free(tmp1); - /* Stop searching if we find a match */ - safe_strncpy(m_filename, filename, sizeof(m_filename)); - return (TRUE); - } - free(tmp1); - } - return (FALSE); -} - - -/*======================================================================*/ - -static struct obj_file *arch_new_file(void) -{ - struct arch_file *f; - f = xmalloc(sizeof(*f)); - -#if defined(BB_USE_PLT_ENTRIES) - f->plt = NULL; -#endif -#if defined(BB_USE_GOT_ENTRIES) - f->got = NULL; -#endif -#if defined(__mips__) - f->mips_hi16_list = NULL; -#endif - - return &f->root; -} - -static struct obj_section *arch_new_section(void) -{ - return xmalloc(sizeof(struct obj_section)); -} - -static struct obj_symbol *arch_new_symbol(void) -{ - struct arch_symbol *sym; - sym = xmalloc(sizeof(*sym)); - -#if defined(BB_USE_PLT_ENTRIES) - memset(&sym->pltent, 0, sizeof(sym->pltent)); -#endif -#if defined(BB_USE_GOT_ENTRIES) - memset(&sym->gotent, 0, sizeof(sym->gotent)); -#endif - - return &sym->root; -} - -static enum obj_reloc -arch_apply_relocation(struct obj_file *f, - struct obj_section *targsec, - struct obj_section *symsec, - struct obj_symbol *sym, - ElfW(RelM) *rel, ElfW(Addr) v) -{ - struct arch_file *ifile = (struct arch_file *) f; -#if !(defined(__mips__)) - struct arch_symbol *isym = (struct arch_symbol *) sym; -#endif - - ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset); - ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset; -#if defined(BB_USE_GOT_ENTRIES) - ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0; -#endif -#if defined(BB_USE_PLT_ENTRIES) - ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0; - struct arch_plt_entry *pe; - unsigned long *ip; -#endif - enum obj_reloc ret = obj_reloc_ok; - - switch (ELF32_R_TYPE(rel->r_info)) { - -/* even though these constants seem to be the same for - the i386 and the sh, we "#if define" them for clarity - and in case that ever changes */ -#if defined(__sh__) - case R_SH_NONE: -#elif defined(__arm__) - case R_ARM_NONE: -#elif defined(__i386__) - case R_386_NONE: -#elif defined(__mc68000__) - case R_68K_NONE: -#elif defined(__powerpc__) - case R_PPC_NONE: -#elif defined(__mips__) - case R_MIPS_NONE: -#endif - break; - -#if defined(__sh__) - case R_SH_DIR32: -#elif defined(__arm__) - case R_ARM_ABS32: -#elif defined(__i386__) - case R_386_32: -#elif defined(__mc68000__) - case R_68K_32: -#elif defined(__powerpc__) - case R_PPC_ADDR32: -#elif defined(__mips__) - case R_MIPS_32: -#endif - *loc += v; - break; -#if defined(__mc68000__) - case R_68K_8: - if (v > 0xff) - ret = obj_reloc_overflow; - *(char *)loc = v; - break; - case R_68K_16: - if (v > 0xffff) - ret = obj_reloc_overflow; - *(short *)loc = v; - break; -#endif /* __mc68000__ */ - -#if defined(__powerpc__) - case R_PPC_ADDR16_HA: - *(unsigned short *)loc = (v + 0x8000) >> 16; - break; - - case R_PPC_ADDR16_HI: - *(unsigned short *)loc = v >> 16; - break; - - case R_PPC_ADDR16_LO: - *(unsigned short *)loc = v; - break; -#endif - -#if defined(__mips__) - case R_MIPS_26: - if (v % 4) - ret = obj_reloc_dangerous; - if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000)) - ret = obj_reloc_overflow; - *loc = - (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) & - 0x03ffffff); - break; - - case R_MIPS_HI16: - { - struct mips_hi16 *n; - - /* We cannot relocate this one now because we don't know the value - of the carry we need to add. Save the information, and let LO16 - do the actual relocation. */ - n = (struct mips_hi16 *) xmalloc(sizeof *n); - n->addr = loc; - n->value = v; - n->next = ifile->mips_hi16_list; - ifile->mips_hi16_list = n; - break; - } - - case R_MIPS_LO16: - { - unsigned long insnlo = *loc; - Elf32_Addr val, vallo; - - /* Sign extend the addend we extract from the lo insn. */ - vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000; - - if (ifile->mips_hi16_list != NULL) { - struct mips_hi16 *l; - - l = ifile->mips_hi16_list; - while (l != NULL) { - struct mips_hi16 *next; - unsigned long insn; - - /* The value for the HI16 had best be the same. */ - assert(v == l->value); - - /* Do the HI16 relocation. Note that we actually don't - need to know anything about the LO16 itself, except where - to find the low 16 bits of the addend needed by the LO16. */ - insn = *l->addr; - val = - ((insn & 0xffff) << 16) + - vallo; - val += v; - - /* Account for the sign extension that will happen in the - low bits. */ - val = - ((val >> 16) + - ((val & 0x8000) != - 0)) & 0xffff; - - insn = (insn & ~0xffff) | val; - *l->addr = insn; - - next = l->next; - free(l); - l = next; - } - - ifile->mips_hi16_list = NULL; - } - - /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */ - val = v + vallo; - insnlo = (insnlo & ~0xffff) | (val & 0xffff); - *loc = insnlo; - break; - } -#endif - -#if defined(__arm__) -#elif defined(__sh__) - case R_SH_REL32: - *loc += v - dot; - break; -#elif defined(__i386__) - case R_386_PLT32: - case R_386_PC32: - *loc += v - dot; - break; -#elif defined(__mc68000__) - case R_68K_PC8: - v -= dot; - if ((Elf32_Sword)v > 0x7f || (Elf32_Sword)v < -(Elf32_Sword)0x80) - ret = obj_reloc_overflow; - *(char *)loc = v; - break; - case R_68K_PC16: - v -= dot; - if ((Elf32_Sword)v > 0x7fff || (Elf32_Sword)v < -(Elf32_Sword)0x8000) - ret = obj_reloc_overflow; - *(short *)loc = v; - break; - case R_68K_PC32: - *(int *)loc = v - dot; - break; -#elif defined(__powerpc__) - case R_PPC_REL32: - *loc = v - dot; - break; -#endif - -#if defined(__sh__) - case R_SH_PLT32: - *loc = v - dot; - break; -#elif defined(__i386__) -#endif - -#if defined(BB_USE_PLT_ENTRIES) - -#if defined(__arm__) - case R_ARM_PC24: - case R_ARM_PLT32: -#endif -#if defined(__powerpc__) - case R_PPC_REL24: -#endif - /* find the plt entry and initialize it if necessary */ - assert(isym != NULL); - - pe = (struct arch_plt_entry*) &isym->pltent; - - if (! pe->inited) { - ip = (unsigned long *) (ifile->plt->contents + pe->offset); - - /* generate some machine code */ - -#if defined(__arm__) - ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */ - ip[1] = v; /* sym@ */ -#endif -#if defined(__powerpc__) - ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */ - ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */ - ip[2] = 0x7d6903a6; /* mtctr r11 */ - ip[3] = 0x4e800420; /* bctr */ -#endif - pe->inited = 1; - } - - /* relative distance to target */ - v -= dot; - /* if the target is too far away.... */ - if ((int)v < -0x02000000 || (int)v >= 0x02000000) { - /* go via the plt */ - v = plt + pe->offset - dot; - } - if (v & 3) - ret = obj_reloc_dangerous; - - /* merge the offset into the instruction. */ -#if defined(__arm__) - /* Convert to words. */ - v >>= 2; - - *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff); -#endif -#if defined(__powerpc__) - *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc); -#endif - break; -#endif /* BB_USE_PLT_ENTRIES */ - -#if defined(__arm__) -#elif defined(__sh__) - case R_SH_GLOB_DAT: - case R_SH_JMP_SLOT: - *loc = v; - break; -#elif defined(__i386__) - case R_386_GLOB_DAT: - case R_386_JMP_SLOT: - *loc = v; - break; -#elif defined(__mc68000__) - case R_68K_GLOB_DAT: - case R_68K_JMP_SLOT: - *loc = v; - break; -#endif - -#if defined(__arm__) -#elif defined(__sh__) - case R_SH_RELATIVE: - *loc += f->baseaddr + rel->r_addend; - break; -#elif defined(__i386__) - case R_386_RELATIVE: - *loc += f->baseaddr; - break; -#elif defined(__mc68000__) - case R_68K_RELATIVE: - *(int *)loc += f->baseaddr; - break; -#endif - -#if defined(BB_USE_GOT_ENTRIES) - -#if !defined(__68k__) -#if defined(__sh__) - case R_SH_GOTPC: -#elif defined(__arm__) - case R_ARM_GOTPC: -#elif defined(__i386__) - case R_386_GOTPC: -#endif - assert(got != 0); -#if defined(__sh__) - *loc += got - dot + rel->r_addend;; -#elif defined(__i386__) || defined(__arm__) || defined(__m68k_) - *loc += got - dot; -#endif - break; -#endif // __68k__ - -#if defined(__sh__) - case R_SH_GOT32: -#elif defined(__arm__) - case R_ARM_GOT32: -#elif defined(__i386__) - case R_386_GOT32: -#elif defined(__mc68000__) - case R_68K_GOT32: -#endif - assert(isym != NULL); - /* needs an entry in the .got: set it, once */ - if (!isym->gotent.reloc_done) { - isym->gotent.reloc_done = 1; - *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v; - } - /* make the reloc with_respect_to_.got */ -#if defined(__sh__) - *loc += isym->gotent.offset + rel->r_addend; -#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__) - *loc += isym->gotent.offset; -#endif - break; - - /* address relative to the got */ -#if !defined(__mc68000__) -#if defined(__sh__) - case R_SH_GOTOFF: -#elif defined(__arm__) - case R_ARM_GOTOFF: -#elif defined(__i386__) - case R_386_GOTOFF: -#elif defined(__mc68000__) - case R_68K_GOTOFF: -#endif - assert(got != 0); - *loc += v - got; - break; -#endif // __mc68000__ - -#endif /* BB_USE_GOT_ENTRIES */ - - default: - printf("Warning: unhandled reloc %d\n",(int)ELF32_R_TYPE(rel->r_info)); - ret = obj_reloc_unhandled; - break; - } - - return ret; -} - -static int arch_create_got(struct obj_file *f) -{ -#if defined(BB_USE_GOT_ENTRIES) || defined(BB_USE_PLT_ENTRIES) - struct arch_file *ifile = (struct arch_file *) f; - int i; -#if defined(BB_USE_GOT_ENTRIES) - int got_offset = 0, gotneeded = 0; -#endif -#if defined(BB_USE_PLT_ENTRIES) - int plt_offset = 0, pltneeded = 0; -#endif - struct obj_section *relsec, *symsec, *strsec; - ElfW(RelM) *rel, *relend; - ElfW(Sym) *symtab, *extsym; - const char *strtab, *name; - struct arch_symbol *intsym; - - for (i = 0; i < f->header.e_shnum; ++i) { - relsec = f->sections[i]; - if (relsec->header.sh_type != SHT_RELM) - continue; - - symsec = f->sections[relsec->header.sh_link]; - strsec = f->sections[symsec->header.sh_link]; - - rel = (ElfW(RelM) *) relsec->contents; - relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM))); - symtab = (ElfW(Sym) *) symsec->contents; - strtab = (const char *) strsec->contents; - - for (; rel < relend; ++rel) { - extsym = &symtab[ELF32_R_SYM(rel->r_info)]; - - switch (ELF32_R_TYPE(rel->r_info)) { -#if defined(__arm__) - case R_ARM_GOT32: - break; -#elif defined(__sh__) - case R_SH_GOT32: - break; -#elif defined(__i386__) - case R_386_GOT32: - break; -#elif defined(__mc68000__) - case R_68K_GOT32: - break; -#endif - -#if defined(__powerpc__) - case R_PPC_REL24: - pltneeded = 1; - break; -#endif - -#if defined(__arm__) - case R_ARM_PC24: - case R_ARM_PLT32: - pltneeded = 1; - break; - - case R_ARM_GOTPC: - case R_ARM_GOTOFF: - gotneeded = 1; - if (got_offset == 0) - got_offset = 4; -#elif defined(__sh__) - case R_SH_GOTPC: - case R_SH_GOTOFF: - gotneeded = 1; -#elif defined(__i386__) - case R_386_GOTPC: - case R_386_GOTOFF: - gotneeded = 1; -#endif - - default: - continue; - } - - if (extsym->st_name != 0) { - name = strtab + extsym->st_name; - } else { - name = f->sections[extsym->st_shndx]->name; - } - intsym = (struct arch_symbol *) obj_find_symbol(f, name); -#if defined(BB_USE_GOT_ENTRIES) - if (!intsym->gotent.offset_done) { - intsym->gotent.offset_done = 1; - intsym->gotent.offset = got_offset; - got_offset += BB_GOT_ENTRY_SIZE; - } -#endif -#if defined(BB_USE_PLT_ENTRIES) - if (pltneeded && intsym->pltent.allocated == 0) { - intsym->pltent.allocated = 1; - intsym->pltent.offset = plt_offset; - plt_offset += BB_PLT_ENTRY_SIZE; - intsym->pltent.inited = 0; - pltneeded = 0; - } -#endif - } - } - -#if defined(BB_USE_GOT_ENTRIES) - if (got_offset) { - struct obj_section* myrelsec = obj_find_section(f, ".got"); - - if (myrelsec) { - obj_extend_section(myrelsec, got_offset); - } else { - myrelsec = obj_create_alloced_section(f, ".got", - BB_GOT_ENTRY_SIZE, - got_offset); - assert(myrelsec); - } - - ifile->got = myrelsec; - } -#endif - -#if defined(BB_USE_PLT_ENTRIES) - if (plt_offset) - ifile->plt = obj_create_alloced_section(f, ".plt", - BB_PLT_ENTRY_SIZE, - plt_offset); -#endif -#endif - return 1; -} - -static int arch_init_module(struct obj_file *f, struct new_module *mod) -{ - return 1; -} - - -/*======================================================================*/ - -/* Standard ELF hash function. */ -static inline unsigned long obj_elf_hash_n(const char *name, unsigned long n) -{ - unsigned long h = 0; - unsigned long g; - unsigned char ch; - - while (n > 0) { - ch = *name++; - h = (h << 4) + ch; - if ((g = (h & 0xf0000000)) != 0) { - h ^= g >> 24; - h &= ~g; - } - n--; - } - return h; -} - -static unsigned long obj_elf_hash(const char *name) -{ - return obj_elf_hash_n(name, strlen(name)); -} - -#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING -/* String comparison for non-co-versioned kernel and module. */ - -static int ncv_strcmp(const char *a, const char *b) -{ - size_t alen = strlen(a), blen = strlen(b); - - if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R') - return strncmp(a, b, alen); - else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R') - return strncmp(a, b, blen); - else - return strcmp(a, b); -} - -/* String hashing for non-co-versioned kernel and module. Here - we are simply forced to drop the crc from the hash. */ - -static unsigned long ncv_symbol_hash(const char *str) -{ - size_t len = strlen(str); - if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R') - len -= 10; - return obj_elf_hash_n(str, len); -} - -static void -obj_set_symbol_compare(struct obj_file *f, - int (*cmp) (const char *, const char *), - unsigned long (*hash) (const char *)) -{ - if (cmp) - f->symbol_cmp = cmp; - if (hash) { - struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next; - int i; - - f->symbol_hash = hash; - - memcpy(tmptab, f->symtab, sizeof(tmptab)); - memset(f->symtab, 0, sizeof(f->symtab)); - - for (i = 0; i < HASH_BUCKETS; ++i) - for (sym = tmptab[i]; sym; sym = next) { - unsigned long h = hash(sym->name) % HASH_BUCKETS; - next = sym->next; - sym->next = f->symtab[h]; - f->symtab[h] = sym; - } - } -} - -#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */ - -static struct obj_symbol * -obj_add_symbol(struct obj_file *f, const char *name, - unsigned long symidx, int info, - int secidx, ElfW(Addr) value, - unsigned long size) -{ - struct obj_symbol *sym; - unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS; - int n_type = ELFW(ST_TYPE) (info); - int n_binding = ELFW(ST_BIND) (info); - - for (sym = f->symtab[hash]; sym; sym = sym->next) - if (f->symbol_cmp(sym->name, name) == 0) { - int o_secidx = sym->secidx; - int o_info = sym->info; - int o_type = ELFW(ST_TYPE) (o_info); - int o_binding = ELFW(ST_BIND) (o_info); - - /* A redefinition! Is it legal? */ - - if (secidx == SHN_UNDEF) - return sym; - else if (o_secidx == SHN_UNDEF) - goto found; - else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) { - /* Cope with local and global symbols of the same name - in the same object file, as might have been created - by ld -r. The only reason locals are now seen at this - level at all is so that we can do semi-sensible things - with parameters. */ - - struct obj_symbol *nsym, **p; - - nsym = arch_new_symbol(); - nsym->next = sym->next; - nsym->ksymidx = -1; - - /* Excise the old (local) symbol from the hash chain. */ - for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next) - continue; - *p = sym = nsym; - goto found; - } else if (n_binding == STB_LOCAL) { - /* Another symbol of the same name has already been defined. - Just add this to the local table. */ - sym = arch_new_symbol(); - sym->next = NULL; - sym->ksymidx = -1; - f->local_symtab[symidx] = sym; - goto found; - } else if (n_binding == STB_WEAK) - return sym; - else if (o_binding == STB_WEAK) - goto found; - /* Don't unify COMMON symbols with object types the programmer - doesn't expect. */ - else if (secidx == SHN_COMMON - && (o_type == STT_NOTYPE || o_type == STT_OBJECT)) - return sym; - else if (o_secidx == SHN_COMMON - && (n_type == STT_NOTYPE || n_type == STT_OBJECT)) - goto found; - else { - /* Don't report an error if the symbol is coming from - the kernel or some external module. */ - if (secidx <= SHN_HIRESERVE) - error_msg("%s multiply defined", name); - return sym; - } - } - - /* Completely new symbol. */ - sym = arch_new_symbol(); - sym->next = f->symtab[hash]; - f->symtab[hash] = sym; - sym->ksymidx = -1; - - if (ELFW(ST_BIND)(info) == STB_LOCAL && symidx != -1) { - if (symidx >= f->local_symtab_size) - error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld", - name, (long) symidx, (long) f->local_symtab_size); - else - f->local_symtab[symidx] = sym; - } - - found: - sym->name = name; - sym->value = value; - sym->size = size; - sym->secidx = secidx; - sym->info = info; - - return sym; -} - -static struct obj_symbol * -obj_find_symbol(struct obj_file *f, const char *name) -{ - struct obj_symbol *sym; - unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS; - - for (sym = f->symtab[hash]; sym; sym = sym->next) - if (f->symbol_cmp(sym->name, name) == 0) - return sym; - - return NULL; -} - -static ElfW(Addr) - obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym) -{ - if (sym) { - if (sym->secidx >= SHN_LORESERVE) - return sym->value; - - return sym->value + f->sections[sym->secidx]->header.sh_addr; - } else { - /* As a special case, a NULL sym has value zero. */ - return 0; - } -} - -static struct obj_section *obj_find_section(struct obj_file *f, const char *name) -{ - int i, n = f->header.e_shnum; - - for (i = 0; i < n; ++i) - if (strcmp(f->sections[i]->name, name) == 0) - return f->sections[i]; - - return NULL; -} - -static int obj_load_order_prio(struct obj_section *a) -{ - unsigned long af, ac; - - af = a->header.sh_flags; - - ac = 0; - if (a->name[0] != '.' || strlen(a->name) != 10 || - strcmp(a->name + 5, ".init")) - ac |= 32; - if (af & SHF_ALLOC) - ac |= 16; - if (!(af & SHF_WRITE)) - ac |= 8; - if (af & SHF_EXECINSTR) - ac |= 4; - if (a->header.sh_type != SHT_NOBITS) - ac |= 2; - - return ac; -} - -static void -obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec) -{ - struct obj_section **p; - int prio = obj_load_order_prio(sec); - for (p = f->load_order_search_start; *p; p = &(*p)->load_next) - if (obj_load_order_prio(*p) < prio) - break; - sec->load_next = *p; - *p = sec; -} - -static struct obj_section *obj_create_alloced_section(struct obj_file *f, - const char *name, - unsigned long align, - unsigned long size) -{ - int newidx = f->header.e_shnum++; - struct obj_section *sec; - - f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec)); - f->sections[newidx] = sec = arch_new_section(); - - memset(sec, 0, sizeof(*sec)); - sec->header.sh_type = SHT_PROGBITS; - sec->header.sh_flags = SHF_WRITE | SHF_ALLOC; - sec->header.sh_size = size; - sec->header.sh_addralign = align; - sec->name = name; - sec->idx = newidx; - if (size) - sec->contents = xmalloc(size); - - obj_insert_section_load_order(f, sec); - - return sec; -} - -static struct obj_section *obj_create_alloced_section_first(struct obj_file *f, - const char *name, - unsigned long align, - unsigned long size) -{ - int newidx = f->header.e_shnum++; - struct obj_section *sec; - - f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec)); - f->sections[newidx] = sec = arch_new_section(); - - memset(sec, 0, sizeof(*sec)); - sec->header.sh_type = SHT_PROGBITS; - sec->header.sh_flags = SHF_WRITE | SHF_ALLOC; - sec->header.sh_size = size; - sec->header.sh_addralign = align; - sec->name = name; - sec->idx = newidx; - if (size) - sec->contents = xmalloc(size); - - sec->load_next = f->load_order; - f->load_order = sec; - if (f->load_order_search_start == &f->load_order) - f->load_order_search_start = &sec->load_next; - - return sec; -} - -static void *obj_extend_section(struct obj_section *sec, unsigned long more) -{ - unsigned long oldsize = sec->header.sh_size; - if (more) { - sec->contents = xrealloc(sec->contents, sec->header.sh_size += more); - } - return sec->contents + oldsize; -} - - -/* Conditionally add the symbols from the given symbol set to the - new module. */ - -static int -add_symbols_from( - struct obj_file *f, - int idx, struct new_module_symbol *syms, size_t nsyms) -{ - struct new_module_symbol *s; - size_t i; - int used = 0; - - for (i = 0, s = syms; i < nsyms; ++i, ++s) { - - /* Only add symbols that are already marked external. If we - override locals we may cause problems for argument initialization. - We will also create a false dependency on the module. */ - struct obj_symbol *sym; - - sym = obj_find_symbol(f, (char *) s->name); - if (sym && !ELFW(ST_BIND) (sym->info) == STB_LOCAL) { - sym = obj_add_symbol(f, (char *) s->name, -1, - ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE), - idx, s->value, 0); - /* Did our symbol just get installed? If so, mark the - module as "used". */ - if (sym->secidx == idx) - used = 1; - } - } - - return used; -} - -static void add_kernel_symbols(struct obj_file *f) -{ - struct external_module *m; - int i, nused = 0; - - /* Add module symbols first. */ - - for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m) - if (m->nsyms - && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms, - m->nsyms)) m->used = 1, ++nused; - - n_ext_modules_used = nused; - - /* And finally the symbols from the kernel proper. */ - - if (nksyms) - add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms); -} - -static char *get_modinfo_value(struct obj_file *f, const char *key) -{ - struct obj_section *sec; - char *p, *v, *n, *ep; - size_t klen = strlen(key); - - sec = obj_find_section(f, ".modinfo"); - if (sec == NULL) - return NULL; - p = sec->contents; - ep = p + sec->header.sh_size; - while (p < ep) { - v = strchr(p, '='); - n = strchr(p, '\0'); - if (v) { - if (p + klen == v && strncmp(p, key, klen) == 0) - return v + 1; - } else { - if (p + klen == n && strcmp(p, key) == 0) - return n; - } - p = n + 1; - } - - return NULL; -} - - -/*======================================================================*/ -/* Functions relating to module loading in pre 2.1 kernels. */ - -static int -old_process_module_arguments(struct obj_file *f, int argc, char **argv) -{ - while (argc > 0) { - char *p, *q; - struct obj_symbol *sym; - int *loc; - - p = *argv; - if ((q = strchr(p, '=')) == NULL) { - argc--; - continue; - } - *q++ = '\0'; - - sym = obj_find_symbol(f, p); - - /* Also check that the parameter was not resolved from the kernel. */ - if (sym == NULL || sym->secidx > SHN_HIRESERVE) { - error_msg("symbol for parameter %s not found", p); - return 0; - } - - loc = (int *) (f->sections[sym->secidx]->contents + sym->value); - - /* Do C quoting if we begin with a ". */ - if (*q == '"') { - char *r, *str; - - str = alloca(strlen(q)); - for (r = str, q++; *q != '"'; ++q, ++r) { - if (*q == '\0') { - error_msg("improperly terminated string argument for %s", p); - return 0; - } else if (*q == '\\') - switch (*++q) { - case 'a': - *r = '\a'; - break; - case 'b': - *r = '\b'; - break; - case 'e': - *r = '\033'; - break; - case 'f': - *r = '\f'; - break; - case 'n': - *r = '\n'; - break; - case 'r': - *r = '\r'; - break; - case 't': - *r = '\t'; - break; - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - { - int c = *q - '0'; - if (q[1] >= '0' && q[1] <= '7') { - c = (c * 8) + *++q - '0'; - if (q[1] >= '0' && q[1] <= '7') - c = (c * 8) + *++q - '0'; - } - *r = c; - } - break; - - default: - *r = *q; - break; - } else - *r = *q; - } - *r = '\0'; - obj_string_patch(f, sym->secidx, sym->value, str); - } else if (*q >= '0' && *q <= '9') { - do - *loc++ = strtoul(q, &q, 0); - while (*q++ == ','); - } else { - char *contents = f->sections[sym->secidx]->contents; - char *myloc = contents + sym->value; - char *r; /* To search for commas */ - - /* Break the string with comas */ - while ((r = strchr(q, ',')) != (char *) NULL) { - *r++ = '\0'; - obj_string_patch(f, sym->secidx, myloc - contents, q); - myloc += sizeof(char *); - q = r; - } - - /* last part */ - obj_string_patch(f, sym->secidx, myloc - contents, q); - } - - argc--, argv++; - } - - return 1; -} - -#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING -static int old_is_module_checksummed(struct obj_file *f) -{ - return obj_find_symbol(f, "Using_Versions") != NULL; -} -/* Get the module's kernel version in the canonical integer form. */ - -static int -old_get_module_version(struct obj_file *f, char str[STRVERSIONLEN]) -{ - struct obj_symbol *sym; - char *p, *q; - int a, b, c; - - sym = obj_find_symbol(f, "kernel_version"); - if (sym == NULL) - return -1; - - p = f->sections[sym->secidx]->contents + sym->value; - strncpy(str, p, STRVERSIONLEN); - - a = strtoul(p, &p, 10); - if (*p != '.') - return -1; - b = strtoul(p + 1, &p, 10); - if (*p != '.') - return -1; - c = strtoul(p + 1, &q, 10); - if (p + 1 == q) - return -1; - - return a << 16 | b << 8 | c; -} - -#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */ - -#ifdef BB_FEATURE_OLD_MODULE_INTERFACE - -/* Fetch all the symbols and divvy them up as appropriate for the modules. */ - -static int old_get_kernel_symbols(const char *m_name) -{ - struct old_kernel_sym *ks, *k; - struct new_module_symbol *s; - struct external_module *mod; - int nks, nms, nmod, i; - - nks = get_kernel_syms(NULL); - if (nks <= 0) { - if (nks) - perror_msg("get_kernel_syms: %s", m_name); - else - error_msg("No kernel symbols"); - return 0; - } - - ks = k = xmalloc(nks * sizeof(*ks)); - - if (get_kernel_syms(ks) != nks) { - perror("inconsistency with get_kernel_syms -- is someone else " - "playing with modules?"); - free(ks); - return 0; - } - - /* Collect the module information. */ - - mod = NULL; - nmod = -1; - - while (k->name[0] == '#' && k->name[1]) { - struct old_kernel_sym *k2; - - /* Find out how many symbols this module has. */ - for (k2 = k + 1; k2->name[0] != '#'; ++k2) - continue; - nms = k2 - k - 1; - - mod = xrealloc(mod, (++nmod + 1) * sizeof(*mod)); - mod[nmod].name = k->name + 1; - mod[nmod].addr = k->value; - mod[nmod].used = 0; - mod[nmod].nsyms = nms; - mod[nmod].syms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL); - - for (i = 0, ++k; i < nms; ++i, ++s, ++k) { - s->name = (unsigned long) k->name; - s->value = k->value; - } - - k = k2; - } - - ext_modules = mod; - n_ext_modules = nmod + 1; - - /* Now collect the symbols for the kernel proper. */ - - if (k->name[0] == '#') - ++k; - - nksyms = nms = nks - (k - ks); - ksyms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL); - - for (i = 0; i < nms; ++i, ++s, ++k) { - s->name = (unsigned long) k->name; - s->value = k->value; - } - - return 1; -} - -/* Return the kernel symbol checksum version, or zero if not used. */ - -static int old_is_kernel_checksummed(void) -{ - /* Using_Versions is the first symbol. */ - if (nksyms > 0 - && strcmp((char *) ksyms[0].name, - "Using_Versions") == 0) return ksyms[0].value; - else - return 0; -} - - -static int old_create_mod_use_count(struct obj_file *f) -{ - struct obj_section *sec; - - sec = obj_create_alloced_section_first(f, ".moduse", sizeof(long), - sizeof(long)); - - obj_add_symbol(f, "mod_use_count_", -1, - ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0, - sizeof(long)); - - return 1; -} - -static int -old_init_module(const char *m_name, struct obj_file *f, - unsigned long m_size) -{ - char *image; - struct old_mod_routines routines; - struct old_symbol_table *symtab; - int ret; - - /* Create the symbol table */ - { - int nsyms = 0, strsize = 0, total; - - /* Size things first... */ - if (flag_export) { - int i; - for (i = 0; i < HASH_BUCKETS; ++i) { - struct obj_symbol *sym; - for (sym = f->symtab[i]; sym; sym = sym->next) - if (ELFW(ST_BIND) (sym->info) != STB_LOCAL - && sym->secidx <= SHN_HIRESERVE) - { - sym->ksymidx = nsyms++; - strsize += strlen(sym->name) + 1; - } - } - } - - total = (sizeof(struct old_symbol_table) - + nsyms * sizeof(struct old_module_symbol) - + n_ext_modules_used * sizeof(struct old_module_ref) - + strsize); - symtab = xmalloc(total); - symtab->size = total; - symtab->n_symbols = nsyms; - symtab->n_refs = n_ext_modules_used; - - if (flag_export && nsyms) { - struct old_module_symbol *ksym; - char *str; - int i; - - ksym = symtab->symbol; - str = ((char *) ksym + nsyms * sizeof(struct old_module_symbol) - + n_ext_modules_used * sizeof(struct old_module_ref)); - - for (i = 0; i < HASH_BUCKETS; ++i) { - struct obj_symbol *sym; - for (sym = f->symtab[i]; sym; sym = sym->next) - if (sym->ksymidx >= 0) { - ksym->addr = obj_symbol_final_value(f, sym); - ksym->name = - (unsigned long) str - (unsigned long) symtab; - - strcpy(str, sym->name); - str += strlen(sym->name) + 1; - ksym++; - } - } - } - - if (n_ext_modules_used) { - struct old_module_ref *ref; - int i; - - ref = (struct old_module_ref *) - ((char *) symtab->symbol + nsyms * sizeof(struct old_module_symbol)); - - for (i = 0; i < n_ext_modules; ++i) - if (ext_modules[i].used) - ref++->module = ext_modules[i].addr; - } - } - - /* Fill in routines. */ - - routines.init = - obj_symbol_final_value(f, obj_find_symbol(f, "init_module")); - routines.cleanup = - obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module")); - - /* Whew! All of the initialization is complete. Collect the final - module image and give it to the kernel. */ - - image = xmalloc(m_size); - obj_create_image(f, image); - - /* image holds the complete relocated module, accounting correctly for - mod_use_count. However the old module kernel support assume that - it is receiving something which does not contain mod_use_count. */ - ret = old_sys_init_module(m_name, image + sizeof(long), - m_size | (flag_autoclean ? OLD_MOD_AUTOCLEAN - : 0), &routines, symtab); - if (ret) - perror_msg("init_module: %s", m_name); - - free(image); - free(symtab); - - return ret == 0; -} - -#else - -#define old_create_mod_use_count(x) TRUE -#define old_init_module(x, y, z) TRUE - -#endif /* BB_FEATURE_OLD_MODULE_INTERFACE */ - - - -/*======================================================================*/ -/* Functions relating to module loading after 2.1.18. */ - -static int -new_process_module_arguments(struct obj_file *f, int argc, char **argv) -{ - while (argc > 0) { - char *p, *q, *key; - struct obj_symbol *sym; - char *contents, *loc; - int min, max, n; - - p = *argv; - if ((q = strchr(p, '=')) == NULL) { - argc--; - continue; - } - - key = alloca(q - p + 6); - memcpy(key, "parm_", 5); - memcpy(key + 5, p, q - p); - key[q - p + 5] = 0; - - p = get_modinfo_value(f, key); - key += 5; - if (p == NULL) { - error_msg("invalid parameter %s", key); - return 0; - } - - sym = obj_find_symbol(f, key); - - /* Also check that the parameter was not resolved from the kernel. */ - if (sym == NULL || sym->secidx > SHN_HIRESERVE) { - error_msg("symbol for parameter %s not found", key); - return 0; - } - - if (isdigit(*p)) { - min = strtoul(p, &p, 10); - if (*p == '-') - max = strtoul(p + 1, &p, 10); - else - max = min; - } else - min = max = 1; - - contents = f->sections[sym->secidx]->contents; - loc = contents + sym->value; - n = (*++q != '\0'); - - while (1) { - if ((*p == 's') || (*p == 'c')) { - char *str; - - /* Do C quoting if we begin with a ", else slurp the lot. */ - if (*q == '"') { - char *r; - - str = alloca(strlen(q)); - for (r = str, q++; *q != '"'; ++q, ++r) { - if (*q == '\0') { - error_msg("improperly terminated string argument for %s", - key); - return 0; - } else if (*q == '\\') - switch (*++q) { - case 'a': - *r = '\a'; - break; - case 'b': - *r = '\b'; - break; - case 'e': - *r = '\033'; - break; - case 'f': - *r = '\f'; - break; - case 'n': - *r = '\n'; - break; - case 'r': - *r = '\r'; - break; - case 't': - *r = '\t'; - break; - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - { - int c = *q - '0'; - if (q[1] >= '0' && q[1] <= '7') { - c = (c * 8) + *++q - '0'; - if (q[1] >= '0' && q[1] <= '7') - c = (c * 8) + *++q - '0'; - } - *r = c; - } - break; - - default: - *r = *q; - break; - } else - *r = *q; - } - *r = '\0'; - ++q; - } else { - char *r; - - /* In this case, the string is not quoted. We will break - it using the coma (like for ints). If the user wants to - include comas in a string, he just has to quote it */ - - /* Search the next coma */ - r = strchr(q, ','); - - /* Found ? */ - if (r != (char *) NULL) { - /* Recopy the current field */ - str = alloca(r - q + 1); - memcpy(str, q, r - q); - - /* I don't know if it is usefull, as the previous case - doesn't null terminate the string ??? */ - str[r - q] = '\0'; - - /* Keep next fields */ - q = r; - } else { - /* last string */ - str = q; - q = ""; - } - } - - if (*p == 's') { - /* Normal string */ - obj_string_patch(f, sym->secidx, loc - contents, str); - loc += tgt_sizeof_char_p; - } else { - /* Array of chars (in fact, matrix !) */ - unsigned long charssize; /* size of each member */ - - /* Get the size of each member */ - /* Probably we should do that outside the loop ? */ - if (!isdigit(*(p + 1))) { - error_msg("parameter type 'c' for %s must be followed by" - " the maximum size", key); - return 0; - } - charssize = strtoul(p + 1, (char **) NULL, 10); - - /* Check length */ - if (strlen(str) >= charssize) { - error_msg("string too long for %s (max %ld)", key, - charssize - 1); - return 0; - } - - /* Copy to location */ - strcpy((char *) loc, str); - loc += charssize; - } - } else { - long v = strtoul(q, &q, 0); - switch (*p) { - case 'b': - *loc++ = v; - break; - case 'h': - *(short *) loc = v; - loc += tgt_sizeof_short; - break; - case 'i': - *(int *) loc = v; - loc += tgt_sizeof_int; - break; - case 'l': - *(long *) loc = v; - loc += tgt_sizeof_long; - break; - - default: - error_msg("unknown parameter type '%c' for %s", *p, key); - return 0; - } - } - - retry_end_of_value: - switch (*q) { - case '\0': - goto end_of_arg; - - case ' ': - case '\t': - case '\n': - case '\r': - ++q; - goto retry_end_of_value; - - case ',': - if (++n > max) { - error_msg("too many values for %s (max %d)", key, max); - return 0; - } - ++q; - break; - - default: - error_msg("invalid argument syntax for %s", key); - return 0; - } - } - - end_of_arg: - if (n < min) { - error_msg("too few values for %s (min %d)", key, min); - return 0; - } - - argc--, argv++; - } - - return 1; -} - -#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING -static int new_is_module_checksummed(struct obj_file *f) -{ - const char *p = get_modinfo_value(f, "using_checksums"); - if (p) - return atoi(p); - else - return 0; -} - -/* Get the module's kernel version in the canonical integer form. */ - -static int -new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN]) -{ - char *p, *q; - int a, b, c; - - p = get_modinfo_value(f, "kernel_version"); - if (p == NULL) - return -1; - strncpy(str, p, STRVERSIONLEN); - - a = strtoul(p, &p, 10); - if (*p != '.') - return -1; - b = strtoul(p + 1, &p, 10); - if (*p != '.') - return -1; - c = strtoul(p + 1, &q, 10); - if (p + 1 == q) - return -1; - - return a << 16 | b << 8 | c; -} - -#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */ - - -#ifdef BB_FEATURE_NEW_MODULE_INTERFACE - -/* Fetch the loaded modules, and all currently exported symbols. */ - -static int new_get_kernel_symbols(void) -{ - char *module_names, *mn; - struct external_module *modules, *m; - struct new_module_symbol *syms, *s; - size_t ret, bufsize, nmod, nsyms, i, j; - - /* Collect the loaded modules. */ - - module_names = xmalloc(bufsize = 256); - retry_modules_load: - if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) { - if (errno == ENOSPC && bufsize < ret) { - module_names = xrealloc(module_names, bufsize = ret); - goto retry_modules_load; - } - perror_msg("QM_MODULES"); - return 0; - } - - n_ext_modules = nmod = ret; - - /* Collect the modules' symbols. */ - - if (nmod){ - ext_modules = modules = xmalloc(nmod * sizeof(*modules)); - memset(modules, 0, nmod * sizeof(*modules)); - for (i = 0, mn = module_names, m = modules; - i < nmod; ++i, ++m, mn += strlen(mn) + 1) { - struct new_module_info info; - - if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) { - if (errno == ENOENT) { - /* The module was removed out from underneath us. */ - continue; - } - perror_msg("query_module: QM_INFO: %s", mn); - return 0; - } - - syms = xmalloc(bufsize = 1024); - retry_mod_sym_load: - if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) { - switch (errno) { - case ENOSPC: - syms = xrealloc(syms, bufsize = ret); - goto retry_mod_sym_load; - case ENOENT: - /* The module was removed out from underneath us. */ - continue; - default: - perror_msg("query_module: QM_SYMBOLS: %s", mn); - return 0; - } - } - nsyms = ret; - - m->name = mn; - m->addr = info.addr; - m->nsyms = nsyms; - m->syms = syms; - - for (j = 0, s = syms; j < nsyms; ++j, ++s) { - s->name += (unsigned long) syms; - } - } - } - - /* Collect the kernel's symbols. */ - - syms = xmalloc(bufsize = 16 * 1024); - retry_kern_sym_load: - if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) { - if (errno == ENOSPC && bufsize < ret) { - syms = xrealloc(syms, bufsize = ret); - goto retry_kern_sym_load; - } - perror_msg("kernel: QM_SYMBOLS"); - return 0; - } - nksyms = nsyms = ret; - ksyms = syms; - - for (j = 0, s = syms; j < nsyms; ++j, ++s) { - s->name += (unsigned long) syms; - } - return 1; -} - - -/* Return the kernel symbol checksum version, or zero if not used. */ - -static int new_is_kernel_checksummed(void) -{ - struct new_module_symbol *s; - size_t i; - - /* Using_Versions is not the first symbol, but it should be in there. */ - - for (i = 0, s = ksyms; i < nksyms; ++i, ++s) - if (strcmp((char *) s->name, "Using_Versions") == 0) - return s->value; - - return 0; -} - - -static int new_create_this_module(struct obj_file *f, const char *m_name) -{ - struct obj_section *sec; - - sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long, - sizeof(struct new_module)); - memset(sec->contents, 0, sizeof(struct new_module)); - - obj_add_symbol(f, "__this_module", -1, - ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0, - sizeof(struct new_module)); - - obj_string_patch(f, sec->idx, offsetof(struct new_module, name), - m_name); - - return 1; -} - - -static int new_create_module_ksymtab(struct obj_file *f) -{ - struct obj_section *sec; - int i; - - /* We must always add the module references. */ - - if (n_ext_modules_used) { - struct new_module_ref *dep; - struct obj_symbol *tm; - - sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p, - (sizeof(struct new_module_ref) - * n_ext_modules_used)); - if (!sec) - return 0; - - tm = obj_find_symbol(f, "__this_module"); - dep = (struct new_module_ref *) sec->contents; - for (i = 0; i < n_ext_modules; ++i) - if (ext_modules[i].used) { - dep->dep = ext_modules[i].addr; - obj_symbol_patch(f, sec->idx, - (char *) &dep->ref - sec->contents, tm); - dep->next_ref = 0; - ++dep; - } - } - - if (flag_export && !obj_find_section(f, "__ksymtab")) { - size_t nsyms; - int *loaded; - - sec = - obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p, - 0); - - /* We don't want to export symbols residing in sections that - aren't loaded. There are a number of these created so that - we make sure certain module options don't appear twice. */ - - loaded = alloca(sizeof(int) * (i = f->header.e_shnum)); - while (--i >= 0) - loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0; - - for (nsyms = i = 0; i < HASH_BUCKETS; ++i) { - struct obj_symbol *sym; - for (sym = f->symtab[i]; sym; sym = sym->next) - if (ELFW(ST_BIND) (sym->info) != STB_LOCAL - && sym->secidx <= SHN_HIRESERVE - && (sym->secidx >= SHN_LORESERVE - || loaded[sym->secidx])) { - ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p; - - obj_symbol_patch(f, sec->idx, ofs, sym); - obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, - sym->name); - - nsyms++; - } - } - - obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p); - } - - return 1; -} - - -static int -new_init_module(const char *m_name, struct obj_file *f, - unsigned long m_size) -{ - struct new_module *module; - struct obj_section *sec; - void *image; - int ret; - tgt_long m_addr; - - sec = obj_find_section(f, ".this"); - if (!sec || !sec->contents) { - perror_msg_and_die("corrupt module %s?",m_name); - } - module = (struct new_module *) sec->contents; - m_addr = sec->header.sh_addr; - - module->size_of_struct = sizeof(*module); - module->size = m_size; - module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0; - - sec = obj_find_section(f, "__ksymtab"); - if (sec && sec->header.sh_size) { - module->syms = sec->header.sh_addr; - module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p); - } - - if (n_ext_modules_used) { - sec = obj_find_section(f, ".kmodtab"); - module->deps = sec->header.sh_addr; - module->ndeps = n_ext_modules_used; - } - - module->init = - obj_symbol_final_value(f, obj_find_symbol(f, "init_module")); - module->cleanup = - obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module")); - - sec = obj_find_section(f, "__ex_table"); - if (sec) { - module->ex_table_start = sec->header.sh_addr; - module->ex_table_end = sec->header.sh_addr + sec->header.sh_size; - } - - sec = obj_find_section(f, ".text.init"); - if (sec) { - module->runsize = sec->header.sh_addr - m_addr; - } - sec = obj_find_section(f, ".data.init"); - if (sec) { - if (!module->runsize || - module->runsize > sec->header.sh_addr - m_addr) - module->runsize = sec->header.sh_addr - m_addr; - } - sec = obj_find_section(f, ARCHDATA_SEC_NAME); - if (sec && sec->header.sh_size) { - module->archdata_start = (void*)sec->header.sh_addr; - module->archdata_end = module->archdata_start + sec->header.sh_size; - } - sec = obj_find_section(f, KALLSYMS_SEC_NAME); - if (sec && sec->header.sh_size) { - module->kallsyms_start = (void*)sec->header.sh_addr; - module->kallsyms_end = module->kallsyms_start + sec->header.sh_size; - } - - if (!arch_init_module(f, module)) - return 0; - - /* Whew! All of the initialization is complete. Collect the final - module image and give it to the kernel. */ - - image = xmalloc(m_size); - obj_create_image(f, image); - - ret = new_sys_init_module(m_name, (struct new_module *) image); - if (ret) - perror_msg("init_module: %s", m_name); - - free(image); - - return ret == 0; -} - -#else - -#define new_init_module(x, y, z) TRUE -#define new_create_this_module(x, y) 0 -#define new_create_module_ksymtab(x) -#define query_module(v, w, x, y, z) -1 - -#endif /* BB_FEATURE_NEW_MODULE_INTERFACE */ - - -/*======================================================================*/ - -static int -obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, - const char *string) -{ - struct obj_string_patch *p; - struct obj_section *strsec; - size_t len = strlen(string) + 1; - char *loc; - - p = xmalloc(sizeof(*p)); - p->next = f->string_patches; - p->reloc_secidx = secidx; - p->reloc_offset = offset; - f->string_patches = p; - - strsec = obj_find_section(f, ".kstrtab"); - if (strsec == NULL) { - strsec = obj_create_alloced_section(f, ".kstrtab", 1, len); - p->string_offset = 0; - loc = strsec->contents; - } else { - p->string_offset = strsec->header.sh_size; - loc = obj_extend_section(strsec, len); - } - memcpy(loc, string, len); - - return 1; -} - -static int -obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset, - struct obj_symbol *sym) -{ - struct obj_symbol_patch *p; - - p = xmalloc(sizeof(*p)); - p->next = f->symbol_patches; - p->reloc_secidx = secidx; - p->reloc_offset = offset; - p->sym = sym; - f->symbol_patches = p; - - return 1; -} - -static int obj_check_undefineds(struct obj_file *f) -{ - unsigned long i; - int ret = 1; - - for (i = 0; i < HASH_BUCKETS; ++i) { - struct obj_symbol *sym; - for (sym = f->symtab[i]; sym; sym = sym->next) - if (sym->secidx == SHN_UNDEF) { - if (ELFW(ST_BIND) (sym->info) == STB_WEAK) { - sym->secidx = SHN_ABS; - sym->value = 0; - } else { - error_msg("unresolved symbol %s", sym->name); - ret = 0; - } - } - } - - return ret; -} - -static void obj_allocate_commons(struct obj_file *f) -{ - struct common_entry { - struct common_entry *next; - struct obj_symbol *sym; - } *common_head = NULL; - - unsigned long i; - - for (i = 0; i < HASH_BUCKETS; ++i) { - struct obj_symbol *sym; - for (sym = f->symtab[i]; sym; sym = sym->next) - if (sym->secidx == SHN_COMMON) { - /* Collect all COMMON symbols and sort them by size so as to - minimize space wasted by alignment requirements. */ - { - struct common_entry **p, *n; - for (p = &common_head; *p; p = &(*p)->next) - if (sym->size <= (*p)->sym->size) - break; - - n = alloca(sizeof(*n)); - n->next = *p; - n->sym = sym; - *p = n; - } - } - } - - for (i = 1; i < f->local_symtab_size; ++i) { - struct obj_symbol *sym = f->local_symtab[i]; - if (sym && sym->secidx == SHN_COMMON) { - struct common_entry **p, *n; - for (p = &common_head; *p; p = &(*p)->next) - if (sym == (*p)->sym) - break; - else if (sym->size < (*p)->sym->size) { - n = alloca(sizeof(*n)); - n->next = *p; - n->sym = sym; - *p = n; - break; - } - } - } - - if (common_head) { - /* Find the bss section. */ - for (i = 0; i < f->header.e_shnum; ++i) - if (f->sections[i]->header.sh_type == SHT_NOBITS) - break; - - /* If for some reason there hadn't been one, create one. */ - if (i == f->header.e_shnum) { - struct obj_section *sec; - - f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec)); - f->sections[i] = sec = arch_new_section(); - f->header.e_shnum = i + 1; - - memset(sec, 0, sizeof(*sec)); - sec->header.sh_type = SHT_PROGBITS; - sec->header.sh_flags = SHF_WRITE | SHF_ALLOC; - sec->name = ".bss"; - sec->idx = i; - } - - /* Allocate the COMMONS. */ - { - ElfW(Addr) bss_size = f->sections[i]->header.sh_size; - ElfW(Addr) max_align = f->sections[i]->header.sh_addralign; - struct common_entry *c; - - for (c = common_head; c; c = c->next) { - ElfW(Addr) align = c->sym->value; - - if (align > max_align) - max_align = align; - if (bss_size & (align - 1)) - bss_size = (bss_size | (align - 1)) + 1; - - c->sym->secidx = i; - c->sym->value = bss_size; - - bss_size += c->sym->size; - } - - f->sections[i]->header.sh_size = bss_size; - f->sections[i]->header.sh_addralign = max_align; - } - } - - /* For the sake of patch relocation and parameter initialization, - allocate zeroed data for NOBITS sections now. Note that after - this we cannot assume NOBITS are really empty. */ - for (i = 0; i < f->header.e_shnum; ++i) { - struct obj_section *s = f->sections[i]; - if (s->header.sh_type == SHT_NOBITS) { - if (s->header.sh_size != 0) - s->contents = memset(xmalloc(s->header.sh_size), - 0, s->header.sh_size); - else - s->contents = NULL; - - s->header.sh_type = SHT_PROGBITS; - } - } -} - -static unsigned long obj_load_size(struct obj_file *f) -{ - unsigned long dot = 0; - struct obj_section *sec; - - /* Finalize the positions of the sections relative to one another. */ - - for (sec = f->load_order; sec; sec = sec->load_next) { - ElfW(Addr) align; - - align = sec->header.sh_addralign; - if (align && (dot & (align - 1))) - dot = (dot | (align - 1)) + 1; - - sec->header.sh_addr = dot; - dot += sec->header.sh_size; - } - - return dot; -} - -static int obj_relocate(struct obj_file *f, ElfW(Addr) base) -{ - int i, n = f->header.e_shnum; - int ret = 1; - - /* Finalize the addresses of the sections. */ - - f->baseaddr = base; - for (i = 0; i < n; ++i) - f->sections[i]->header.sh_addr += base; - - /* And iterate over all of the relocations. */ - - for (i = 0; i < n; ++i) { - struct obj_section *relsec, *symsec, *targsec, *strsec; - ElfW(RelM) * rel, *relend; - ElfW(Sym) * symtab; - const char *strtab; - - relsec = f->sections[i]; - if (relsec->header.sh_type != SHT_RELM) - continue; - - symsec = f->sections[relsec->header.sh_link]; - targsec = f->sections[relsec->header.sh_info]; - strsec = f->sections[symsec->header.sh_link]; - - rel = (ElfW(RelM) *) relsec->contents; - relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM))); - symtab = (ElfW(Sym) *) symsec->contents; - strtab = (const char *) strsec->contents; - - for (; rel < relend; ++rel) { - ElfW(Addr) value = 0; - struct obj_symbol *intsym = NULL; - unsigned long symndx; - ElfW(Sym) * extsym = 0; - const char *errmsg; - - /* Attempt to find a value to use for this relocation. */ - - symndx = ELFW(R_SYM) (rel->r_info); - if (symndx) { - /* Note we've already checked for undefined symbols. */ - - extsym = &symtab[symndx]; - if (ELFW(ST_BIND) (extsym->st_info) == STB_LOCAL) { - /* Local symbols we look up in the local table to be sure - we get the one that is really intended. */ - intsym = f->local_symtab[symndx]; - } else { - /* Others we look up in the hash table. */ - const char *name; - if (extsym->st_name) - name = strtab + extsym->st_name; - else - name = f->sections[extsym->st_shndx]->name; - intsym = obj_find_symbol(f, name); - } - - value = obj_symbol_final_value(f, intsym); - intsym->referenced = 1; - } -#if SHT_RELM == SHT_RELA -#if defined(__alpha__) && defined(AXP_BROKEN_GAS) - /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */ - if (!extsym || !extsym->st_name || - ELFW(ST_BIND) (extsym->st_info) != STB_LOCAL) -#endif - value += rel->r_addend; -#endif - - /* Do it! */ - switch (arch_apply_relocation - (f, targsec, symsec, intsym, rel, value)) { - case obj_reloc_ok: - break; - - case obj_reloc_overflow: - errmsg = "Relocation overflow"; - goto bad_reloc; - case obj_reloc_dangerous: - errmsg = "Dangerous relocation"; - goto bad_reloc; - case obj_reloc_unhandled: - errmsg = "Unhandled relocation"; - bad_reloc: - if (extsym) { - error_msg("%s of type %ld for %s", errmsg, - (long) ELFW(R_TYPE) (rel->r_info), - strtab + extsym->st_name); - } else { - error_msg("%s of type %ld", errmsg, - (long) ELFW(R_TYPE) (rel->r_info)); - } - ret = 0; - break; - } - } - } - - /* Finally, take care of the patches. */ - - if (f->string_patches) { - struct obj_string_patch *p; - struct obj_section *strsec; - ElfW(Addr) strsec_base; - strsec = obj_find_section(f, ".kstrtab"); - strsec_base = strsec->header.sh_addr; - - for (p = f->string_patches; p; p = p->next) { - struct obj_section *targsec = f->sections[p->reloc_secidx]; - *(ElfW(Addr) *) (targsec->contents + p->reloc_offset) - = strsec_base + p->string_offset; - } - } - - if (f->symbol_patches) { - struct obj_symbol_patch *p; - - for (p = f->symbol_patches; p; p = p->next) { - struct obj_section *targsec = f->sections[p->reloc_secidx]; - *(ElfW(Addr) *) (targsec->contents + p->reloc_offset) - = obj_symbol_final_value(f, p->sym); - } - } - - return ret; -} - -static int obj_create_image(struct obj_file *f, char *image) -{ - struct obj_section *sec; - ElfW(Addr) base = f->baseaddr; - - for (sec = f->load_order; sec; sec = sec->load_next) { - char *secimg; - - if (sec->contents == 0 || sec->header.sh_size == 0) - continue; - - secimg = image + (sec->header.sh_addr - base); - - /* Note that we allocated data for NOBITS sections earlier. */ - memcpy(secimg, sec->contents, sec->header.sh_size); - } - - return 1; -} - -/*======================================================================*/ - -static struct obj_file *obj_load(FILE * fp, int loadprogbits) -{ - struct obj_file *f; - ElfW(Shdr) * section_headers; - int shnum, i; - char *shstrtab; - - /* Read the file header. */ - - f = arch_new_file(); - memset(f, 0, sizeof(*f)); - f->symbol_cmp = strcmp; - f->symbol_hash = obj_elf_hash; - f->load_order_search_start = &f->load_order; - - fseek(fp, 0, SEEK_SET); - if (fread(&f->header, sizeof(f->header), 1, fp) != 1) { - perror_msg("error reading ELF header"); - return NULL; - } - - if (f->header.e_ident[EI_MAG0] != ELFMAG0 - || f->header.e_ident[EI_MAG1] != ELFMAG1 - || f->header.e_ident[EI_MAG2] != ELFMAG2 - || f->header.e_ident[EI_MAG3] != ELFMAG3) { - error_msg("not an ELF file"); - return NULL; - } - if (f->header.e_ident[EI_CLASS] != ELFCLASSM - || f->header.e_ident[EI_DATA] != ELFDATAM - || f->header.e_ident[EI_VERSION] != EV_CURRENT - || !MATCH_MACHINE(f->header.e_machine)) { - error_msg("ELF file not for this architecture"); - return NULL; - } - if (f->header.e_type != ET_REL) { - error_msg("ELF file not a relocatable object"); - return NULL; - } - - /* Read the section headers. */ - - if (f->header.e_shentsize != sizeof(ElfW(Shdr))) { - error_msg("section header size mismatch: %lu != %lu", - (unsigned long) f->header.e_shentsize, - (unsigned long) sizeof(ElfW(Shdr))); - return NULL; - } - - shnum = f->header.e_shnum; - f->sections = xmalloc(sizeof(struct obj_section *) * shnum); - memset(f->sections, 0, sizeof(struct obj_section *) * shnum); - - section_headers = alloca(sizeof(ElfW(Shdr)) * shnum); - fseek(fp, f->header.e_shoff, SEEK_SET); - if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) { - perror_msg("error reading ELF section headers"); - return NULL; - } - - /* Read the section data. */ - - for (i = 0; i < shnum; ++i) { - struct obj_section *sec; - - f->sections[i] = sec = arch_new_section(); - memset(sec, 0, sizeof(*sec)); - - sec->header = section_headers[i]; - sec->idx = i; - - if(sec->header.sh_size) switch (sec->header.sh_type) { - case SHT_NULL: - case SHT_NOTE: - case SHT_NOBITS: - /* ignore */ - break; - - case SHT_PROGBITS: -#if LOADBITS - if (!loadprogbits) { - sec->contents = NULL; - break; - } -#endif - case SHT_SYMTAB: - case SHT_STRTAB: - case SHT_RELM: - if (sec->header.sh_size > 0) { - sec->contents = xmalloc(sec->header.sh_size); - fseek(fp, sec->header.sh_offset, SEEK_SET); - if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) { - perror_msg("error reading ELF section data"); - return NULL; - } - } else { - sec->contents = NULL; - } - break; - -#if SHT_RELM == SHT_REL - case SHT_RELA: - error_msg("RELA relocations not supported on this architecture"); - return NULL; -#else - case SHT_REL: - error_msg("REL relocations not supported on this architecture"); - return NULL; -#endif - - default: - if (sec->header.sh_type >= SHT_LOPROC) { - /* Assume processor specific section types are debug - info and can safely be ignored. If this is ever not - the case (Hello MIPS?), don't put ifdefs here but - create an arch_load_proc_section(). */ - break; - } - - error_msg("can't handle sections of type %ld", - (long) sec->header.sh_type); - return NULL; - } - } - - /* Do what sort of interpretation as needed by each section. */ - - shstrtab = f->sections[f->header.e_shstrndx]->contents; - - for (i = 0; i < shnum; ++i) { - struct obj_section *sec = f->sections[i]; - sec->name = shstrtab + sec->header.sh_name; - } - - for (i = 0; i < shnum; ++i) { - struct obj_section *sec = f->sections[i]; - - /* .modinfo should be contents only but gcc has no attribute for that. - * The kernel may have marked .modinfo as ALLOC, ignore this bit. - */ - if (strcmp(sec->name, ".modinfo") == 0) - sec->header.sh_flags &= ~SHF_ALLOC; - - if (sec->header.sh_flags & SHF_ALLOC) - obj_insert_section_load_order(f, sec); - - switch (sec->header.sh_type) { - case SHT_SYMTAB: - { - unsigned long nsym, j; - char *strtab; - ElfW(Sym) * sym; - - if (sec->header.sh_entsize != sizeof(ElfW(Sym))) { - error_msg("symbol size mismatch: %lu != %lu", - (unsigned long) sec->header.sh_entsize, - (unsigned long) sizeof(ElfW(Sym))); - return NULL; - } - - nsym = sec->header.sh_size / sizeof(ElfW(Sym)); - strtab = f->sections[sec->header.sh_link]->contents; - sym = (ElfW(Sym) *) sec->contents; - - /* Allocate space for a table of local symbols. */ - j = f->local_symtab_size = sec->header.sh_info; - f->local_symtab = xcalloc(j, sizeof(struct obj_symbol *)); - - /* Insert all symbols into the hash table. */ - for (j = 1, ++sym; j < nsym; ++j, ++sym) { - const char *name; - if (sym->st_name) - name = strtab + sym->st_name; - else - name = f->sections[sym->st_shndx]->name; - - obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx, - sym->st_value, sym->st_size); - } - } - break; - - case SHT_RELM: - if (sec->header.sh_entsize != sizeof(ElfW(RelM))) { - error_msg("relocation entry size mismatch: %lu != %lu", - (unsigned long) sec->header.sh_entsize, - (unsigned long) sizeof(ElfW(RelM))); - return NULL; - } - break; - /* XXX Relocation code from modutils-2.3.19 is not here. - * Why? That's about 20 lines of code from obj/obj_load.c, - * which gets done in a second pass through the sections. - * This BusyBox insmod does similar work in obj_relocate(). */ - } - } - - return f; -} - -#ifdef BB_FEATURE_INSMOD_LOADINKMEM -/* - * load the unloaded sections directly into the memory allocated by - * kernel for the module - */ - -static int obj_load_progbits(FILE * fp, struct obj_file* f, char* imagebase) -{ - ElfW(Addr) base = f->baseaddr; - struct obj_section* sec; - - for (sec = f->load_order; sec; sec = sec->load_next) { - - /* section already loaded? */ - if (sec->contents != NULL) - continue; - - if (sec->header.sh_size == 0) - continue; - - sec->contents = imagebase + (sec->header.sh_addr - base); - fseek(fp, sec->header.sh_offset, SEEK_SET); - if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) { - error_msg("error reading ELF section data: %s\n", strerror(errno)); - return 0; - } - - } - return 1; -} -#endif - -static void hide_special_symbols(struct obj_file *f) -{ - static const char *const specials[] = { - "cleanup_module", - "init_module", - "kernel_version", - NULL - }; - - struct obj_symbol *sym; - const char *const *p; - - for (p = specials; *p; ++p) - if ((sym = obj_find_symbol(f, *p)) != NULL) - sym->info = - ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info)); -} - - - -extern int insmod_main( int argc, char **argv) -{ - int opt; - int k_crcs; - int k_new_syscalls; - int len; - char *tmp; - unsigned long m_size; - ElfW(Addr) m_addr; - FILE *fp; - struct obj_file *f; - struct stat st; - char m_name[FILENAME_MAX + 1] = "\0"; - int exit_status = EXIT_FAILURE; - int m_has_modinfo; -#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING - struct utsname uts_info; - char m_strversion[STRVERSIONLEN]; - int m_version; - int m_crcs; -#endif - - /* Parse any options */ - while ((opt = getopt(argc, argv, "fkvxLo:")) > 0) { - switch (opt) { - case 'f': /* force loading */ - flag_force_load = 1; - break; - case 'k': /* module loaded by kerneld, auto-cleanable */ - flag_autoclean = 1; - break; - case 'v': /* verbose output */ - flag_verbose = 1; - break; - case 'x': /* do not export externs */ - flag_export = 0; - break; - case 'o': /* name the output module */ - strncpy(m_name, optarg, FILENAME_MAX); - break; - case 'L': /* Stub warning */ - /* This is needed for compatibility with modprobe. - * In theory, this does locking, but we don't do - * that. So be careful and plan your life around not - * loading the same module 50 times concurrently. */ - break; - default: - show_usage(); - } - } - - if (argv[optind] == NULL) { - show_usage(); - } - - /* Grab the module name */ - if ((tmp = strrchr(argv[optind], '/')) != NULL) { - tmp++; - } else { - tmp = argv[optind]; - } - len = strlen(tmp); - - if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') - len -= 2; - memcpy(m_fullName, tmp, len); - m_fullName[len]='\0'; - if (*m_name == '\0') { - strcpy(m_name, m_fullName); - } - strcat(m_fullName, ".o"); - - /* Get a filedesc for the module. Check we we have a complete path */ - if (stat(argv[optind], &st) < 0 || !S_ISREG(st.st_mode) || - (fp = fopen(argv[optind], "r")) == NULL) { - struct utsname myuname; - - /* Hmm. Could not open it. First search under /lib/modules/`uname -r`, - * but do not error out yet if we fail to find it... */ - if (uname(&myuname) == 0) { - char module_dir[FILENAME_MAX]; - char real_module_dir[FILENAME_MAX]; - snprintf (module_dir, sizeof(module_dir), "%s/%s", - _PATH_MODULES, myuname.release); - /* Jump through hoops in case /lib/modules/`uname -r` - * is a symlink. We do not want recursive_action to - * follow symlinks, but we do want to follow the - * /lib/modules/`uname -r` dir, So resolve it ourselves - * if it is a link... */ - if (realpath (module_dir, real_module_dir) == NULL) - strcpy(real_module_dir, module_dir); - recursive_action(real_module_dir, TRUE, FALSE, FALSE, - check_module_name_match, 0, m_fullName); - } - - /* Check if we have found anything yet */ - if (m_filename[0] == '\0' || ((fp = fopen(m_filename, "r")) == NULL)) - { - char module_dir[FILENAME_MAX]; - if (realpath (_PATH_MODULES, module_dir) == NULL) - strcpy(module_dir, _PATH_MODULES); - /* No module found under /lib/modules/`uname -r`, this - * time cast the net a bit wider. Search /lib/modules/ */ - if (recursive_action(module_dir, TRUE, FALSE, FALSE, - check_module_name_match, 0, m_fullName) == FALSE) - { - if (m_filename[0] == '\0' - || ((fp = fopen(m_filename, "r")) == NULL)) - { - error_msg("%s: no module by that name found", m_fullName); - return EXIT_FAILURE; - } - } else - error_msg_and_die("%s: no module by that name found", m_fullName); - } - } else - safe_strncpy(m_filename, argv[optind], sizeof(m_filename)); - - printf("Using %s\n", m_filename); - - if ((f = obj_load(fp, LOADBITS)) == NULL) - perror_msg_and_die("Could not load the module"); - - if (get_modinfo_value(f, "kernel_version") == NULL) - m_has_modinfo = 0; - else - m_has_modinfo = 1; - -#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING - /* Version correspondence? */ - - if (uname(&uts_info) < 0) - uts_info.release[0] = '\0'; - if (m_has_modinfo) { - m_version = new_get_module_version(f, m_strversion); - } else { - m_version = old_get_module_version(f, m_strversion); - if (m_version == -1) { - error_msg("couldn't find the kernel version the module was " - "compiled for"); - goto out; - } - } - - if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) { - if (flag_force_load) { - error_msg("Warning: kernel-module version mismatch\n" - "\t%s was compiled for kernel version %s\n" - "\twhile this kernel is version %s", - m_filename, m_strversion, uts_info.release); - } else { - error_msg("kernel-module version mismatch\n" - "\t%s was compiled for kernel version %s\n" - "\twhile this kernel is version %s.", - m_filename, m_strversion, uts_info.release); - goto out; - } - } - k_crcs = 0; -#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */ - - k_new_syscalls = !query_module(NULL, 0, NULL, 0, NULL); - - if (k_new_syscalls) { -#ifdef BB_FEATURE_NEW_MODULE_INTERFACE - if (!new_get_kernel_symbols()) - goto out; - k_crcs = new_is_kernel_checksummed(); -#else - error_msg("Not configured to support new kernels"); - goto out; -#endif - } else { -#ifdef BB_FEATURE_OLD_MODULE_INTERFACE - if (!old_get_kernel_symbols(m_name)) - goto out; - k_crcs = old_is_kernel_checksummed(); -#else - error_msg("Not configured to support old kernels"); - goto out; -#endif - } - -#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING - if (m_has_modinfo) - m_crcs = new_is_module_checksummed(f); - else - m_crcs = old_is_module_checksummed(f); - - if (m_crcs != k_crcs) - obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash); -#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */ - - /* Let the module know about the kernel symbols. */ - add_kernel_symbols(f); - - /* Allocate common symbols, symbol tables, and string tables. */ - - if (k_new_syscalls - ? !new_create_this_module(f, m_name) - : !old_create_mod_use_count(f)) - { - goto out; - } - - if (!obj_check_undefineds(f)) { - goto out; - } - obj_allocate_commons(f); - - /* done with the module name, on to the optional var=value arguments */ - ++optind; - - if (optind < argc) { - if (m_has_modinfo - ? !new_process_module_arguments(f, argc - optind, argv + optind) - : !old_process_module_arguments(f, argc - optind, argv + optind)) - { - goto out; - } - } - - arch_create_got(f); - hide_special_symbols(f); - - if (k_new_syscalls) - new_create_module_ksymtab(f); - - /* Find current size of the module */ - m_size = obj_load_size(f); - - - m_addr = create_module(m_name, m_size); - if (m_addr==-1) switch (errno) { - case EEXIST: - error_msg("A module named %s already exists", m_name); - goto out; - case ENOMEM: - error_msg("Can't allocate kernel memory for module; needed %lu bytes", - m_size); - goto out; - default: - perror_msg("create_module: %s", m_name); - goto out; - } - -#if !LOADBITS - /* - * the PROGBITS section was not loaded by the obj_load - * now we can load them directly into the kernel memory - */ - if (!obj_load_progbits(fp, f, (char*)m_addr)) { - delete_module(m_name); - goto out; - } -#endif - - if (!obj_relocate(f, m_addr)) { - delete_module(m_name); - goto out; - } - - if (k_new_syscalls - ? !new_init_module(m_name, f, m_size) - : !old_init_module(m_name, f, m_size)) - { - delete_module(m_name); - goto out; - } - - exit_status = EXIT_SUCCESS; - -out: - fclose(fp); - return(exit_status); -} diff --git a/install.sh b/install.sh deleted file mode 100755 index d163a2ef8..000000000 --- a/install.sh +++ /dev/null @@ -1,52 +0,0 @@ -#!/bin/sh - -export LC_ALL=POSIX -export LC_CTYPE=POSIX - -prefix=$1 -if [ "$prefix" = "" ]; then - echo "No installation directory, aborting." - exit 1; -fi -if [ "$2" = "--hardlinks" ]; then - linkopts="-f" -else - linkopts="-fs" -fi -h=`sort busybox.links | uniq` - - -rm -f $prefix/bin/busybox || exit 1 -mkdir -p $prefix/bin || exit 1 -install -m 755 busybox $prefix/bin/busybox || exit 1 - -for i in $h ; do - appdir=`dirname $i` - mkdir -p $prefix/$appdir || exit 1 - if [ "$2" = "--hardlinks" ]; then - bb_path="$prefix/bin/busybox" - else - case "$appdir" in - /) - bb_path="bin/busybox" - ;; - /bin) - bb_path="busybox" - ;; - /sbin) - bb_path="../bin/busybox" - ;; - /usr/bin|/usr/sbin) - bb_path="../../bin/busybox" - ;; - *) - echo "Unknown installation directory: $appdir" - exit 1 - ;; - esac - fi - echo " $prefix$i -> $bb_path" - ln $linkopts $bb_path $prefix$i || exit 1 -done - -exit 0 diff --git a/kill.c b/kill.c deleted file mode 100644 index 3884ebdf4..000000000 --- a/kill.c +++ /dev/null @@ -1,142 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini kill/killall implementation for busybox - * - * Copyright (C) 1995, 1996 by Bruce Perens . - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" - -static const int KILL = 0; -static const int KILLALL = 1; - - -extern int kill_main(int argc, char **argv) -{ - int whichApp, sig = SIGTERM; - const char *name; - -#ifdef BB_KILLALL - /* Figure out what we are trying to do here */ - whichApp = (strcmp(applet_name, "killall") == 0)? KILLALL : KILL; -#else - whichApp = KILL; -#endif - - argc--; - argv++; - /* Parse any options */ - if (argc < 1) - show_usage(); - - while (argc > 0 && **argv == '-') { - while (*++(*argv)) { - switch (**argv) { - case 'l': - if(argc>1) { - for(argv++; *argv; argv++) { - name = u_signal_names(*argv, &sig, -1); - if(name!=NULL) - printf("%s\n", name); - } - } else { - int col = 0; - for(sig=1; sig < NSIG; sig++) { - name = u_signal_names(0, &sig, 1); - if(name==NULL) /* unnamed */ - continue; - col += printf("%2d) %-16s", sig, name); - if (col > 60) { - printf("\n"); - col = 0; - } - } - printf("\n"); - } - return EXIT_SUCCESS; - case '-': - show_usage(); - default: - name = u_signal_names(*argv, &sig, 0); - if(name==NULL) - error_msg_and_die( "bad signal name: %s", *argv); - argc--; - argv++; - goto do_it_now; - } - argc--; - argv++; - } - } - - do_it_now: - - if (whichApp == KILL) { - /* Looks like they want to do a kill. Do that */ - while (--argc >= 0) { - int pid; - - if (!isdigit(**argv)) - perror_msg_and_die( "Bad PID"); - pid = strtol(*argv, NULL, 0); - if (kill(pid, sig) != 0) - perror_msg_and_die( "Could not kill pid '%d'", pid); - argv++; - } - } -#ifdef BB_KILLALL - else { - int all_found = TRUE; - pid_t myPid=getpid(); - /* Looks like they want to do a killall. Do that */ - while (--argc >= 0) { - pid_t* pidList; - - pidList = find_pid_by_name( *argv); - if (!pidList || *pidList<=0) { - all_found = FALSE; - error_msg_and_die( "%s: no process killed", *argv); - } - - for(; pidList && *pidList!=0; pidList++) { - if (*pidList==myPid) - continue; - if (kill(*pidList, sig) != 0) - perror_msg_and_die( "Could not kill pid '%d'", *pidList); - } - /* Note that we don't bother to free the memory - * allocated in find_pid_by_name(). It will be freed - * upon exit, so we can save a byte or two */ - argv++; - } - if (all_found == FALSE) - return EXIT_FAILURE; - } -#endif - - return EXIT_SUCCESS; -} diff --git a/klogd.c b/klogd.c deleted file mode 100644 index d7b54e9c8..000000000 --- a/klogd.c +++ /dev/null @@ -1,153 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini klogd implementation for busybox - * - * Copyright (C) 2001 by Gennady Feldman . - * Changes: Made this a standalone busybox module which uses standalone - * syslog() client interface. - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , - * - * Copyright (C) 2000 by Karl M. Hegbloom - * - * "circular buffer" Copyright (C) 2000 by Gennady Feldman - * - * Maintainer: Gennady Feldman as of Mar 12, 2001 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include /* for our signal() handlers */ -#include /* strncpy() */ -#include /* errno and friends */ -#include -#include -#include - -#if __GNU_LIBRARY__ < 5 -# ifdef __alpha__ -# define klogctl syslog -# endif -#else -# include -#endif - -#include "busybox.h" - -static void klogd_signal(int sig) -{ - klogctl(7, NULL, 0); - klogctl(0, 0, 0); - //logMessage(0, "Kernel log daemon exiting."); - syslog_msg(LOG_DAEMON, 0, "Kernel log daemon exiting."); - exit(TRUE); -} - -static void doKlogd (void) __attribute__ ((noreturn)); -static void doKlogd (void) -{ - int priority = LOG_INFO; - char log_buffer[4096]; - int i, n, lastc; - char *start; - - /* Set up sig handlers */ - signal(SIGINT, klogd_signal); - signal(SIGKILL, klogd_signal); - signal(SIGTERM, klogd_signal); - signal(SIGHUP, SIG_IGN); - - /* "Open the log. Currently a NOP." */ - klogctl(1, NULL, 0); - - syslog_msg(LOG_DAEMON, 0, "klogd started: " BB_BANNER); - - while (1) { - /* Use kernel syscalls */ - memset(log_buffer, '\0', sizeof(log_buffer)); - n = klogctl(2, log_buffer, sizeof(log_buffer)); - if (n < 0) { - char message[80]; - - if (errno == EINTR) - continue; - snprintf(message, 79, "klogd: Error return from sys_sycall: %d - %s.\n", - errno, strerror(errno)); - syslog_msg(LOG_DAEMON, LOG_SYSLOG | LOG_ERR, message); - exit(1); - } - - /* klogctl buffer parsing modelled after code in dmesg.c */ - start=&log_buffer[0]; - lastc='\0'; - for (i=0; i') i++; - start = &log_buffer[i]; - } - if (log_buffer[i] == '\n') { - log_buffer[i] = '\0'; /* zero terminate this message */ - syslog_msg(LOG_DAEMON, LOG_KERN | priority, start); - start = &log_buffer[i+1]; - priority = LOG_INFO; - } - lastc = log_buffer[i]; - } - } -} - -extern int klogd_main(int argc, char **argv) -{ - /* no options, no getopt */ - int opt; - int doFork = TRUE; - - /* do normal option parsing */ - while ((opt = getopt(argc, argv, "n")) > 0) { - switch (opt) { - case 'n': - doFork = FALSE; - break; - default: - show_usage(); - } - } - - if (doFork == TRUE) { - if (daemon(0, 1) < 0) - perror_msg_and_die("daemon"); - } - doKlogd(); - - return EXIT_SUCCESS; -} - -/* -Local Variables -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ diff --git a/lash.c b/lash.c deleted file mode 100644 index ffdec8781..000000000 --- a/lash.c +++ /dev/null @@ -1,1640 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * lash -- the BusyBox Lame-Ass SHell - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , - * - * Based in part on ladsh.c by Michael K. Johnson and Erik W. Troan, which is - * under the following liberal license: "We have placed this source code in the - * public domain. Use it in any project, free or commercial." - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* This shell's parsing engine is officially at a dead-end. - * Future work shell work should be done using hush.c - */ - -//For debugging/development on the shell only... -//#define DEBUG_SHELL - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" -#include "cmdedit.h" - -#ifdef BB_LOCALE_SUPPORT -#include -#endif - -#include -#define expand_t glob_t - - -static const int MAX_READ = 128; /* size of input buffer for `read' builtin */ -#define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n" - - -enum redir_type { REDIRECT_INPUT, REDIRECT_OVERWRITE, - REDIRECT_APPEND -}; - -static const unsigned int DEFAULT_CONTEXT=0x1; -static const unsigned int IF_TRUE_CONTEXT=0x2; -static const unsigned int IF_FALSE_CONTEXT=0x4; -static const unsigned int THEN_EXP_CONTEXT=0x8; -static const unsigned int ELSE_EXP_CONTEXT=0x10; - - -struct jobset { - struct job *head; /* head of list of running jobs */ - struct job *fg; /* current foreground job */ -}; - -struct redir_struct { - enum redir_type type; /* type of redirection */ - int fd; /* file descriptor being redirected */ - char *filename; /* file to redirect fd to */ -}; - -struct child_prog { - pid_t pid; /* 0 if exited */ - char **argv; /* program name and arguments */ - int num_redirects; /* elements in redirection array */ - struct redir_struct *redirects; /* I/O redirects */ - int is_stopped; /* is the program currently running? */ - struct job *family; /* pointer back to the child's parent job */ -}; - -struct job { - int jobid; /* job number */ - int num_progs; /* total number of programs in job */ - int running_progs; /* number of programs running */ - char *text; /* name of job */ - char *cmdbuf; /* buffer various argv's point into */ - pid_t pgrp; /* process group ID for the job */ - struct child_prog *progs; /* array of programs in job */ - struct job *next; /* to track background commands */ - int stopped_progs; /* number of programs alive, but stopped */ - unsigned int job_context; /* bitmask defining current context */ - struct jobset *job_list; -}; - -struct built_in_command { - char *cmd; /* name */ - char *descr; /* description */ - int (*function) (struct child_prog *); /* function ptr */ -}; - -struct close_me { - int fd; - struct close_me *next; -}; - -/* function prototypes for builtins */ -static int builtin_cd(struct child_prog *cmd); -static int builtin_exec(struct child_prog *cmd); -static int builtin_exit(struct child_prog *cmd); -static int builtin_fg_bg(struct child_prog *cmd); -static int builtin_help(struct child_prog *cmd); -static int builtin_jobs(struct child_prog *dummy); -static int builtin_pwd(struct child_prog *dummy); -static int builtin_export(struct child_prog *cmd); -static int builtin_source(struct child_prog *cmd); -static int builtin_unset(struct child_prog *cmd); -static int builtin_read(struct child_prog *cmd); - - -/* function prototypes for shell stuff */ -static void mark_open(int fd); -static void mark_closed(int fd); -static void close_all(void); -static void checkjobs(struct jobset *job_list); -static void remove_job(struct jobset *j_list, struct job *job); -static int get_command(FILE * source, char *command); -static int parse_command(char **command_ptr, struct job *job, int *inbg); -static int run_command(struct job *newjob, int inbg, int outpipe[2]); -static int pseudo_exec(struct child_prog *cmd) __attribute__ ((noreturn)); -static int busy_loop(FILE * input); - - -/* Table of built-in functions (these are non-forking builtins, meaning they - * can change global variables in the parent shell process but they will not - * work with pipes and redirects; 'unset foo | whatever' will not work) */ -static struct built_in_command bltins[] = { - {"bg", "Resume a job in the background", builtin_fg_bg}, - {"cd", "Change working directory", builtin_cd}, - {"exec", "Exec command, replacing this shell with the exec'd process", builtin_exec}, - {"exit", "Exit from shell()", builtin_exit}, - {"fg", "Bring job into the foreground", builtin_fg_bg}, - {"jobs", "Lists the active jobs", builtin_jobs}, - {"export", "Set environment variable", builtin_export}, - {"unset", "Unset environment variable", builtin_unset}, - {"read", "Input environment variable", builtin_read}, - {".", "Source-in and run commands in a file", builtin_source}, - /* to do: add ulimit */ - {NULL, NULL, NULL} -}; - -/* Table of forking built-in functions (things that fork cannot change global - * variables in the parent process, such as the current working directory) */ -static struct built_in_command bltins_forking[] = { - {"pwd", "Print current directory", builtin_pwd}, - {"help", "List shell built-in commands", builtin_help}, - {NULL, NULL, NULL} -}; - - -static int shell_context; /* Type prompt trigger (PS1 or PS2) */ - - -/* Globals that are static to this file */ -static const char *cwd; -static char *local_pending_command = NULL; -static struct jobset job_list = { NULL, NULL }; -static int argc; -static char **argv; -static struct close_me *close_me_head; -static int last_return_code; -static int last_bg_pid; -static unsigned int last_jobid; -static int shell_terminal; -static pid_t shell_pgrp; -static char *PS1; -static char *PS2 = "> "; - - -#ifdef DEBUG_SHELL -static inline void debug_printf(const char *format, ...) -{ - va_list args; - va_start(args, format); - vfprintf(stderr, format, args); - va_end(args); -} -#else -static inline void debug_printf(const char *format, ...) { } -#endif - -/* - Most builtins need access to the struct child_prog that has - their arguments, previously coded as cmd->progs[0]. That coding - can exhibit a bug, if the builtin is not the first command in - a pipeline: "echo foo | exec sort" will attempt to exec foo. - -builtin previous use notes ------- ----------------- --------- -cd cmd->progs[0] -exec cmd->progs[0] squashed bug: didn't look for applets or forking builtins -exit cmd->progs[0] -fg_bg cmd->progs[0], job_list->head, job_list->fg -help 0 -jobs job_list->head -pwd 0 -export cmd->progs[0] -source cmd->progs[0] -unset cmd->progs[0] -read cmd->progs[0] - -I added "struct job *family;" to struct child_prog, -and switched API to builtin_foo(struct child_prog *child); -So cmd->text becomes child->family->text - cmd->job_context becomes child->family->job_context - cmd->progs[0] becomes *child - job_list becomes child->family->job_list - */ - -/* built-in 'cd ' handler */ -static int builtin_cd(struct child_prog *child) -{ - char *newdir; - - if (child->argv[1] == NULL) - newdir = getenv("HOME"); - else - newdir = child->argv[1]; - if (chdir(newdir)) { - printf("cd: %s: %m\n", newdir); - return EXIT_FAILURE; - } - cwd = xgetcwd((char *)cwd); - if (!cwd) - cwd = unknown; - return EXIT_SUCCESS; -} - -/* built-in 'exec' handler */ -static int builtin_exec(struct child_prog *child) -{ - if (child->argv[1] == NULL) - return EXIT_SUCCESS; /* Really? */ - child->argv++; - close_all(); - pseudo_exec(child); - /* never returns */ -} - -/* built-in 'exit' handler */ -static int builtin_exit(struct child_prog *child) -{ - if (child->argv[1] == NULL) - exit(EXIT_SUCCESS); - - exit (atoi(child->argv[1])); -} - -/* built-in 'fg' and 'bg' handler */ -static int builtin_fg_bg(struct child_prog *child) -{ - int i, jobnum; - struct job *job=NULL; - - /* If they gave us no args, assume they want the last backgrounded task */ - if (!child->argv[1]) { - for (job = child->family->job_list->head; job; job = job->next) { - if (job->jobid == last_jobid) { - break; - } - } - if (!job) { - error_msg("%s: no current job", child->argv[0]); - return EXIT_FAILURE; - } - } else { - if (sscanf(child->argv[1], "%%%d", &jobnum) != 1) { - error_msg("%s: bad argument '%s'", child->argv[0], child->argv[1]); - return EXIT_FAILURE; - } - for (job = child->family->job_list->head; job; job = job->next) { - if (job->jobid == jobnum) { - break; - } - } - if (!job) { - error_msg("%s: %d: no such job", child->argv[0], jobnum); - return EXIT_FAILURE; - } - } - - if (*child->argv[0] == 'f') { - /* Put the job into the foreground. */ - tcsetpgrp(shell_terminal, job->pgrp); - - child->family->job_list->fg = job; - } - - /* Restart the processes in the job */ - for (i = 0; i < job->num_progs; i++) - job->progs[i].is_stopped = 0; - - job->stopped_progs = 0; - - if ( (i=kill(- job->pgrp, SIGCONT)) < 0) { - if (i == ESRCH) { - remove_job(&job_list, job); - } else { - perror_msg("kill (SIGCONT)"); - } - } - - return EXIT_SUCCESS; -} - -/* built-in 'help' handler */ -static int builtin_help(struct child_prog *dummy) -{ - struct built_in_command *x; - - printf("\nBuilt-in commands:\n"); - printf("-------------------\n"); - for (x = bltins; x->cmd; x++) { - if (x->descr==NULL) - continue; - printf("%s\t%s\n", x->cmd, x->descr); - } - for (x = bltins_forking; x->cmd; x++) { - if (x->descr==NULL) - continue; - printf("%s\t%s\n", x->cmd, x->descr); - } - printf("\n\n"); - return EXIT_SUCCESS; -} - -/* built-in 'jobs' handler */ -static int builtin_jobs(struct child_prog *child) -{ - struct job *job; - char *status_string; - - for (job = child->family->job_list->head; job; job = job->next) { - if (job->running_progs == job->stopped_progs) - status_string = "Stopped"; - else - status_string = "Running"; - - printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->text); - } - return EXIT_SUCCESS; -} - - -/* built-in 'pwd' handler */ -static int builtin_pwd(struct child_prog *dummy) -{ - cwd = xgetcwd((char *)cwd); - if (!cwd) - cwd = unknown; - puts(cwd); - return EXIT_SUCCESS; -} - -/* built-in 'export VAR=value' handler */ -static int builtin_export(struct child_prog *child) -{ - int res; - char *v = child->argv[1]; - - if (v == NULL) { - char **e; - for (e = environ; *e; e++) { - puts(*e); - } - return 0; - } - res = putenv(v); - if (res) - fprintf(stderr, "export: %m\n"); -#ifdef BB_FEATURE_SH_FANCY_PROMPT - if (strncmp(v, "PS1=", 4)==0) - PS1 = getenv("PS1"); -#endif - -#ifdef BB_LOCALE_SUPPORT - if(strncmp(v, "LC_ALL=", 7)==0) - setlocale(LC_ALL, getenv("LC_ALL")); - if(strncmp(v, "LC_CTYPE=", 9)==0) - setlocale(LC_CTYPE, getenv("LC_CTYPE")); -#endif - - return (res); -} - -/* built-in 'read VAR' handler */ -static int builtin_read(struct child_prog *child) -{ - int res = 0, len, newlen; - char *s; - char string[MAX_READ]; - - if (child->argv[1]) { - /* argument (VAR) given: put "VAR=" into buffer */ - strcpy(string, child->argv[1]); - len = strlen(string); - string[len++] = '='; - string[len] = '\0'; - fgets(&string[len], sizeof(string) - len, stdin); /* read string */ - newlen = strlen(string); - if(newlen > len) - string[--newlen] = '\0'; /* chomp trailing newline */ - /* - ** string should now contain "VAR=" - ** copy it (putenv() won't do that, so we must make sure - ** the string resides in a static buffer!) - */ - res = -1; - if((s = strdup(string))) - res = putenv(s); - if (res) - fprintf(stderr, "read: %m\n"); - } - else - fgets(string, sizeof(string), stdin); - - return (res); -} - -/* Built-in '.' handler (read-in and execute commands from file) */ -static int builtin_source(struct child_prog *child) -{ - FILE *input; - int status; - int fd; - - if (child->argv[1] == NULL) - return EXIT_FAILURE; - - input = fopen(child->argv[1], "r"); - if (!input) { - printf( "Couldn't open file '%s'\n", child->argv[1]); - return EXIT_FAILURE; - } - - fd=fileno(input); - mark_open(fd); - /* Now run the file */ - status = busy_loop(input); - fclose(input); - mark_closed(fd); - return (status); -} - -/* built-in 'unset VAR' handler */ -static int builtin_unset(struct child_prog *child) -{ - if (child->argv[1] == NULL) { - printf( "unset: parameter required.\n"); - return EXIT_FAILURE; - } - unsetenv(child->argv[1]); - return EXIT_SUCCESS; -} - -static void mark_open(int fd) -{ - struct close_me *new = xmalloc(sizeof(struct close_me)); - new->fd = fd; - new->next = close_me_head; - close_me_head = new; -} - -static void mark_closed(int fd) -{ - struct close_me *tmp; - if (close_me_head == NULL || close_me_head->fd != fd) - error_msg_and_die("corrupt close_me"); - tmp = close_me_head; - close_me_head = close_me_head->next; - free(tmp); -} - -static void close_all() -{ - struct close_me *c, *tmp; - for (c=close_me_head; c; c=tmp) { - close(c->fd); - tmp=c->next; - free(c); - } - close_me_head = NULL; -} - - -/* free up all memory from a job */ -static void free_job(struct job *cmd) -{ - int i; - struct jobset *keep; - - for (i = 0; i < cmd->num_progs; i++) { - free(cmd->progs[i].argv); - if (cmd->progs[i].redirects) - free(cmd->progs[i].redirects); - } - if (cmd->progs) - free(cmd->progs); - if (cmd->text) - free(cmd->text); - if (cmd->cmdbuf) - free(cmd->cmdbuf); - keep = cmd->job_list; - memset(cmd, 0, sizeof(struct job)); - cmd->job_list = keep; -} - -/* remove a job from a jobset */ -static void remove_job(struct jobset *j_list, struct job *job) -{ - struct job *prevjob; - - free_job(job); - if (job == j_list->head) { - j_list->head = job->next; - } else { - prevjob = j_list->head; - while (prevjob->next != job) - prevjob = prevjob->next; - prevjob->next = job->next; - } - - if (j_list->head) - last_jobid = j_list->head->jobid; - else - last_jobid = 0; - - free(job); -} - -/* Checks to see if any background processes have exited -- if they - have, figure out why and see if a job has completed */ -static void checkjobs(struct jobset *j_list) -{ - struct job *job; - pid_t childpid; - int status; - int prognum = 0; - - while ((childpid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) { - for (job = j_list->head; job; job = job->next) { - prognum = 0; - while (prognum < job->num_progs && - job->progs[prognum].pid != childpid) prognum++; - if (prognum < job->num_progs) - break; - } - - /* This happens on backticked commands */ - if(job==NULL) - return; - - if (WIFEXITED(status) || WIFSIGNALED(status)) { - /* child exited */ - job->running_progs--; - job->progs[prognum].pid = 0; - - if (!job->running_progs) { - printf(JOB_STATUS_FORMAT, job->jobid, "Done", job->text); - last_jobid=0; - remove_job(j_list, job); - } - } else { - /* child stopped */ - job->stopped_progs++; - job->progs[prognum].is_stopped = 1; - -#if 0 - /* Printing this stuff is a pain, since it tends to - * overwrite the prompt an inconveinient moments. So - * don't do that. */ - if (job->stopped_progs == job->num_progs) { - printf(JOB_STATUS_FORMAT, job->jobid, "Stopped", - job->text); - } -#endif - } - } - - if (childpid == -1 && errno != ECHILD) - perror_msg("waitpid"); -} - -/* squirrel != NULL means we squirrel away copies of stdin, stdout, - * and stderr if they are redirected. */ -static int setup_redirects(struct child_prog *prog, int squirrel[]) -{ - int i; - int openfd; - int mode = O_RDONLY; - struct redir_struct *redir = prog->redirects; - - for (i = 0; i < prog->num_redirects; i++, redir++) { - switch (redir->type) { - case REDIRECT_INPUT: - mode = O_RDONLY; - break; - case REDIRECT_OVERWRITE: - mode = O_WRONLY | O_CREAT | O_TRUNC; - break; - case REDIRECT_APPEND: - mode = O_WRONLY | O_CREAT | O_APPEND; - break; - } - - openfd = open(redir->filename, mode, 0666); - if (openfd < 0) { - /* this could get lost if stderr has been redirected, but - bash and ash both lose it as well (though zsh doesn't!) */ - perror_msg("error opening %s", redir->filename); - return 1; - } - - if (openfd != redir->fd) { - if (squirrel && redir->fd < 3) { - squirrel[redir->fd] = dup(redir->fd); - } - dup2(openfd, redir->fd); - close(openfd); - } - } - - return 0; -} - -static void restore_redirects(int squirrel[]) -{ - int i, fd; - for (i=0; i<3; i++) { - fd = squirrel[i]; - if (fd != -1) { - /* No error checking. I sure wouldn't know what - * to do with an error if I found one! */ - dup2(fd, i); - close(fd); - } - } -} - -static inline void cmdedit_set_initial_prompt(void) -{ -#ifndef BB_FEATURE_SH_FANCY_PROMPT - PS1 = NULL; -#else - PS1 = getenv("PS1"); - if(PS1==0) - PS1 = "\\w \\$ "; -#endif -} - -static inline void setup_prompt_string(char **prompt_str) -{ -#ifndef BB_FEATURE_SH_FANCY_PROMPT - /* Set up the prompt */ - if (shell_context == 0) { - if (PS1) - free(PS1); - PS1=xmalloc(strlen(cwd)+4); - sprintf(PS1, "%s %s", cwd, ( geteuid() != 0 ) ? "$ ":"# "); - *prompt_str = PS1; - } else { - *prompt_str = PS2; - } -#else - *prompt_str = (shell_context==0)? PS1 : PS2; -#endif -} - -static int get_command(FILE * source, char *command) -{ - char *prompt_str; - - if (source == NULL) { - if (local_pending_command) { - /* a command specified (-c option): return it & mark it done */ - strcpy(command, local_pending_command); - free(local_pending_command); - local_pending_command = NULL; - return 0; - } - return 1; - } - - if (source == stdin) { - setup_prompt_string(&prompt_str); - -#ifdef BB_FEATURE_COMMAND_EDITING - /* - ** enable command line editing only while a command line - ** is actually being read; otherwise, we'll end up bequeathing - ** atexit() handlers and other unwanted stuff to our - ** child processes (rob@sysgo.de) - */ - cmdedit_read_input(prompt_str, command); - return 0; -#else - fputs(prompt_str, stdout); -#endif - } - - if (!fgets(command, BUFSIZ - 2, source)) { - if (source == stdin) - printf("\n"); - return 1; - } - - return 0; -} - -static char* itoa(register int i) -{ - static char a[7]; /* Max 7 ints */ - register char *b = a + sizeof(a) - 1; - int sign = (i < 0); - - if (sign) - i = -i; - *b = 0; - do - { - *--b = '0' + (i % 10); - i /= 10; - } - while (i); - if (sign) - *--b = '-'; - return b; -} - -char * strsep_space( char *string, int * ix) -{ - char *token, *begin; - - begin = string; - - /* Short circuit the trivial case */ - if ( !string || ! string[*ix]) - return NULL; - - /* Find the end of the token. */ - while( string && string[*ix] && !isspace(string[*ix]) ) { - (*ix)++; - } - - /* Find the end of any whitespace trailing behind - * the token and let that be part of the token */ - while( string && string[*ix] && isspace(string[*ix]) ) { - (*ix)++; - } - - if (! string && *ix==0) { - /* Nothing useful was found */ - return NULL; - } - - token = xmalloc(*ix+1); - token[*ix] = '\0'; - strncpy(token, string, *ix); - - return token; -} - -static int expand_arguments(char *command) -{ - int total_length=0, length, i, retval, ix = 0; - expand_t expand_result; - char *tmpcmd, *cmd, *cmd_copy; - char *src, *dst, *var; - const char *out_of_space = "out of space during expansion"; - int flags = GLOB_NOCHECK -#ifdef GLOB_BRACE - | GLOB_BRACE -#endif -#ifdef GLOB_TILDE - | GLOB_TILDE -#endif - ; - - /* get rid of the terminating \n */ - chomp(command); - - /* Fix up escape sequences to be the Real Thing(tm) */ - while( command && command[ix]) { - if (command[ix] == '\\') { - const char *tmp = command+ix+1; - command[ix] = process_escape_sequence( &tmp ); - memmove(command+ix + 1, tmp, strlen(tmp)+1); - } - ix++; - } - /* Use glob and then fixup environment variables and such */ - - /* It turns out that glob is very stupid. We have to feed it one word at a - * time since it can't cope with a full string. Here we convert command - * (char*) into cmd (char**, one word per string) */ - - /* We need a clean copy, so strsep can mess up the copy while - * we write stuff into the original (in a minute) */ - cmd = cmd_copy = strdup(command); - *command = '\0'; - for (ix = 0, tmpcmd = cmd; - (tmpcmd = strsep_space(cmd, &ix)) != NULL; cmd += ix, ix=0) { - if (*tmpcmd == '\0') - break; - /* we need to trim() the result for glob! */ - trim(tmpcmd); - retval = glob(tmpcmd, flags, NULL, &expand_result); - free(tmpcmd); /* Free mem allocated by strsep_space */ - if (retval == GLOB_NOSPACE) { - /* Mem may have been allocated... */ - globfree (&expand_result); - error_msg(out_of_space); - return FALSE; - } else if (retval != 0) { - /* Some other error. GLOB_NOMATCH shouldn't - * happen because of the GLOB_NOCHECK flag in - * the glob call. */ - error_msg("syntax error"); - return FALSE; - } else { - /* Convert from char** (one word per string) to a simple char*, - * but don't overflow command which is BUFSIZ in length */ - for (i=0; i < expand_result.gl_pathc; i++) { - length=strlen(expand_result.gl_pathv[i]); - if (total_length+length+1 >= BUFSIZ) { - error_msg(out_of_space); - return FALSE; - } - strcat(command+total_length, " "); - total_length+=1; - strcat(command+total_length, expand_result.gl_pathv[i]); - total_length+=length; - } - globfree (&expand_result); - } - } - free(cmd_copy); - trim(command); - - /* Now do the shell variable substitutions which - * wordexp can't do for us, namely $? and $! */ - src = command; - while((dst = strchr(src,'$')) != NULL){ - var = NULL; - switch(*(dst+1)) { - case '?': - var = itoa(last_return_code); - break; - case '!': - if (last_bg_pid==-1) - *(var)='\0'; - else - var = itoa(last_bg_pid); - break; - /* Everything else like $$, $#, $[0-9], etc. should all be - * expanded by wordexp(), so we can in theory skip that stuff - * here, but just to be on the safe side (i.e., since uClibc - * wordexp doesn't do this stuff yet), lets leave it in for - * now. */ - case '$': - var = itoa(getpid()); - break; - case '#': - var = itoa(argc-1); - break; - case '0':case '1':case '2':case '3':case '4': - case '5':case '6':case '7':case '8':case '9': - { - int ixx=*(dst + 1)-48; - if (ixx >= argc) { - var='\0'; - } else { - var = argv[ixx]; - } - } - break; - - } - if (var) { - /* a single character construction was found, and - * already handled in the case statement */ - src=dst+2; - } else { - /* Looks like an environment variable */ - char delim_hold; - int num_skip_chars=0; - int dstlen = strlen(dst); - /* Is this a ${foo} type variable? */ - if (dstlen >=2 && *(dst+1) == '{') { - src=strchr(dst+1, '}'); - num_skip_chars=1; - } else { - src=dst+1; - while(isalnum(*src) || *src=='_') src++; - } - if (src == NULL) { - src = dst+dstlen; - } - delim_hold=*src; - *src='\0'; /* temporary */ - var = getenv(dst + 1 + num_skip_chars); - *src=delim_hold; - src += num_skip_chars; - } - if (var == NULL) { - /* Seems we got an un-expandable variable. So delete it. */ - var = ""; - } - { - int subst_len = strlen(var); - int trail_len = strlen(src); - if (dst+subst_len+trail_len >= command+BUFSIZ) { - error_msg(out_of_space); - return FALSE; - } - /* Move stuff to the end of the string to accommodate - * filling the created gap with the new stuff */ - memmove(dst+subst_len, src, trail_len+1); - /* Now copy in the new stuff */ - memcpy(dst, var, subst_len); - src = dst+subst_len; - } - } - - return TRUE; -} - -/* Return cmd->num_progs as 0 if no command is present (e.g. an empty - line). If a valid command is found, command_ptr is set to point to - the beginning of the next command (if the original command had more - then one job associated with it) or NULL if no more commands are - present. */ -static int parse_command(char **command_ptr, struct job *job, int *inbg) -{ - char *command; - char *return_command = NULL; - char *src, *buf, *chptr; - int argc_l = 0; - int done = 0; - int argv_alloced; - int i, saw_quote = 0; - char quote = '\0'; - int count; - struct child_prog *prog; - - /* skip leading white space */ - while (**command_ptr && isspace(**command_ptr)) - (*command_ptr)++; - - /* this handles empty lines or leading '#' characters */ - if (!**command_ptr || (**command_ptr == '#')) { - job->num_progs=0; - return 0; - } - - *inbg = 0; - job->num_progs = 1; - job->progs = xmalloc(sizeof(*job->progs)); - - /* We set the argv elements to point inside of this string. The - memory is freed by free_job(). Allocate twice the original - length in case we need to quote every single character. - - Getting clean memory relieves us of the task of NULL - terminating things and makes the rest of this look a bit - cleaner (though it is, admittedly, a tad less efficient) */ - job->cmdbuf = command = xcalloc(2*strlen(*command_ptr) + 1, sizeof(char)); - job->text = NULL; - - prog = job->progs; - prog->num_redirects = 0; - prog->redirects = NULL; - prog->is_stopped = 0; - prog->family = job; - - argv_alloced = 5; - prog->argv = xmalloc(sizeof(*prog->argv) * argv_alloced); - prog->argv[0] = job->cmdbuf; - - buf = command; - src = *command_ptr; - while (*src && !done) { - if (quote == *src) { - quote = '\0'; - } else if (quote) { - if (*src == '\\') { - src++; - if (!*src) { - error_msg("character expected after \\"); - free_job(job); - return 1; - } - - /* in shell, "\'" should yield \' */ - if (*src != quote) { - *buf++ = '\\'; - *buf++ = '\\'; - } - } else if (*src == '*' || *src == '?' || *src == '[' || - *src == ']') *buf++ = '\\'; - *buf++ = *src; - } else if (isspace(*src)) { - if (*prog->argv[argc_l] || saw_quote) { - buf++, argc_l++; - /* +1 here leaves room for the NULL which ends argv */ - if ((argc_l + 1) == argv_alloced) { - argv_alloced += 5; - prog->argv = xrealloc(prog->argv, - sizeof(*prog->argv) * - argv_alloced); - } - prog->argv[argc_l] = buf; - saw_quote = 0; - } - } else - switch (*src) { - case '"': - case '\'': - quote = *src; - saw_quote = 1; - break; - - case '#': /* comment */ - if (*(src-1)== '$') - *buf++ = *src; - else - done = 1; - break; - - case '>': /* redirects */ - case '<': - i = prog->num_redirects++; - prog->redirects = xrealloc(prog->redirects, - sizeof(*prog->redirects) * - (i + 1)); - - prog->redirects[i].fd = -1; - if (buf != prog->argv[argc_l]) { - /* the stuff before this character may be the file number - being redirected */ - prog->redirects[i].fd = - strtol(prog->argv[argc_l], &chptr, 10); - - if (*chptr && *prog->argv[argc_l]) { - buf++, argc_l++; - prog->argv[argc_l] = buf; - } - } - - if (prog->redirects[i].fd == -1) { - if (*src == '>') - prog->redirects[i].fd = 1; - else - prog->redirects[i].fd = 0; - } - - if (*src++ == '>') { - if (*src == '>') - prog->redirects[i].type = - REDIRECT_APPEND, src++; - else - prog->redirects[i].type = REDIRECT_OVERWRITE; - } else { - prog->redirects[i].type = REDIRECT_INPUT; - } - - /* This isn't POSIX sh compliant. Oh well. */ - chptr = src; - while (isspace(*chptr)) - chptr++; - - if (!*chptr) { - error_msg("file name expected after %c", *(src-1)); - free_job(job); - job->num_progs=0; - return 1; - } - - prog->redirects[i].filename = buf; - while (*chptr && !isspace(*chptr)) - *buf++ = *chptr++; - - src = chptr - 1; /* we src++ later */ - prog->argv[argc_l] = ++buf; - break; - - case '|': /* pipe */ - /* finish this command */ - if (*prog->argv[argc_l] || saw_quote) - argc_l++; - if (!argc_l) { - error_msg("empty command in pipe"); - free_job(job); - job->num_progs=0; - return 1; - } - prog->argv[argc_l] = NULL; - - /* and start the next */ - job->num_progs++; - job->progs = xrealloc(job->progs, - sizeof(*job->progs) * job->num_progs); - prog = job->progs + (job->num_progs - 1); - prog->num_redirects = 0; - prog->redirects = NULL; - prog->is_stopped = 0; - prog->family = job; - argc_l = 0; - - argv_alloced = 5; - prog->argv = xmalloc(sizeof(*prog->argv) * argv_alloced); - prog->argv[0] = ++buf; - - src++; - while (*src && isspace(*src)) - src++; - - if (!*src) { - error_msg("empty command in pipe"); - free_job(job); - job->num_progs=0; - return 1; - } - src--; /* we'll ++ it at the end of the loop */ - - break; - - case '&': /* background */ - *inbg = 1; - case ';': /* multiple commands */ - done = 1; - return_command = *command_ptr + (src - *command_ptr) + 1; - break; - - case '\\': - src++; - if (!*src) { - error_msg("character expected after \\"); - free_job(job); - return 1; - } - if (*src == '*' || *src == '[' || *src == ']' - || *src == '?') *buf++ = '\\'; - /* fallthrough */ - default: - *buf++ = *src; - } - - src++; - } - - if (*prog->argv[argc_l] || saw_quote) { - argc_l++; - } - if (!argc_l) { - free_job(job); - return 0; - } - prog->argv[argc_l] = NULL; - - if (!return_command) { - job->text = xmalloc(strlen(*command_ptr) + 1); - strcpy(job->text, *command_ptr); - } else { - /* This leaves any trailing spaces, which is a bit sloppy */ - count = return_command - *command_ptr; - job->text = xmalloc(count + 1); - strncpy(job->text, *command_ptr, count); - job->text[count] = '\0'; - } - - *command_ptr = return_command; - - return 0; -} - -/* Run the child_prog, no matter what kind of command it uses. - */ -static int pseudo_exec(struct child_prog *child) -{ - struct built_in_command *x; -#ifdef BB_FEATURE_SH_STANDALONE_SHELL - char *name; -#endif - - /* Check if the command matches any of the non-forking builtins. - * Depending on context, this might be redundant. But it's - * easier to waste a few CPU cycles than it is to figure out - * if this is one of those cases. - */ - for (x = bltins; x->cmd; x++) { - if (strcmp(child->argv[0], x->cmd) == 0 ) { - exit(x->function(child)); - } - } - - /* Check if the command matches any of the forking builtins. */ - for (x = bltins_forking; x->cmd; x++) { - if (strcmp(child->argv[0], x->cmd) == 0) { - applet_name=x->cmd; - exit (x->function(child)); - } - } -#ifdef BB_FEATURE_SH_STANDALONE_SHELL - /* Check if the command matches any busybox internal - * commands ("applets") here. Following discussions from - * November 2000 on busybox@opensource.lineo.com, don't use - * get_last_path_component(). This way explicit (with - * slashes) filenames will never be interpreted as an - * applet, just like with builtins. This way the user can - * override an applet with an explicit filename reference. - * The only downside to this change is that an explicit - * /bin/foo invocation will fork and exec /bin/foo, even if - * /bin/foo is a symlink to busybox. - */ - name = child->argv[0]; - -#ifdef BB_FEATURE_SH_APPLETS_ALWAYS_WIN - /* If you enable BB_FEATURE_SH_APPLETS_ALWAYS_WIN, then - * if you run /bin/cat, it will use BusyBox cat even if - * /bin/cat exists on the filesystem and is _not_ busybox. - * Some systems want this, others do not. Choose wisely. :-) - */ - name = get_last_path_component(name); -#endif - - { - char** argv_l=child->argv; - int argc_l; - for(argc_l=0;*argv_l!=NULL; argv_l++, argc_l++); - optind = 1; - run_applet_by_name(name, argc_l, child->argv); - } -#endif - - execvp(child->argv[0], child->argv); - perror_msg_and_die("%s", child->argv[0]); -} - -static void insert_job(struct job *newjob, int inbg) -{ - struct job *thejob; - struct jobset *j_list=newjob->job_list; - - /* find the ID for thejob to use */ - newjob->jobid = 1; - for (thejob = j_list->head; thejob; thejob = thejob->next) - if (thejob->jobid >= newjob->jobid) - newjob->jobid = thejob->jobid + 1; - - /* add thejob to the list of running jobs */ - if (!j_list->head) { - thejob = j_list->head = xmalloc(sizeof(*thejob)); - } else { - for (thejob = j_list->head; thejob->next; thejob = thejob->next) /* nothing */; - thejob->next = xmalloc(sizeof(*thejob)); - thejob = thejob->next; - } - - *thejob = *newjob; /* physically copy the struct job */ - thejob->next = NULL; - thejob->running_progs = thejob->num_progs; - thejob->stopped_progs = 0; - - if (inbg) { - /* we don't wait for background thejobs to return -- append it - to the list of backgrounded thejobs and leave it alone */ - printf("[%d] %d\n", thejob->jobid, - newjob->progs[newjob->num_progs - 1].pid); - last_jobid = newjob->jobid; - last_bg_pid=newjob->progs[newjob->num_progs - 1].pid; - } else { - newjob->job_list->fg = thejob; - - /* move the new process group into the foreground */ - /* suppress messages when run from /linuxrc mag@sysgo.de */ - if (tcsetpgrp(shell_terminal, newjob->pgrp) && errno != ENOTTY) - perror_msg("tcsetpgrp"); - } -} - -static int run_command(struct job *newjob, int inbg, int outpipe[2]) -{ - /* struct job *thejob; */ - int i; - int nextin, nextout; - int pipefds[2]; /* pipefd[0] is for reading */ - struct built_in_command *x; - struct child_prog *child; - - nextin = 0, nextout = 1; - for (i = 0; i < newjob->num_progs; i++) { - child = & (newjob->progs[i]); - - if ((i + 1) < newjob->num_progs) { - if (pipe(pipefds)<0) perror_msg_and_die("pipe"); - nextout = pipefds[1]; - } else { - if (outpipe[1]!=-1) { - nextout = outpipe[1]; - } else { - nextout = 1; - } - } - - - /* Check if the command matches any non-forking builtins, - * but only if this is a simple command. - * Non-forking builtins within pipes have to fork anyway, - * and are handled in pseudo_exec. "echo foo | read bar" - * is doomed to failure, and doesn't work on bash, either. - */ - if (newjob->num_progs == 1) { - for (x = bltins; x->cmd; x++) { - if (strcmp(child->argv[0], x->cmd) == 0 ) { - int squirrel[] = {-1, -1, -1}; - int rcode; - setup_redirects(child, squirrel); - rcode = x->function(child); - restore_redirects(squirrel); - return rcode; - } - } - } - - if (!(child->pid = fork())) { - /* Set the handling for job control signals back to the default. */ - signal(SIGINT, SIG_DFL); - signal(SIGQUIT, SIG_DFL); - signal(SIGTSTP, SIG_DFL); - signal(SIGTTIN, SIG_DFL); - signal(SIGTTOU, SIG_DFL); - signal(SIGCHLD, SIG_DFL); - - close_all(); - - if (outpipe[1]!=-1) { - close(outpipe[0]); - } - if (nextin != 0) { - dup2(nextin, 0); - close(nextin); - } - - if (nextout != 1) { - dup2(nextout, 1); - dup2(nextout, 2); /* Really? */ - close(nextout); - close(pipefds[0]); - } - - /* explicit redirects override pipes */ - setup_redirects(child,NULL); - - pseudo_exec(child); - } - if (outpipe[1]!=-1) { - close(outpipe[1]); - } - - /* put our child in the process group whose leader is the - first process in this pipe */ - setpgid(child->pid, newjob->progs[0].pid); - if (nextin != 0) - close(nextin); - if (nextout != 1) - close(nextout); - - /* If there isn't another process, nextin is garbage - but it doesn't matter */ - nextin = pipefds[0]; - } - - newjob->pgrp = newjob->progs[0].pid; - - insert_job(newjob, inbg); - - return 0; -} - -static int busy_loop(FILE * input) -{ - char *command; - char *next_command = NULL; - struct job newjob; - pid_t parent_pgrp; - int i; - int inbg; - int status; - newjob.job_list = &job_list; - newjob.job_context = DEFAULT_CONTEXT; - - /* save current owner of TTY so we can restore it on exit */ - parent_pgrp = tcgetpgrp(shell_terminal); - - command = (char *) xcalloc(BUFSIZ, sizeof(char)); - - while (1) { - if (!job_list.fg) { - /* no job is in the foreground */ - - /* see if any background processes have exited */ - checkjobs(&job_list); - - if (!next_command) { - if (get_command(input, command)) - break; - next_command = command; - } - - if (expand_arguments(next_command) == FALSE) { - free(command); - command = (char *) xcalloc(BUFSIZ, sizeof(char)); - next_command = NULL; - continue; - } - - if (!parse_command(&next_command, &newjob, &inbg) && - newjob.num_progs) { - int pipefds[2] = {-1,-1}; - debug_printf( "job=%p fed to run_command by busy_loop()'\n", - &newjob); - run_command(&newjob, inbg, pipefds); - } - else { - free(command); - command = (char *) xcalloc(BUFSIZ, sizeof(char)); - next_command = NULL; - } - } else { - /* a job is running in the foreground; wait for it */ - i = 0; - while (!job_list.fg->progs[i].pid || - job_list.fg->progs[i].is_stopped == 1) i++; - - if (waitpid(job_list.fg->progs[i].pid, &status, WUNTRACED)<0) - perror_msg_and_die("waitpid(%d)",job_list.fg->progs[i].pid); - - if (WIFEXITED(status) || WIFSIGNALED(status)) { - /* the child exited */ - job_list.fg->running_progs--; - job_list.fg->progs[i].pid = 0; - - last_return_code=WEXITSTATUS(status); - - if (!job_list.fg->running_progs) { - /* child exited */ - remove_job(&job_list, job_list.fg); - job_list.fg = NULL; - } - } else { - /* the child was stopped */ - job_list.fg->stopped_progs++; - job_list.fg->progs[i].is_stopped = 1; - - if (job_list.fg->stopped_progs == job_list.fg->running_progs) { - printf("\n" JOB_STATUS_FORMAT, job_list.fg->jobid, - "Stopped", job_list.fg->text); - job_list.fg = NULL; - } - } - - if (!job_list.fg) { - /* move the shell to the foreground */ - /* suppress messages when run from /linuxrc mag@sysgo.de */ - if (tcsetpgrp(shell_terminal, getpgrp()) && errno != ENOTTY) - perror_msg("tcsetpgrp"); - } - } - } - free(command); - - /* return controlling TTY back to parent process group before exiting */ - if (tcsetpgrp(shell_terminal, parent_pgrp)) - perror_msg("tcsetpgrp"); - - /* return exit status if called with "-c" */ - if (input == NULL && WIFEXITED(status)) - return WEXITSTATUS(status); - - return 0; -} - - -#ifdef BB_FEATURE_CLEAN_UP -void free_memory(void) -{ - if (cwd && cwd!=unknown) { - free((char*)cwd); - } - if (local_pending_command) - free(local_pending_command); - - if (job_list.fg && !job_list.fg->running_progs) { - remove_job(&job_list, job_list.fg); - } -} -#endif - -/* Make sure we have a controlling tty. If we get started under a job - * aware app (like bash for example), make sure we are now in charge so - * we don't fight over who gets the foreground */ -static void setup_job_control() -{ - int status; - - /* Loop until we are in the foreground. */ - while ((status = tcgetpgrp (shell_terminal)) >= 0) { - if (status == (shell_pgrp = getpgrp ())) { - break; - } - kill (- shell_pgrp, SIGTTIN); - } - - /* Ignore interactive and job-control signals. */ - signal(SIGINT, SIG_IGN); - signal(SIGQUIT, SIG_IGN); - signal(SIGTSTP, SIG_IGN); - signal(SIGTTIN, SIG_IGN); - signal(SIGTTOU, SIG_IGN); - signal(SIGCHLD, SIG_IGN); - - /* Put ourselves in our own process group. */ - setsid(); - shell_pgrp = getpid (); - setpgid (shell_pgrp, shell_pgrp); - - /* Grab control of the terminal. */ - tcsetpgrp(shell_terminal, shell_pgrp); -} - -int lash_main(int argc_l, char **argv_l) -{ - int opt, interactive=FALSE; - FILE *input = stdin; - argc = argc_l; - argv = argv_l; - - /* These variables need re-initializing when recursing */ - last_jobid = 0; - local_pending_command = NULL; - close_me_head = NULL; - job_list.head = NULL; - job_list.fg = NULL; - last_return_code=1; - - if (argv[0] && argv[0][0] == '-') { - FILE *prof_input; - prof_input = fopen("/etc/profile", "r"); - if (prof_input) { - int tmp_fd = fileno(prof_input); - mark_open(tmp_fd); - /* Now run the file */ - busy_loop(prof_input); - fclose(prof_input); - mark_closed(tmp_fd); - } - } - - while ((opt = getopt(argc_l, argv_l, "cxi")) > 0) { - switch (opt) { - case 'c': - input = NULL; - if (local_pending_command != 0) - error_msg_and_die("multiple -c arguments"); - local_pending_command = xstrdup(argv[optind]); - optind++; - argv = argv+optind; - break; - case 'i': - interactive = TRUE; - break; - default: - show_usage(); - } - } - /* A shell is interactive if the `-i' flag was given, or if all of - * the following conditions are met: - * no -c command - * no arguments remaining or the -s flag given - * standard input is a terminal - * standard output is a terminal - * Refer to Posix.2, the description of the `sh' utility. */ - if (argv[optind]==NULL && input==stdin && - isatty(fileno(stdin)) && isatty(fileno(stdout))) { - interactive=TRUE; - } - setup_job_control(); - if (interactive==TRUE) { - //printf( "optind=%d argv[optind]='%s'\n", optind, argv[optind]); - /* Looks like they want an interactive shell */ -#ifndef BB_FEATURE_SH_EXTRA_QUIET - printf( "\n\n" BB_BANNER " Built-in shell (lash)\n"); - printf( "Enter 'help' for a list of built-in commands.\n\n"); -#endif - } else if (local_pending_command==NULL) { - //printf( "optind=%d argv[optind]='%s'\n", optind, argv[optind]); - input = xfopen(argv[optind], "r"); - mark_open(fileno(input)); /* be lazy, never mark this closed */ - } - - /* initialize the cwd -- this is never freed...*/ - cwd = xgetcwd(0); - if (!cwd) - cwd = unknown; - -#ifdef BB_FEATURE_CLEAN_UP - atexit(free_memory); -#endif - -#ifdef BB_FEATURE_COMMAND_EDITING - cmdedit_set_initial_prompt(); -#else - PS1 = NULL; -#endif - - return (busy_loop(input)); -} diff --git a/length.c b/length.c deleted file mode 100644 index 73becd28a..000000000 --- a/length.c +++ /dev/null @@ -1,13 +0,0 @@ -/* vi: set sw=4 ts=4: */ -#include -#include -#include -#include "busybox.h" - -extern int length_main(int argc, char **argv) -{ - if (argc != 2 || **(argv + 1) == '-') - show_usage(); - printf("%lu\n", (long)strlen(argv[1])); - return EXIT_SUCCESS; -} diff --git a/libbb/Makefile b/libbb/Makefile index a9ea76947..60c3dda97 100644 --- a/libbb/Makefile +++ b/libbb/Makefile @@ -1,11 +1,75 @@ -# Silly wrapper makefile. This Makefile is _not_ used by the build system for -# busybox, it is just to make working on libbb more conveinient. -# -Erik Andersen +# Makefile for busybox +# +# Copyright (C) 2001 Erik Andersen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -all: - make -C .. libbb.a + + +TOPDIR :=.. +L_TARGET := libbb.a + +LIBBB_MSRC=messages.c +LIBBB_OBJ= full_version name_too_long omitting_directory not_a_directory \ + memory_exhausted invalid_date invalid_option io_error dash_dash_help \ + write_error too_few_args name_longer_than_foo unknown can_not_create_raw_socket +LIBBB_MOBJS=$(patsubst %,%.o, $(LIBBB_OBJ)) + +LIBBB_ARCSRC=unarchive.c +LIBBB_ARCOBJ= archive_offset seek_sub_file extract_archive unarchive \ + get_header_ar get_header_cpio get_header_tar deb_extract +LIBBB_AROBJS=$(patsubst %,%.o, $(LIBBB_ARCOBJ)) + + +obj-y := +obj-n := +obj- := + +obj-y += ask_confirmation.o chomp.o concat_path_file.o copy_file.o \ + copy_file_chunk.o libc5.o device_open.o error_msg.o \ + error_msg_and_die.o fgets_str.o find_mount_point.o find_pid_by_name.o \ + find_root_device.o full_read.o full_write.o get_console.o \ + get_last_path_component.o get_line_from_file.o gz_open.o human_readable.o \ + isdirectory.o kernel_version.o loop.o mode_string.o module_syscalls.o mtab.o \ + mtab_file.o my_getgrnam.o my_getgrgid.o my_getpwnam.o my_getpwnamegid.o \ + my_getpwuid.o parse_mode.o parse_number.o perror_msg.o perror_msg_and_die.o \ + print_file.o process_escape_sequence.o read_package_field.o recursive_action.o \ + safe_read.o safe_strncpy.o syscalls.o syslog_msg_with_name.o time_string.o \ + trim.o unzip.o vdprintf.o verror_msg.o vperror_msg.o wfopen.o xfuncs.o \ + xgetcwd.o xreadlink.o xregcomp.o interface.o remove_file.o last_char_is.o \ + copyfd.o vherror_msg.o herror_msg.o herror_msg_and_die.o xgethostbyname.o \ + dirname.o make_directory.o create_icmp_socket.o u_signal_names.o arith.o \ + simplify_path.o $(LIBBB_MOBJS) $(LIBBB_AROBJS) + + +# Hand off to toplevel Rules.mak +include $(TOPDIR)/Rules.mak + +$(LIBBB_MOBJS): $(LIBBB_MSRC) + $(CC) $(CFLAGS) -DBB_VER='"$(VERSION)"' -DBB_BT='"$(BUILDTIME)"' \ + $(LIBBB_CFLAGS) -DL_$(patsubst %,%,$*) -c $< -o $*.o + +$(LIBBB_AROBJS): $(LIBBB_ARCSRC) + $(CC) $(CFLAGS) $(LIBBB_CFLAGS) -DL_$(patsubst %,%,$*) -c $< -o $*.o + +loop.o: loop.h + +loop.h: mk_loop_h.sh + @ $(SHELL) $< > $@ clean: - - rm -rf libbb.a - - find -name \*.o -exec rm -f {} \; + rm -f $(L_TARGET) *.o core + diff --git a/libbb/ask_confirmation.c b/libbb/ask_confirmation.c index f2922379c..d4d943ad7 100644 --- a/libbb/ask_confirmation.c +++ b/libbb/ask_confirmation.c @@ -2,27 +2,23 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) many different people. If you wrote this, please + * acknowledge your work. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA */ #include diff --git a/libbb/chomp.c b/libbb/chomp.c index 111d4cf77..94404a98d 100644 --- a/libbb/chomp.c +++ b/libbb/chomp.c @@ -2,27 +2,23 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) many different people. If you wrote this, please + * acknowledge your work. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA */ #include diff --git a/libbb/concat_path_file.c b/libbb/concat_path_file.c index 86dd2fbbf..e62b99ef6 100644 --- a/libbb/concat_path_file.c +++ b/libbb/concat_path_file.c @@ -1,9 +1,28 @@ +/* vi: set sw=4 ts=4: */ /* - * busybox library eXtendet funcion + * Utility routines. * - * concatenate path and file name to new allocation buffer, + * Copyright (C) many different people. If you wrote this, please + * acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +/* concatenate path and file name to new allocation buffer, * not addition '/' if path name already have '/' - * */ #include diff --git a/libbb/copy_file.c b/libbb/copy_file.c index d3902ffbe..a80e30b50 100644 --- a/libbb/copy_file.c +++ b/libbb/copy_file.c @@ -2,7 +2,6 @@ /* * Mini copy_file implementation for busybox * - * * Copyright (C) 2001 by Matt Kraai * * This program is free software; you can redistribute it and/or modify diff --git a/libbb/copy_file_chunk.c b/libbb/copy_file_chunk.c index c440a6102..63d2ab173 100644 --- a/libbb/copy_file_chunk.c +++ b/libbb/copy_file_chunk.c @@ -2,27 +2,23 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) many different people. If you wrote this, please + * acknowledge your work. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA */ #include diff --git a/libbb/copyfd.c b/libbb/copyfd.c index aa938d105..22d8c3996 100644 --- a/libbb/copyfd.c +++ b/libbb/copyfd.c @@ -2,7 +2,7 @@ /* * Utility routines. * - * Copyright (C) 1999-2001 Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/libbb/device_open.c b/libbb/device_open.c index 8e97ce6c5..30b33d7f0 100644 --- a/libbb/device_open.c +++ b/libbb/device_open.c @@ -2,9 +2,7 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,10 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * */ #include diff --git a/libbb/error_msg.c b/libbb/error_msg.c index c7d5fdb98..58308b6be 100644 --- a/libbb/error_msg.c +++ b/libbb/error_msg.c @@ -2,9 +2,7 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,10 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * */ #include diff --git a/libbb/error_msg_and_die.c b/libbb/error_msg_and_die.c index b950ee00c..67a79c375 100644 --- a/libbb/error_msg_and_die.c +++ b/libbb/error_msg_and_die.c @@ -2,9 +2,7 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,10 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * */ #include diff --git a/libbb/fgets_str.c b/libbb/fgets_str.c index 4943464d5..6588f9482 100644 --- a/libbb/fgets_str.c +++ b/libbb/fgets_str.c @@ -1,17 +1,23 @@ +/* vi: set sw=4 ts=4: */ /* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * Utility routines. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. + * Copyright (C) many different people. If you wrote this, please + * acknowledge your work. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ diff --git a/libbb/find_mount_point.c b/libbb/find_mount_point.c index 2d9481a69..1eb5dc942 100644 --- a/libbb/find_mount_point.c +++ b/libbb/find_mount_point.c @@ -2,9 +2,7 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,10 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * */ #include diff --git a/libbb/find_pid_by_name.c b/libbb/find_pid_by_name.c index 7f39dd41c..f183cc0bd 100644 --- a/libbb/find_pid_by_name.c +++ b/libbb/find_pid_by_name.c @@ -2,9 +2,7 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,10 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * */ #include @@ -36,7 +30,7 @@ /* For Erik's nifty devps device driver */ -#ifdef BB_FEATURE_USE_DEVPS_PATCH +#ifdef CONFIG_FEATURE_USE_DEVPS_PATCH #include /* find_pid_by_name() @@ -120,7 +114,7 @@ extern pid_t* find_pid_by_name( char* pidName) return pidList; } -#else /* BB_FEATURE_USE_DEVPS_PATCH */ +#else /* CONFIG_FEATURE_USE_DEVPS_PATCH */ /* find_pid_by_name() * @@ -187,7 +181,7 @@ extern pid_t* find_pid_by_name( char* pidName) } return pidList; } -#endif /* BB_FEATURE_USE_DEVPS_PATCH */ +#endif /* CONFIG_FEATURE_USE_DEVPS_PATCH */ /* END CODE */ /* diff --git a/libbb/find_root_device.c b/libbb/find_root_device.c index f8f68464d..0a3f1bc77 100644 --- a/libbb/find_root_device.c +++ b/libbb/find_root_device.c @@ -1,8 +1,9 @@ /* vi: set sw=4 ts=4: */ /* - * Copyright (C) 2000,2001 by Lineo, inc. - * Written by Erik Andersen , + * Utility routines. * + * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen * Patched by a bunch of people. Feel free to acknowledge your work. * * This program is free software; you can redistribute it and/or modify @@ -18,7 +19,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * */ #include diff --git a/libbb/full_read.c b/libbb/full_read.c index e9c4bbfc6..ccf26fc3d 100644 --- a/libbb/full_read.c +++ b/libbb/full_read.c @@ -2,9 +2,7 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,10 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * */ #include diff --git a/libbb/full_write.c b/libbb/full_write.c index dc9937fa3..a2c07fbc9 100644 --- a/libbb/full_write.c +++ b/libbb/full_write.c @@ -2,9 +2,7 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,10 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * */ #include diff --git a/libbb/get_console.c b/libbb/get_console.c index 3b36a59e7..04a6bd1a6 100644 --- a/libbb/get_console.c +++ b/libbb/get_console.c @@ -2,9 +2,8 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) many different people. If you wrote this, please + * acknowledge your work. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,10 +18,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * */ #include diff --git a/libbb/get_last_path_component.c b/libbb/get_last_path_component.c index f1ddfbde0..85c7609c9 100644 --- a/libbb/get_last_path_component.c +++ b/libbb/get_last_path_component.c @@ -2,9 +2,7 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,10 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * */ #include diff --git a/libbb/get_line_from_file.c b/libbb/get_line_from_file.c index 759481731..9035c0412 100644 --- a/libbb/get_line_from_file.c +++ b/libbb/get_line_from_file.c @@ -2,9 +2,8 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) many different people. If you wrote this, please + * acknowledge your work. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,10 +18,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * */ #include diff --git a/libbb/gz_open.c b/libbb/gz_open.c index ef30ff894..dbaf3bb02 100644 --- a/libbb/gz_open.c +++ b/libbb/gz_open.c @@ -1,3 +1,26 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) many different people. If you wrote this, please + * acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + #include #include #include diff --git a/libbb/herror_msg.c b/libbb/herror_msg.c index f4210edad..1081a56b1 100644 --- a/libbb/herror_msg.c +++ b/libbb/herror_msg.c @@ -2,9 +2,7 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,10 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * */ #include diff --git a/libbb/herror_msg_and_die.c b/libbb/herror_msg_and_die.c index 0df5ed016..64482d859 100644 --- a/libbb/herror_msg_and_die.c +++ b/libbb/herror_msg_and_die.c @@ -2,9 +2,7 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,11 +17,8 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * */ +/* vi: set sw=4 ts=4: */ #include #include diff --git a/libbb/inode_hash.c b/libbb/inode_hash.c index 790af8f31..52c54cdc1 100644 --- a/libbb/inode_hash.c +++ b/libbb/inode_hash.c @@ -2,27 +2,23 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) many different people. If you wrote this, please + * acknowledge your work. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA */ #include diff --git a/libbb/interface.c b/libbb/interface.c index 484597c5f..e69be15e6 100644 --- a/libbb/interface.c +++ b/libbb/interface.c @@ -1,9 +1,21 @@ /* + * stolen from net-tools-1.59 and stripped down for busybox by + * Erik Andersen + * + * Heavily modified by Manuel Novoa III Mar 12, 2001 + * + * Pruned unused code using KEEP_UNUSED define. + * Added print_bytes_scaled function to reduce code size. + * Added some (potentially) missing defines. + * Improved display support for -a and for a named interface. + * + * ----------------------------------------------------------- + * * ifconfig This file contains an implementation of the command * that either displays or sets the characteristics of * one or more of the system's networking interfaces. * - * Version: $Id: interface.c,v 1.4 2001/07/19 22:28:02 andersen Exp $ + * Version: $Id: interface.c,v 1.5 2001/10/24 04:59:38 andersen Exp $ * * Author: Fred N. van Kempen, * and others. Copyright 1993 MicroWalt Corporation @@ -22,17 +34,6 @@ * 10/1998 - Andi Kleen. Use interface list primitives. * 20001008 - Bernd Eckenfels, Patch from RH for setting mtu * (default AF was wrong) - * stolen from net-tools-1.59 and stripped down for busybox by - * Erik Andersen - */ - -/* - * Heavily modified by Manuel Novoa III Mar 12, 2001 - * - * Pruned unused code using KEEP_UNUSED define. - * Added print_bytes_scaled function to reduce code size. - * Added some (potentially) missing defines. - * Improved display support for -a and for a named interface. */ /* #define KEEP_UNUSED */ diff --git a/libbb/isdirectory.c b/libbb/isdirectory.c index 65f4fee00..3dfe10522 100644 --- a/libbb/isdirectory.c +++ b/libbb/isdirectory.c @@ -2,9 +2,8 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Based in part on code from sash, Copyright (c) 1999 by David I. Bell + * Permission has been granted to redistribute this code under the GPL. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,10 +18,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * */ #include diff --git a/libbb/kernel_version.c b/libbb/kernel_version.c index 09cd582c4..694af8e2c 100644 --- a/libbb/kernel_version.c +++ b/libbb/kernel_version.c @@ -2,9 +2,7 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,10 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * */ #include diff --git a/libbb/libbb.h b/libbb/libbb.h deleted file mode 100644 index 3ef0278f8..000000000 --- a/libbb/libbb.h +++ /dev/null @@ -1,326 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Busybox main internal header file - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * - */ -#ifndef __LIBBB_H__ -#define __LIBBB_H__ 1 - -#include -#include -#include -#include - -#include - -#ifdef DMALLOC -#include "dmalloc.h" -#endif - -#include - -#ifndef _BB_INTERNAL_H_ -#include "../busybox.h" -#endif - -#if (__GNU_LIBRARY__ < 5) && (!defined __dietlibc__) -/* libc5 doesn't define socklen_t */ -typedef unsigned int socklen_t; -/* libc5 doesn't implement BSD 4.4 daemon() */ -extern int daemon (int nochdir, int noclose); -/* libc5 doesn't implement strtok_r */ -char *strtok_r(char *s, const char *delim, char **ptrptr); -#endif - -/* Some useful definitions */ -#define FALSE ((int) 0) -#define TRUE ((int) 1) -#define SKIP ((int) 2) - -/* for mtab.c */ -#define MTAB_GETMOUNTPT '1' -#define MTAB_GETDEVICE '2' - -#define BUF_SIZE 8192 -#define EXPAND_ALLOC 1024 - -static inline int is_decimal(int ch) { return ((ch >= '0') && (ch <= '9')); } -static inline int is_octal(int ch) { return ((ch >= '0') && (ch <= '7')); } - -/* Macros for min/max. */ -#ifndef MIN -#define MIN(a,b) (((a)<(b))?(a):(b)) -#endif - -#ifndef MAX -#define MAX(a,b) (((a)>(b))?(a):(b)) -#endif - - - -extern void show_usage(void) __attribute__ ((noreturn)); -extern void error_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))); -extern void error_msg_and_die(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2))); -extern void perror_msg(const char *s, ...); -extern void perror_msg_and_die(const char *s, ...) __attribute__ ((noreturn)); -extern void vherror_msg(const char *s, va_list p); -extern void herror_msg(const char *s, ...); -extern void herror_msg_and_die(const char *s, ...) __attribute__ ((noreturn)); - -/* These two are used internally -- you shouldn't need to use them */ -extern void verror_msg(const char *s, va_list p); -extern void vperror_msg(const char *s, va_list p); - -const char *mode_string(int mode); -const char *time_string(time_t timeVal); -int is_directory(const char *name, int followLinks, struct stat *statBuf); -int isDevice(const char *name); - -int remove_file(const char *path, int flags); -int copy_file(const char *source, const char *dest, int flags); -int copy_file_chunk(FILE *src_file, FILE *dst_file, unsigned long long chunksize); -char *buildName(const char *dirName, const char *fileName); -int makeString(int argc, const char **argv, char *buf, int bufLen); -char *getChunk(int size); -char *chunkstrdup(const char *str); -void freeChunks(void); -ssize_t safe_read(int fd, void *buf, size_t count); -int full_write(int fd, const char *buf, int len); -int full_read(int fd, char *buf, int len); -int recursive_action(const char *fileName, int recurse, int followLinks, int depthFirst, - int (*fileAction) (const char *fileName, struct stat* statbuf, void* userData), - int (*dirAction) (const char *fileName, struct stat* statbuf, void* userData), - void* userData); - -extern int parse_mode( const char* s, mode_t* theMode); - -extern int get_kernel_revision(void); - -extern int get_console_fd(char* tty_name); -extern struct mntent *find_mount_point(const char *name, const char *table); -extern void write_mtab(char* blockDevice, char* directory, - char* filesystemType, long flags, char* string_flags); -extern void erase_mtab(const char * name); -extern long atoi_w_units (const char *cp); -extern pid_t* find_pid_by_name( char* pidName); -extern char *find_real_root_device_name(const char* name); -extern char *get_line_from_file(FILE *file); -extern void print_file(FILE *file); -extern int copyfd(int fd1, int fd2); -extern int print_file_by_name(char *filename); -extern char process_escape_sequence(const char **ptr); -extern char *get_last_path_component(char *path); -extern FILE *wfopen(const char *path, const char *mode); -extern FILE *xfopen(const char *path, const char *mode); -extern void chomp(char *s); -extern void trim(char *s); -extern struct BB_applet *find_applet_by_name(const char *name); -void run_applet_by_name(const char *name, int argc, char **argv); - -#ifndef DMALLOC -extern void *xmalloc (size_t size); -extern void *xrealloc(void *old, size_t size); -extern void *xcalloc(size_t nmemb, size_t size); -extern char *xstrdup (const char *s); -#endif -extern char *xstrndup (const char *s, int n); -extern char * safe_strncpy(char *dst, const char *src, size_t size); - -struct suffix_mult { - const char *suffix; - int mult; -}; - -extern unsigned long parse_number(const char *numstr, - const struct suffix_mult *suffixes); - - -/* These parse entries in /etc/passwd and /etc/group. This is desirable - * for BusyBox since we want to avoid using the glibc NSS stuff, which - * increases target size and is often not needed embedded systems. */ -extern long my_getpwnam(const char *name); -extern long my_getgrnam(const char *name); -extern void my_getpwuid(char *name, long uid); -extern void my_getgrgid(char *group, long gid); -extern long my_getpwnamegid(const char *name); - -extern int device_open(char *device, int mode); - -extern int del_loop(const char *device); -extern int set_loop(const char *device, const char *file, int offset, int *loopro); -extern char *find_unused_loop_device (void); - - -#if (__GLIBC__ < 2) -extern int vdprintf(int d, const char *format, va_list ap); -#endif - -int nfsmount(const char *spec, const char *node, int *flags, - char **extra_opts, char **mount_opts, int running_bg); - -void syslog_msg_with_name(const char *name, int facility, int pri, const char *msg); -void syslog_msg(int facility, int pri, const char *msg); - -/* Include our own copy of struct sysinfo to avoid binary compatability - * problems with Linux 2.4, which changed things. Grumble, grumble. */ -struct sysinfo { - long uptime; /* Seconds since boot */ - unsigned long loads[3]; /* 1, 5, and 15 minute load averages */ - unsigned long totalram; /* Total usable main memory size */ - unsigned long freeram; /* Available memory size */ - unsigned long sharedram; /* Amount of shared memory */ - unsigned long bufferram; /* Memory used by buffers */ - unsigned long totalswap; /* Total swap space size */ - unsigned long freeswap; /* swap space still available */ - unsigned short procs; /* Number of current processes */ - unsigned short pad; /* Padding needed for m68k */ - unsigned long totalhigh; /* Total high memory size */ - unsigned long freehigh; /* Available high memory size */ - unsigned int mem_unit; /* Memory unit size in bytes */ - char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding: libc5 uses this.. */ -}; -extern int sysinfo (struct sysinfo* info); - -enum { - KILOBYTE = 1024, - MEGABYTE = (KILOBYTE*1024), - GIGABYTE = (MEGABYTE*1024) -}; -const char *make_human_readable_str(unsigned long size, unsigned long block_size, unsigned long display_unit); - -int ask_confirmation(void); -int klogctl(int type, char * b, int len); - -char *xgetcwd(char *cwd); -char *xreadlink(const char *path); -char *concat_path_file(const char *path, const char *filename); -char *last_char_is(const char *s, int c); - -extern long arith (const char *startbuf, int *errcode); - -typedef struct file_headers_s { - char *name; - char *link_name; - off_t size; - uid_t uid; - gid_t gid; - mode_t mode; - time_t mtime; - dev_t device; -} file_header_t; -file_header_t *get_header_ar(FILE *in_file); -file_header_t *get_header_cpio(FILE *src_stream); -file_header_t *get_header_tar(FILE *tar_stream); - -enum extract_functions_e { - extract_verbose_list = 1, - extract_list = 2, - extract_one_to_buffer = 4, - extract_to_stdout = 8, - extract_all_to_fs = 16, - extract_preserve_date = 32, - extract_data_tar_gz = 64, - extract_control_tar_gz = 128, - extract_unzip_only = 256, - extract_unconditional = 512, - extract_create_leading_dirs = 1024, - extract_quiet = 2048, - extract_exclude_list = 4096 -}; -char *unarchive(FILE *src_stream, FILE *out_stream, file_header_t *(*get_headers)(FILE *), - const int extract_function, const char *prefix, char **include_name, char **exclude_name); -char *deb_extract(const char *package_filename, FILE *out_stream, const int extract_function, - const char *prefix, const char *filename); -int read_package_field(const char *package_buffer, char **field_name, char **field_value); -char *fgets_str(FILE *file, const char *terminating_string); - -extern int unzip(FILE *l_in_file, FILE *l_out_file); -extern void gz_close(int gunzip_pid); -extern FILE *gz_open(FILE *compressed_file, int *pid); - -extern struct hostent *xgethostbyname(const char *name); -extern int create_icmp_socket(void); - -char *dirname (char *path); - -int make_directory (char *path, long mode, int flags); - -const char *u_signal_names(const char *str_sig, int *signo, int startnum); -char *simplify_path(const char *path); - -#define CT_AUTO 0 -#define CT_UNIX2DOS 1 -#define CT_DOS2UNIX 2 -/* extern int convert(char *fn, int ConvType); */ - -enum { - FILEUTILS_PRESERVE_STATUS = 1, - FILEUTILS_DEREFERENCE = 2, - FILEUTILS_RECUR = 4, - FILEUTILS_FORCE = 8, - FILEUTILS_INTERACTIVE = 16 -}; - -extern const char *applet_name; -extern const char * const full_version; -extern const char * const name_too_long; -extern const char * const omitting_directory; -extern const char * const not_a_directory; -extern const char * const memory_exhausted; -extern const char * const invalid_date; -extern const char * const invalid_option; -extern const char * const io_error; -extern const char * const dash_dash_help; -extern const char * const write_error; -extern const char * const too_few_args; -extern const char * const name_longer_than_foo; -extern const char * const unknown; -extern const char * const can_not_create_raw_socket; - -#ifdef BB_FEATURE_DEVFS -# define CURRENT_VC "/dev/vc/0" -# define VC_1 "/dev/vc/1" -# define VC_2 "/dev/vc/2" -# define VC_3 "/dev/vc/3" -# define VC_4 "/dev/vc/4" -# define VC_5 "/dev/vc/5" -# define SC_0 "/dev/tts/0" -# define SC_1 "/dev/tts/1" -# define VC_FORMAT "/dev/vc/%d" -# define SC_FORMAT "/dev/tts/%d" -#else -# define CURRENT_VC "/dev/tty0" -# define VC_1 "/dev/tty1" -# define VC_2 "/dev/tty2" -# define VC_3 "/dev/tty3" -# define VC_4 "/dev/tty4" -# define VC_5 "/dev/tty5" -# define SC_0 "/dev/ttyS0" -# define SC_1 "/dev/ttyS1" -# define VC_FORMAT "/dev/tty%d" -# define SC_FORMAT "/dev/ttyS%d" -#endif - -/* The following devices are the same on devfs and non-devfs systems. */ -#define CURRENT_TTY "/dev/tty" -#define CONSOLE_DEV "/dev/console" - -#endif /* __LIBBB_H__ */ diff --git a/libbb/loop.c b/libbb/loop.c index 4754b8da1..36b13d6e6 100644 --- a/libbb/loop.c +++ b/libbb/loop.c @@ -2,9 +2,7 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,10 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * */ #include diff --git a/libbb/messages.c b/libbb/messages.c index 552c3ab5b..895cfdc2b 100644 --- a/libbb/messages.c +++ b/libbb/messages.c @@ -1,7 +1,7 @@ /* vi: set sw=4 ts=4: */ /* - * Copyright (C) 2001 by Lineo, inc. - * Written by Erik Andersen , + * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,6 +19,7 @@ * */ +#include "busybox.h" #include "libbb.h" #ifdef L_full_version diff --git a/libbb/mode_string.c b/libbb/mode_string.c index 0a3d6e6f0..12dc17966 100644 --- a/libbb/mode_string.c +++ b/libbb/mode_string.c @@ -2,27 +2,23 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) many different people. If you wrote this, please + * acknowledge your work. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA */ #include diff --git a/libbb/module_syscalls.c b/libbb/module_syscalls.c index 8326f15ad..3b60649a8 100644 --- a/libbb/module_syscalls.c +++ b/libbb/module_syscalls.c @@ -2,8 +2,8 @@ /* * some system calls possibly missing from libc * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , + * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/libbb/mtab.c b/libbb/mtab.c index 28c9978ef..c521b1e05 100644 --- a/libbb/mtab.c +++ b/libbb/mtab.c @@ -1,4 +1,24 @@ /* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) 1999,2000,2001 by Erik Andersen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + #include #include #include diff --git a/libbb/mtab_file.c b/libbb/mtab_file.c index 56f8e06ab..267a13720 100644 --- a/libbb/mtab_file.c +++ b/libbb/mtab_file.c @@ -2,9 +2,7 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,10 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * */ #include @@ -31,10 +25,10 @@ /* Busybox mount uses either /proc/mounts or /dev/mtab to * get the list of currently mounted filesystems */ -#if defined BB_FEATURE_MTAB_SUPPORT +#if defined CONFIG_FEATURE_MTAB_SUPPORT const char mtab_file[] = "/etc/mtab"; #else -# if defined BB_FEATURE_USE_DEVPS_PATCH +# if defined CONFIG_FEATURE_USE_DEVPS_PATCH const char mtab_file[] = "/dev/mtab"; # else const char mtab_file[] = "/proc/mounts"; diff --git a/libbb/my_getgrgid.c b/libbb/my_getgrgid.c index fabd4776c..27b671922 100644 --- a/libbb/my_getgrgid.c +++ b/libbb/my_getgrgid.c @@ -2,9 +2,7 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,16 +17,12 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * */ #include #include -#include "../pwd_grp/pwd.h" -#include "../pwd_grp/grp.h" +#include "pwd.h" +#include "grp.h" #include "libbb.h" diff --git a/libbb/my_getgrnam.c b/libbb/my_getgrnam.c index e3226a275..dbacf5192 100644 --- a/libbb/my_getgrnam.c +++ b/libbb/my_getgrnam.c @@ -2,9 +2,7 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,20 +17,15 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * */ #include #include -#include "../pwd_grp/pwd.h" -#include "../pwd_grp/grp.h" +#include "pwd.h" +#include "grp.h" #include "libbb.h" - /* returns a gid given a group name */ long my_getgrnam(const char *name) { diff --git a/libbb/my_getpwnam.c b/libbb/my_getpwnam.c index ae73ae7f1..90277040e 100644 --- a/libbb/my_getpwnam.c +++ b/libbb/my_getpwnam.c @@ -2,9 +2,7 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,20 +17,15 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * */ #include #include -#include "../pwd_grp/pwd.h" -#include "../pwd_grp/grp.h" +#include "pwd.h" +#include "grp.h" #include "libbb.h" - /* returns a uid given a username */ long my_getpwnam(const char *name) { diff --git a/libbb/my_getpwnamegid.c b/libbb/my_getpwnamegid.c index fb3d148ce..9c45580b5 100644 --- a/libbb/my_getpwnamegid.c +++ b/libbb/my_getpwnamegid.c @@ -2,9 +2,7 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,16 +17,12 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * */ #include #include -#include "../pwd_grp/pwd.h" -#include "../pwd_grp/grp.h" +#include "pwd.h" +#include "grp.h" #include "libbb.h" diff --git a/libbb/my_getpwuid.c b/libbb/my_getpwuid.c index 46c7a884a..49bc8fb49 100644 --- a/libbb/my_getpwuid.c +++ b/libbb/my_getpwuid.c @@ -2,9 +2,7 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,16 +17,12 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * */ #include #include -#include "../pwd_grp/pwd.h" -#include "../pwd_grp/grp.h" +#include "pwd.h" +#include "grp.h" #include "libbb.h" diff --git a/libbb/parse_mode.c b/libbb/parse_mode.c index 30d2f21cf..ba34ea929 100644 --- a/libbb/parse_mode.c +++ b/libbb/parse_mode.c @@ -2,27 +2,23 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) many different people. If you wrote this, please + * acknowledge your work. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA */ #include diff --git a/libbb/parse_number.c b/libbb/parse_number.c index c90511dca..755a357ad 100644 --- a/libbb/parse_number.c +++ b/libbb/parse_number.c @@ -2,27 +2,23 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) many different people. If you wrote this, please + * acknowledge your work. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA */ #include diff --git a/libbb/perror_msg.c b/libbb/perror_msg.c index 18c71ab1c..8c57b0d16 100644 --- a/libbb/perror_msg.c +++ b/libbb/perror_msg.c @@ -2,9 +2,7 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,10 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * */ #include diff --git a/libbb/perror_msg_and_die.c b/libbb/perror_msg_and_die.c index 9d304a26b..9004925cc 100644 --- a/libbb/perror_msg_and_die.c +++ b/libbb/perror_msg_and_die.c @@ -2,9 +2,7 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,10 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * */ #include diff --git a/libbb/print_file.c b/libbb/print_file.c index bfedc5eff..a6df14ed9 100644 --- a/libbb/print_file.c +++ b/libbb/print_file.c @@ -2,7 +2,7 @@ /* * Utility routines. * - * Copyright (C) 1999-2001 Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/libbb/read_package_field.c b/libbb/read_package_field.c index f561df831..ac5f80167 100644 --- a/libbb/read_package_field.c +++ b/libbb/read_package_field.c @@ -1,3 +1,26 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) many different people. If you wrote this, please + * acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + #include #include #include "libbb.h" diff --git a/libbb/recursive_action.c b/libbb/recursive_action.c index 6672db17f..e87ab9860 100644 --- a/libbb/recursive_action.c +++ b/libbb/recursive_action.c @@ -2,9 +2,7 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,10 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * */ #include diff --git a/libbb/remove_file.c b/libbb/remove_file.c index 3b84680c4..988b09124 100644 --- a/libbb/remove_file.c +++ b/libbb/remove_file.c @@ -2,10 +2,8 @@ /* * Mini remove_file implementation for busybox * - * * Copyright (C) 2001 Matt Kraai * - * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -19,7 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * */ #include diff --git a/libbb/safe_read.c b/libbb/safe_read.c index dbf4aa7e4..b6d6d742f 100644 --- a/libbb/safe_read.c +++ b/libbb/safe_read.c @@ -2,9 +2,7 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,10 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * */ #include diff --git a/libbb/safe_strncpy.c b/libbb/safe_strncpy.c index 55ec79802..0c5cf12ef 100644 --- a/libbb/safe_strncpy.c +++ b/libbb/safe_strncpy.c @@ -2,9 +2,7 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,10 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * */ #include diff --git a/libbb/syscalls.c b/libbb/syscalls.c index 426a14aa1..383eb6ab9 100644 --- a/libbb/syscalls.c +++ b/libbb/syscalls.c @@ -2,8 +2,8 @@ /* * some system calls possibly missing from libc * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , + * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/libbb/syslog_msg_with_name.c b/libbb/syslog_msg_with_name.c index 5dadcc433..6474da459 100644 --- a/libbb/syslog_msg_with_name.c +++ b/libbb/syslog_msg_with_name.c @@ -2,9 +2,7 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,10 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * */ #include diff --git a/libbb/time_string.c b/libbb/time_string.c index 076529006..d103a02f8 100644 --- a/libbb/time_string.c +++ b/libbb/time_string.c @@ -2,9 +2,7 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,10 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * */ #include diff --git a/libbb/trim.c b/libbb/trim.c index 76b87ca1c..cb673cac3 100644 --- a/libbb/trim.c +++ b/libbb/trim.c @@ -2,27 +2,23 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) many different people. If you wrote this, please + * acknowledge your work. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA */ #include diff --git a/libbb/u_signal_names.c b/libbb/u_signal_names.c index 623b10312..aee1db07c 100644 --- a/libbb/u_signal_names.c +++ b/libbb/u_signal_names.c @@ -1,3 +1,26 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) many different people. If you wrote this, please + * acknowledge your work. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + #include #include #include diff --git a/libbb/vdprintf.c b/libbb/vdprintf.c index 8c3e32a7a..0f250ae69 100644 --- a/libbb/vdprintf.c +++ b/libbb/vdprintf.c @@ -2,9 +2,7 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,10 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * */ #include diff --git a/libbb/verror_msg.c b/libbb/verror_msg.c index b34821561..21cde2047 100644 --- a/libbb/verror_msg.c +++ b/libbb/verror_msg.c @@ -2,9 +2,7 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,10 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * */ #include diff --git a/libbb/vherror_msg.c b/libbb/vherror_msg.c index 44f6ebd28..67db17fe4 100644 --- a/libbb/vherror_msg.c +++ b/libbb/vherror_msg.c @@ -2,9 +2,7 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,10 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * */ #include diff --git a/libbb/vperror_msg.c b/libbb/vperror_msg.c index ca9361e45..7da5bae0a 100644 --- a/libbb/vperror_msg.c +++ b/libbb/vperror_msg.c @@ -2,9 +2,7 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,10 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * */ #include diff --git a/libbb/wfopen.c b/libbb/wfopen.c index 8b074d2f7..f58ec90c0 100644 --- a/libbb/wfopen.c +++ b/libbb/wfopen.c @@ -2,9 +2,7 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,10 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * */ #include diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c index eb93bf139..291bfafd6 100644 --- a/libbb/xfuncs.c +++ b/libbb/xfuncs.c @@ -2,9 +2,7 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,10 +17,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * */ #include diff --git a/libbb/xgethostbyname.c b/libbb/xgethostbyname.c index be56f2ed1..b71979701 100644 --- a/libbb/xgethostbyname.c +++ b/libbb/xgethostbyname.c @@ -2,7 +2,6 @@ /* * Mini xgethostbyname implementation. * - * * Copyright (C) 2001 Matt Kraai . * * This program is free software; you can redistribute it and/or modify diff --git a/libbb/xregcomp.c b/libbb/xregcomp.c index 6f5e2f0cb..07cf779d1 100644 --- a/libbb/xregcomp.c +++ b/libbb/xregcomp.c @@ -2,27 +2,23 @@ /* * Utility routines. * - * Copyright (C) tons of folks. Tracking down who wrote what - * isn't something I'm going to worry about... If you wrote something - * here, please feel free to acknowledge your work. + * Copyright (C) many different people. If you wrote this, please + * acknowledge your work. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based in part on code from sash, Copyright (c) 1999 by David I. Bell - * Permission has been granted to redistribute this code under the GPL. - * + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA */ #include diff --git a/ln.c b/ln.c deleted file mode 100644 index 7412a86fd..000000000 --- a/ln.c +++ /dev/null @@ -1,131 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini ln implementation for busybox - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include "busybox.h" - - -static const int LN_SYMLINK = 1; -static const int LN_FORCE = 2; -static const int LN_NODEREFERENCE = 4; - -/* - * linkDestName is where the link points to, - * linkSrcName is the name of the link to be created. - */ -static int fs_link(const char *link_destname, const char *link_srcname, - const int flag) -{ - int status; - int src_is_dir; - char *src_name; - - if (link_destname==NULL) - return(FALSE); - - src_name = (char *) xmalloc(strlen(link_srcname)+strlen(link_destname)+1); - - if (link_srcname==NULL) - strcpy(src_name, link_destname); - else - strcpy(src_name, link_srcname); - - if (flag&LN_NODEREFERENCE) - src_is_dir = is_directory(src_name, TRUE, NULL); - else - src_is_dir = is_directory(src_name, FALSE, NULL); - - if ((src_is_dir==TRUE)&&((flag&LN_NODEREFERENCE)==0)) { - char* srcdir_name; - - srcdir_name = xstrdup(link_destname); - strcat(src_name, "/"); - strcat(src_name, get_last_path_component(srcdir_name)); - free(srcdir_name); - } - - if (flag&LN_FORCE) - unlink(src_name); - - if (flag&LN_SYMLINK) - status = symlink(link_destname, src_name); - else - status = link(link_destname, src_name); - - if (status != 0) { - perror_msg(src_name); - return(FALSE); - } - return(TRUE); -} - -extern int ln_main(int argc, char **argv) -{ - int status = EXIT_SUCCESS; - int flag = 0; - int opt; - - /* Parse any options */ - while ((opt=getopt(argc, argv, "sfn")) != -1) { - switch(opt) { - case 's': - flag |= LN_SYMLINK; - break; - case 'f': - flag |= LN_FORCE; - break; - case 'n': - flag |= LN_NODEREFERENCE; - break; - default: - show_usage(); - } - } - if (optind > (argc-1)) { - show_usage(); - } - if (optind == (argc-1)) { - if (fs_link(argv[optind], - get_last_path_component(argv[optind]), flag)==FALSE) - status = EXIT_FAILURE; - } - while(optind<(argc-1)) { - if (fs_link(argv[optind], argv[argc-1], flag)==FALSE) - status = EXIT_FAILURE; - optind++; - } - exit(status); -} - -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ diff --git a/loadacm.c b/loadacm.c deleted file mode 100644 index 3fb4e7665..000000000 --- a/loadacm.c +++ /dev/null @@ -1,357 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Derived from - * mapscrn.c - version 0.92 - * - * Was taken from console-tools and adapted by - * Peter Novodvorsky - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" - -typedef unsigned short unicode; - -static long int ctoi(unsigned char *s, int *is_unicode); -static int old_screen_map_read_ascii(FILE * fp, unsigned char buf[]); -static int uni_screen_map_read_ascii(FILE * fp, unicode buf[], int *is_unicode); -static unicode utf8_to_ucs2(char *buf); -static int screen_map_load(int fd, FILE * fp); - -int loadacm_main(int argc, char **argv) -{ - int fd; - - if (argc>=2 && *argv[1]=='-') { - show_usage(); - } - - fd = open(CURRENT_VC, O_RDWR); - if (fd < 0) { - perror_msg_and_die("Error opening " CURRENT_VC); - } - - if (screen_map_load(fd, stdin)) { - perror_msg_and_die("Error loading acm"); - } - - write(fd, "\033(K", 3); - - return EXIT_SUCCESS; -} - -static int screen_map_load(int fd, FILE * fp) -{ - struct stat stbuf; - unicode wbuf[E_TABSZ]; - unsigned char buf[E_TABSZ]; - int parse_failed = 0; - int is_unicode; - - if (fstat(fileno(fp), &stbuf)) - perror_msg_and_die("Cannot stat map file"); - - /* first try a UTF screen-map: either ASCII (no restriction) or binary (regular file) */ - if (! - (parse_failed = - (-1 == uni_screen_map_read_ascii(fp, wbuf, &is_unicode))) -|| (S_ISREG(stbuf.st_mode) && (stbuf.st_size == (sizeof(unicode) * E_TABSZ)))) { /* test for binary UTF map by size */ - if (parse_failed) { - if (-1 == fseek(fp, 0, SEEK_SET)) { - if (errno == ESPIPE) - error_msg_and_die("16bit screen-map MUST be a regular file."); - else - perror_msg_and_die("fseek failed reading binary 16bit screen-map"); - } - - if (fread(wbuf, sizeof(unicode) * E_TABSZ, 1, fp) != 1) - perror_msg_and_die("Cannot read [new] map from file"); -#if 0 - else - error_msg("Input screen-map is binary."); -#endif - } - - /* if it was effectively a 16-bit ASCII, OK, else try to read as 8-bit map */ - /* same if it was binary, ie. if parse_failed */ - if (parse_failed || is_unicode) { - if (ioctl(fd, PIO_UNISCRNMAP, wbuf)) - perror_msg_and_die("PIO_UNISCRNMAP ioctl"); - else - return 0; - } - } - - /* rewind... */ - if (-1 == fseek(fp, 0, SEEK_SET)) { - if (errno == ESPIPE) - error_msg("Assuming 8bit screen-map - MUST be a regular file."), - exit(1); - else - perror_msg_and_die("fseek failed assuming 8bit screen-map"); - } - - /* ... and try an old 8-bit screen-map */ - if (!(parse_failed = (-1 == old_screen_map_read_ascii(fp, buf))) || - (S_ISREG(stbuf.st_mode) && (stbuf.st_size == E_TABSZ))) { /* test for binary old 8-bit map by size */ - if (parse_failed) { - if (-1 == fseek(fp, 0, SEEK_SET)) { - if (errno == ESPIPE) - /* should not - it succedeed above */ - error_msg_and_die("fseek() returned ESPIPE !"); - else - perror_msg_and_die("fseek for binary 8bit screen-map"); - } - - if (fread(buf, E_TABSZ, 1, fp) != 1) - perror_msg_and_die("Cannot read [old] map from file"); -#if 0 - else - error_msg("Input screen-map is binary."); -#endif - } - - if (ioctl(fd, PIO_SCRNMAP, buf)) - perror_msg_and_die("PIO_SCRNMAP ioctl"); - else - return 0; - } - error_msg("Error parsing symbolic map"); - return(1); -} - - -/* - * - reads `fp' as a 16-bit ASCII SFM file. - * - returns -1 on error. - * - returns it in `unicode' in an E_TABSZ-elements array. - * - sets `*is_unicode' flagiff there were any non-8-bit - * (ie. real 16-bit) mapping. - * - * FIXME: ignores everything after second word - */ -static int uni_screen_map_read_ascii(FILE * fp, unicode buf[], int *is_unicode) -{ - char buffer[256]; /* line buffer reading file */ - char *p, *q; /* 1st + 2nd words in line */ - int in, on; /* the same, as numbers */ - int tmp_is_unicode; /* tmp for is_unicode calculation */ - int i; /* loop index - result holder */ - int ret_code = 0; /* return code */ - sigset_t acmsigset, old_sigset; - - assert(is_unicode); - - *is_unicode = 0; - - /* first 128 codes defaults to ASCII */ - for (i = 0; i < 128; i++) - buf[i] = i; - /* remaining defaults to replacement char (usually E_TABSZ = 256) */ - for (; i < E_TABSZ; i++) - buf[i] = 0xfffd; - - /* block SIGCHLD */ - sigemptyset(&acmsigset); - sigaddset(&acmsigset, SIGCHLD); - sigprocmask(SIG_BLOCK, &acmsigset, &old_sigset); - - do { - if (NULL == fgets(buffer, sizeof(buffer), fp)) { - if (feof(fp)) - break; - else - perror_msg_and_die("uni_screen_map_read_ascii() can't read line"); - } - - /* get "charset-relative charcode", stripping leading spaces */ - p = strtok(buffer, " \t\n"); - - /* skip empty lines and comments */ - if (!p || *p == '#') - continue; - - /* get unicode mapping */ - q = strtok(NULL, " \t\n"); - if (q) { - in = ctoi(p, NULL); - if (in < 0 || in > 255) { - ret_code = -1; - break; - } - - on = ctoi(q, &tmp_is_unicode); - if (in < 0 && on > 65535) { - ret_code = -1; - break; - } - - *is_unicode |= tmp_is_unicode; - buf[in] = on; - } else { - ret_code = -1; - break; - } - } - while (1); /* terminated by break on feof() */ - - /* restore sig mask */ - sigprocmask(SIG_SETMASK, &old_sigset, NULL); - - return ret_code; -} - - -static int old_screen_map_read_ascii(FILE * fp, unsigned char buf[]) -{ - char buffer[256]; - int in, on; - char *p, *q; - - for (in = 0; in < 256; in++) - buf[in] = in; - - while (fgets(buffer, sizeof(buffer) - 1, fp)) { - p = strtok(buffer, " \t\n"); - - if (!p || *p == '#') - continue; - - q = strtok(NULL, " \t\n#"); - if (q) { - in = ctoi(p, NULL); - if (in < 0 || in > 255) - return -1; - - on = ctoi(q, NULL); - if (in < 0 && on > 255) - return -1; - - buf[in] = on; - } else - return -1; - } - - return (0); -} - - -/* - * - converts a string into an int. - * - supports dec and hex bytes, hex UCS2, single-quoted byte and UTF8 chars. - * - returns the converted value - * - if `is_unicode != NULL', use it to tell whether it was unicode - * - * CAVEAT: will report valid UTF mappings using only 1 byte as 8-bit ones. - */ -static long int ctoi(unsigned char *s, int *is_unicode) -{ - int i; - size_t ls; - - ls = strlen(s); - if (is_unicode) - *is_unicode = 0; - - /* hex-specified UCS2 */ - if ((strncmp(s, "U+", 2) == 0) && - (strspn(s + 2, "0123456789abcdefABCDEF") == ls - 2)) { - sscanf(s + 2, "%x", &i); - if (is_unicode) - *is_unicode = 1; - } - - /* hex-specified byte */ - else if ((ls <= 4) && (strncmp(s, "0x", 2) == 0) && - (strspn(s + 2, "0123456789abcdefABCDEF") == ls - 2)) - sscanf(s + 2, "%x", &i); - - /* oct-specified number (byte) */ - else if ((*s == '0') && (strspn(s, "01234567") == ls)) - sscanf(s, "%o", &i); - - /* dec-specified number (byte) */ - else if (strspn(s, "0123456789") == ls) - sscanf(s, "%d", &i); - - /* single-byte quoted char */ - else if ((strlen(s) == 3) && (s[0] == '\'') && (s[2] == '\'')) - i = s[1]; - - /* multi-byte UTF8 quoted char */ - else if ((s[0] == '\'') && (s[ls - 1] == '\'')) { - s[ls - 1] = 0; /* ensure we'll not "parse UTF too far" */ - i = utf8_to_ucs2(s + 1); - if (is_unicode) - *is_unicode = 1; - } else - return (-1); - - return (i); -} - - -static unicode utf8_to_ucs2(char *buf) -{ - int utf_count = 0; - long utf_char = 0; - unicode tc = 0; - unsigned char c; - - do { - c = *buf; - buf++; - - /* if byte should be part of multi-byte sequence */ - if (c & 0x80) { - /* if we have already started to parse a UTF8 sequence */ - if (utf_count > 0 && (c & 0xc0) == 0x80) { - utf_char = (utf_char << 6) | (c & 0x3f); - utf_count--; - if (utf_count == 0) - tc = utf_char; - else - continue; - } else { /* Possibly 1st char of a UTF8 sequence */ - - if ((c & 0xe0) == 0xc0) { - utf_count = 1; - utf_char = (c & 0x1f); - } else if ((c & 0xf0) == 0xe0) { - utf_count = 2; - utf_char = (c & 0x0f); - } else if ((c & 0xf8) == 0xf0) { - utf_count = 3; - utf_char = (c & 0x07); - } else if ((c & 0xfc) == 0xf8) { - utf_count = 4; - utf_char = (c & 0x03); - } else if ((c & 0xfe) == 0xfc) { - utf_count = 5; - utf_char = (c & 0x01); - } else - utf_count = 0; - continue; - } - } else { /* not part of multi-byte sequence - treat as ASCII - * this makes incomplete sequences to be ignored - */ - tc = c; - utf_count = 0; - } - } - while (utf_count); - - return tc; -} diff --git a/loadfont.c b/loadfont.c deleted file mode 100644 index d66500195..000000000 --- a/loadfont.c +++ /dev/null @@ -1,209 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * loadfont.c - Eugene Crosser & Andries Brouwer - * - * Version 0.96bb - * - * Loads the console font, and possibly the corresponding screen map(s). - * (Adapted for busybox by Matej Vela.) - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" - -static const int PSF_MAGIC1 = 0x36; -static const int PSF_MAGIC2 = 0x04; - -static const int PSF_MODE512 = 0x01; -static const int PSF_MODEHASTAB = 0x02; -static const int PSF_MAXMODE = 0x03; -static const int PSF_SEPARATOR = 0xFFFF; - -struct psf_header { - unsigned char magic1, magic2; /* Magic number */ - unsigned char mode; /* PSF font mode */ - unsigned char charsize; /* Character size */ -}; - -#define PSF_MAGIC_OK(x) ((x).magic1 == PSF_MAGIC1 && (x).magic2 == PSF_MAGIC2) - -static void loadnewfont(int fd); - -extern int loadfont_main(int argc, char **argv) -{ - int fd; - - if (argc != 1) - show_usage(); - - fd = open(CURRENT_VC, O_RDWR); - if (fd < 0) - perror_msg_and_die("Error opening " CURRENT_VC); - loadnewfont(fd); - - return EXIT_SUCCESS; -} - -static void do_loadfont(int fd, char *inbuf, int unit, int fontsize) -{ - char buf[16384]; - int i; - - memset(buf, 0, sizeof(buf)); - - if (unit < 1 || unit > 32) - error_msg_and_die("Bad character size %d", unit); - - for (i = 0; i < fontsize; i++) - memcpy(buf + (32 * i), inbuf + (unit * i), unit); - -#if defined( PIO_FONTX ) && !defined( __sparc__ ) - { - struct consolefontdesc cfd; - - cfd.charcount = fontsize; - cfd.charheight = unit; - cfd.chardata = buf; - - if (ioctl(fd, PIO_FONTX, &cfd) == 0) - return; /* success */ - perror_msg("PIO_FONTX ioctl error (trying PIO_FONT)"); - } -#endif - if (ioctl(fd, PIO_FONT, buf)) - perror_msg_and_die("PIO_FONT ioctl error"); -} - -static void -do_loadtable(int fd, unsigned char *inbuf, int tailsz, int fontsize) -{ - struct unimapinit advice; - struct unimapdesc ud; - struct unipair *up; - int ct = 0, maxct; - int glyph; - u_short unicode; - - maxct = tailsz; /* more than enough */ - up = (struct unipair *) xmalloc(maxct * sizeof(struct unipair)); - - for (glyph = 0; glyph < fontsize; glyph++) { - while (tailsz >= 2) { - unicode = (((u_short) inbuf[1]) << 8) + inbuf[0]; - tailsz -= 2; - inbuf += 2; - if (unicode == PSF_SEPARATOR) - break; - up[ct].unicode = unicode; - up[ct].fontpos = glyph; - ct++; - } - } - - /* Note: after PIO_UNIMAPCLR and before PIO_UNIMAP - this printf did not work on many kernels */ - - advice.advised_hashsize = 0; - advice.advised_hashstep = 0; - advice.advised_hashlevel = 0; - if (ioctl(fd, PIO_UNIMAPCLR, &advice)) { -#ifdef ENOIOCTLCMD - if (errno == ENOIOCTLCMD) { - error_msg("It seems this kernel is older than 1.1.92"); - error_msg_and_die("No Unicode mapping table loaded."); - } else -#endif - perror_msg_and_die("PIO_UNIMAPCLR"); - } - ud.entry_ct = ct; - ud.entries = up; - if (ioctl(fd, PIO_UNIMAP, &ud)) { -#if 0 - if (errno == ENOMEM) { - /* change advice parameters */ - } -#endif - perror_msg_and_die("PIO_UNIMAP"); - } -} - -static void loadnewfont(int fd) -{ - int unit; - char inbuf[32768]; /* primitive */ - unsigned int inputlth, offset; - - /* - * We used to look at the length of the input file - * with stat(); now that we accept compressed files, - * just read the entire file. - */ - inputlth = fread(inbuf, 1, sizeof(inbuf), stdin); - if (ferror(stdin)) - perror_msg_and_die("Error reading input font"); - /* use malloc/realloc in case of giant files; - maybe these do not occur: 16kB for the font, - and 16kB for the map leaves 32 unicode values - for each font position */ - if (!feof(stdin)) - perror_msg_and_die("Font too large"); - - /* test for psf first */ - { - struct psf_header psfhdr; - int fontsize; - int hastable; - unsigned int head0, head; - - if (inputlth < sizeof(struct psf_header)) - goto no_psf; - - psfhdr = *(struct psf_header *) &inbuf[0]; - - if (!PSF_MAGIC_OK(psfhdr)) - goto no_psf; - - if (psfhdr.mode > PSF_MAXMODE) - error_msg_and_die("Unsupported psf file mode"); - fontsize = ((psfhdr.mode & PSF_MODE512) ? 512 : 256); -#if !defined( PIO_FONTX ) || defined( __sparc__ ) - if (fontsize != 256) - error_msg_and_die("Only fontsize 256 supported"); -#endif - hastable = (psfhdr.mode & PSF_MODEHASTAB); - unit = psfhdr.charsize; - head0 = sizeof(struct psf_header); - - head = head0 + fontsize * unit; - if (head > inputlth || (!hastable && head != inputlth)) - error_msg_and_die("Input file: bad length"); - do_loadfont(fd, inbuf + head0, unit, fontsize); - if (hastable) - do_loadtable(fd, inbuf + head, inputlth - head, fontsize); - return; - } - no_psf: - - /* file with three code pages? */ - if (inputlth == 9780) { - offset = 40; - unit = 16; - } else { - /* bare font */ - if (inputlth & 0377) - error_msg_and_die("Bad input file size"); - offset = 0; - unit = inputlth / 256; - } - do_loadfont(fd, inbuf + offset, unit, 256); -} diff --git a/loadkmap.c b/loadkmap.c deleted file mode 100644 index 4f217d630..000000000 --- a/loadkmap.c +++ /dev/null @@ -1,89 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini loadkmap implementation for busybox - * - * Copyright (C) 1998 Enrique Zanardi - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" - -#define BINARY_KEYMAP_MAGIC "bkeymap" - -/* From */ -struct kbentry { - unsigned char kb_table; - unsigned char kb_index; - unsigned short kb_value; -}; -static const int KDSKBENT = 0x4B47; /* sets one entry in translation table */ - -/* From */ -static const int NR_KEYS = 128; -static const int MAX_NR_KEYMAPS = 256; - -int loadkmap_main(int argc, char **argv) -{ - struct kbentry ke; - u_short *ibuff; - int i, j, fd, readsz, pos, ibuffsz = NR_KEYS * sizeof(u_short); - char flags[MAX_NR_KEYMAPS], buff[7]; - - if (argc != 1) - show_usage(); - - fd = open(CURRENT_VC, O_RDWR); - if (fd < 0) - perror_msg_and_die("Error opening " CURRENT_VC); - - read(0, buff, 7); - if (0 != strncmp(buff, BINARY_KEYMAP_MAGIC, 7)) - error_msg_and_die("This is not a valid binary keymap."); - - if (MAX_NR_KEYMAPS != read(0, flags, MAX_NR_KEYMAPS)) - perror_msg_and_die("Error reading keymap flags"); - - ibuff = (u_short *) xmalloc(ibuffsz); - - for (i = 0; i < MAX_NR_KEYMAPS; i++) { - if (flags[i] == 1) { - pos = 0; - while (pos < ibuffsz) { - if ((readsz = read(0, (char *) ibuff + pos, ibuffsz - pos)) < 0) - perror_msg_and_die("Error reading keymap"); - pos += readsz; - } - for (j = 0; j < NR_KEYS; j++) { - ke.kb_index = j; - ke.kb_table = i; - ke.kb_value = ibuff[j]; - ioctl(fd, KDSKBENT, &ke); - } - } - } - /* Don't bother to close files. Exit does that - * automagically, so we can save a few bytes */ - /* close(fd); */ - return EXIT_SUCCESS; -} diff --git a/logger.c b/logger.c deleted file mode 100644 index 9f730915f..000000000 --- a/logger.c +++ /dev/null @@ -1,200 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini logger implementation for busybox - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "busybox.h" -#if !defined BB_SYSLOGD - -#define SYSLOG_NAMES -#include - -#else -#include -# ifndef __dietlibc__ - /* We have to do this since the header file defines static - * structures. Argh.... bad libc, bad, bad... - */ - typedef struct _code { - char *c_name; - int c_val; - } CODE; - extern CODE prioritynames[]; - extern CODE facilitynames[]; -# endif -#endif - -/* Decode a symbolic name to a numeric value - * this function is based on code - * Copyright (c) 1983, 1993 - * The Regents of the University of California. All rights reserved. - * - * Original copyright notice is retained at the end of this file. - */ -static int decode(char *name, CODE * codetab) -{ - CODE *c; - - if (isdigit(*name)) - return (atoi(name)); - for (c = codetab; c->c_name; c++) { - if (!strcasecmp(name, c->c_name)) { - return (c->c_val); - } - } - - return (-1); -} - -/* Decode a symbolic name to a numeric value - * this function is based on code - * Copyright (c) 1983, 1993 - * The Regents of the University of California. All rights reserved. - * - * Original copyright notice is retained at the end of this file. - */ -static int pencode(char *s) -{ - char *save; - int lev, fac = LOG_USER; - - for (save = s; *s && *s != '.'; ++s); - if (*s) { - *s = '\0'; - fac = decode(save, facilitynames); - if (fac < 0) - error_msg_and_die("unknown facility name: %s", save); - *s++ = '.'; - } else { - s = save; - } - lev = decode(s, prioritynames); - if (lev < 0) - error_msg_and_die("unknown priority name: %s", save); - return ((lev & LOG_PRIMASK) | (fac & LOG_FACMASK)); -} - - -extern int logger_main(int argc, char **argv) -{ - int pri = LOG_USER | LOG_NOTICE; - int option = 0; - int c, i, len, opt; - char *message=NULL, buf[1024], name[128]; - - /* Fill out the name string early (may be overwritten later) */ - my_getpwuid(name, geteuid()); - - /* Parse any options */ - while ((opt = getopt(argc, argv, "p:st:")) > 0) { - switch (opt) { - case 's': - option |= LOG_PERROR; - break; - case 'p': - pri = pencode(optarg); - break; - case 't': - strncpy(name, optarg, sizeof(name)); - break; - default: - show_usage(); - } - } - - openlog(name, option, (pri | LOG_FACMASK)); - if (optind == argc) { - do { - /* read from stdin */ - i = 0; - while ((c = getc(stdin)) != EOF && c != '\n' && - i < (sizeof(buf)-1)) { - buf[i++] = c; - } - if (i > 0) { - buf[i++] = '\0'; - syslog(pri, "%s", buf); - } - } while (c != EOF); - } else { - len = 1; /* for the '\0' */ - message=xcalloc(1, 1); - for (i = optind; i < argc; i++) { - len += strlen(argv[i]); - len += 1; /* for the space between the args */ - message = xrealloc(message, len); - strcat(message, argv[i]); - strcat(message, " "); - } - message[strlen(message)-1] = '\0'; - syslog(pri, "%s", message); - } - - closelog(); - return EXIT_SUCCESS; -} - - -/*- - * Copyright (c) 1983, 1993 - * The Regents of the University of California. All rights reserved. - * - * This is the original license statement for the decode and pencode functions. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. - * - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - - - diff --git a/logname.c b/logname.c deleted file mode 100644 index 0924b2471..000000000 --- a/logname.c +++ /dev/null @@ -1,41 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini logname implementation for busybox - * - * Copyright (C) 2000 Edward Betts . - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include "busybox.h" - -extern int logname_main(int argc, char **argv) -{ - char user[9]; - - if (argc > 1) - show_usage(); - - my_getpwuid(user, geteuid()); - if (*user) { - puts(user); - return EXIT_SUCCESS; - } - error_msg_and_die("no login name"); -} diff --git a/logread.c b/logread.c deleted file mode 100644 index d3349625c..000000000 --- a/logread.c +++ /dev/null @@ -1,144 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * circular buffer syslog implementation for busybox - * - * Copyright (C) 2000 by Gennady Feldman - * - * Maintainer: Gennady Feldman as of Mar 12, 2001 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - * 02111-1307 USA - * - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" - -#if __GNU_LIBRARY__ < 5 -#error Sorry. Looks like you are using libc5. -#error libc5 shm support isnt good enough. -#error Please disable BB_FEATURE_IPC_SYSLOG -#endif - - -static const long KEY_ID = 0x414e4547; /*"GENA"*/ - -static struct shbuf_ds { - int size; // size of data written - int head; // start of message list - int tail; // end of message list - char data[1]; // data/messages -} *buf = NULL; // shared memory pointer - - -// Semaphore operation structures -static struct sembuf SMrup[1] = {{0, -1, IPC_NOWAIT | SEM_UNDO}}; // set SMrup -static struct sembuf SMrdn[2] = {{1, 0}, {0, +1, SEM_UNDO}}; // set SMrdn - -static int log_shmid = -1; // ipc shared memory id -static int log_semid = -1; // ipc semaphore id -static jmp_buf jmp_env; - -static void error_exit(const char *str); -static void interrupted(int sig); - -/* - * sem_up - up()'s a semaphore. - */ -static inline void sem_up(int semid) -{ - if ( semop(semid, SMrup, 1) == -1 ) - error_exit("semop[SMrup]"); -} - -/* - * sem_down - down()'s a semaphore - */ -static inline void sem_down(int semid) -{ - if ( semop(semid, SMrdn, 2) == -1 ) - error_exit("semop[SMrdn]"); -} - -extern int logread_main(int argc, char **argv) -{ - int i; - - /* no options, no getopt */ - if (argc > 1) - show_usage(); - - // handle intrrupt signal - if (setjmp(jmp_env)) goto output_end; - - // attempt to redefine ^C signal - signal(SIGINT, interrupted); - - if ( (log_shmid = shmget(KEY_ID, 0, 0)) == -1) - error_exit("Can't find circular buffer"); - - // Attach shared memory to our char* - if ( (buf = shmat(log_shmid, NULL, SHM_RDONLY)) == NULL) - error_exit("Can't get access to circular buffer from syslogd"); - - if ( (log_semid = semget(KEY_ID, 0, 0)) == -1) - error_exit("Can't get access to semaphone(s) for circular buffer from syslogd"); - - sem_down(log_semid); - // Read Memory - i=buf->head; - - //printf("head: %i tail: %i size: %i\n",buf->head,buf->tail,buf->size); - if (buf->head == buf->tail) { - printf("\n"); - } - - while ( i != buf->tail) { - printf("%s", buf->data+i); - i+= strlen(buf->data+i) + 1; - if (i >= buf->size ) - i=0; - } - sem_up(log_semid); - -output_end: - if (log_shmid != -1) - shmdt(buf); - - return EXIT_SUCCESS; -} - -static void interrupted(int sig){ - signal(SIGINT, SIG_IGN); - longjmp(jmp_env, 1); -} - -static void error_exit(const char *str){ - perror(str); - //release all acquired resources - if (log_shmid != -1) - shmdt(buf); - - exit(1); -} diff --git a/ls.c b/ls.c deleted file mode 100644 index 8d0282dfe..000000000 --- a/ls.c +++ /dev/null @@ -1,937 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * tiny-ls.c version 0.1.0: A minimalist 'ls' - * Copyright (C) 1996 Brian Candler - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * To achieve a small memory footprint, this version of 'ls' doesn't do any - * file sorting, and only has the most essential command line switches - * (i.e., the ones I couldn't live without :-) All features which involve - * linking in substantial chunks of libc can be disabled. - * - * Although I don't really want to add new features to this program to - * keep it small, I *am* interested to receive bug fixes and ways to make - * it more portable. - * - * KNOWN BUGS: - * 1. ls -l of a directory doesn't give "total " header - * 2. ls of a symlink to a directory doesn't list directory contents - * 3. hidden files can make column width too large - * - * NON-OPTIMAL BEHAVIOUR: - * 1. autowidth reads directories twice - * 2. if you do a short directory listing without filetype characters - * appended, there's no need to stat each one - * PORTABILITY: - * 1. requires lstat (BSD) - how do you do it without? - */ - -enum { - TERMINAL_WIDTH = 80, /* use 79 if terminal has linefold bug */ - COLUMN_WIDTH = 14, /* default if AUTOWIDTH not defined */ - COLUMN_GAP = 2, /* includes the file type char */ -}; - - -/************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" - -#ifdef BB_FEATURE_LS_TIMESTAMPS -#include -#endif - -#ifndef MAJOR -#define MAJOR(dev) (((dev)>>8)&0xff) -#define MINOR(dev) ((dev)&0xff) -#endif - -/* what is the overall style of the listing */ -enum { -STYLE_AUTO = 0, -STYLE_LONG = 1, /* one record per line, extended info */ -STYLE_SINGLE = 2, /* one record per line */ -STYLE_COLUMNS = 3 /* fill columns */ -}; - -/* 51306 lrwxrwxrwx 1 root root 2 May 11 01:43 /bin/view -> vi* */ -/* what file information will be listed */ -#define LIST_INO (1<<0) -#define LIST_BLOCKS (1<<1) -#define LIST_MODEBITS (1<<2) -#define LIST_NLINKS (1<<3) -#define LIST_ID_NAME (1<<4) -#define LIST_ID_NUMERIC (1<<5) -#define LIST_SIZE (1<<6) -#define LIST_DEV (1<<7) -#define LIST_DATE_TIME (1<<8) -#define LIST_FULLTIME (1<<9) -#define LIST_FILENAME (1<<10) -#define LIST_SYMLINK (1<<11) -#define LIST_FILETYPE (1<<12) -#define LIST_EXEC (1<<13) - -/* what files will be displayed */ -#define DISP_NORMAL (0) /* show normal filenames */ -#define DISP_DIRNAME (1<<0) /* 2 or more items? label directories */ -#define DISP_HIDDEN (1<<1) /* show filenames starting with . */ -#define DISP_DOT (1<<2) /* show . and .. */ -#define DISP_NOLIST (1<<3) /* show directory as itself, not contents */ -#define DISP_RECURSIVE (1<<4) /* show directory and everything below it */ -#define DISP_ROWS (1<<5) /* print across rows */ - -#ifdef BB_FEATURE_LS_SORTFILES -/* how will the files be sorted */ -static const int SORT_FORWARD = 0; /* sort in reverse order */ -static const int SORT_REVERSE = 1; /* sort in reverse order */ -static const int SORT_NAME = 2; /* sort by file name */ -static const int SORT_SIZE = 3; /* sort by file size */ -static const int SORT_ATIME = 4; /* sort by last access time */ -static const int SORT_CTIME = 5; /* sort by last change time */ -static const int SORT_MTIME = 6; /* sort by last modification time */ -static const int SORT_VERSION = 7; /* sort by version */ -static const int SORT_EXT = 8; /* sort by file name extension */ -static const int SORT_DIR = 9; /* sort by file or directory */ -#endif - -#ifdef BB_FEATURE_LS_TIMESTAMPS -/* which of the three times will be used */ -static const int TIME_MOD = 0; -static const int TIME_CHANGE = 1; -static const int TIME_ACCESS = 2; -#endif - -#define LIST_SHORT (LIST_FILENAME) -#define LIST_ISHORT (LIST_INO | LIST_FILENAME) -#define LIST_LONG (LIST_MODEBITS | LIST_NLINKS | LIST_ID_NAME | \ - LIST_SIZE | LIST_DATE_TIME | LIST_FILENAME | \ - LIST_SYMLINK) -#define LIST_ILONG (LIST_INO | LIST_LONG) - -static const int SPLIT_DIR = 0; -static const int SPLIT_FILE = 1; -static const int SPLIT_SUBDIR = 2; - -#define TYPEINDEX(mode) (((mode) >> 12) & 0x0f) -#define TYPECHAR(mode) ("0pcCd?bB-?l?s???" [TYPEINDEX(mode)]) -#ifdef BB_FEATURE_LS_FILETYPES -#define APPCHAR(mode) ("\0|\0\0/\0\0\0\0\0@\0=\0\0\0" [TYPEINDEX(mode)]) -#endif - -/* - * a directory entry and its stat info are stored here - */ -struct dnode { /* the basic node */ - char *name; /* the dir entry name */ - char *fullname; /* the dir entry name */ - struct stat dstat; /* the file stat info */ - struct dnode *next; /* point at the next node */ -}; -typedef struct dnode dnode_t; - -static struct dnode **list_dir(char *); -static struct dnode **dnalloc(int); -static int list_single(struct dnode *); - -static unsigned int disp_opts; -static unsigned int style_fmt; -static unsigned int list_fmt; -#ifdef BB_FEATURE_LS_SORTFILES -static unsigned int sort_opts; -static unsigned int sort_order; -#endif -#ifdef BB_FEATURE_LS_TIMESTAMPS -static unsigned int time_fmt; -#endif -#ifdef BB_FEATURE_LS_FOLLOWLINKS -static unsigned int follow_links=FALSE; -#endif - -static unsigned short column = 0; -#ifdef BB_FEATURE_AUTOWIDTH -static unsigned short terminal_width = TERMINAL_WIDTH; -static unsigned short column_width = COLUMN_WIDTH; -static unsigned short tabstops = COLUMN_GAP; -#else -static unsigned short column_width = COLUMN_WIDTH; -#endif - -static int status = EXIT_SUCCESS; - -#ifdef BB_FEATURE_HUMAN_READABLE -static unsigned long ls_disp_hr = 0; -#endif - -static int my_stat(struct dnode *cur) -{ -#ifdef BB_FEATURE_LS_FOLLOWLINKS - if (follow_links == TRUE) { - if (stat(cur->fullname, &cur->dstat)) { - perror_msg("%s", cur->fullname); - status = EXIT_FAILURE; - free(cur->fullname); - free(cur); - return -1; - } - } else -#endif - if (lstat(cur->fullname, &cur->dstat)) { - perror_msg("%s", cur->fullname); - status = EXIT_FAILURE; - free(cur->fullname); - free(cur); - return -1; - } - return 0; -} - -static void newline(void) -{ - if (column > 0) { - putchar('\n'); - column = 0; - } -} - -/*----------------------------------------------------------------------*/ -#ifdef BB_FEATURE_LS_FILETYPES -static char append_char(mode_t mode) -{ - if ( !(list_fmt & LIST_FILETYPE)) - return '\0'; - if ((list_fmt & LIST_EXEC) && S_ISREG(mode) - && (mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return '*'; - return APPCHAR(mode); -} -#endif - -/*----------------------------------------------------------------------*/ -static void nexttabstop( void ) -{ - static short nexttab= 0; - int n=0; - - if (column > 0) { - n= nexttab - column; - if (n < 1) n= 1; - while (n--) { - putchar(' '); - column++; - } - } - nexttab= column + column_width + COLUMN_GAP; -} - -/*----------------------------------------------------------------------*/ -static int is_subdir(struct dnode *dn) -{ - return (S_ISDIR(dn->dstat.st_mode) && strcmp(dn->name, ".") != 0 && - strcmp(dn->name, "..") != 0); -} - -static int countdirs(struct dnode **dn, int nfiles) -{ - int i, dirs; - - if (dn==NULL || nfiles < 1) return(0); - dirs= 0; - for (i=0; idstat.st_mode)) dirs++; - } - return(dirs); -} - -static int countsubdirs(struct dnode **dn, int nfiles) -{ - int i, subdirs; - - if (dn == NULL || nfiles < 1) return 0; - subdirs = 0; - for (i = 0; i < nfiles; i++) - if (is_subdir(dn[i])) - subdirs++; - return subdirs; -} - -static int countfiles(struct dnode **dnp) -{ - int nfiles; - struct dnode *cur; - - if (dnp == NULL) return(0); - nfiles= 0; - for (cur= dnp[0]; cur->next != NULL ; cur= cur->next) nfiles++; - nfiles++; - return(nfiles); -} - -/* get memory to hold an array of pointers */ -static struct dnode **dnalloc(int num) -{ - struct dnode **p; - - if (num < 1) return(NULL); - - p= (struct dnode **)xcalloc((size_t)num, (size_t)(sizeof(struct dnode *))); - return(p); -} - -#ifdef BB_FEATURE_LS_RECURSIVE -static void dfree(struct dnode **dnp) -{ - struct dnode *cur, *next; - - if(dnp == NULL) return; - - cur=dnp[0]; - while (cur != NULL) { - if (cur->fullname != NULL) free(cur->fullname); /* free the filename */ - next= cur->next; - free(cur); /* free the dnode */ - cur= next; - } - free(dnp); /* free the array holding the dnode pointers */ -} -#endif - -static struct dnode **splitdnarray(struct dnode **dn, int nfiles, int which) -{ - int dncnt, i, d; - struct dnode **dnp; - - if (dn==NULL || nfiles < 1) return(NULL); - - /* count how many dirs and regular files there are */ - if (which == SPLIT_SUBDIR) - dncnt = countsubdirs(dn, nfiles); - else { - dncnt= countdirs(dn, nfiles); /* assume we are looking for dirs */ - if (which == SPLIT_FILE) - dncnt= nfiles - dncnt; /* looking for files */ - } - - /* allocate a file array and a dir array */ - dnp= dnalloc(dncnt); - - /* copy the entrys into the file or dir array */ - for (d= i=0; idstat.st_mode)) { - dnp[d++]= dn[i]; - } /* else skip the file */ - } else if (which == SPLIT_SUBDIR) { - if (is_subdir(dn[i])) { - dnp[d++]= dn[i]; - } /* else skip the file or dir */ - } else { - if (!(S_ISDIR(dn[i]->dstat.st_mode))) { - dnp[d++]= dn[i]; - } /* else skip the dir */ - } - } - return(dnp); -} - -/*----------------------------------------------------------------------*/ -#ifdef BB_FEATURE_LS_SORTFILES -static int sortcmp(struct dnode *d1, struct dnode *d2) -{ - int cmp, dif; - - cmp= 0; - if (sort_opts == SORT_SIZE) { - dif= (int)(d1->dstat.st_size - d2->dstat.st_size); - } else if (sort_opts == SORT_ATIME) { - dif= (int)(d1->dstat.st_atime - d2->dstat.st_atime); - } else if (sort_opts == SORT_CTIME) { - dif= (int)(d1->dstat.st_ctime - d2->dstat.st_ctime); - } else if (sort_opts == SORT_MTIME) { - dif= (int)(d1->dstat.st_mtime - d2->dstat.st_mtime); - } else if (sort_opts == SORT_DIR) { - dif= S_ISDIR(d1->dstat.st_mode) - S_ISDIR(d2->dstat.st_mode); - /* } else if (sort_opts == SORT_VERSION) { */ - /* } else if (sort_opts == SORT_EXT) { */ - } else { /* assume SORT_NAME */ - dif= 0; - } - - if (dif > 0) cmp= -1; - if (dif < 0) cmp= 1; - if (dif == 0) { - /* sort by name- may be a tie_breaker for time or size cmp */ - dif= strcmp(d1->name, d2->name); - if (dif > 0) cmp= 1; - if (dif < 0) cmp= -1; - } - - if (sort_order == SORT_REVERSE) { - cmp= -1 * cmp; - } - return(cmp); -} - -/*----------------------------------------------------------------------*/ -static void shellsort(struct dnode **dn, int size) -{ - struct dnode *temp; - int gap, i, j; - - /* shell short the array */ - if(dn==NULL || size < 2) return; - - for (gap= size/2; gap>0; gap /=2) { - for (i=gap; i=0; j-=gap) { - if (sortcmp(dn[j], dn[j+gap]) <= 0) - break; - /* they are out of order, swap them */ - temp= dn[j]; - dn[j]= dn[j+gap]; - dn[j+gap]= temp; - } - } - } -} -#endif - -/*----------------------------------------------------------------------*/ -static void showfiles(struct dnode **dn, int nfiles) -{ - int i, ncols, nrows, row, nc; -#ifdef BB_FEATURE_AUTOWIDTH - int len; -#endif - - if(dn==NULL || nfiles < 1) return; - -#ifdef BB_FEATURE_AUTOWIDTH - /* find the longest file name- use that as the column width */ - column_width= 0; - for (i=0; iname) + - ((list_fmt & LIST_INO) ? 8 : 0) + - ((list_fmt & LIST_BLOCKS) ? 5 : 0) - ; - if (column_width < len) - column_width= len; - } - if (column_width >= 6) - ncols = (int)(terminal_width / (column_width + COLUMN_GAP)); - else { - ncols = 1; - column_width = COLUMN_WIDTH; - } -#else - ncols= TERMINAL_WIDTH; -#endif - switch (style_fmt) { - case STYLE_LONG: /* one record per line, extended info */ - case STYLE_SINGLE: /* one record per line */ - ncols= 1; - break; - } - - if (ncols > 1) { - nrows = nfiles / ncols; - } else { - nrows = nfiles; - ncols = 1; - } - if ((nrows * ncols) < nfiles) nrows++; /* round up fractionals */ - - if (nrows > nfiles) nrows= nfiles; - for (row=0; rowfullname); - } - subdnp= list_dir(dn[i]->fullname); - nfiles= countfiles(subdnp); - if (nfiles > 0) { - /* list all files at this level */ -#ifdef BB_FEATURE_LS_SORTFILES - shellsort(subdnp, nfiles); -#endif - showfiles(subdnp, nfiles); -#ifdef BB_FEATURE_LS_RECURSIVE - if (disp_opts & DISP_RECURSIVE) { - /* recursive- list the sub-dirs */ - dnd= splitdnarray(subdnp, nfiles, SPLIT_SUBDIR); - dndirs= countsubdirs(subdnp, nfiles); - if (dndirs > 0) { -#ifdef BB_FEATURE_LS_SORTFILES - shellsort(dnd, dndirs); -#endif - showdirs(dnd, dndirs); - free(dnd); /* free the array of dnode pointers to the dirs */ - } - } - dfree(subdnp); /* free the dnodes and the fullname mem */ -#endif - } - } -} - -/*----------------------------------------------------------------------*/ -static struct dnode **list_dir(char *path) -{ - struct dnode *dn, *cur, **dnp; - struct dirent *entry; - DIR *dir; - int i, nfiles; - - if (path==NULL) return(NULL); - - dn= NULL; - nfiles= 0; - dir = opendir(path); - if (dir == NULL) { - perror_msg("%s", path); - status = EXIT_FAILURE; - return(NULL); /* could not open the dir */ - } - while ((entry = readdir(dir)) != NULL) { - /* are we going to list the file- it may be . or .. or a hidden file */ - if ((strcmp(entry->d_name, ".")==0) && !(disp_opts & DISP_DOT)) - continue; - if ((strcmp(entry->d_name, "..")==0) && !(disp_opts & DISP_DOT)) - continue; - if ((entry->d_name[0] == '.') && !(disp_opts & DISP_HIDDEN)) - continue; - cur= (struct dnode *)xmalloc(sizeof(struct dnode)); - cur->fullname = concat_path_file(path, entry->d_name); - cur->name = cur->fullname + - (strlen(cur->fullname) - strlen(entry->d_name)); - if (my_stat(cur)) - continue; - cur->next= dn; - dn= cur; - nfiles++; - } - closedir(dir); - - /* now that we know how many files there are - ** allocate memory for an array to hold dnode pointers - */ - if (nfiles < 1) return(NULL); - dnp= dnalloc(nfiles); - for (i=0, cur=dn; inext; - } - - return(dnp); -} - -/*----------------------------------------------------------------------*/ -static int list_single(struct dnode *dn) -{ - int i; - char scratch[BUFSIZ + 1]; -#ifdef BB_FEATURE_LS_TIMESTAMPS - char *filetime; - time_t ttime, age; -#endif -#if defined (BB_FEATURE_LS_FILETYPES) - struct stat info; -#endif -#ifdef BB_FEATURE_LS_FILETYPES - char append; -#endif - - if (dn==NULL || dn->fullname==NULL) return(0); - -#ifdef BB_FEATURE_LS_TIMESTAMPS - ttime= dn->dstat.st_mtime; /* the default time */ - if (time_fmt & TIME_ACCESS) ttime= dn->dstat.st_atime; - if (time_fmt & TIME_CHANGE) ttime= dn->dstat.st_ctime; - filetime= ctime(&ttime); -#endif -#ifdef BB_FEATURE_LS_FILETYPES - append = append_char(dn->dstat.st_mode); -#endif - - for (i=0; i<=31; i++) { - switch (list_fmt & (1<dstat.st_ino); - column += 8; - break; - case LIST_BLOCKS: -#ifdef BB_FEATURE_HUMAN_READABLE - fprintf(stdout, "%6s ", make_human_readable_str(dn->dstat.st_blocks>>1, - KILOBYTE, (ls_disp_hr==TRUE)? 0: KILOBYTE)); -#else -#if _FILE_OFFSET_BITS == 64 - printf("%4lld ", dn->dstat.st_blocks>>1); -#else - printf("%4ld ", dn->dstat.st_blocks>>1); -#endif -#endif - column += 5; - break; - case LIST_MODEBITS: - printf("%-10s ", (char *)mode_string(dn->dstat.st_mode)); - column += 10; - break; - case LIST_NLINKS: - printf("%4ld ", (long)dn->dstat.st_nlink); - column += 10; - break; - case LIST_ID_NAME: -#ifdef BB_FEATURE_LS_USERNAME - my_getpwuid(scratch, dn->dstat.st_uid); - printf("%-8.8s ", scratch); - my_getgrgid(scratch, dn->dstat.st_gid); - printf("%-8.8s", scratch); - column += 17; - break; -#endif - case LIST_ID_NUMERIC: - printf("%-8d %-8d", dn->dstat.st_uid, dn->dstat.st_gid); - column += 17; - break; - case LIST_SIZE: - case LIST_DEV: - if (S_ISBLK(dn->dstat.st_mode) || S_ISCHR(dn->dstat.st_mode)) { - printf("%4d, %3d ", (int)MAJOR(dn->dstat.st_rdev), (int)MINOR(dn->dstat.st_rdev)); - } else { -#ifdef BB_FEATURE_HUMAN_READABLE - if (ls_disp_hr==TRUE) { - fprintf(stdout, "%8s ", make_human_readable_str(dn->dstat.st_size, 1, 0)); - } else -#endif - { -#if _FILE_OFFSET_BITS == 64 - printf("%9lld ", (long long)dn->dstat.st_size); -#else - printf("%9ld ", dn->dstat.st_size); -#endif - } - } - column += 10; - break; -#ifdef BB_FEATURE_LS_TIMESTAMPS - case LIST_FULLTIME: - case LIST_DATE_TIME: - if (list_fmt & LIST_FULLTIME) { - printf("%24.24s ", filetime); - column += 25; - break; - } - age = time(NULL) - ttime; - printf("%6.6s ", filetime+4); - if (age < 3600L * 24 * 365 / 2 && age > -15 * 60) { - /* hh:mm if less than 6 months old */ - printf("%5.5s ", filetime+11); - } else { - printf(" %4.4s ", filetime+20); - } - column += 13; - break; -#endif - case LIST_FILENAME: - printf("%s", dn->name); - column += strlen(dn->name); - break; - case LIST_SYMLINK: - if (S_ISLNK(dn->dstat.st_mode)) { - char *lpath = xreadlink(dn->fullname); - if (lpath) { - printf(" -> %s", lpath); -#ifdef BB_FEATURE_LS_FILETYPES - if (!stat(dn->fullname, &info)) { - append = append_char(info.st_mode); - } -#endif - column += strlen(lpath) + 4; - free(lpath); - } - } - break; -#ifdef BB_FEATURE_LS_FILETYPES - case LIST_FILETYPE: - if (append != '\0') { - printf("%1c", append); - column++; - } - break; -#endif - } - } - - return(0); -} - -/*----------------------------------------------------------------------*/ -extern int ls_main(int argc, char **argv) -{ - struct dnode **dnf, **dnd; - int dnfiles, dndirs; - struct dnode *dn, *cur, **dnp; - int i, nfiles; - int opt; - int oi, ac; - char **av; -#ifdef BB_FEATURE_AUTOWIDTH - struct winsize win = { 0, 0, 0, 0 }; -#endif - - disp_opts= DISP_NORMAL; - style_fmt= STYLE_AUTO; - list_fmt= LIST_SHORT; -#ifdef BB_FEATURE_LS_SORTFILES - sort_opts= SORT_NAME; - sort_order= SORT_FORWARD; -#endif -#ifdef BB_FEATURE_LS_TIMESTAMPS - time_fmt= TIME_MOD; -#endif -#ifdef BB_FEATURE_AUTOWIDTH - ioctl(fileno(stdout), TIOCGWINSZ, &win); - if (win.ws_row > 4) - column_width = win.ws_row - 2; - if (win.ws_col > 0) - terminal_width = win.ws_col - 1; -#endif - nfiles=0; - - /* process options */ - while ((opt = getopt(argc, argv, "1AaCdgilnsx" -#ifdef BB_FEATURE_AUTOWIDTH -"T:w:" -#endif -#ifdef BB_FEATURE_LS_FILETYPES -"Fp" -#endif -#ifdef BB_FEATURE_LS_RECURSIVE -"R" -#endif -#ifdef BB_FEATURE_LS_SORTFILES -"rSvX" -#endif -#ifdef BB_FEATURE_LS_TIMESTAMPS -"cetu" -#endif -#ifdef BB_FEATURE_LS_FOLLOWLINKS -"L" -#endif -#ifdef BB_FEATURE_HUMAN_READABLE -"h" -#endif -"k")) > 0) { - switch (opt) { - case '1': style_fmt = STYLE_SINGLE; break; - case 'A': disp_opts |= DISP_HIDDEN; break; - case 'a': disp_opts |= DISP_HIDDEN | DISP_DOT; break; - case 'C': style_fmt = STYLE_COLUMNS; break; - case 'd': disp_opts |= DISP_NOLIST; break; - case 'g': /* ignore -- for ftp servers */ break; - case 'i': list_fmt |= LIST_INO; break; - case 'l': - style_fmt = STYLE_LONG; - list_fmt |= LIST_LONG; -#ifdef BB_FEATURE_HUMAN_READABLE - ls_disp_hr = FALSE; -#endif - break; - case 'n': list_fmt |= LIST_ID_NUMERIC; break; - case 's': list_fmt |= LIST_BLOCKS; break; - case 'x': disp_opts = DISP_ROWS; break; -#ifdef BB_FEATURE_LS_FILETYPES - case 'F': list_fmt |= LIST_FILETYPE | LIST_EXEC; break; - case 'p': list_fmt |= LIST_FILETYPE; break; -#endif -#ifdef BB_FEATURE_LS_RECURSIVE - case 'R': disp_opts |= DISP_RECURSIVE; break; -#endif -#ifdef BB_FEATURE_LS_SORTFILES - case 'r': sort_order |= SORT_REVERSE; break; - case 'S': sort_opts= SORT_SIZE; break; - case 'v': sort_opts= SORT_VERSION; break; - case 'X': sort_opts= SORT_EXT; break; -#endif -#ifdef BB_FEATURE_LS_TIMESTAMPS - case 'e': list_fmt |= LIST_FULLTIME; break; - case 'c': - time_fmt = TIME_CHANGE; -#ifdef BB_FEATURE_LS_SORTFILES - sort_opts= SORT_CTIME; -#endif - break; - case 'u': - time_fmt = TIME_ACCESS; -#ifdef BB_FEATURE_LS_SORTFILES - sort_opts= SORT_ATIME; -#endif - break; - case 't': -#ifdef BB_FEATURE_LS_SORTFILES - sort_opts= SORT_MTIME; -#endif - break; -#endif -#ifdef BB_FEATURE_LS_FOLLOWLINKS - case 'L': follow_links= TRUE; break; -#endif -#ifdef BB_FEATURE_AUTOWIDTH - case 'T': tabstops= atoi(optarg); break; - case 'w': terminal_width= atoi(optarg); break; -#endif -#ifdef BB_FEATURE_HUMAN_READABLE - case 'h': ls_disp_hr = TRUE; break; -#endif - case 'k': break; - default: - goto print_usage_message; - } - } - - /* sort out which command line options take precedence */ -#ifdef BB_FEATURE_LS_RECURSIVE - if (disp_opts & DISP_NOLIST) - disp_opts &= ~DISP_RECURSIVE; /* no recurse if listing only dir */ -#endif -#if defined (BB_FEATURE_LS_TIMESTAMPS) && defined (BB_FEATURE_LS_SORTFILES) - if (time_fmt & TIME_CHANGE) sort_opts= SORT_CTIME; - if (time_fmt & TIME_ACCESS) sort_opts= SORT_ATIME; -#endif - if (style_fmt != STYLE_LONG) - list_fmt &= ~LIST_ID_NUMERIC; /* numeric uid only for long list */ -#ifdef BB_FEATURE_LS_USERNAME - if (style_fmt == STYLE_LONG && (list_fmt & LIST_ID_NUMERIC)) - list_fmt &= ~LIST_ID_NAME; /* don't list names if numeric uid */ -#endif - - /* choose a display format */ - if (style_fmt == STYLE_AUTO) - style_fmt = isatty(fileno(stdout)) ? STYLE_COLUMNS : STYLE_SINGLE; - - /* - * when there are no cmd line args we have to supply a default "." arg. - * we will create a second argv array, "av" that will hold either - * our created "." arg, or the real cmd line args. The av array - * just holds the pointers- we don't move the date the pointers - * point to. - */ - ac= argc - optind; /* how many cmd line args are left */ - if (ac < 1) { - av= (char **)xcalloc((size_t)1, (size_t)(sizeof(char *))); - av[0]= xstrdup("."); - ac=1; - } else { - av= (char **)xcalloc((size_t)ac, (size_t)(sizeof(char *))); - for (oi=0 ; oi < ac; oi++) { - av[oi]= argv[optind++]; /* copy pointer to real cmd line arg */ - } - } - - /* now, everything is in the av array */ - if (ac > 1) - disp_opts |= DISP_DIRNAME; /* 2 or more items? label directories */ - - /* stuff the command line file names into an dnode array */ - dn=NULL; - for (oi=0 ; oi < ac; oi++) { - cur= (struct dnode *)xmalloc(sizeof(struct dnode)); - cur->fullname= xstrdup(av[oi]); - cur->name= cur->fullname; - if (my_stat(cur)) - continue; - cur->next= dn; - dn= cur; - nfiles++; - } - - /* now that we know how many files there are - ** allocate memory for an array to hold dnode pointers - */ - dnp= dnalloc(nfiles); - for (i=0, cur=dn; inext; - } - - - if (disp_opts & DISP_NOLIST) { -#ifdef BB_FEATURE_LS_SORTFILES - shellsort(dnp, nfiles); -#endif - if (nfiles > 0) showfiles(dnp, nfiles); - } else { - dnd= splitdnarray(dnp, nfiles, SPLIT_DIR); - dnf= splitdnarray(dnp, nfiles, SPLIT_FILE); - dndirs= countdirs(dnp, nfiles); - dnfiles= nfiles - dndirs; - if (dnfiles > 0) { -#ifdef BB_FEATURE_LS_SORTFILES - shellsort(dnf, dnfiles); -#endif - showfiles(dnf, dnfiles); - } - if (dndirs > 0) { -#ifdef BB_FEATURE_LS_SORTFILES - shellsort(dnd, dndirs); -#endif - showdirs(dnd, dndirs); - } - } - return(status); - - print_usage_message: - show_usage(); -} diff --git a/lsmod.c b/lsmod.c deleted file mode 100644 index 76ed2fdd8..000000000 --- a/lsmod.c +++ /dev/null @@ -1,166 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini lsmod implementation for busybox - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , - * - * Modified by Alcove, Julien Gaulmin and - * Nicolas Ferre to support pre 2.1 kernels - * (which lack the query_module() interface). - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" - - - -#ifdef BB_FEATURE_NEW_MODULE_INTERFACE - -struct module_info -{ - unsigned long addr; - unsigned long size; - unsigned long flags; - long usecount; -}; - - -int query_module(const char *name, int which, void *buf, size_t bufsize, size_t *ret); - -/* Values for query_module's which. */ -static const int QM_MODULES = 1; -static const int QM_DEPS = 2; -static const int QM_REFS = 3; -static const int QM_SYMBOLS = 4; -static const int QM_INFO = 5; - -/* Bits of module.flags. */ -static const int NEW_MOD_RUNNING = 1; -static const int NEW_MOD_DELETED = 2; -static const int NEW_MOD_AUTOCLEAN = 4; -static const int NEW_MOD_VISITED = 8; -static const int NEW_MOD_USED_ONCE = 16; -static const int NEW_MOD_INITIALIZING = 64; - -static int my_query_module(const char *name, int which, void **buf, - size_t *bufsize, size_t *ret) -{ - int my_ret; - - my_ret = query_module(name, which, *buf, *bufsize, ret); - - if (my_ret == -1 && errno == ENOSPC) { - *buf = xrealloc(*buf, *ret); - *bufsize = *ret; - - my_ret = query_module(name, which, *buf, *bufsize, ret); - } - - return my_ret; -} - -extern int lsmod_main(int argc, char **argv) -{ - struct module_info info; - char *module_names, *mn, *deps, *dn; - size_t bufsize, depsize, nmod, count, i, j; - - module_names = xmalloc(bufsize = 256); - if (my_query_module(NULL, QM_MODULES, (void **)&module_names, &bufsize, - &nmod)) { - perror_msg_and_die("QM_MODULES"); - } - - deps = xmalloc(depsize = 256); - printf("Module Size Used by\n"); - for (i = 0, mn = module_names; i < nmod; mn += strlen(mn) + 1, i++) { - if (query_module(mn, QM_INFO, &info, sizeof(info), &count)) { - if (errno == ENOENT) { - /* The module was removed out from underneath us. */ - continue; - } - /* else choke */ - perror_msg_and_die("module %s: QM_INFO", mn); - } - if (my_query_module(mn, QM_REFS, (void **)&deps, &depsize, &count)) { - if (errno == ENOENT) { - /* The module was removed out from underneath us. */ - continue; - } - perror_msg_and_die("module %s: QM_REFS", mn); - } - printf("%-20s%8lu%4ld ", mn, info.size, info.usecount); - if (info.flags & NEW_MOD_DELETED) - printf("(deleted)"); - else if (info.flags & NEW_MOD_INITIALIZING) - printf("(initializing)"); - else if (!(info.flags & NEW_MOD_RUNNING)) - printf("(uninitialized)"); - else { - if (info.flags & NEW_MOD_AUTOCLEAN) - printf("(autoclean) "); - if (!(info.flags & NEW_MOD_USED_ONCE)) - printf("(unused)"); - } - if (count) printf("["); - for (j = 0, dn = deps; j < count; dn += strlen(dn) + 1, j++) { - printf("%s%s", dn, (j==count-1)? "":" "); - } - if (count) printf("] "); - - printf("\n"); - } - - - return( 0); -} - -#else /*BB_FEATURE_OLD_MODULE_INTERFACE*/ - -extern int lsmod_main(int argc, char **argv) -{ - int fd, i; - char line[128]; - - puts("Module Size Used by"); - fflush(stdout); - - if ((fd = open("/proc/modules", O_RDONLY)) >= 0 ) { - while ((i = read(fd, line, sizeof(line))) > 0) { - write(fileno(stdout), line, i); - } - close(fd); - return 0; - } - perror_msg_and_die("/proc/modules"); - return 1; -} - -#endif /*BB_FEATURE_OLD_MODULE_INTERFACE*/ diff --git a/makedevs.c b/makedevs.c deleted file mode 100644 index b8c6dd1d8..000000000 --- a/makedevs.c +++ /dev/null @@ -1,95 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * public domain -- Dave 'Kill a Cop' Cinege - * - * makedevs - * Make ranges of device files quickly. - * known bugs: can't deal with alpha ranges - */ - -#include -#include -#include -#include -#include -#include -#include "busybox.h" - -int makedevs_main(int argc, char **argv) -{ - - const char *basedev = argv[1]; - const char *type = argv[2]; - int major = atoi(argv[3]); - int Sminor = atoi(argv[4]); - int S = atoi(argv[5]); - int E = atoi(argv[6]); - int sbase = argc == 8 ? 1 : 0; - - mode_t mode = 0; - dev_t dev = 0; - char devname[255]; - char buf[255]; - - if (argc < 7 || *argv[1]=='-') - show_usage(); - - switch (type[0]) { - case 'c': - mode = S_IFCHR; - break; - case 'b': - mode = S_IFBLK; - break; - case 'f': - mode = S_IFIFO; - break; - default: - show_usage(); - } - mode |= 0660; - - while (S <= E) { - - if (type[0] != 'f') - dev = (major << 8) | Sminor; - strcpy(devname, basedev); - - if (sbase == 0) { - sprintf(buf, "%d", S); - strcat(devname, buf); - } else { - sbase = 0; - } - - if (mknod(devname, mode, dev)) - printf("Failed to create: %s\n", devname); - - S++; - Sminor++; - } - - return 0; -} - -/* -And this is what this program replaces. The shell is too slow! - -makedev () { -local basedev=$1; local S=$2; local E=$3 -local major=$4; local Sminor=$5; local type=$6 -local sbase=$7 - - if [ ! "$sbase" = "" ]; then - mknod "$basedev" $type $major $Sminor - S=`expr $S + 1` - Sminor=`expr $Sminor + 1` - fi - - while [ $S -le $E ]; do - mknod "$basedev$S" $type $major $Sminor - S=`expr $S + 1` - Sminor=`expr $Sminor + 1` - done -} -*/ diff --git a/md5sum.c b/md5sum.c deleted file mode 100644 index bb4d115ca..000000000 --- a/md5sum.c +++ /dev/null @@ -1,1074 +0,0 @@ -/* md5sum.c - Compute MD5 checksum of files or strings according to the - * definition of MD5 in RFC 1321 from April 1992. - * Copyright (C) 1995-1999 Free Software Foundation, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* Written by Ulrich Drepper */ -/* Hacked to work with BusyBox by Alfred M. Szmidt */ - -/* - * June 29, 2001 Manuel Novoa III - * - * Added MD5SUM_SIZE_VS_SPEED configuration option. - * - * Current valid values, with data from my system for comparison, are: - * (using uClibc and running on linux-2.4.4.tar.bz2) - * user times (sec) text size (386) - * 0 (fastest) 1.1 6144 - * 1 1.4 5392 - * 2 3.0 5088 - * 3 (smallest) 5.1 4912 - */ - -#define MD5SUM_SIZE_VS_SPEED 2 - -/**********************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#if defined HAVE_LIMITS_H -# include -#endif -#include "busybox.h" - -/* For some silly reason, this file uses backwards TRUE and FALSE conventions */ -#undef TRUE -#undef FALSE -#define FALSE ((int) 1) -#define TRUE ((int) 0) - -//---------------------------------------------------------------------------- -//--------md5.c -//---------------------------------------------------------------------------- - -/* md5.c - Functions to compute MD5 message digest of files or memory blocks - * according to the definition of MD5 in RFC 1321 from April 1992. - */ - -/* Written by Ulrich Drepper , 1995. */ - -//---------------------------------------------------------------------------- -//--------md5.h -//---------------------------------------------------------------------------- - -/* md5.h - Declaration of functions and data types used for MD5 sum - computing library functions. */ - -typedef u_int32_t md5_uint32; - -/* Structure to save state of computation between the single steps. */ -struct md5_ctx -{ - md5_uint32 A; - md5_uint32 B; - md5_uint32 C; - md5_uint32 D; - - md5_uint32 total[2]; - md5_uint32 buflen; - char buffer[128]; -}; - -/* - * The following three functions are build up the low level used in - * the functions `md5_stream' and `md5_buffer'. - */ - -/* Initialize structure containing state of computation. - (RFC 1321, 3.3: Step 3) */ -static void md5_init_ctx __P ((struct md5_ctx *ctx)); - -/* Starting with the result of former calls of this function (or the - initialization function update the context for the next LEN bytes - starting at BUFFER. - It is necessary that LEN is a multiple of 64!!! */ -static void md5_process_block __P ((const void *buffer, size_t len, - struct md5_ctx *ctx)); - -/* Starting with the result of former calls of this function (or the - initialization function update the context for the next LEN bytes - starting at BUFFER. - It is NOT required that LEN is a multiple of 64. */ -static void md5_process_bytes __P ((const void *buffer, size_t len, - struct md5_ctx *ctx)); - -/* Process the remaining bytes in the buffer and put result from CTX - in first 16 bytes following RESBUF. The result is always in little - endian byte order, so that a byte-wise output yields to the wanted - ASCII representation of the message digest. - - IMPORTANT: On some systems it is required that RESBUF is correctly - aligned for a 32 bits value. */ -static void *md5_finish_ctx __P ((struct md5_ctx *ctx, void *resbuf)); - - - - -/* Compute MD5 message digest for bytes read from STREAM. The - resulting message digest number will be written into the 16 bytes - beginning at RESBLOCK. */ -static int md5_stream __P ((FILE *stream, void *resblock)); - -/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The - result is always in little endian byte order, so that a byte-wise - output yields to the wanted ASCII representation of the message - digest. */ -static void *md5_buffer __P ((const char *buffer, size_t len, void *resblock)); - -//---------------------------------------------------------------------------- -//--------end of md5.h -//---------------------------------------------------------------------------- - -/* Handle endian-ness */ -#if __BYTE_ORDER == __LITTLE_ENDIAN - #define SWAP(n) (n) -#else - #define SWAP(n) ((n << 24) | ((n&65280)<<8) | ((n&16711680)>>8) | (n>>24)) -#endif - - - -#if MD5SUM_SIZE_VS_SPEED == 0 -/* This array contains the bytes used to pad the buffer to the next - 64-byte boundary. (RFC 1321, 3.1: Step 1) */ -static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; -#endif - -/* Initialize structure containing state of computation. - (RFC 1321, 3.3: Step 3) */ -void md5_init_ctx(struct md5_ctx *ctx) -{ - ctx->A = 0x67452301; - ctx->B = 0xefcdab89; - ctx->C = 0x98badcfe; - ctx->D = 0x10325476; - - ctx->total[0] = ctx->total[1] = 0; - ctx->buflen = 0; -} - -/* Process the remaining bytes in the internal buffer and the usual - prolog according to the standard and write the result to RESBUF. - - IMPORTANT: On some systems it is required that RESBUF is correctly - aligned for a 32 bits value. */ -static void *md5_finish_ctx(struct md5_ctx *ctx, void *resbuf) -{ - /* Take yet unprocessed bytes into account. */ - md5_uint32 bytes = ctx->buflen; - size_t pad; - - /* Now count remaining bytes. */ - ctx->total[0] += bytes; - if (ctx->total[0] < bytes) - ++ctx->total[1]; - - pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes; -#if MD5SUM_SIZE_VS_SPEED > 0 - memset(&ctx->buffer[bytes], 0, pad); - ctx->buffer[bytes] = 0x80; -#else - memcpy(&ctx->buffer[bytes], fillbuf, pad); -#endif - - /* Put the 64-bit file length in *bits* at the end of the buffer. */ - *(md5_uint32 *) & ctx->buffer[bytes + pad] = SWAP(ctx->total[0] << 3); - *(md5_uint32 *) & ctx->buffer[bytes + pad + 4] = - SWAP( ((ctx->total[1] << 3) | (ctx->total[0] >> 29)) ); - - /* Process last bytes. */ - md5_process_block(ctx->buffer, bytes + pad + 8, ctx); - -/* Put result from CTX in first 16 bytes following RESBUF. The result is - always in little endian byte order, so that a byte-wise output yields - to the wanted ASCII representation of the message digest. - - IMPORTANT: On some systems it is required that RESBUF is correctly - aligned for a 32 bits value. */ - ((md5_uint32 *) resbuf)[0] = SWAP(ctx->A); - ((md5_uint32 *) resbuf)[1] = SWAP(ctx->B); - ((md5_uint32 *) resbuf)[2] = SWAP(ctx->C); - ((md5_uint32 *) resbuf)[3] = SWAP(ctx->D); - - return resbuf; -} - -/* Compute MD5 message digest for bytes read from STREAM. The - resulting message digest number will be written into the 16 bytes - beginning at RESBLOCK. */ -static int md5_stream(FILE *stream, void *resblock) -{ - /* Important: BLOCKSIZE must be a multiple of 64. */ -static const int BLOCKSIZE = 4096; - struct md5_ctx ctx; - char buffer[BLOCKSIZE + 72]; - size_t sum; - - /* Initialize the computation context. */ - md5_init_ctx(&ctx); - - /* Iterate over full file contents. */ - while (1) { - /* We read the file in blocks of BLOCKSIZE bytes. One call of the - computation function processes the whole buffer so that with the - next round of the loop another block can be read. */ - size_t n; - sum = 0; - - /* Read block. Take care for partial reads. */ - do { - n = fread(buffer + sum, 1, BLOCKSIZE - sum, stream); - - sum += n; - } - while (sum < BLOCKSIZE && n != 0); - if (n == 0 && ferror(stream)) - return 1; - - /* If end of file is reached, end the loop. */ - if (n == 0) - break; - - /* Process buffer with BLOCKSIZE bytes. Note that - BLOCKSIZE % 64 == 0 - */ - md5_process_block(buffer, BLOCKSIZE, &ctx); - } - - /* Add the last bytes if necessary. */ - if (sum > 0) - md5_process_bytes(buffer, sum, &ctx); - - /* Construct result in desired memory. */ - md5_finish_ctx(&ctx, resblock); - return 0; -} - -/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The - result is always in little endian byte order, so that a byte-wise - output yields to the wanted ASCII representation of the message - digest. */ -static void *md5_buffer(const char *buffer, size_t len, void *resblock) -{ - struct md5_ctx ctx; - - /* Initialize the computation context. */ - md5_init_ctx(&ctx); - - /* Process whole buffer but last len % 64 bytes. */ - md5_process_bytes(buffer, len, &ctx); - - /* Put result in desired memory area. */ - return md5_finish_ctx(&ctx, resblock); -} - -static void md5_process_bytes(const void *buffer, size_t len, struct md5_ctx *ctx) -{ - /* When we already have some bits in our internal buffer concatenate - both inputs first. */ - if (ctx->buflen != 0) { - size_t left_over = ctx->buflen; - size_t add = 128 - left_over > len ? len : 128 - left_over; - - memcpy(&ctx->buffer[left_over], buffer, add); - ctx->buflen += add; - - if (left_over + add > 64) { - md5_process_block(ctx->buffer, (left_over + add) & ~63, ctx); - /* The regions in the following copy operation cannot overlap. */ - memcpy(ctx->buffer, &ctx->buffer[(left_over + add) & ~63], - (left_over + add) & 63); - ctx->buflen = (left_over + add) & 63; - } - - buffer = (const char *) buffer + add; - len -= add; - } - - /* Process available complete blocks. */ - if (len > 64) { - md5_process_block(buffer, len & ~63, ctx); - buffer = (const char *) buffer + (len & ~63); - len &= 63; - } - - /* Move remaining bytes in internal buffer. */ - if (len > 0) { - memcpy(ctx->buffer, buffer, len); - ctx->buflen = len; - } -} - -/* These are the four functions used in the four steps of the MD5 algorithm - and defined in the RFC 1321. The first function is a little bit optimized - (as found in Colin Plumbs public domain implementation). */ -/* #define FF(b, c, d) ((b & c) | (~b & d)) */ -#define FF(b, c, d) (d ^ (b & (c ^ d))) -#define FG(b, c, d) FF (d, b, c) -#define FH(b, c, d) (b ^ c ^ d) -#define FI(b, c, d) (c ^ (b | ~d)) - -/* Process LEN bytes of BUFFER, accumulating context into CTX. - It is assumed that LEN % 64 == 0. */ -static void md5_process_block(const void *buffer, size_t len, struct md5_ctx *ctx) -{ - md5_uint32 correct_words[16]; - const md5_uint32 *words = buffer; - size_t nwords = len / sizeof(md5_uint32); - const md5_uint32 *endp = words + nwords; -#if MD5SUM_SIZE_VS_SPEED > 0 - static const md5_uint32 C_array[] = { - /* round 1 */ - 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, - 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, - 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, - 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, - /* round 2 */ - 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, - 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8, - 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, - 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, - /* round 3 */ - 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, - 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, - 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05, - 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, - /* round 4 */ - 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, - 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, - 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, - 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 - }; - - static const char P_array[] = { -#if MD5SUM_SIZE_VS_SPEED > 1 - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 1 */ -#endif - 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, /* 2 */ - 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, /* 3 */ - 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 /* 4 */ - }; - -#if MD5SUM_SIZE_VS_SPEED > 1 - static const char S_array[] = { - 7, 12, 17, 22, - 5, 9, 14, 20, - 4, 11, 16, 23, - 6, 10, 15, 21 - }; -#endif -#endif - - md5_uint32 A = ctx->A; - md5_uint32 B = ctx->B; - md5_uint32 C = ctx->C; - md5_uint32 D = ctx->D; - - /* First increment the byte count. RFC 1321 specifies the possible - length of the file up to 2^64 bits. Here we only compute the - number of bytes. Do a double word increment. */ - ctx->total[0] += len; - if (ctx->total[0] < len) - ++ctx->total[1]; - - /* Process all bytes in the buffer with 64 bytes in each round of - the loop. */ - while (words < endp) { - md5_uint32 *cwp = correct_words; - md5_uint32 A_save = A; - md5_uint32 B_save = B; - md5_uint32 C_save = C; - md5_uint32 D_save = D; - -#if MD5SUM_SIZE_VS_SPEED > 1 -#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s))) - - const md5_uint32 *pc; - const char *pp; - const char *ps; - int i; - md5_uint32 temp; - - for ( i=0 ; i < 16 ; i++ ) { - cwp[i] = SWAP(words[i]); - } - words += 16; - -#if MD5SUM_SIZE_VS_SPEED > 2 - pc = C_array; pp = P_array; ps = S_array - 4; - - for ( i = 0 ; i < 64 ; i++ ) { - if ((i&0x0f) == 0) ps += 4; - temp = A; - switch (i>>4) { - case 0: - temp += FF(B,C,D); - break; - case 1: - temp += FG(B,C,D); - break; - case 2: - temp += FH(B,C,D); - break; - case 3: - temp += FI(B,C,D); - } - temp += cwp[(int)(*pp++)] + *pc++; - temp = CYCLIC (temp, ps[i&3]); - temp += B; - A = D; D = C; C = B; B = temp; - } -#else - pc = C_array; pp = P_array; ps = S_array; - - for ( i = 0 ; i < 16 ; i++ ) { - temp = A + FF(B,C,D) + cwp[(int)(*pp++)] + *pc++; - temp = CYCLIC (temp, ps[i&3]); - temp += B; - A = D; D = C; C = B; B = temp; - } - - ps += 4; - for ( i = 0 ; i < 16 ; i++ ) { - temp = A + FG(B,C,D) + cwp[(int)(*pp++)] + *pc++; - temp = CYCLIC (temp, ps[i&3]); - temp += B; - A = D; D = C; C = B; B = temp; - } - ps += 4; - for ( i = 0 ; i < 16 ; i++ ) { - temp = A + FH(B,C,D) + cwp[(int)(*pp++)] + *pc++; - temp = CYCLIC (temp, ps[i&3]); - temp += B; - A = D; D = C; C = B; B = temp; - } - ps += 4; - for ( i = 0 ; i < 16 ; i++ ) { - temp = A + FI(B,C,D) + cwp[(int)(*pp++)] + *pc++; - temp = CYCLIC (temp, ps[i&3]); - temp += B; - A = D; D = C; C = B; B = temp; - } - -#endif -#else - /* First round: using the given function, the context and a constant - the next context is computed. Because the algorithms processing - unit is a 32-bit word and it is determined to work on words in - little endian byte order we perhaps have to change the byte order - before the computation. To reduce the work for the next steps - we store the swapped words in the array CORRECT_WORDS. */ - -#define OP(a, b, c, d, s, T) \ - do \ - { \ - a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \ - ++words; \ - CYCLIC (a, s); \ - a += b; \ - } \ - while (0) - - /* It is unfortunate that C does not provide an operator for - cyclic rotation. Hope the C compiler is smart enough. */ - /* gcc 2.95.4 seems to be --aaronl */ -#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s))) - - /* Before we start, one word to the strange constants. - They are defined in RFC 1321 as - - T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64 - */ - -#if MD5SUM_SIZE_VS_SPEED == 1 - const md5_uint32 *pc; - const char *pp; - int i; -#endif - - /* Round 1. */ -#if MD5SUM_SIZE_VS_SPEED == 1 - pc = C_array; - for ( i=0 ; i < 4 ; i++ ) { - OP(A, B, C, D, 7, *pc++); - OP(D, A, B, C, 12, *pc++); - OP(C, D, A, B, 17, *pc++); - OP(B, C, D, A, 22, *pc++); - } -#else - OP(A, B, C, D, 7, 0xd76aa478); - OP(D, A, B, C, 12, 0xe8c7b756); - OP(C, D, A, B, 17, 0x242070db); - OP(B, C, D, A, 22, 0xc1bdceee); - OP(A, B, C, D, 7, 0xf57c0faf); - OP(D, A, B, C, 12, 0x4787c62a); - OP(C, D, A, B, 17, 0xa8304613); - OP(B, C, D, A, 22, 0xfd469501); - OP(A, B, C, D, 7, 0x698098d8); - OP(D, A, B, C, 12, 0x8b44f7af); - OP(C, D, A, B, 17, 0xffff5bb1); - OP(B, C, D, A, 22, 0x895cd7be); - OP(A, B, C, D, 7, 0x6b901122); - OP(D, A, B, C, 12, 0xfd987193); - OP(C, D, A, B, 17, 0xa679438e); - OP(B, C, D, A, 22, 0x49b40821); -#endif - - /* For the second to fourth round we have the possibly swapped words - in CORRECT_WORDS. Redefine the macro to take an additional first - argument specifying the function to use. */ -#undef OP -#define OP(f, a, b, c, d, k, s, T) \ - do \ - { \ - a += f (b, c, d) + correct_words[k] + T; \ - CYCLIC (a, s); \ - a += b; \ - } \ - while (0) - - /* Round 2. */ -#if MD5SUM_SIZE_VS_SPEED == 1 - pp = P_array; - for ( i=0 ; i < 4 ; i++ ) { - OP(FG, A, B, C, D, (int)(*pp++), 5, *pc++); - OP(FG, D, A, B, C, (int)(*pp++), 9, *pc++); - OP(FG, C, D, A, B, (int)(*pp++), 14, *pc++); - OP(FG, B, C, D, A, (int)(*pp++), 20, *pc++); - } -#else - OP(FG, A, B, C, D, 1, 5, 0xf61e2562); - OP(FG, D, A, B, C, 6, 9, 0xc040b340); - OP(FG, C, D, A, B, 11, 14, 0x265e5a51); - OP(FG, B, C, D, A, 0, 20, 0xe9b6c7aa); - OP(FG, A, B, C, D, 5, 5, 0xd62f105d); - OP(FG, D, A, B, C, 10, 9, 0x02441453); - OP(FG, C, D, A, B, 15, 14, 0xd8a1e681); - OP(FG, B, C, D, A, 4, 20, 0xe7d3fbc8); - OP(FG, A, B, C, D, 9, 5, 0x21e1cde6); - OP(FG, D, A, B, C, 14, 9, 0xc33707d6); - OP(FG, C, D, A, B, 3, 14, 0xf4d50d87); - OP(FG, B, C, D, A, 8, 20, 0x455a14ed); - OP(FG, A, B, C, D, 13, 5, 0xa9e3e905); - OP(FG, D, A, B, C, 2, 9, 0xfcefa3f8); - OP(FG, C, D, A, B, 7, 14, 0x676f02d9); - OP(FG, B, C, D, A, 12, 20, 0x8d2a4c8a); -#endif - - /* Round 3. */ -#if MD5SUM_SIZE_VS_SPEED == 1 - for ( i=0 ; i < 4 ; i++ ) { - OP(FH, A, B, C, D, (int)(*pp++), 4, *pc++); - OP(FH, D, A, B, C, (int)(*pp++), 11, *pc++); - OP(FH, C, D, A, B, (int)(*pp++), 16, *pc++); - OP(FH, B, C, D, A, (int)(*pp++), 23, *pc++); - } -#else - OP(FH, A, B, C, D, 5, 4, 0xfffa3942); - OP(FH, D, A, B, C, 8, 11, 0x8771f681); - OP(FH, C, D, A, B, 11, 16, 0x6d9d6122); - OP(FH, B, C, D, A, 14, 23, 0xfde5380c); - OP(FH, A, B, C, D, 1, 4, 0xa4beea44); - OP(FH, D, A, B, C, 4, 11, 0x4bdecfa9); - OP(FH, C, D, A, B, 7, 16, 0xf6bb4b60); - OP(FH, B, C, D, A, 10, 23, 0xbebfbc70); - OP(FH, A, B, C, D, 13, 4, 0x289b7ec6); - OP(FH, D, A, B, C, 0, 11, 0xeaa127fa); - OP(FH, C, D, A, B, 3, 16, 0xd4ef3085); - OP(FH, B, C, D, A, 6, 23, 0x04881d05); - OP(FH, A, B, C, D, 9, 4, 0xd9d4d039); - OP(FH, D, A, B, C, 12, 11, 0xe6db99e5); - OP(FH, C, D, A, B, 15, 16, 0x1fa27cf8); - OP(FH, B, C, D, A, 2, 23, 0xc4ac5665); -#endif - - /* Round 4. */ -#if MD5SUM_SIZE_VS_SPEED == 1 - for ( i=0 ; i < 4 ; i++ ) { - OP(FI, A, B, C, D, (int)(*pp++), 6, *pc++); - OP(FI, D, A, B, C, (int)(*pp++), 10, *pc++); - OP(FI, C, D, A, B, (int)(*pp++), 15, *pc++); - OP(FI, B, C, D, A, (int)(*pp++), 21, *pc++); - } -#else - OP(FI, A, B, C, D, 0, 6, 0xf4292244); - OP(FI, D, A, B, C, 7, 10, 0x432aff97); - OP(FI, C, D, A, B, 14, 15, 0xab9423a7); - OP(FI, B, C, D, A, 5, 21, 0xfc93a039); - OP(FI, A, B, C, D, 12, 6, 0x655b59c3); - OP(FI, D, A, B, C, 3, 10, 0x8f0ccc92); - OP(FI, C, D, A, B, 10, 15, 0xffeff47d); - OP(FI, B, C, D, A, 1, 21, 0x85845dd1); - OP(FI, A, B, C, D, 8, 6, 0x6fa87e4f); - OP(FI, D, A, B, C, 15, 10, 0xfe2ce6e0); - OP(FI, C, D, A, B, 6, 15, 0xa3014314); - OP(FI, B, C, D, A, 13, 21, 0x4e0811a1); - OP(FI, A, B, C, D, 4, 6, 0xf7537e82); - OP(FI, D, A, B, C, 11, 10, 0xbd3af235); - OP(FI, C, D, A, B, 2, 15, 0x2ad7d2bb); - OP(FI, B, C, D, A, 9, 21, 0xeb86d391); -#endif -#endif - - /* Add the starting values of the context. */ - A += A_save; - B += B_save; - C += C_save; - D += D_save; - } - - /* Put checksum in context given as argument. */ - ctx->A = A; - ctx->B = B; - ctx->C = C; - ctx->D = D; -} - -//---------------------------------------------------------------------------- -//--------end of md5.c -//---------------------------------------------------------------------------- - -#define ISWHITE(c) ((c) == ' ' || (c) == '\t') -#define ISXDIGIT(c) (isxdigit (c)) - -/* The minimum length of a valid digest line in a file produced - by `md5sum FILE' and read by `md5sum -c'. This length does - not include any newline character at the end of a line. */ -static const int MIN_DIGEST_LINE_LENGTH = 35; /* 32 - message digest length - 2 - blank and binary indicator - 1 - minimum filename length */ - -static int have_read_stdin; /* Nonzero if any of the files read were - the standard input. */ - -static int status_only = 0; /* With -c, don't generate any output. - The exit code indicates success or failure */ -static int warn = 0; /* With -w, print a message to standard error warning - about each improperly formatted MD5 checksum line */ - -static int split_3(char *s, - size_t s_len, - unsigned char **u, - char **w) -{ - size_t i = 0; - int escaped_filename = 0; - - while (ISWHITE(s[i])) - ++i; - - /* The line must have at least 35 (36 if the first is a backslash) - more characters to contain correct message digest information. - Ignore this line if it is too short. */ - if (!(s_len - i >= MIN_DIGEST_LINE_LENGTH - || (s[i] == '\\' && s_len - i >= 1 + MIN_DIGEST_LINE_LENGTH))) - return FALSE; - - if (s[i] == '\\') { - ++i; - escaped_filename = 1; - } - *u = (unsigned char *) &s[i]; - - /* The first field has to be the 32-character hexadecimal - representation of the message digest. If it is not followed - immediately by a white space it's an error. */ - i += 32; - if (!ISWHITE(s[i])) - return FALSE; - - s[i++] = '\0'; - - if (s[i] != ' ' && s[i++] != '*') - return FALSE; - - /* All characters between the type indicator and end of line are - significant -- that includes leading and trailing white space. */ - *w = &s[i]; - - if (escaped_filename) { - /* Translate each `\n' string in the file name to a NEWLINE, - and each `\\' string to a backslash. */ - - char *dst = &s[i]; - - while (i < s_len) { - switch (s[i]) { - case '\\': - if (i == s_len - 1) { - /* A valid line does not end with a backslash. */ - return FALSE; - } - ++i; - switch (s[i++]) { - case 'n': - *dst++ = '\n'; - break; - case '\\': - *dst++ = '\\'; - break; - default: - /* Only `\' or `n' may follow a backslash. */ - return FALSE; - } - break; - - case '\0': - /* The file name may not contain a NUL. */ - return FALSE; - break; - - default: - *dst++ = s[i++]; - break; - } - } - *dst = '\0'; - } - return TRUE; -} - -static inline int hex_digits(unsigned char const *s) -{ - while (*s) { - if (!ISXDIGIT(*s)) - return TRUE; - ++s; - } - return FALSE; -} - -/* An interface to md5_stream. Operate on FILENAME (it may be "-") and - put the result in *MD5_RESULT. Return non-zero upon failure, zero - to indicate success. */ -static int md5_file(const char *filename, - unsigned char *md5_result) -{ - FILE *fp; - - if (filename[0] == '-' && filename[1] == '\0') { - have_read_stdin = 1; - fp = stdin; - } else { - fp = wfopen(filename, "r"); - if (fp == NULL) - return FALSE; - } - - if (md5_stream(fp, md5_result)) { - perror_msg("%s", filename); - - if (fp != stdin) - fclose(fp); - return FALSE; - } - - if (fp != stdin && fclose(fp) == EOF) { - perror_msg("%s", filename); - return FALSE; - } - - return TRUE; -} - -static int md5_check(const char *checkfile_name) -{ - FILE *checkfile_stream; - int n_properly_formated_lines = 0; - int n_mismatched_checksums = 0; - int n_open_or_read_failures = 0; - unsigned char md5buffer[16]; - size_t line_number; - char line[BUFSIZ]; - - if (checkfile_name[0] == '-' && checkfile_name[1] == '\0') { - have_read_stdin = 1; - checkfile_stream = stdin; - } else { - checkfile_stream = wfopen(checkfile_name, "r"); - if (checkfile_stream == NULL) - return FALSE; - } - - line_number = 0; - - do { - char *filename; - unsigned char *md5num; - int line_length; - - ++line_number; - - fgets(line, BUFSIZ-1, checkfile_stream); - line_length = strlen(line); - - if (line_length <= 0 || line==NULL) - break; - - /* Ignore comment lines, which begin with a '#' character. */ - if (line[0] == '#') - continue; - - /* Remove any trailing newline. */ - if (line[line_length - 1] == '\n') - line[--line_length] = '\0'; - - if (split_3(line, line_length, &md5num, &filename) - || !hex_digits(md5num)) { - if (warn) { - error_msg("%s: %lu: improperly formatted MD5 checksum line", - checkfile_name, (unsigned long) line_number); - } - } else { - static const char bin2hex[] = { - '0', '1', '2', '3', - '4', '5', '6', '7', - '8', '9', 'a', 'b', - 'c', 'd', 'e', 'f' - }; - - ++n_properly_formated_lines; - - if (md5_file(filename, md5buffer)) { - ++n_open_or_read_failures; - if (!status_only) { - printf("%s: FAILED open or read\n", filename); - fflush(stdout); - } - } else { - size_t cnt; - /* Compare generated binary number with text representation - in check file. Ignore case of hex digits. */ - for (cnt = 0; cnt < 16; ++cnt) { - if (tolower(md5num[2 * cnt]) - != bin2hex[md5buffer[cnt] >> 4] - || (tolower(md5num[2 * cnt + 1]) - != (bin2hex[md5buffer[cnt] & 0xf]))) - break; - } - if (cnt != 16) - ++n_mismatched_checksums; - - if (!status_only) { - printf("%s: %s\n", filename, - (cnt != 16 ? "FAILED" : "OK")); - fflush(stdout); - } - } - } - } - - while (!feof(checkfile_stream) && !ferror(checkfile_stream)); - - if (ferror(checkfile_stream)) { - error_msg("%s: read error", checkfile_name); - return FALSE; - } - - if (checkfile_stream != stdin && fclose(checkfile_stream) == EOF) { - perror_msg("md5sum: %s", checkfile_name); - return FALSE; - } - - if (n_properly_formated_lines == 0) { - /* Warn if no tests are found. */ - error_msg("%s: no properly formatted MD5 checksum lines found", - checkfile_name); - return FALSE; - } else { - if (!status_only) { - int n_computed_checkums = (n_properly_formated_lines - - n_open_or_read_failures); - - if (n_open_or_read_failures > 0) { - error_msg("WARNING: %d of %d listed files could not be read", - n_open_or_read_failures, n_properly_formated_lines); - return FALSE; - } - - if (n_mismatched_checksums > 0) { - error_msg("WARNING: %d of %d computed checksums did NOT match", - n_mismatched_checksums, n_computed_checkums); - return FALSE; - } - } - } - - return ((n_properly_formated_lines > 0 && n_mismatched_checksums == 0 - && n_open_or_read_failures == 0) ? 0 : 1); -} - -int md5sum_main(int argc, - char **argv) -{ - unsigned char md5buffer[16]; - int do_check = 0; - int opt; - char **string = NULL; - size_t n_strings = 0; - size_t err = 0; - char file_type_specified = 0; - char binary = 0; - - while ((opt = getopt(argc, argv, "g:bcstw")) != -1) { - switch (opt) { - case 'g': { /* read a string */ - if (string == NULL) - string = (char **) xmalloc ((argc - 1) * sizeof (char *)); - - string[n_strings++] = optarg; - break; - } - - case 'b': /* read files in binary mode */ - file_type_specified = 1; - binary = 1; - break; - - case 'c': /* check MD5 sums against given list */ - do_check = 1; - break; - - case 's': /* don't output anything, status code shows success */ - status_only = 1; - warn = 0; - break; - - case 't': /* read files in text mode (default) */ - file_type_specified = 1; - binary = 0; - break; - - case 'w': /* warn about improperly formated MD5 checksum lines */ - status_only = 0; - warn = 1; - break; - - default: - show_usage(); - } - } - - if (file_type_specified && do_check) { - error_msg_and_die("the -b and -t options are meaningless when verifying checksums"); - } - - if (n_strings > 0 && do_check) { - error_msg_and_die("the -g and -c options are mutually exclusive"); - } - - if (status_only && !do_check) { - error_msg_and_die("the -s option is meaningful only when verifying checksums"); - } - - if (warn && !do_check) { - error_msg_and_die("the -w option is meaningful only when verifying checksums"); - } - - if (n_strings > 0) { - size_t i; - - if (optind < argc) { - error_msg_and_die("no files may be specified when using -g"); - } - for (i = 0; i < n_strings; ++i) { - size_t cnt; - md5_buffer (string[i], strlen (string[i]), md5buffer); - - for (cnt = 0; cnt < 16; ++cnt) - printf ("%02x", md5buffer[cnt]); - - printf (" \"%s\"\n", string[i]); - } - } else if (do_check) { - if (optind + 1 < argc) { - error_msg("only one argument may be specified when using -c"); - } - - err = md5_check ((optind == argc) ? "-" : argv[optind]); - } else { - if (optind == argc) - argv[argc++] = "-"; - - for (; optind < argc; ++optind) { - int fail; - char *file = argv[optind]; - - fail = md5_file (file, md5buffer); - err |= fail; - if (!fail && file[0]=='-' && file[1] == '\0') { - size_t i; - for (i = 0; i < 16; ++i) - printf ("%02x", md5buffer[i]); - putchar ('\n'); - } else if (!fail) { - size_t i; - /* Output a leading backslash if the file name contains - a newline or backslash. */ - if (strchr (file, '\n') || strchr (file, '\\')) - putchar ('\\'); - - for (i = 0; i < 16; ++i) - printf ("%02x", md5buffer[i]); - - putchar (' '); - if (binary) - putchar ('*'); - else - putchar (' '); - - /* Translate each NEWLINE byte to the string, "\\n", - and each backslash to "\\\\". */ - for (i = 0; i < strlen (file); ++i) { - switch (file[i]) { - case '\n': - fputs ("\\n", stdout); - break; - - case '\\': - fputs ("\\\\", stdout); - break; - - default: - putchar (file[i]); - break; - } - } - putchar ('\n'); - } - } - } - - if (fclose (stdout) == EOF) { - error_msg_and_die("write error"); - } - - if (have_read_stdin && fclose (stdin) == EOF) { - error_msg_and_die("standard input"); - } - - if (err == 0) - return EXIT_SUCCESS; - else - return EXIT_FAILURE; -} diff --git a/miscutils/Makefile b/miscutils/Makefile new file mode 100644 index 000000000..4e006ba57 --- /dev/null +++ b/miscutils/Makefile @@ -0,0 +1,44 @@ +# Makefile for busybox +# +# Copyright (C) 1999,2000,2001 by Erik Andersen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +TOPDIR :=.. +L_TARGET := miscutils.a + +obj-y := +obj-n := +obj- := + + +obj-$(CONFIG_ADJTIMEX) += adjtimex.o +obj-$(CONFIG_DC) += dc.o +obj-$(CONFIG_DUTMP) += dutmp.o +obj-$(CONFIG_MAKEDEVS) += makedevs.o +obj-$(CONFIG_mktemp) += mktemp.o +obj-$(CONFIG_mt) += mt.o +obj-$(CONFIG_readlink) += readlink.o +obj-$(CONFIG_update) += update.o +obj-$(CONFIG_watchdog) += watchdog.o + + +# Hand off to toplevel Rules.mak +include $(TOPDIR)/Rules.mak + +clean: + rm -f $(L_TARGET) *.o core + diff --git a/miscutils/config.in b/miscutils/config.in new file mode 100644 index 000000000..61b2113bc --- /dev/null +++ b/miscutils/config.in @@ -0,0 +1,20 @@ +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +mainmenu_option next_comment +comment 'Miscellaneous Utilities' + +bool 'adjtimex' CONFIG_ADJTIMEX +bool 'dc' CONFIG_DC +bool 'dutmp' CONFIG_DUTMP +bool 'makedevs' CONFIG_MAKEDEVS +bool 'mktemp' CONFIG_MKTEMP +bool 'mt' CONFIG_MT +bool 'readlink' CONFIG_READLINK +bool 'update' CONFIG_UPDATE +bool 'watchdog' CONFIG_WATCHDOG + +endmenu + diff --git a/miscutils/readlink.c b/miscutils/readlink.c index c46ebd108..da5259038 100644 --- a/miscutils/readlink.c +++ b/miscutils/readlink.c @@ -2,9 +2,7 @@ /* * Mini readlink implementation for busybox * - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Matt Kraai + * Copyright (C) 2000,2001 Matt Kraai * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -40,7 +38,7 @@ int readlink_main(int argc, char **argv) if (!buf) return EXIT_FAILURE; puts(buf); -#ifdef BB_FEATURE_CLEAN_UP +#ifdef CONFIG_FEATURE_CLEAN_UP free(buf); #endif diff --git a/mk_loop_h.sh b/mk_loop_h.sh deleted file mode 100755 index 71c987376..000000000 --- a/mk_loop_h.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh -# -# Figure out (i) the type of dev_t (ii) the defines for loop stuff -# -# Output of this script is normally redirected to "loop.h". - -# Since 1.3.79 there is an include file -# that defines __kernel_dev_t. -# (The file itself appeared in 1.3.78, but there it defined __dev_t.) -# If it exists, we use it, or, rather, which -# avoids namespace pollution. Otherwise we guess that __kernel_dev_t -# is an unsigned short (which is true on i386, but false on alpha). - -# BUG: This test is actually broken if your gcc is not configured to -# search /usr/include, as may well happen with cross-compilers. -# It would be better to ask $(CC) if these files can be found. - -if [ -f /usr/include/linux/posix_types.h ]; then - echo '#include ' - echo '#undef dev_t' - echo '#define dev_t __kernel_dev_t' -else - echo '#undef dev_t' - echo '#define dev_t unsigned short' -fi - -# Next we have to find the loop stuff itself. -# First try kernel source, then a private version. - -if [ -f /usr/include/linux/loop.h ]; then - echo '#include ' -else - echo '#include "real_loop.h"' -fi - -echo '#undef dev_t' - diff --git a/mkdir.c b/mkdir.c deleted file mode 100644 index 03c49f098..000000000 --- a/mkdir.c +++ /dev/null @@ -1,64 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini mkdir implementation for busybox - * - * Copyright (C) 2001 Matt Kraai - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "busybox.h" - -extern int mkdir_main (int argc, char **argv) -{ - mode_t mode = -1; - int flags = 0; - int status = 0; - int i, opt; - - while ((opt = getopt (argc, argv, "m:p")) != -1) { - switch (opt) { - case 'm': - mode = 0777; - if (!parse_mode (optarg, &mode)) - error_msg_and_die ("invalid mode `%s'", optarg); - break; - case 'p': - flags |= FILEUTILS_RECUR; - break; - default: - show_usage (); - } - } - - if (optind == argc) - show_usage (); - - for (i = optind; i < argc; i++) - if (make_directory (argv[i], mode, flags) < 0) - status = 1; - - return status; -} diff --git a/mkfifo.c b/mkfifo.c deleted file mode 100644 index ca217fa23..000000000 --- a/mkfifo.c +++ /dev/null @@ -1,60 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini mkfifo implementation for busybox - * - * Copyright (C) 1999 by Randolph Chung - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include "busybox.h" - -extern int mkfifo_main(int argc, char **argv) -{ - char *thisarg; - mode_t mode = 0666; - - argc--; - argv++; - - /* Parse any options */ - while (argc > 1) { - if (**argv != '-') - show_usage(); - thisarg = *argv; - thisarg++; - switch (*thisarg) { - case 'm': - argc--; - argv++; - parse_mode(*argv, &mode); - break; - default: - show_usage(); - } - argc--; - argv++; - } - if (argc < 1 || *argv[0] == '-') - show_usage(); - if (mkfifo(*argv, mode) < 0) - perror_msg_and_die("mkfifo"); - return EXIT_SUCCESS; -} diff --git a/mkfs_minix.c b/mkfs_minix.c deleted file mode 100644 index ccc0e85d7..000000000 --- a/mkfs_minix.c +++ /dev/null @@ -1,847 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * mkfs.c - make a linux (minix) file-system. - * - * (C) 1991 Linus Torvalds. This file may be redistributed as per - * the Linux copyright. - */ - -/* - * DD.MM.YY - * - * 24.11.91 - Time began. Used the fsck sources to get started. - * - * 25.11.91 - Corrected some bugs. Added support for ".badblocks" - * The algorithm for ".badblocks" is a bit weird, but - * it should work. Oh, well. - * - * 25.01.92 - Added the -l option for getting the list of bad blocks - * out of a named file. (Dave Rivers, rivers@ponds.uucp) - * - * 28.02.92 - Added %-information when using -c. - * - * 28.02.93 - Added support for other namelengths than the original - * 14 characters so that I can test the new kernel routines.. - * - * 09.10.93 - Make exit status conform to that required by fsutil - * (Rik Faith, faith@cs.unc.edu) - * - * 31.10.93 - Added inode request feature, for backup floppies: use - * 32 inodes, for a news partition use more. - * (Scott Heavner, sdh@po.cwru.edu) - * - * 03.01.94 - Added support for file system valid flag. - * (Dr. Wettstein, greg%wind.uucp@plains.nodak.edu) - * - * 30.10.94 - added support for v2 filesystem - * (Andreas Schwab, schwab@issan.informatik.uni-dortmund.de) - * - * 09.11.94 - Added test to prevent overwrite of mounted fs adapted - * from Theodore Ts'o's (tytso@athena.mit.edu) mke2fs - * program. (Daniel Quinlan, quinlan@yggdrasil.com) - * - * 03.20.95 - Clear first 512 bytes of filesystem to make certain that - * the filesystem is not misidentified as a MS-DOS FAT filesystem. - * (Daniel Quinlan, quinlan@yggdrasil.com) - * - * 02.07.96 - Added small patch from Russell King to make the program a - * good deal more portable (janl@math.uio.no) - * - * Usage: mkfs [-c | -l filename ] [-v] [-nXX] [-iXX] device [size-in-blocks] - * - * -c for readablility checking (SLOW!) - * -l for getting a list of bad blocks from a file. - * -n for namelength (currently the kernel only uses 14 or 30) - * -i for number of inodes - * -v for v2 filesystem - * - * The device may be a block device or a image of one, but this isn't - * enforced (but it's not much fun on a character device :-). - * - * Modified for BusyBox by Erik Andersen -- - * removed getopt based parser and added a hand rolled one. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" - -#define MINIX_ROOT_INO 1 -#define MINIX_LINK_MAX 250 -#define MINIX2_LINK_MAX 65530 - -#define MINIX_I_MAP_SLOTS 8 -#define MINIX_Z_MAP_SLOTS 64 -#define MINIX_SUPER_MAGIC 0x137F /* original minix fs */ -#define MINIX_SUPER_MAGIC2 0x138F /* minix fs, 30 char names */ -#define MINIX2_SUPER_MAGIC 0x2468 /* minix V2 fs */ -#define MINIX2_SUPER_MAGIC2 0x2478 /* minix V2 fs, 30 char names */ -#define MINIX_VALID_FS 0x0001 /* Clean fs. */ -#define MINIX_ERROR_FS 0x0002 /* fs has errors. */ - -#define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode))) -#define MINIX2_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix2_inode))) - -#define MINIX_V1 0x0001 /* original minix fs */ -#define MINIX_V2 0x0002 /* minix V2 fs */ - -#define INODE_VERSION(inode) inode->i_sb->u.minix_sb.s_version - -/* - * This is the original minix inode layout on disk. - * Note the 8-bit gid and atime and ctime. - */ -struct minix_inode { - u_int16_t i_mode; - u_int16_t i_uid; - u_int32_t i_size; - u_int32_t i_time; - u_int8_t i_gid; - u_int8_t i_nlinks; - u_int16_t i_zone[9]; -}; - -/* - * The new minix inode has all the time entries, as well as - * long block numbers and a third indirect block (7+1+1+1 - * instead of 7+1+1). Also, some previously 8-bit values are - * now 16-bit. The inode is now 64 bytes instead of 32. - */ -struct minix2_inode { - u_int16_t i_mode; - u_int16_t i_nlinks; - u_int16_t i_uid; - u_int16_t i_gid; - u_int32_t i_size; - u_int32_t i_atime; - u_int32_t i_mtime; - u_int32_t i_ctime; - u_int32_t i_zone[10]; -}; - -/* - * minix super-block data on disk - */ -struct minix_super_block { - u_int16_t s_ninodes; - u_int16_t s_nzones; - u_int16_t s_imap_blocks; - u_int16_t s_zmap_blocks; - u_int16_t s_firstdatazone; - u_int16_t s_log_zone_size; - u_int32_t s_max_size; - u_int16_t s_magic; - u_int16_t s_state; - u_int32_t s_zones; -}; - -struct minix_dir_entry { - u_int16_t inode; - char name[0]; -}; - -#define BLOCK_SIZE_BITS 10 -#define BLOCK_SIZE (1<> 3] & (1<<(i & 7))) != 0; -} -#define inode_in_use(x) (bit(inode_map,(x))) -#define zone_in_use(x) (bit(zone_map,(x)-FIRSTZONE+1)) - -#define mark_inode(x) (setbit(inode_map,(x))) -#define unmark_inode(x) (clrbit(inode_map,(x))) - -#define mark_zone(x) (setbit(zone_map,(x)-FIRSTZONE+1)) -#define unmark_zone(x) (clrbit(zone_map,(x)-FIRSTZONE+1)) - -/* - * Check to make certain that our new filesystem won't be created on - * an already mounted partition. Code adapted from mke2fs, Copyright - * (C) 1994 Theodore Ts'o. Also licensed under GPL. - */ -static void check_mount(void) -{ - FILE *f; - struct mntent *mnt; - - if ((f = setmntent(MOUNTED, "r")) == NULL) - return; - while ((mnt = getmntent(f)) != NULL) - if (strcmp(device_name, mnt->mnt_fsname) == 0) - break; - endmntent(f); - if (!mnt) - return; - - error_msg_and_die("%s is mounted; will not make a filesystem here!", device_name); -} - -static long valid_offset(int fd, int offset) -{ - char ch; - - if (lseek(fd, offset, 0) < 0) - return 0; - if (read(fd, &ch, 1) < 1) - return 0; - return 1; -} - -static int count_blocks(int fd) -{ - int high, low; - - low = 0; - for (high = 1; valid_offset(fd, high); high *= 2) - low = high; - while (low < high - 1) { - const int mid = (low + high) / 2; - - if (valid_offset(fd, mid)) - low = mid; - else - high = mid; - } - valid_offset(fd, 0); - return (low + 1); -} - -static int get_size(const char *file) -{ - int fd; - long size; - - if ((fd = open(file, O_RDWR)) < 0) - perror_msg_and_die("%s", file); - if (ioctl(fd, BLKGETSIZE, &size) >= 0) { - close(fd); - return (size * 512); - } - - size = count_blocks(fd); - close(fd); - return size; -} - -static void write_tables(void) -{ - /* Mark the super block valid. */ - Super.s_state |= MINIX_VALID_FS; - Super.s_state &= ~MINIX_ERROR_FS; - - if (lseek(DEV, 0, SEEK_SET)) - error_msg_and_die("seek to boot block failed in write_tables"); - if (512 != write(DEV, boot_block_buffer, 512)) - error_msg_and_die("unable to clear boot sector"); - if (BLOCK_SIZE != lseek(DEV, BLOCK_SIZE, SEEK_SET)) - error_msg_and_die("seek failed in write_tables"); - if (BLOCK_SIZE != write(DEV, super_block_buffer, BLOCK_SIZE)) - error_msg_and_die("unable to write super-block"); - if (IMAPS * BLOCK_SIZE != write(DEV, inode_map, IMAPS * BLOCK_SIZE)) - error_msg_and_die("unable to write inode map"); - if (ZMAPS * BLOCK_SIZE != write(DEV, zone_map, ZMAPS * BLOCK_SIZE)) - error_msg_and_die("unable to write zone map"); - if (INODE_BUFFER_SIZE != write(DEV, inode_buffer, INODE_BUFFER_SIZE)) - error_msg_and_die("unable to write inodes"); - -} - -static void write_block(int blk, char *buffer) -{ - if (blk * BLOCK_SIZE != lseek(DEV, blk * BLOCK_SIZE, SEEK_SET)) - error_msg_and_die("seek failed in write_block"); - if (BLOCK_SIZE != write(DEV, buffer, BLOCK_SIZE)) - error_msg_and_die("write failed in write_block"); -} - -static int get_free_block(void) -{ - int blk; - - if (used_good_blocks + 1 >= MAX_GOOD_BLOCKS) - error_msg_and_die("too many bad blocks"); - if (used_good_blocks) - blk = good_blocks_table[used_good_blocks - 1] + 1; - else - blk = FIRSTZONE; - while (blk < ZONES && zone_in_use(blk)) - blk++; - if (blk >= ZONES) - error_msg_and_die("not enough good blocks"); - good_blocks_table[used_good_blocks] = blk; - used_good_blocks++; - return blk; -} - -static void mark_good_blocks(void) -{ - int blk; - - for (blk = 0; blk < used_good_blocks; blk++) - mark_zone(good_blocks_table[blk]); -} - -static int next(int zone) -{ - if (!zone) - zone = FIRSTZONE - 1; - while (++zone < ZONES) - if (zone_in_use(zone)) - return zone; - return 0; -} - -static void make_bad_inode(void) -{ - struct minix_inode *inode = &Inode[MINIX_BAD_INO]; - int i, j, zone; - int ind = 0, dind = 0; - unsigned short ind_block[BLOCK_SIZE >> 1]; - unsigned short dind_block[BLOCK_SIZE >> 1]; - -#define NEXT_BAD (zone = next(zone)) - - if (!badblocks) - return; - mark_inode(MINIX_BAD_INO); - inode->i_nlinks = 1; - inode->i_time = time(NULL); - inode->i_mode = S_IFREG + 0000; - inode->i_size = badblocks * BLOCK_SIZE; - zone = next(0); - for (i = 0; i < 7; i++) { - inode->i_zone[i] = zone; - if (!NEXT_BAD) - goto end_bad; - } - inode->i_zone[7] = ind = get_free_block(); - memset(ind_block, 0, BLOCK_SIZE); - for (i = 0; i < 512; i++) { - ind_block[i] = zone; - if (!NEXT_BAD) - goto end_bad; - } - inode->i_zone[8] = dind = get_free_block(); - memset(dind_block, 0, BLOCK_SIZE); - for (i = 0; i < 512; i++) { - write_block(ind, (char *) ind_block); - dind_block[i] = ind = get_free_block(); - memset(ind_block, 0, BLOCK_SIZE); - for (j = 0; j < 512; j++) { - ind_block[j] = zone; - if (!NEXT_BAD) - goto end_bad; - } - } - error_msg_and_die("too many bad blocks"); - end_bad: - if (ind) - write_block(ind, (char *) ind_block); - if (dind) - write_block(dind, (char *) dind_block); -} - -#ifdef BB_FEATURE_MINIX2 -static void make_bad_inode2(void) -{ - struct minix2_inode *inode = &Inode2[MINIX_BAD_INO]; - int i, j, zone; - int ind = 0, dind = 0; - unsigned long ind_block[BLOCK_SIZE >> 2]; - unsigned long dind_block[BLOCK_SIZE >> 2]; - - if (!badblocks) - return; - mark_inode(MINIX_BAD_INO); - inode->i_nlinks = 1; - inode->i_atime = inode->i_mtime = inode->i_ctime = time(NULL); - inode->i_mode = S_IFREG + 0000; - inode->i_size = badblocks * BLOCK_SIZE; - zone = next(0); - for (i = 0; i < 7; i++) { - inode->i_zone[i] = zone; - if (!NEXT_BAD) - goto end_bad; - } - inode->i_zone[7] = ind = get_free_block(); - memset(ind_block, 0, BLOCK_SIZE); - for (i = 0; i < 256; i++) { - ind_block[i] = zone; - if (!NEXT_BAD) - goto end_bad; - } - inode->i_zone[8] = dind = get_free_block(); - memset(dind_block, 0, BLOCK_SIZE); - for (i = 0; i < 256; i++) { - write_block(ind, (char *) ind_block); - dind_block[i] = ind = get_free_block(); - memset(ind_block, 0, BLOCK_SIZE); - for (j = 0; j < 256; j++) { - ind_block[j] = zone; - if (!NEXT_BAD) - goto end_bad; - } - } - /* Could make triple indirect block here */ - error_msg_and_die("too many bad blocks"); - end_bad: - if (ind) - write_block(ind, (char *) ind_block); - if (dind) - write_block(dind, (char *) dind_block); -} -#endif - -static void make_root_inode(void) -{ - struct minix_inode *inode = &Inode[MINIX_ROOT_INO]; - - mark_inode(MINIX_ROOT_INO); - inode->i_zone[0] = get_free_block(); - inode->i_nlinks = 2; - inode->i_time = time(NULL); - if (badblocks) - inode->i_size = 3 * dirsize; - else { - root_block[2 * dirsize] = '\0'; - root_block[2 * dirsize + 1] = '\0'; - inode->i_size = 2 * dirsize; - } - inode->i_mode = S_IFDIR + 0755; - inode->i_uid = getuid(); - if (inode->i_uid) - inode->i_gid = getgid(); - write_block(inode->i_zone[0], root_block); -} - -#ifdef BB_FEATURE_MINIX2 -static void make_root_inode2(void) -{ - struct minix2_inode *inode = &Inode2[MINIX_ROOT_INO]; - - mark_inode(MINIX_ROOT_INO); - inode->i_zone[0] = get_free_block(); - inode->i_nlinks = 2; - inode->i_atime = inode->i_mtime = inode->i_ctime = time(NULL); - if (badblocks) - inode->i_size = 3 * dirsize; - else { - root_block[2 * dirsize] = '\0'; - root_block[2 * dirsize + 1] = '\0'; - inode->i_size = 2 * dirsize; - } - inode->i_mode = S_IFDIR + 0755; - inode->i_uid = getuid(); - if (inode->i_uid) - inode->i_gid = getgid(); - write_block(inode->i_zone[0], root_block); -} -#endif - -static void setup_tables(void) -{ - int i; - unsigned long inodes; - - memset(super_block_buffer, 0, BLOCK_SIZE); - memset(boot_block_buffer, 0, 512); - MAGIC = magic; - ZONESIZE = 0; - MAXSIZE = version2 ? 0x7fffffff : (7 + 512 + 512 * 512) * 1024; - ZONES = BLOCKS; -/* some magic nrs: 1 inode / 3 blocks */ - if (req_nr_inodes == 0) - inodes = BLOCKS / 3; - else - inodes = req_nr_inodes; - /* Round up inode count to fill block size */ -#ifdef BB_FEATURE_MINIX2 - if (version2) - inodes = ((inodes + MINIX2_INODES_PER_BLOCK - 1) & - ~(MINIX2_INODES_PER_BLOCK - 1)); - else -#endif - inodes = ((inodes + MINIX_INODES_PER_BLOCK - 1) & - ~(MINIX_INODES_PER_BLOCK - 1)); - if (inodes > 65535) - inodes = 65535; - INODES = inodes; - IMAPS = UPPER(INODES + 1, BITS_PER_BLOCK); - ZMAPS = 0; - i = 0; - while (ZMAPS != - UPPER(BLOCKS - (2 + IMAPS + ZMAPS + INODE_BLOCKS) + 1, - BITS_PER_BLOCK) && i < 1000) { - ZMAPS = - UPPER(BLOCKS - (2 + IMAPS + ZMAPS + INODE_BLOCKS) + 1, - BITS_PER_BLOCK); - i++; - } - /* Real bad hack but overwise mkfs.minix can be thrown - * in infinite loop... - * try: - * dd if=/dev/zero of=test.fs count=10 bs=1024 - * /sbin/mkfs.minix -i 200 test.fs - * */ - if (i >= 999) { - error_msg_and_die("unable to allocate buffers for maps"); - } - FIRSTZONE = NORM_FIRSTZONE; - inode_map = xmalloc(IMAPS * BLOCK_SIZE); - zone_map = xmalloc(ZMAPS * BLOCK_SIZE); - memset(inode_map, 0xff, IMAPS * BLOCK_SIZE); - memset(zone_map, 0xff, ZMAPS * BLOCK_SIZE); - for (i = FIRSTZONE; i < ZONES; i++) - unmark_zone(i); - for (i = MINIX_ROOT_INO; i <= INODES; i++) - unmark_inode(i); - inode_buffer = xmalloc(INODE_BUFFER_SIZE); - memset(inode_buffer, 0, INODE_BUFFER_SIZE); - printf("%ld inodes\n", INODES); - printf("%ld blocks\n", ZONES); - printf("Firstdatazone=%ld (%ld)\n", FIRSTZONE, NORM_FIRSTZONE); - printf("Zonesize=%d\n", BLOCK_SIZE << ZONESIZE); - printf("Maxsize=%ld\n\n", MAXSIZE); -} - -/* - * Perform a test of a block; return the number of - * blocks readable/writeable. - */ -static long do_check(char *buffer, int try, unsigned int current_block) -{ - long got; - - /* Seek to the correct loc. */ - if (lseek(DEV, current_block * BLOCK_SIZE, SEEK_SET) != - current_block * BLOCK_SIZE) { - error_msg_and_die("seek failed during testing of blocks"); - } - - - /* Try the read */ - got = read(DEV, buffer, try * BLOCK_SIZE); - if (got < 0) - got = 0; - if (got & (BLOCK_SIZE - 1)) { - printf("Weird values in do_check: probably bugs\n"); - } - got /= BLOCK_SIZE; - return got; -} - -static unsigned int currently_testing = 0; - -static void alarm_intr(int alnum) -{ - if (currently_testing >= ZONES) - return; - signal(SIGALRM, alarm_intr); - alarm(5); - if (!currently_testing) - return; - printf("%d ...", currently_testing); - fflush(stdout); -} - -static void check_blocks(void) -{ - int try, got; - static char buffer[BLOCK_SIZE * TEST_BUFFER_BLOCKS]; - - currently_testing = 0; - signal(SIGALRM, alarm_intr); - alarm(5); - while (currently_testing < ZONES) { - if (lseek(DEV, currently_testing * BLOCK_SIZE, SEEK_SET) != - currently_testing * BLOCK_SIZE) - error_msg_and_die("seek failed in check_blocks"); - try = TEST_BUFFER_BLOCKS; - if (currently_testing + try > ZONES) - try = ZONES - currently_testing; - got = do_check(buffer, try, currently_testing); - currently_testing += got; - if (got == try) - continue; - if (currently_testing < FIRSTZONE) - error_msg_and_die("bad blocks before data-area: cannot make fs"); - mark_zone(currently_testing); - badblocks++; - currently_testing++; - } - if (badblocks > 1) - printf("%d bad blocks\n", badblocks); - else if (badblocks == 1) - printf("one bad block\n"); -} - -static void get_list_blocks(filename) -char *filename; - -{ - FILE *listfile; - unsigned long blockno; - - listfile = xfopen(filename, "r"); - while (!feof(listfile)) { - fscanf(listfile, "%ld\n", &blockno); - mark_zone(blockno); - badblocks++; - } - if (badblocks > 1) - printf("%d bad blocks\n", badblocks); - else if (badblocks == 1) - printf("one bad block\n"); -} - -extern int mkfs_minix_main(int argc, char **argv) -{ - int i=1; - char *tmp; - struct stat statbuf; - char *listfile = NULL; - int stopIt=FALSE; - - if (INODE_SIZE * MINIX_INODES_PER_BLOCK != BLOCK_SIZE) - error_msg_and_die("bad inode size"); -#ifdef BB_FEATURE_MINIX2 - if (INODE_SIZE2 * MINIX2_INODES_PER_BLOCK != BLOCK_SIZE) - error_msg_and_die("bad inode size"); -#endif - - /* Parse options */ - argv++; - while (--argc >= 0 && *argv && **argv) { - if (**argv == '-') { - stopIt=FALSE; - while (i > 0 && *++(*argv) && stopIt==FALSE) { - switch (**argv) { - case 'c': - check = 1; - break; - case 'i': - { - char *cp=NULL; - if (*(*argv+1) != 0) { - cp = ++(*argv); - } else { - if (--argc == 0) { - goto goodbye; - } - cp = *(++argv); - } - req_nr_inodes = strtoul(cp, &tmp, 0); - if (*tmp) - show_usage(); - stopIt=TRUE; - break; - } - case 'l': - if (--argc == 0) { - goto goodbye; - } - listfile = *(++argv); - break; - case 'n': - { - char *cp=NULL; - - if (*(*argv+1) != 0) { - cp = ++(*argv); - } else { - if (--argc == 0) { - goto goodbye; - } - cp = *(++argv); - } - i = strtoul(cp, &tmp, 0); - if (*tmp) - show_usage(); - if (i == 14) - magic = MINIX_SUPER_MAGIC; - else if (i == 30) - magic = MINIX_SUPER_MAGIC2; - else - show_usage(); - namelen = i; - dirsize = i + 2; - stopIt=TRUE; - break; - } - case 'v': -#ifdef BB_FEATURE_MINIX2 - version2 = 1; -#else - error_msg("%s: not compiled with minix v2 support", - device_name); - exit(-1); -#endif - break; - case '-': - case 'h': - default: -goodbye: - show_usage(); - } - } - } else { - if (device_name == NULL) - device_name = *argv; - else if (BLOCKS == 0) - BLOCKS = strtol(*argv, &tmp, 0); - else { - goto goodbye; - } - } - argv++; - } - - if (device_name && !BLOCKS) - BLOCKS = get_size(device_name) / 1024; - if (!device_name || BLOCKS < 10) { - show_usage(); - } -#ifdef BB_FEATURE_MINIX2 - if (version2) { - if (namelen == 14) - magic = MINIX2_SUPER_MAGIC; - else - magic = MINIX2_SUPER_MAGIC2; - } else -#endif - if (BLOCKS > 65535) - BLOCKS = 65535; - check_mount(); /* is it already mounted? */ - tmp = root_block; - *(short *) tmp = 1; - strcpy(tmp + 2, "."); - tmp += dirsize; - *(short *) tmp = 1; - strcpy(tmp + 2, ".."); - tmp += dirsize; - *(short *) tmp = 2; - strcpy(tmp + 2, ".badblocks"); - DEV = open(device_name, O_RDWR); - if (DEV < 0) - error_msg_and_die("unable to open %s", device_name); - if (fstat(DEV, &statbuf) < 0) - error_msg_and_die("unable to stat %s", device_name); - if (!S_ISBLK(statbuf.st_mode)) - check = 0; - else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340) - error_msg_and_die("will not try to make filesystem on '%s'", device_name); - setup_tables(); - if (check) - check_blocks(); - else if (listfile) - get_list_blocks(listfile); -#ifdef BB_FEATURE_MINIX2 - if (version2) { - make_root_inode2(); - make_bad_inode2(); - } else -#endif - { - make_root_inode(); - make_bad_inode(); - } - mark_good_blocks(); - write_tables(); - return( 0); - -} diff --git a/mknod.c b/mknod.c deleted file mode 100644 index b4d4b82a1..000000000 --- a/mknod.c +++ /dev/null @@ -1,92 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini mknod implementation for busybox - * - * Copyright (C) 1995, 1996 by Bruce Perens . - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" - -int mknod_main(int argc, char **argv) -{ - char *thisarg; - mode_t mode = 0; - mode_t perm = 0666; - dev_t dev = 0; - - argc--; - argv++; - - /* Parse any options */ - while (argc > 1) { - if (**argv != '-') - break; - thisarg = *argv; - thisarg++; - switch (*thisarg) { - case 'm': - argc--; - argv++; - parse_mode(*argv, &perm); - umask(0); - break; - default: - show_usage(); - } - argc--; - argv++; - } - if (argc != 4 && argc != 2) { - show_usage(); - } - switch (argv[1][0]) { - case 'c': - case 'u': - mode = S_IFCHR; - break; - case 'b': - mode = S_IFBLK; - break; - case 'p': - mode = S_IFIFO; - if (argc!=2) { - show_usage(); - } - break; - default: - show_usage(); - } - - if (mode == S_IFCHR || mode == S_IFBLK) { - dev = (atoi(argv[2]) << 8) | atoi(argv[3]); - } - - mode |= perm; - - if (mknod(argv[0], mode, dev) != 0) - perror_msg_and_die("%s", argv[0]); - return EXIT_SUCCESS; -} - diff --git a/mkswap.c b/mkswap.c deleted file mode 100644 index c773ecef9..000000000 --- a/mkswap.c +++ /dev/null @@ -1,422 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * mkswap.c - set up a linux swap device - * - * (C) 1991 Linus Torvalds. This file may be redistributed as per - * the Linux copyright. - */ - -/* - * 20.12.91 - time began. Got VM working yesterday by doing this by hand. - * - * Usage: mkswap [-c] [-vN] [-f] device [size-in-blocks] - * - * -c for readability checking. (Use it unless you are SURE!) - * -vN for swap areas version N. (Only N=0,1 known today.) - * -f for forcing swap creation even if it would smash partition table. - * - * The device may be a block device or an image of one, but this isn't - * enforced (but it's not much fun on a character device :-). - * - * Patches from jaggy@purplet.demon.co.uk (Mike Jagdis) to make the - * size-in-blocks parameter optional added Wed Feb 8 10:33:43 1995. - * - * Version 1 swap area code (for kernel 2.1.117), aeb, 981010. - * - * Sparc fixes, jj@ultra.linux.cz (Jakub Jelinek), 981201 - mangled by aeb. - * V1_MAX_PAGES fixes, jj, 990325. - * - * 1999-02-22 Arkadiusz Mi¶kiewicz - * - added Native Language Support - * - * from util-linux -- adapted for busybox by - * Erik Andersen . I ripped out Native Language - * Support, made some stuff smaller, and fitted for life in busybox. - * - */ - -#include -#include -#include -#include -#include -#include /* for _IO */ -#include -#include /* for PAGE_SIZE and PAGE_SHIFT */ - /* we also get PAGE_SIZE via getpagesize() */ -#include "busybox.h" - -#ifndef _IO -/* pre-1.3.45 */ -static const int BLKGETSIZE = 0x1260; -#else -/* same on i386, m68k, arm; different on alpha, mips, sparc, ppc */ -#define BLKGETSIZE _IO(0x12,96) -#endif - -static char *device_name = NULL; -static int DEV = -1; -static long PAGES = 0; -static int check = 0; -static int badpages = 0; -static int version = -1; - -#define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r)) - -/* - * The definition of the union swap_header uses the constant PAGE_SIZE. - * Unfortunately, on some architectures this depends on the hardware model, - * and can only be found at run time -- we use getpagesize(). - */ - -static int pagesize; -static int *signature_page; - -static struct swap_header_v1 { - char bootbits[1024]; /* Space for disklabel etc. */ - unsigned int version; - unsigned int last_page; - unsigned int nr_badpages; - unsigned int padding[125]; - unsigned int badpages[1]; -} *p; - -static void init_signature_page(void) -{ - pagesize = getpagesize(); - -#ifdef PAGE_SIZE - if (pagesize != PAGE_SIZE) - error_msg("Assuming pages of size %d", pagesize); -#endif - signature_page = (int *) xmalloc(pagesize); - memset(signature_page, 0, pagesize); - p = (struct swap_header_v1 *) signature_page; -} - -static void write_signature(char *sig) -{ - char *sp = (char *) signature_page; - - strncpy(sp + pagesize - 10, sig, 10); -} - -#define V0_MAX_PAGES (8 * (pagesize - 10)) -/* Before 2.2.0pre9 */ -#define V1_OLD_MAX_PAGES ((0x7fffffff / pagesize) - 1) -/* Since 2.2.0pre9: - error if nr of pages >= SWP_OFFSET(SWP_ENTRY(0,~0UL)) - with variations on - #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8)) - #define SWP_OFFSET(entry) ((entry) >> 8) - on the various architectures. Below the result - yuk. - - Machine pagesize SWP_ENTRY SWP_OFFSET bound+1 oldbound+2 - i386 2^12 o<<8 e>>8 1<<24 1<<19 - mips 2^12 o<<15 e>>15 1<<17 1<<19 - alpha 2^13 o<<40 e>>40 1<<24 1<<18 - m68k 2^12 o<<12 e>>12 1<<20 1<<19 - sparc 2^{12,13} (o&0x3ffff)<<9 (e>>9)&0x3ffff 1<<18 1<<{19,18} - sparc64 2^13 o<<13 e>>13 1<<51 1<<18 - ppc 2^12 o<<8 e>>8 1<<24 1<<19 - armo 2^{13,14,15} o<<8 e>>8 1<<24 1<<{18,17,16} - armv 2^12 o<<9 e>>9 1<<23 1<<19 - - assuming that longs have 64 bits on alpha and sparc64 and 32 bits elsewhere. - - The bad part is that we need to know this since the kernel will - refuse a swap space if it is too large. -*/ -/* patch from jj - why does this differ from the above? */ -#if defined(__alpha__) -#define V1_MAX_PAGES ((1 << 24) - 1) -#elif defined(__mips__) -#define V1_MAX_PAGES ((1 << 17) - 1) -#elif defined(__sparc_v9__) -#define V1_MAX_PAGES ((3 << 29) - 1) -#elif defined(__sparc__) -#define V1_MAX_PAGES (pagesize == 8192 ? ((3 << 29) - 1) : ((1 << 18) - 1)) -#else -#define V1_MAX_PAGES V1_OLD_MAX_PAGES -#endif -/* man page now says: -The maximum useful size of a swap area now depends on the architecture. -It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips, -128GB on alpha and 3TB on sparc64. -*/ - -#define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int)) - -static void bit_set(unsigned int *addr, unsigned int nr) -{ - unsigned int r, m; - - addr += nr / (8 * sizeof(int)); - - r = *addr; - m = 1 << (nr & (8 * sizeof(int) - 1)); - - *addr = r | m; -} - -static int bit_test_and_clear(unsigned int *addr, unsigned int nr) -{ - unsigned int r, m; - - addr += nr / (8 * sizeof(int)); - - r = *addr; - m = 1 << (nr & (8 * sizeof(int) - 1)); - - *addr = r & ~m; - return (r & m) != 0; -} - - -static void page_ok(int page) -{ - if (version == 0) - bit_set(signature_page, page); -} - -static void page_bad(int page) -{ - if (version == 0) - bit_test_and_clear(signature_page, page); - else { - if (badpages == MAX_BADPAGES) - error_msg_and_die("too many bad pages"); - p->badpages[badpages] = page; - } - badpages++; -} - -static void check_blocks(void) -{ - unsigned int current_page; - int do_seek = 1; - char *buffer; - - buffer = xmalloc(pagesize); - current_page = 0; - while (current_page < PAGES) { - if (!check) { - page_ok(current_page++); - continue; - } - if (do_seek && lseek(DEV, current_page * pagesize, SEEK_SET) != - current_page * pagesize) - error_msg_and_die("seek failed in check_blocks"); - if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) { - page_bad(current_page++); - continue; - } - page_ok(current_page++); - } - if (badpages == 1) - printf("one bad page\n"); - else if (badpages > 1) - printf("%d bad pages\n", badpages); -} - -static long valid_offset(int fd, int offset) -{ - char ch; - - if (lseek(fd, offset, 0) < 0) - return 0; - if (read(fd, &ch, 1) < 1) - return 0; - return 1; -} - -static int find_size(int fd) -{ - unsigned int high, low; - - low = 0; - for (high = 1; high > 0 && valid_offset(fd, high); high *= 2) - low = high; - while (low < high - 1) { - const int mid = (low + high) / 2; - - if (valid_offset(fd, mid)) - low = mid; - else - high = mid; - } - return (low + 1); -} - -/* return size in pages, to avoid integer overflow */ -static long get_size(const char *file) -{ - int fd; - long size; - - if ((fd = open(file, O_RDONLY)) < 0) - perror_msg_and_die("%s", file); - if (ioctl(fd, BLKGETSIZE, &size) >= 0) { - int sectors_per_page = pagesize / 512; - - size /= sectors_per_page; - } else { - size = find_size(fd) / pagesize; - } - close(fd); - return size; -} - -int mkswap_main(int argc, char **argv) -{ - char *tmp; - struct stat statbuf; - int sz; - int maxpages; - int goodpages; - int offset; - int force = 0; - - init_signature_page(); /* get pagesize */ - - while (argc-- > 1) { - argv++; - if (argv[0][0] != '-') { - if (device_name) { - int blocks_per_page = pagesize / 1024; - - PAGES = strtol(argv[0], &tmp, 0) / blocks_per_page; - if (*tmp) - show_usage(); - } else - device_name = argv[0]; - } else { - switch (argv[0][1]) { - case 'c': - check = 1; - break; - case 'f': - force = 1; - break; - case 'v': - version = atoi(argv[0] + 2); - break; - default: - show_usage(); - } - } - } - if (!device_name) { - error_msg("error: Nowhere to set up swap on?"); - show_usage(); - } - sz = get_size(device_name); - if (!PAGES) { - PAGES = sz; - } else if (PAGES > sz && !force) { - error_msg("error: size %ld is larger than device size %d", - PAGES * (pagesize / 1024), sz * (pagesize / 1024)); - return EXIT_FAILURE; - } - - if (version == -1) { - if (PAGES <= V0_MAX_PAGES) - version = 0; - else if (get_kernel_revision() < MAKE_VERSION(2, 1, 117)) - version = 0; - else if (pagesize < 2048) - version = 0; - else - version = 1; - } - if (version != 0 && version != 1) { - error_msg("error: unknown version %d", version); - show_usage(); - } - if (PAGES < 10) { - error_msg("error: swap area needs to be at least %ldkB", - (long) (10 * pagesize / 1024)); - show_usage(); - } -#if 0 - maxpages = ((version == 0) ? V0_MAX_PAGES : V1_MAX_PAGES); -#else - if (!version) - maxpages = V0_MAX_PAGES; - else if (get_kernel_revision() >= MAKE_VERSION(2, 2, 1)) - maxpages = V1_MAX_PAGES; - else { - maxpages = V1_OLD_MAX_PAGES; - if (maxpages > V1_MAX_PAGES) - maxpages = V1_MAX_PAGES; - } -#endif - if (PAGES > maxpages) { - PAGES = maxpages; - error_msg("warning: truncating swap area to %ldkB", - PAGES * pagesize / 1024); - } - - DEV = open(device_name, O_RDWR); - if (DEV < 0 || fstat(DEV, &statbuf) < 0) - perror_msg_and_die("%s", device_name); - if (!S_ISBLK(statbuf.st_mode)) - check = 0; - else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340) - error_msg_and_die("Will not try to make swapdevice on '%s'", device_name); - -#ifdef __sparc__ - if (!force && version == 0) { - /* Don't overwrite partition table unless forced */ - unsigned char *buffer = (unsigned char *) signature_page; - unsigned short *q, sum; - - if (read(DEV, buffer, 512) != 512) - error_msg_and_die("fatal: first page unreadable"); - if (buffer[508] == 0xDA && buffer[509] == 0xBE) { - q = (unsigned short *) (buffer + 510); - for (sum = 0; q >= (unsigned short *) buffer;) - sum ^= *q--; - if (!sum) { - error_msg("Device '%s' contains a valid Sun disklabel.\n" -"This probably means creating v0 swap would destroy your partition table\n" -"No swap created. If you really want to create swap v0 on that device, use\n" -"the -f option to force it.", device_name); - return EXIT_FAILURE; - } - } - } -#endif - - if (version == 0 || check) - check_blocks(); - if (version == 0 && !bit_test_and_clear(signature_page, 0)) - error_msg_and_die("fatal: first page unreadable"); - if (version == 1) { - p->version = version; - p->last_page = PAGES - 1; - p->nr_badpages = badpages; - } - - goodpages = PAGES - badpages - 1; - if (goodpages <= 0) - error_msg_and_die("Unable to set up swap-space: unreadable"); - printf("Setting up swapspace version %d, size = %ld bytes\n", - version, (long) (goodpages * pagesize)); - write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2"); - - offset = ((version == 0) ? 0 : 1024); - if (lseek(DEV, offset, SEEK_SET) != offset) - error_msg_and_die("unable to rewind swap-device"); - if (write(DEV, (char *) signature_page + offset, pagesize - offset) - != pagesize - offset) - error_msg_and_die("unable to write signature page"); - - /* - * A subsequent swapon() will fail if the signature - * is not actually on disk. (This is a kernel bug.) - */ - if (fsync(DEV)) - error_msg_and_die("fsync failed"); - return EXIT_SUCCESS; -} diff --git a/mktemp.c b/mktemp.c deleted file mode 100644 index bc47d0af0..000000000 --- a/mktemp.c +++ /dev/null @@ -1,40 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini mktemp implementation for busybox - * - * - * Copyright (C) 2000 by Daniel Jacobowitz - * Written by Daniel Jacobowitz - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include "busybox.h" - -extern int mktemp_main(int argc, char **argv) -{ - if (argc != 2 && (argc != 3 || strcmp(argv[1], "-q"))) - show_usage(); - if(mkstemp(argv[argc-1]) < 0) - return EXIT_FAILURE; - (void) puts(argv[argc-1]); - return EXIT_SUCCESS; -} diff --git a/modprobe.c b/modprobe.c deleted file mode 100644 index 05b40c53f..000000000 --- a/modprobe.c +++ /dev/null @@ -1,121 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * really dumb modprobe implementation for busybox - * Copyright (C) 2001 Lineo, davidm@lineo.com - */ - -#include -#include -#include -#include -#include -#include -#include "busybox.h" - -static char cmd[128]; - -extern int modprobe_main(int argc, char** argv) -{ - int ch, rc = 0; - int loadall = 0, showconfig = 0, debug = 0, autoclean = 0, list = 0; - int show_only = 0, quiet = 0, remove_opt = 0, do_syslog = 0, verbose = 0; - char *load_type = NULL, *config = NULL; - - while ((ch = getopt(argc, argv, "acdklnqrst:vVC:")) != -1) - switch(ch) { - case 'a': - loadall++; - break; - case 'c': - showconfig++; - break; - case 'd': - debug++; - break; - case 'k': - autoclean++; - break; - case 'l': - list++; - break; - case 'n': - show_only++; - break; - case 'q': - quiet++; - break; - case 'r': - remove_opt++; - break; - case 's': - do_syslog++; - break; - case 't': - load_type = optarg; - break; - case 'v': - verbose++; - break; - case 'C': - config = optarg; - break; - case 'V': - default: - show_usage(); - break; - } - - if (load_type || config) { - fprintf(stderr, "-t and -C not supported\n"); - exit(EXIT_FAILURE); - } - - if (showconfig) - exit(EXIT_SUCCESS); - - if (list) - exit(EXIT_SUCCESS); - - if (remove_opt) { - do { - sprintf(cmd, "rmmod %s %s %s", - optind >= argc ? "-a" : "", - do_syslog ? "-s" : "", - optind < argc ? argv[optind] : ""); - if (do_syslog) - syslog(LOG_INFO, "%s", cmd); - if (show_only || verbose) - printf("%s\n", cmd); - if (!show_only) - rc = system(cmd); - } while (++optind < argc); - exit(EXIT_SUCCESS); - } - - if (optind >= argc) { - fprintf(stderr, "No module or pattern provided\n"); - exit(EXIT_FAILURE); - } - - sprintf(cmd, "insmod %s %s %s", - do_syslog ? "-s" : "", - quiet ? "-q" : "", - autoclean ? "-k" : ""); - while (optind < argc) { - strcat(cmd, argv[optind]); - strcat(cmd, " "); - optind++; - } - if (do_syslog) - syslog(LOG_INFO, "%s", cmd); - if (show_only || verbose) - printf("%s\n", cmd); - if (!show_only) - rc = system(cmd); - else - rc = 0; - - exit(rc ? EXIT_FAILURE : EXIT_SUCCESS); -} - - diff --git a/modutils/Makefile b/modutils/Makefile new file mode 100644 index 000000000..7a8d4664e --- /dev/null +++ b/modutils/Makefile @@ -0,0 +1,39 @@ +# Makefile for busybox +# +# Copyright (C) 1999,2000,2001 by Erik Andersen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +TOPDIR :=.. +L_TARGET := modutils.a + +obj-y := +obj-n := +obj- := + + +obj-$(CONFIG_INSMOD) += insmod.o +obj-$(CONFIG_LSMOD) += lsmod.o +obj-$(CONFIG_MODPROBE) += modprobe.o +obj-$(CONFIG_RMMOD) += rmmod.o + + +# Hand off to toplevel Rules.mak +include $(TOPDIR)/Rules.mak + +clean: + rm -f $(L_TARGET) *.o core + diff --git a/modutils/config.in b/modutils/config.in new file mode 100644 index 000000000..fc00e333a --- /dev/null +++ b/modutils/config.in @@ -0,0 +1,22 @@ +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +mainmenu_option next_comment +comment 'Module Utilities' + + +bool 'insmod' CONFIG_INSMOD +bool 'lsmod' CONFIG_LSMOD +bool 'modprobe' CONFIG_MODPROBE +bool 'rmmod' CONFIG_RMMOD + +if [ "$CONFIG_INSMOD" = "y" ]; then + bool 'Support insmod/lsmod/rmmod for post 2.1 kernels' CONFIG_FEATURE_NEW_MODULE_INTERFACE + bool 'Support insmod/lsmod/rmmod for pre 2.1 kernels' CONFIG_FEATURE_OLD_MODULE_INTERFACE + bool 'Support module version checking' CONFIG_FEATURE_INSMOD_VERSION_CHECKING +fi + +endmenu + diff --git a/modutils/insmod.c b/modutils/insmod.c index 6b81ca754..c21f22b74 100644 --- a/modutils/insmod.c +++ b/modutils/insmod.c @@ -5,9 +5,8 @@ * This version of insmod supports x86, ARM, SH3/4, powerpc, m68k, * and MIPS. * - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen + * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen * and Ron Alder * * Modified by Bryan Rittmeyer to support SH4 @@ -22,7 +21,7 @@ * PowerPC specific code stolen from modutils-2.3.16, * written by Paul Mackerras, Copyright 1996, 1997 Linux International. * I've only tested the code on mpc8xx platforms in big-endian mode. - * Did some cleanup and added BB_USE_xxx_ENTRIES... + * Did some cleanup and added CONFIG_USE_xxx_ENTRIES... * * Quinn Jensen added MIPS support 23-Feb-2001. * based on modutils-2.4.2 @@ -66,39 +65,39 @@ #include #include "busybox.h" -#ifdef BB_FEATURE_NEW_MODULE_INTERFACE -# undef BB_FEATURE_OLD_MODULE_INTERFACE +#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE +# undef CONFIG_FEATURE_OLD_MODULE_INTERFACE # define new_sys_init_module init_module #else # define old_sys_init_module init_module #endif -#ifdef BB_FEATURE_INSMOD_LOADINKMEM +#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM #define LOADBITS 0 #else #define LOADBITS 1 #endif #if defined(__powerpc__) -#define BB_USE_PLT_ENTRIES -#define BB_PLT_ENTRY_SIZE 16 +#define CONFIG_USE_PLT_ENTRIES +#define CONFIG_PLT_ENTRY_SIZE 16 #endif #if defined(__arm__) -#define BB_USE_PLT_ENTRIES -#define BB_PLT_ENTRY_SIZE 8 -#define BB_USE_GOT_ENTRIES -#define BB_GOT_ENTRY_SIZE 8 +#define CONFIG_USE_PLT_ENTRIES +#define CONFIG_PLT_ENTRY_SIZE 8 +#define CONFIG_USE_GOT_ENTRIES +#define CONFIG_GOT_ENTRY_SIZE 8 #endif #if defined(__sh__) -#define BB_USE_GOT_ENTRIES -#define BB_GOT_ENTRY_SIZE 4 +#define CONFIG_USE_GOT_ENTRIES +#define CONFIG_GOT_ENTRY_SIZE 4 #endif #if defined(__i386__) -#define BB_USE_GOT_ENTRIES -#define BB_GOT_ENTRY_SIZE 4 +#define CONFIG_USE_GOT_ENTRIES +#define CONFIG_GOT_ENTRY_SIZE 4 #endif #if defined(__mips__) @@ -134,7 +133,7 @@ #ifndef MODUTILS_MODULE_H static const int MODUTILS_MODULE_H = 1; -#ident "$Id: insmod.c,v 1.73 2001/08/22 05:41:57 andersen Exp $" +#ident "$Id: insmod.c,v 1.74 2001/10/24 04:59:54 andersen Exp $" /* This file contains the structures used by the 2.0 and 2.1 kernels. We do not use the kernel headers directly because we do not wish @@ -267,7 +266,7 @@ struct new_module unsigned tgt_long persist_end; unsigned tgt_long can_unload; unsigned tgt_long runsize; -#ifdef BB_FEATURE_NEW_MODULE_INTERFACE +#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE const char *kallsyms_start; /* All symbols for kernel debugging */ const char *kallsyms_end; const char *archdata_start; /* arch specific data for module */ @@ -351,7 +350,7 @@ int delete_module(const char *); #ifndef MODUTILS_OBJ_H static const int MODUTILS_OBJ_H = 1; -#ident "$Id: insmod.c,v 1.73 2001/08/22 05:41:57 andersen Exp $" +#ident "$Id: insmod.c,v 1.74 2001/10/24 04:59:54 andersen Exp $" /* The relocatable object is manipulated using elfin types. */ @@ -551,7 +550,7 @@ static struct obj_symbol *obj_find_symbol (struct obj_file *f, static ElfW(Addr) obj_symbol_final_value(struct obj_file *f, struct obj_symbol *sym); -#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING +#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING static void obj_set_symbol_compare(struct obj_file *f, int (*cmp)(const char *, const char *), unsigned long (*hash)(const char *)); @@ -643,7 +642,7 @@ static int flag_export = 1; -#if defined(BB_USE_PLT_ENTRIES) +#if defined(CONFIG_USE_PLT_ENTRIES) struct arch_plt_entry { int offset; @@ -652,7 +651,7 @@ struct arch_plt_entry }; #endif -#if defined(BB_USE_GOT_ENTRIES) +#if defined(CONFIG_USE_GOT_ENTRIES) struct arch_got_entry { int offset; unsigned offset_done:1; @@ -671,10 +670,10 @@ struct mips_hi16 struct arch_file { struct obj_file root; -#if defined(BB_USE_PLT_ENTRIES) +#if defined(CONFIG_USE_PLT_ENTRIES) struct obj_section *plt; #endif -#if defined(BB_USE_GOT_ENTRIES) +#if defined(CONFIG_USE_GOT_ENTRIES) struct obj_section *got; #endif #if defined(__mips__) @@ -684,10 +683,10 @@ struct arch_file { struct arch_symbol { struct obj_symbol root; -#if defined(BB_USE_PLT_ENTRIES) +#if defined(CONFIG_USE_PLT_ENTRIES) struct arch_plt_entry pltent; #endif -#if defined(BB_USE_GOT_ENTRIES) +#if defined(CONFIG_USE_GOT_ENTRIES) struct arch_got_entry gotent; #endif }; @@ -746,10 +745,10 @@ static struct obj_file *arch_new_file(void) struct arch_file *f; f = xmalloc(sizeof(*f)); -#if defined(BB_USE_PLT_ENTRIES) +#if defined(CONFIG_USE_PLT_ENTRIES) f->plt = NULL; #endif -#if defined(BB_USE_GOT_ENTRIES) +#if defined(CONFIG_USE_GOT_ENTRIES) f->got = NULL; #endif #if defined(__mips__) @@ -769,10 +768,10 @@ static struct obj_symbol *arch_new_symbol(void) struct arch_symbol *sym; sym = xmalloc(sizeof(*sym)); -#if defined(BB_USE_PLT_ENTRIES) +#if defined(CONFIG_USE_PLT_ENTRIES) memset(&sym->pltent, 0, sizeof(sym->pltent)); #endif -#if defined(BB_USE_GOT_ENTRIES) +#if defined(CONFIG_USE_GOT_ENTRIES) memset(&sym->gotent, 0, sizeof(sym->gotent)); #endif @@ -793,10 +792,10 @@ arch_apply_relocation(struct obj_file *f, ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset); ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset; -#if defined(BB_USE_GOT_ENTRIES) +#if defined(CONFIG_USE_GOT_ENTRIES) ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0; #endif -#if defined(BB_USE_PLT_ENTRIES) +#if defined(CONFIG_USE_PLT_ENTRIES) ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0; struct arch_plt_entry *pe; unsigned long *ip; @@ -984,7 +983,7 @@ arch_apply_relocation(struct obj_file *f, #elif defined(__i386__) #endif -#if defined(BB_USE_PLT_ENTRIES) +#if defined(CONFIG_USE_PLT_ENTRIES) #if defined(__arm__) case R_ARM_PC24: @@ -1037,7 +1036,7 @@ arch_apply_relocation(struct obj_file *f, *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc); #endif break; -#endif /* BB_USE_PLT_ENTRIES */ +#endif /* CONFIG_USE_PLT_ENTRIES */ #if defined(__arm__) #elif defined(__sh__) @@ -1072,7 +1071,7 @@ arch_apply_relocation(struct obj_file *f, break; #endif -#if defined(BB_USE_GOT_ENTRIES) +#if defined(CONFIG_USE_GOT_ENTRIES) #if !defined(__68k__) #if defined(__sh__) @@ -1130,7 +1129,7 @@ arch_apply_relocation(struct obj_file *f, break; #endif // __mc68000__ -#endif /* BB_USE_GOT_ENTRIES */ +#endif /* CONFIG_USE_GOT_ENTRIES */ default: printf("Warning: unhandled reloc %d\n",(int)ELF32_R_TYPE(rel->r_info)); @@ -1143,13 +1142,13 @@ arch_apply_relocation(struct obj_file *f, static int arch_create_got(struct obj_file *f) { -#if defined(BB_USE_GOT_ENTRIES) || defined(BB_USE_PLT_ENTRIES) +#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES) struct arch_file *ifile = (struct arch_file *) f; int i; -#if defined(BB_USE_GOT_ENTRIES) +#if defined(CONFIG_USE_GOT_ENTRIES) int got_offset = 0, gotneeded = 0; #endif -#if defined(BB_USE_PLT_ENTRIES) +#if defined(CONFIG_USE_PLT_ENTRIES) int plt_offset = 0, pltneeded = 0; #endif struct obj_section *relsec, *symsec, *strsec; @@ -1226,18 +1225,18 @@ static int arch_create_got(struct obj_file *f) name = f->sections[extsym->st_shndx]->name; } intsym = (struct arch_symbol *) obj_find_symbol(f, name); -#if defined(BB_USE_GOT_ENTRIES) +#if defined(CONFIG_USE_GOT_ENTRIES) if (!intsym->gotent.offset_done) { intsym->gotent.offset_done = 1; intsym->gotent.offset = got_offset; - got_offset += BB_GOT_ENTRY_SIZE; + got_offset += CONFIG_GOT_ENTRY_SIZE; } #endif -#if defined(BB_USE_PLT_ENTRIES) +#if defined(CONFIG_USE_PLT_ENTRIES) if (pltneeded && intsym->pltent.allocated == 0) { intsym->pltent.allocated = 1; intsym->pltent.offset = plt_offset; - plt_offset += BB_PLT_ENTRY_SIZE; + plt_offset += CONFIG_PLT_ENTRY_SIZE; intsym->pltent.inited = 0; pltneeded = 0; } @@ -1245,7 +1244,7 @@ static int arch_create_got(struct obj_file *f) } } -#if defined(BB_USE_GOT_ENTRIES) +#if defined(CONFIG_USE_GOT_ENTRIES) if (got_offset) { struct obj_section* myrelsec = obj_find_section(f, ".got"); @@ -1253,7 +1252,7 @@ static int arch_create_got(struct obj_file *f) obj_extend_section(myrelsec, got_offset); } else { myrelsec = obj_create_alloced_section(f, ".got", - BB_GOT_ENTRY_SIZE, + CONFIG_GOT_ENTRY_SIZE, got_offset); assert(myrelsec); } @@ -1262,10 +1261,10 @@ static int arch_create_got(struct obj_file *f) } #endif -#if defined(BB_USE_PLT_ENTRIES) +#if defined(CONFIG_USE_PLT_ENTRIES) if (plt_offset) ifile->plt = obj_create_alloced_section(f, ".plt", - BB_PLT_ENTRY_SIZE, + CONFIG_PLT_ENTRY_SIZE, plt_offset); #endif #endif @@ -1304,7 +1303,7 @@ static unsigned long obj_elf_hash(const char *name) return obj_elf_hash_n(name, strlen(name)); } -#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING +#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING /* String comparison for non-co-versioned kernel and module. */ static int ncv_strcmp(const char *a, const char *b) @@ -1356,7 +1355,7 @@ obj_set_symbol_compare(struct obj_file *f, } } -#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */ +#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */ static struct obj_symbol * obj_add_symbol(struct obj_file *f, const char *name, @@ -1787,7 +1786,7 @@ old_process_module_arguments(struct obj_file *f, int argc, char **argv) return 1; } -#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING +#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING static int old_is_module_checksummed(struct obj_file *f) { return obj_find_symbol(f, "Using_Versions") != NULL; @@ -1821,9 +1820,9 @@ old_get_module_version(struct obj_file *f, char str[STRVERSIONLEN]) return a << 16 | b << 8 | c; } -#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */ +#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */ -#ifdef BB_FEATURE_OLD_MODULE_INTERFACE +#ifdef CONFIG_FEATURE_OLD_MODULE_INTERFACE /* Fetch all the symbols and divvy them up as appropriate for the modules. */ @@ -2033,7 +2032,7 @@ old_init_module(const char *m_name, struct obj_file *f, #define old_create_mod_use_count(x) TRUE #define old_init_module(x, y, z) TRUE -#endif /* BB_FEATURE_OLD_MODULE_INTERFACE */ +#endif /* CONFIG_FEATURE_OLD_MODULE_INTERFACE */ @@ -2273,7 +2272,7 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv) return 1; } -#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING +#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING static int new_is_module_checksummed(struct obj_file *f) { const char *p = get_modinfo_value(f, "using_checksums"); @@ -2309,10 +2308,10 @@ new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN]) return a << 16 | b << 8 | c; } -#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */ +#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */ -#ifdef BB_FEATURE_NEW_MODULE_INTERFACE +#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE /* Fetch the loaded modules, and all currently exported symbols. */ @@ -2601,7 +2600,7 @@ new_init_module(const char *m_name, struct obj_file *f, #define new_create_module_ksymtab(x) #define query_module(v, w, x, y, z) -1 -#endif /* BB_FEATURE_NEW_MODULE_INTERFACE */ +#endif /* CONFIG_FEATURE_NEW_MODULE_INTERFACE */ /*======================================================================*/ @@ -3155,7 +3154,7 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits) return f; } -#ifdef BB_FEATURE_INSMOD_LOADINKMEM +#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM /* * load the unloaded sections directly into the memory allocated by * kernel for the module @@ -3222,7 +3221,7 @@ extern int insmod_main( int argc, char **argv) char m_name[FILENAME_MAX + 1] = "\0"; int exit_status = EXIT_FAILURE; int m_has_modinfo; -#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING +#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING struct utsname uts_info; char m_strversion[STRVERSIONLEN]; int m_version; @@ -3335,7 +3334,7 @@ extern int insmod_main( int argc, char **argv) else m_has_modinfo = 1; -#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING +#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING /* Version correspondence? */ if (uname(&uts_info) < 0) @@ -3366,12 +3365,12 @@ extern int insmod_main( int argc, char **argv) } } k_crcs = 0; -#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */ +#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */ k_new_syscalls = !query_module(NULL, 0, NULL, 0, NULL); if (k_new_syscalls) { -#ifdef BB_FEATURE_NEW_MODULE_INTERFACE +#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE if (!new_get_kernel_symbols()) goto out; k_crcs = new_is_kernel_checksummed(); @@ -3380,7 +3379,7 @@ extern int insmod_main( int argc, char **argv) goto out; #endif } else { -#ifdef BB_FEATURE_OLD_MODULE_INTERFACE +#ifdef CONFIG_FEATURE_OLD_MODULE_INTERFACE if (!old_get_kernel_symbols(m_name)) goto out; k_crcs = old_is_kernel_checksummed(); @@ -3390,7 +3389,7 @@ extern int insmod_main( int argc, char **argv) #endif } -#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING +#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING if (m_has_modinfo) m_crcs = new_is_module_checksummed(f); else @@ -3398,7 +3397,7 @@ extern int insmod_main( int argc, char **argv) if (m_crcs != k_crcs) obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash); -#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */ +#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */ /* Let the module know about the kernel symbols. */ add_kernel_symbols(f); diff --git a/modutils/lsmod.c b/modutils/lsmod.c index 76ed2fdd8..7b6ad14c6 100644 --- a/modutils/lsmod.c +++ b/modutils/lsmod.c @@ -2,8 +2,8 @@ /* * Mini lsmod implementation for busybox * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , + * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen * * Modified by Alcove, Julien Gaulmin and * Nicolas Ferre to support pre 2.1 kernels @@ -41,7 +41,7 @@ -#ifdef BB_FEATURE_NEW_MODULE_INTERFACE +#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE struct module_info { @@ -142,7 +142,7 @@ extern int lsmod_main(int argc, char **argv) return( 0); } -#else /*BB_FEATURE_OLD_MODULE_INTERFACE*/ +#else /*CONFIG_FEATURE_OLD_MODULE_INTERFACE*/ extern int lsmod_main(int argc, char **argv) { @@ -163,4 +163,4 @@ extern int lsmod_main(int argc, char **argv) return 1; } -#endif /*BB_FEATURE_OLD_MODULE_INTERFACE*/ +#endif /*CONFIG_FEATURE_OLD_MODULE_INTERFACE*/ diff --git a/modutils/rmmod.c b/modutils/rmmod.c index 7596d0232..affe975fa 100644 --- a/modutils/rmmod.c +++ b/modutils/rmmod.c @@ -2,8 +2,8 @@ /* * Mini rmmod implementation for busybox * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , + * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/more.c b/more.c deleted file mode 100644 index 780cddf66..000000000 --- a/more.c +++ /dev/null @@ -1,217 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini more implementation for busybox - * - * - * Copyright (C) 1995, 1996 by Bruce Perens . - * - * Latest version blended together by Erik Andersen , - * based on the original more implementation by Bruce, and code from the - * Debian boot-floppies team. - * - * Termios corrects by Vladimir Oleynik - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include "busybox.h" - -static FILE *cin; - -#ifdef BB_FEATURE_USE_TERMIOS -#include -#define setTermSettings(fd,argp) tcsetattr(fd,TCSANOW,argp) -#define getTermSettings(fd,argp) tcgetattr(fd, argp); - -static struct termios initial_settings, new_settings; - -static void set_tty_to_initial_mode(void) -{ - setTermSettings(fileno(cin), &initial_settings); -} - -static void gotsig(int sig) -{ - putchar('\n'); - exit(EXIT_FAILURE); -} -#endif /* BB_FEATURE_USE_TERMIOS */ - - -static int terminal_width = 79; /* not 80 in case terminal has linefold bug */ -static int terminal_height = 24; - - -extern int more_main(int argc, char **argv) -{ - int c, lines, input = 0; - int please_display_more_prompt = -1; - struct stat st; - FILE *file; - int len, page_height; - -#if defined BB_FEATURE_AUTOWIDTH && defined BB_FEATURE_USE_TERMIOS - struct winsize win = { 0, 0, 0, 0 }; -#endif - - argc--; - argv++; - - - /* not use inputing from terminal if usage: more > outfile */ - if(isatty(fileno(stdout))) { - cin = fopen(CURRENT_TTY, "r"); - if (!cin) - cin = xfopen(CONSOLE_DEV, "r"); - please_display_more_prompt = 0; -#ifdef BB_FEATURE_USE_TERMIOS - getTermSettings(fileno(cin), &initial_settings); - new_settings = initial_settings; - new_settings.c_lflag &= ~ICANON; - new_settings.c_lflag &= ~ECHO; -#ifndef linux - /* Hmm, in linux c_cc[] not parsed if set ~ICANON */ - new_settings.c_cc[VMIN] = 1; - new_settings.c_cc[VTIME] = 0; -#endif - setTermSettings(fileno(cin), &new_settings); - atexit(set_tty_to_initial_mode); - (void) signal(SIGINT, gotsig); - (void) signal(SIGQUIT, gotsig); - (void) signal(SIGTERM, gotsig); -#endif - } - - do { - if (argc == 0) { - file = stdin; - } else - file = wfopen(*argv, "r"); - if(file==0) - goto loop; - - fstat(fileno(file), &st); - - if(please_display_more_prompt>0) - please_display_more_prompt = 0; - -#if defined BB_FEATURE_AUTOWIDTH && defined BB_FEATURE_USE_TERMIOS - ioctl(fileno(stdout), TIOCGWINSZ, &win); - if (win.ws_row > 4) - terminal_height = win.ws_row - 2; - if (win.ws_col > 0) - terminal_width = win.ws_col - 1; -#endif - len=0; - lines = 0; - page_height = terminal_height; - while ((c = getc(file)) != EOF) { - - if (please_display_more_prompt>0) { - len = printf("--More-- "); - if (file != stdin) { -#if _FILE_OFFSET_BITS == 64 - len += printf("(%d%% of %lld bytes)", - (int) (100 * ((double) ftell(file) / - (double) st.st_size)), (long long)st.st_size); -#else - len += printf("(%d%% of %ld bytes)", - (int) (100 * ((double) ftell(file) / - (double) st.st_size)), (long)st.st_size); -#endif - } - - fflush(stdout); - - /* - * We've just displayed the "--More--" prompt, so now we need - * to get input from the user. - */ - input = getc(cin); -#ifndef BB_FEATURE_USE_TERMIOS - printf("\033[A"); /* up cursor */ -#endif - /* Erase the "More" message */ - putc('\r', stdout); - while (--len >= 0) - putc(' ', stdout); - putc('\r', stdout); - fflush(stdout); - len=0; - lines = 0; - page_height = terminal_height; - please_display_more_prompt = 0; - - if (input == 'q') - goto end; - } - - /* - * There are two input streams to worry about here: - * - * c : the character we are reading from the file being "mored" - * input : a character received from the keyboard - * - * If we hit a newline in the _file_ stream, we want to test and - * see if any characters have been hit in the _input_ stream. This - * allows the user to quit while in the middle of a file. - */ - if (c == '\n') { - /* increment by just one line if we are at - * the end of this line */ - if (input == '\n') - if(please_display_more_prompt==0) - please_display_more_prompt = 1; - /* Adjust the terminal height for any overlap, so that - * no lines get lost off the top. */ - if (len >= terminal_width) { - int quot, rem; - quot = len / terminal_width; - rem = len - (quot * terminal_width); - if (quot) { - if (rem) - page_height-=quot; - else - page_height-=(quot-1); - } - } - if (++lines >= page_height) { - if(please_display_more_prompt==0) - please_display_more_prompt = 1; - } - len=0; - } - /* - * If we just read a newline from the file being 'mored' and any - * key other than a return is hit, scroll by one page - */ - putc(c, stdout); - len++; - } - fclose(file); - fflush(stdout); -loop: - argv++; - } while (--argc > 0); - end: - return 0; -} diff --git a/mount.c b/mount.c deleted file mode 100644 index af57a7623..000000000 --- a/mount.c +++ /dev/null @@ -1,498 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini mount implementation for busybox - * - * Copyright (C) 1995, 1996 by Bruce Perens . - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * 3/21/1999 Charles P. Wright - * searches through fstab when -a is passed - * will try mounting stuff with all fses when passed -t auto - * - * 1999-04-17 Dave Cinege...Rewrote -t auto. Fixed ro mtab. - * - * 1999-10-07 Erik Andersen , . - * Rewrite of a lot of code. Removed mtab usage (I plan on - * putting it back as a compile-time option some time), - * major adjustments to option parsing, and some serious - * dieting all around. - * - * 1999-11-06 mtab suppport is back - andersee - * - * 2000-01-12 Ben Collins , Borrowed utils-linux's - * mount to add loop support. - * - * 2000-04-30 Dave Cinege - * Rewrote fstab while loop and lower mount section. Can now do - * single mounts from fstab. Can override fstab options for single - * mount. Common mount_one call for single mounts and 'all'. Fixed - * mtab updating and stale entries. Removed 'remount' default. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" -#if defined BB_FEATURE_USE_DEVPS_PATCH -# include /* For Erik's nifty devmtab device driver */ -#endif - -enum { - MS_MGC_VAL = 0xc0ed0000, /* Magic number indicatng "new" flags */ - MS_RDONLY = 1, /* Mount read-only */ - MS_NOSUID = 2, /* Ignore suid and sgid bits */ - MS_NODEV = 4, /* Disallow access to device special files */ - MS_NOEXEC = 8, /* Disallow program execution */ - MS_SYNCHRONOUS = 16, /* Writes are synced at once */ - MS_REMOUNT = 32, /* Alter flags of a mounted FS */ - MS_MANDLOCK = 64, /* Allow mandatory locks on an FS */ - S_QUOTA = 128, /* Quota initialized for file/directory/symlink */ - S_APPEND = 256, /* Append-only file */ - S_IMMUTABLE = 512, /* Immutable file */ - MS_NOATIME = 1024, /* Do not update access times. */ - MS_NODIRATIME = 2048, /* Do not update directory access times */ - MS_BIND = 4096, /* Use the new linux 2.4.x "mount --bind" feature */ -}; - - -#if defined BB_FEATURE_MOUNT_LOOP -#include -#include -static int use_loop = FALSE; -#endif - -extern int mount (__const char *__special_file, __const char *__dir, - __const char *__fstype, unsigned long int __rwflag, - __const void *__data); -extern int umount (__const char *__special_file); -extern int umount2 (__const char *__special_file, int __flags); - -extern int sysfs( int option, unsigned int fs_index, char * buf); - -extern const char mtab_file[]; /* Defined in utility.c */ - -struct mount_options { - const char *name; - unsigned long and; - unsigned long or; -}; - -static const struct mount_options mount_options[] = { - {"async", ~MS_SYNCHRONOUS, 0}, - {"atime", ~0, ~MS_NOATIME}, - {"defaults", ~0, 0}, - {"dev", ~MS_NODEV, 0}, - {"diratime", ~0, ~MS_NODIRATIME}, - {"exec", ~MS_NOEXEC, 0}, - {"noatime", ~0, MS_NOATIME}, - {"nodev", ~0, MS_NODEV}, - {"nodiratime", ~0, MS_NODIRATIME}, - {"noexec", ~0, MS_NOEXEC}, - {"nosuid", ~0, MS_NOSUID}, - {"remount", ~0, MS_REMOUNT}, - {"ro", ~0, MS_RDONLY}, - {"rw", ~MS_RDONLY, 0}, - {"suid", ~MS_NOSUID, 0}, - {"sync", ~0, MS_SYNCHRONOUS}, - {"bind", ~0, MS_BIND}, - {0, 0, 0} -}; - -static int -do_mount(char *specialfile, char *dir, char *filesystemtype, - long flags, void *string_flags, int useMtab, int fakeIt, - char *mtab_opts, int mount_all) -{ - int status = 0; -#if defined BB_FEATURE_MOUNT_LOOP - char *lofile = NULL; -#endif - - if (fakeIt == FALSE) - { -#if defined BB_FEATURE_MOUNT_LOOP - if (use_loop==TRUE) { - int loro = flags & MS_RDONLY; - - lofile = specialfile; - - specialfile = find_unused_loop_device(); - if (specialfile == NULL) { - error_msg_and_die("Could not find a spare loop device"); - } - if (set_loop(specialfile, lofile, 0, &loro)) { - error_msg_and_die("Could not setup loop device"); - } - if (!(flags & MS_RDONLY) && loro) { /* loop is ro, but wanted rw */ - error_msg("WARNING: loop device is read-only"); - flags |= MS_RDONLY; - } - } -#endif - status = mount(specialfile, dir, filesystemtype, flags, string_flags); - if (status < 0 && errno == EROFS) { - error_msg("%s is write-protected, mounting read-only", specialfile); - status = mount(specialfile, dir, filesystemtype, flags |= MS_RDONLY, string_flags); - } - /* Don't whine about already mounted filesystems when mounting all. */ - if (status < 0 && errno == EBUSY && mount_all) - return TRUE; - } - - - /* If the mount was sucessful, do anything needed, then return TRUE */ - if (status == 0 || fakeIt==TRUE) { - -#if defined BB_FEATURE_MTAB_SUPPORT - if (useMtab == TRUE) { - erase_mtab(specialfile); // Clean any stale entries - write_mtab(specialfile, dir, filesystemtype, flags, mtab_opts); - } -#endif - return (TRUE); - } - - /* Bummer. mount failed. Clean up */ -#if defined BB_FEATURE_MOUNT_LOOP - if (lofile != NULL) { - del_loop(specialfile); - } -#endif - - if (errno == EPERM) { - error_msg_and_die("permission denied. Are you root?"); - } - - return (FALSE); -} - - - -/* Seperate standard mount options from the nonstandard string options */ -static void -parse_mount_options(char *options, int *flags, char *strflags) -{ - while (options) { - int gotone = FALSE; - char *comma = strchr(options, ','); - const struct mount_options *f = mount_options; - - if (comma) - *comma = '\0'; - - while (f->name != 0) { - if (strcasecmp(f->name, options) == 0) { - - *flags &= f->and; - *flags |= f->or; - gotone = TRUE; - break; - } - f++; - } -#if defined BB_FEATURE_MOUNT_LOOP - if (gotone == FALSE && !strcasecmp("loop", options)) { /* loop device support */ - use_loop = TRUE; - gotone = TRUE; - } -#endif - if (*strflags && strflags != '\0' && gotone == FALSE) { - char *temp = strflags; - - temp += strlen(strflags); - *temp++ = ','; - *temp++ = '\0'; - } - if (gotone == FALSE) - strcat(strflags, options); - if (comma) { - *comma = ','; - options = ++comma; - } else { - break; - } - } -} - -static int -mount_one(char *blockDevice, char *directory, char *filesystemType, - unsigned long flags, char *string_flags, int useMtab, int fakeIt, - char *mtab_opts, int whineOnErrors, int mount_all) -{ - int status = 0; - -#if defined BB_FEATURE_USE_DEVPS_PATCH - if (strcmp(filesystemType, "auto") == 0) { - static const char *noauto_array[] = { "tmpfs", "shm", "proc", "ramfs", "devpts", "devfs", "usbdevfs", 0 }; - const char **noauto_fstype; - const int num_of_filesystems = sysfs(3, 0, 0); - char buf[255]; - int i=0; - - filesystemType=buf; - - while(i < num_of_filesystems) { - sysfs(2, i++, filesystemType); - for (noauto_fstype = noauto_array; *noauto_fstype; noauto_fstype++) { - if (!strcmp(filesystemType, *noauto_fstype)) { - break; - } - } - if (!*noauto_fstype) { - status = do_mount(blockDevice, directory, filesystemType, - flags | MS_MGC_VAL, string_flags, - useMtab, fakeIt, mtab_opts, mount_all); - if (status == TRUE) - break; - } - } - } -#else - if (strcmp(filesystemType, "auto") == 0) { - char buf[255]; - FILE *f = xfopen("/proc/filesystems", "r"); - - while (fgets(buf, sizeof(buf), f) != NULL) { - filesystemType = buf; - if (*filesystemType == '\t') { // Not a nodev filesystem - - // Add NULL termination to each line - while (*filesystemType && *filesystemType != '\n') - filesystemType++; - *filesystemType = '\0'; - - filesystemType = buf; - filesystemType++; // hop past tab - - status = do_mount(blockDevice, directory, filesystemType, - flags | MS_MGC_VAL, string_flags, - useMtab, fakeIt, mtab_opts, mount_all); - if (status == TRUE) - break; - } - } - fclose(f); - } -#endif - else { - status = do_mount(blockDevice, directory, filesystemType, - flags | MS_MGC_VAL, string_flags, useMtab, - fakeIt, mtab_opts, mount_all); - } - - if (status == FALSE) { - if (whineOnErrors == TRUE) { - perror_msg("Mounting %s on %s failed", blockDevice, directory); - } - return (FALSE); - } - return (TRUE); -} - -void show_mounts(void) -{ -#if defined BB_FEATURE_USE_DEVPS_PATCH - int fd, i, numfilesystems; - char device[] = "/dev/mtab"; - struct k_mntent *mntentlist; - - /* open device */ - fd = open(device, O_RDONLY); - if (fd < 0) - perror_msg_and_die("open failed for `%s'", device); - - /* How many mounted filesystems? We need to know to - * allocate enough space for later... */ - numfilesystems = ioctl (fd, DEVMTAB_COUNT_MOUNTS); - if (numfilesystems<0) - perror_msg_and_die( "\nDEVMTAB_COUNT_MOUNTS"); - mntentlist = (struct k_mntent *) xcalloc ( numfilesystems, sizeof(struct k_mntent)); - - /* Grab the list of mounted filesystems */ - if (ioctl (fd, DEVMTAB_GET_MOUNTS, mntentlist)<0) - perror_msg_and_die( "\nDEVMTAB_GET_MOUNTS"); - - for( i = 0 ; i < numfilesystems ; i++) { - printf( "%s %s %s %s %d %d\n", mntentlist[i].mnt_fsname, - mntentlist[i].mnt_dir, mntentlist[i].mnt_type, - mntentlist[i].mnt_opts, mntentlist[i].mnt_freq, - mntentlist[i].mnt_passno); - } -#ifdef BB_FEATURE_CLEAN_UP - /* Don't bother to close files or free memory. Exit - * does that automagically, so we can save a few bytes */ - free( mntentlist); - close(fd); -#endif - exit(EXIT_SUCCESS); -#else - FILE *mountTable = setmntent(mtab_file, "r"); - - if (mountTable) { - struct mntent *m; - - while ((m = getmntent(mountTable)) != 0) { - char *blockDevice = m->mnt_fsname; - if (strcmp(blockDevice, "/dev/root") == 0) { - blockDevice = find_real_root_device_name(blockDevice); - } - printf("%s on %s type %s (%s)\n", blockDevice, m->mnt_dir, - m->mnt_type, m->mnt_opts); -#ifdef BB_FEATURE_CLEAN_UP - if(blockDevice != m->mnt_fsname) - free(blockDevice); -#endif - } - endmntent(mountTable); - } else { - perror_msg_and_die("%s", mtab_file); - } - exit(EXIT_SUCCESS); -#endif -} - -extern int mount_main(int argc, char **argv) -{ - struct stat statbuf; - char string_flags_buf[1024] = ""; - char *string_flags = string_flags_buf; - char *extra_opts = string_flags_buf; - int flags = 0; - char *filesystemType = "auto"; - char *device = xmalloc(PATH_MAX); - char *directory = xmalloc(PATH_MAX); - int all = FALSE; - int fakeIt = FALSE; - int useMtab = TRUE; - int rc = EXIT_FAILURE; - int fstabmount = FALSE; - int opt; - - /* Parse options */ - while ((opt = getopt(argc, argv, "o:rt:wafnv")) > 0) { - switch (opt) { - case 'o': - parse_mount_options(optarg, &flags, string_flags); - break; - case 'r': - flags |= MS_RDONLY; - break; - case 't': - filesystemType = optarg; - break; - case 'w': - flags &= ~MS_RDONLY; - break; - case 'a': - all = TRUE; - break; - case 'f': - fakeIt = TRUE; - break; -#ifdef BB_FEATURE_MTAB_SUPPORT - case 'n': - useMtab = FALSE; - break; -#endif - case 'v': - break; /* ignore -v */ - } - } - - if (!all && optind == argc) - show_mounts(); - - if (optind < argc) { - /* if device is a filename get its real path */ - if (stat(argv[optind], &statbuf) == 0) { - device = simplify_path(argv[optind]); - } else { - safe_strncpy(device, argv[optind], PATH_MAX); - } - } - - if (optind + 1 < argc) - directory = simplify_path(argv[optind + 1]); - - if (all == TRUE || optind + 1 == argc) { - struct mntent *m = NULL; - FILE *f = setmntent("/etc/fstab", "r"); - fstabmount = TRUE; - - if (f == NULL) - perror_msg_and_die( "\nCannot read /etc/fstab"); - - while ((m = getmntent(f)) != NULL) { - if (all == FALSE && optind + 1 == argc && ( - (strcmp(device, m->mnt_fsname) != 0) && - (strcmp(device, m->mnt_dir) != 0) ) ) { - continue; - } - - if (all == TRUE && ( // If we're mounting 'all' - (strstr(m->mnt_opts, "noauto")) || // and the file system isn't noauto, - (strstr(m->mnt_type, "swap")) || // and isn't swap or nfs, then mount it - (strstr(m->mnt_type, "nfs")) ) ) { - continue; - } - - if (all == TRUE || flags == 0) { // Allow single mount to override fstab flags - flags = 0; - *string_flags = '\0'; - parse_mount_options(m->mnt_opts, &flags, string_flags); - } - - strcpy(device, m->mnt_fsname); - strcpy(directory, m->mnt_dir); - filesystemType = strdup(m->mnt_type); -singlemount: - string_flags = strdup(string_flags); - rc = EXIT_SUCCESS; -#ifdef BB_NFSMOUNT - if (strchr(device, ':') != NULL) - filesystemType = "nfs"; - if (strcmp(filesystemType, "nfs") == 0) { - if (nfsmount (device, directory, &flags, &extra_opts, - &string_flags, 1)) { - perror_msg("nfsmount failed"); - rc = EXIT_FAILURE; - } - } -#endif - if (!mount_one(device, directory, filesystemType, flags, - string_flags, useMtab, fakeIt, extra_opts, TRUE, all)) - rc = EXIT_FAILURE; - - if (all == FALSE) - break; - } - if (fstabmount == TRUE) - endmntent(f); - - if (all == FALSE && fstabmount == TRUE && m == NULL) - fprintf(stderr, "Can't find %s in /etc/fstab\n", device); - - return rc; - } - - goto singlemount; -} diff --git a/msh.c b/msh.c deleted file mode 100644 index 5c4ec1019..000000000 --- a/msh.c +++ /dev/null @@ -1,4870 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Minix shell port for busybox - * - * This version of the Minix shell was adapted for use in busybox - * by Erik Andersen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Original copyright notice is retained at the end of this file. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "cmdedit.h" -#include "busybox.h" - - -/* -------- sh.h -------- */ -/* - * shell - */ - -#define LINELIM 2100 -#define NPUSH 8 /* limit to input nesting */ - -#define NOFILE 20 /* Number of open files */ -#define NUFILE 10 /* Number of user-accessible files */ -#define FDBASE 10 /* First file usable by Shell */ - -/* - * values returned by wait - */ -#define WAITSIG(s) ((s)&0177) -#define WAITVAL(s) (((s)>>8)&0377) -#define WAITCORE(s) (((s)&0200)!=0) - -/* - * library and system defintions - */ -typedef void xint; /* base type of jmp_buf, for not broken compilers */ - -/* - * shell components - */ - -#define QUOTE 0200 - -#define NOBLOCK ((struct op *)NULL) -#define NOWORD ((char *)NULL) -#define NOWORDS ((char **)NULL) -#define NOPIPE ((int *)NULL) - -/* - * Description of a command or an operation on commands. - * Might eventually use a union. - */ -struct op { - int type; /* operation type, see below */ - char **words; /* arguments to a command */ - struct ioword **ioact; /* IO actions (eg, < > >>) */ - struct op *left; - struct op *right; - char *str; /* identifier for case and for */ -}; - -#define TCOM 1 /* command */ -#define TPAREN 2 /* (c-list) */ -#define TPIPE 3 /* a | b */ -#define TLIST 4 /* a [&;] b */ -#define TOR 5 /* || */ -#define TAND 6 /* && */ -#define TFOR 7 -#define TDO 8 -#define TCASE 9 -#define TIF 10 -#define TWHILE 11 -#define TUNTIL 12 -#define TELIF 13 -#define TPAT 14 /* pattern in case */ -#define TBRACE 15 /* {c-list} */ -#define TASYNC 16 /* c & */ - -/* - * actions determining the environment of a process - */ -#define BIT(i) (1<<(i)) -#define FEXEC BIT(0) /* execute without forking */ - -/* - * flags to control evaluation of words - */ -#define DOSUB 1 /* interpret $, `, and quotes */ -#define DOBLANK 2 /* perform blank interpretation */ -#define DOGLOB 4 /* interpret [?* */ -#define DOKEY 8 /* move words with `=' to 2nd arg. list */ -#define DOTRIM 16 /* trim resulting string */ - -#define DOALL (DOSUB|DOBLANK|DOGLOB|DOKEY|DOTRIM) - -static char **dolv; -static int dolc; -static int exstat; -static char gflg; -static int interactive; /* Is this an interactive shell */ -static int execflg; -static int multiline; /* \n changed to ; */ -static struct op *outtree; /* result from parser */ - -static xint *failpt; -static xint *errpt; -static struct brkcon *brklist; -static int isbreak; -static int newfile(char *s); -static char *findeq(char *cp); -static char *cclass(char *p, int sub); -static void initarea(void); -extern int msh_main(int argc, char **argv); - - -struct brkcon { - jmp_buf brkpt; - struct brkcon *nextlev; -} ; - -/* - * redirection - */ -struct ioword { - short io_unit; /* unit affected */ - short io_flag; /* action (below) */ - char *io_name; /* file name */ -}; -#define IOREAD 1 /* < */ -#define IOHERE 2 /* << (here file) */ -#define IOWRITE 4 /* > */ -#define IOCAT 8 /* >> */ -#define IOXHERE 16 /* ${}, ` in << */ -#define IODUP 32 /* >&digit */ -#define IOCLOSE 64 /* >&- */ - -#define IODEFAULT (-1) /* token for default IO unit */ - -static struct wdblock *wdlist; -static struct wdblock *iolist; - -/* - * parsing & execution environment - */ -static struct env { - char *linep; - struct io *iobase; - struct io *iop; - xint *errpt; - int iofd; - struct env *oenv; -} e; - -/* - * flags: - * -e: quit on error - * -k: look for name=value everywhere on command line - * -n: no execution - * -t: exit after reading and executing one command - * -v: echo as read - * -x: trace - * -u: unset variables net diagnostic - */ -static char *flag; - -static char *null; /* null value for variable */ -static int intr; /* interrupt pending */ - -static char *trap[_NSIG+1]; -static char ourtrap[_NSIG+1]; -static int trapset; /* trap pending */ - -static int heedint; /* heed interrupt signals */ - -static int yynerrs; /* yacc */ - -static char line[LINELIM]; -static char *elinep; - -/* - * other functions - */ -static int (*inbuilt(char *s ))(void); - -static char *rexecve (char *c , char **v, char **envp ); -static char *space (int n ); -static char *strsave (char *s, int a ); -static char *evalstr (char *cp, int f ); -static char *putn (int n ); -static char *itoa (unsigned u, int n ); -static char *unquote (char *as ); -static struct var *lookup (char *n ); -static int rlookup (char *n ); -static struct wdblock *glob (char *cp, struct wdblock *wb ); -static int my_getc( int ec); -static int subgetc (int ec, int quoted ); -static char **makenv (void); -static char **eval (char **ap, int f ); -static int setstatus (int s ); -static int waitfor (int lastpid, int canintr ); - -static void onintr (int s ); /* SIGINT handler */ - -static int newenv (int f ); -static void quitenv (void); -static void err (char *s ); -static int anys (char *s1, char *s2 ); -static int any (int c, char *s ); -static void next (int f ); -static void setdash (void); -static void onecommand (void); -static void runtrap (int i ); -static int gmatch (char *s, char *p ); - -/* - * error handling - */ -static void leave (void); /* abort shell (or fail in subshell) */ -static void fail (void); /* fail but return to process next command */ -static void warn (char *s ); -static void sig (int i ); /* default signal handler */ - - - -/* -------- area stuff -------- */ - -#define REGSIZE sizeof(struct region) -#define GROWBY 256 -//#define SHRINKBY 64 -#undef SHRINKBY -#define FREE 32767 -#define BUSY 0 -#define ALIGN (sizeof(int)-1) - - -struct region { - struct region *next; - int area; -}; - - - -/* -------- grammar stuff -------- */ -typedef union { - char *cp; - char **wp; - int i; - struct op *o; -} YYSTYPE; -#define WORD 256 -#define LOGAND 257 -#define LOGOR 258 -#define BREAK 259 -#define IF 260 -#define THEN 261 -#define ELSE 262 -#define ELIF 263 -#define FI 264 -#define CASE 265 -#define ESAC 266 -#define FOR 267 -#define WHILE 268 -#define UNTIL 269 -#define DO 270 -#define DONE 271 -#define IN 272 -#define YYERRCODE 300 - -/* flags to yylex */ -#define CONTIN 01 /* skip new lines to complete command */ - -#define SYNTAXERR zzerr() -static struct op *pipeline(int cf ); -static struct op *andor(void); -static struct op *c_list(void); -static int synio(int cf ); -static void musthave (int c, int cf ); -static struct op *simple(void); -static struct op *nested(int type, int mark ); -static struct op *command(int cf ); -static struct op *dogroup(int onlydone ); -static struct op *thenpart(void); -static struct op *elsepart(void); -static struct op *caselist(void); -static struct op *casepart(void); -static char **pattern(void); -static char **wordlist(void); -static struct op *list(struct op *t1, struct op *t2 ); -static struct op *block(int type, struct op *t1, struct op *t2, char **wp ); -static struct op *newtp(void); -static struct op *namelist(struct op *t ); -static char **copyw(void); -static void word(char *cp ); -static struct ioword **copyio(void); -static struct ioword *io (int u, int f, char *cp ); -static void zzerr(void); -static void yyerror(char *s ); -static int yylex(int cf ); -static int collect(int c, int c1 ); -static int dual(int c ); -static void diag(int ec ); -static char *tree(unsigned size ); - -/* -------- var.h -------- */ - -struct var { - char *value; - char *name; - struct var *next; - char status; -}; -#define COPYV 1 /* flag to setval, suggesting copy */ -#define RONLY 01 /* variable is read-only */ -#define EXPORT 02 /* variable is to be exported */ -#define GETCELL 04 /* name & value space was got with getcell */ - -static struct var *vlist; /* dictionary */ - -static struct var *homedir; /* home directory */ -static struct var *prompt; /* main prompt */ -static struct var *cprompt; /* continuation prompt */ -static struct var *path; /* search path for commands */ -static struct var *shell; /* shell to interpret command files */ -static struct var *ifs; /* field separators */ - -static int yyparse (void); -static struct var *lookup (char *n ); -static void setval (struct var *vp, char *val ); -static void nameval (struct var *vp, char *val, char *name ); -static void export (struct var *vp ); -static void ronly (struct var *vp ); -static int isassign (char *s ); -static int checkname (char *cp ); -static int assign (char *s, int cf ); -static void putvlist (int f, int out ); -static int eqname (char *n1, char *n2 ); - -static int execute (struct op *t, int *pin, int *pout, int act ); - -/* -------- io.h -------- */ -/* io buffer */ -struct iobuf { - unsigned id; /* buffer id */ - char buf[512]; /* buffer */ - char *bufp; /* pointer into buffer */ - char *ebufp; /* pointer to end of buffer */ -}; - -/* possible arguments to an IO function */ -struct ioarg { - char *aword; - char **awordlist; - int afile; /* file descriptor */ - unsigned afid; /* buffer id */ - long afpos; /* file position */ - struct iobuf *afbuf; /* buffer for this file */ -}; -//static struct ioarg ioargstack[NPUSH]; -#define AFID_NOBUF (~0) -#define AFID_ID 0 - -/* an input generator's state */ -struct io { - int (*iofn)(); - struct ioarg *argp; - int peekc; - char prev; /* previous character read by readc() */ - char nlcount; /* for `'s */ - char xchar; /* for `'s */ - char task; /* reason for pushed IO */ -}; -//static struct io iostack[NPUSH]; -#define XOTHER 0 /* none of the below */ -#define XDOLL 1 /* expanding ${} */ -#define XGRAVE 2 /* expanding `'s */ -#define XIO 3 /* file IO */ - -/* in substitution */ -#define INSUB() (e.iop->task == XGRAVE || e.iop->task == XDOLL) - -/* - * input generators for IO structure - */ -static int nlchar (struct ioarg *ap ); -static int strchar (struct ioarg *ap ); -static int qstrchar (struct ioarg *ap ); -static int filechar (struct ioarg *ap ); -static int herechar (struct ioarg *ap ); -static int linechar (struct ioarg *ap ); -static int gravechar (struct ioarg *ap, struct io *iop ); -static int qgravechar (struct ioarg *ap, struct io *iop ); -static int dolchar (struct ioarg *ap ); -static int wdchar (struct ioarg *ap ); -static void scraphere (void); -static void freehere (int area ); -static void gethere (void); -static void markhere (char *s, struct ioword *iop ); -static int herein (char *hname, int xdoll ); -static int run (struct ioarg *argp, int (*f)()); - -/* - * IO functions - */ -static int eofc (void); -static int readc (void); -static void unget (int c ); -static void ioecho (int c ); -static void prs (char *s ); -static void prn (unsigned u ); -static void closef (int i ); -static void closeall (void); - -/* - * IO control - */ -static void pushio (struct ioarg *argp, int (*fn)()); -static int remap (int fd ); -static int openpipe (int *pv ); -static void closepipe (int *pv ); -static struct io *setbase (struct io *ip ); - -static struct ioarg temparg; /* temporary for PUSHIO */ -#define PUSHIO(what,arg,gen) ((temparg.what = (arg)),pushio(&temparg,(gen))) -#define RUN(what,arg,gen) ((temparg.what = (arg)), run(&temparg,(gen))) - -/* -------- word.h -------- */ - -#define NSTART 16 /* default number of words to allow for initially */ - -struct wdblock { - short w_bsize; - short w_nword; - /* bounds are arbitrary */ - char *w_words[1]; -}; - -static struct wdblock *addword (char *wd, struct wdblock *wb ); -static struct wdblock *newword (int nw ); -static char **getwords (struct wdblock *wb ); - -/* -------- area.h -------- */ - -/* - * storage allocation - */ -static char *getcell (unsigned nbytes ); -static void garbage (void); -static void setarea (char *cp, int a ); -static int getarea (char *cp ); -static void freearea (int a ); -static void freecell (char *cp ); -static int areanum; /* current allocation area */ - -#define NEW(type) (type *)getcell(sizeof(type)) -#define DELETE(obj) freecell((char *)obj) - - -/* -------- misc stuff -------- */ - -static int forkexec (struct op *t, int *pin, int *pout, int act, char **wp, int *pforked ); -static int iosetup (struct ioword *iop, int pipein, int pipeout ); -static void echo(char **wp ); -static struct op **find1case (struct op *t, char *w ); -static struct op *findcase (struct op *t, char *w ); -static void brkset(struct brkcon *bc ); -static int dolabel(void); -static int dohelp(void); -static int dochdir(struct op *t ); -static int doshift(struct op *t ); -static int dologin(struct op *t ); -static int doumask(struct op *t ); -static int doexec(struct op *t ); -static int dodot(struct op *t ); -static int dowait(struct op *t ); -static int doread(struct op *t ); -static int doeval(struct op *t ); -static int dotrap(struct op *t ); -static int getsig(char *s ); -static void setsig (int n, void (*f)()); -static int getn(char *as ); -static int dobreak(struct op *t ); -static int docontinue(struct op *t ); -static int brkcontin (char *cp, int val ); -static int doexit(struct op *t ); -static int doexport(struct op *t ); -static int doreadonly(struct op *t ); -static void rdexp (char **wp, void (*f)(), int key); -static void badid(char *s ); -static int doset(struct op *t ); -static void varput (char *s, int out ); -static int dotimes(void); -static int expand (char *cp, struct wdblock **wbp, int f ); -static char *blank(int f ); -static int dollar(int quoted ); -static int grave(int quoted ); -static void globname (char *we, char *pp ); -static char *generate (char *start1, char *end1, char *middle, char *end ); -static int anyspcl(struct wdblock *wb ); -static int xstrcmp (char *p1, char *p2 ); -static void glob0 (char *a0, unsigned int a1, int a2, int (*a3)(char *, char *)); -static void glob1 (char *base, char *lim ); -static void glob2 (char *i, char *j ); -static void glob3 (char *i, char *j, char *k ); -static void readhere (char **name, char *s, int ec ); -static void pushio(struct ioarg *argp, int (*fn)()); -static int xxchar(struct ioarg *ap ); - -struct here { - char *h_tag; - int h_dosub; - struct ioword *h_iop; - struct here *h_next; -}; - -static char *signame[] = { - "Signal 0", - "Hangup", - (char *)NULL, /* interrupt */ - "Quit", - "Illegal instruction", - "Trace/BPT trap", - "Abort", - "Bus error", - "Floating Point Exception", - "Killed", - "SIGUSR1", - "SIGSEGV", - "SIGUSR2", - (char *)NULL, /* broken pipe */ - "Alarm clock", - "Terminated", -}; -#define NSIGNAL (sizeof(signame)/sizeof(signame[0])) - -struct res { - char *r_name; - int r_val; -}; -static struct res restab[] = { - {"for", FOR}, - {"case", CASE}, - {"esac", ESAC}, - {"while", WHILE}, - {"do", DO}, - {"done", DONE}, - {"if", IF}, - {"in", IN}, - {"then", THEN}, - {"else", ELSE}, - {"elif", ELIF}, - {"until", UNTIL}, - {"fi", FI}, - - {";;", BREAK}, - {"||", LOGOR}, - {"&&", LOGAND}, - {"{", '{'}, - {"}", '}'}, - {0, 0}, -}; - - -struct builtincmd { - const char *name; - int (*builtinfunc)(); -}; -static const struct builtincmd builtincmds[] = { - {".", dodot}, - {":", dolabel}, - {"break", dobreak}, - {"cd", dochdir}, - {"continue",docontinue}, - {"eval", doeval}, - {"exec", doexec}, - {"exit", doexit}, - {"export", doexport}, - {"help", dohelp}, - {"login", dologin}, - {"newgrp", dologin}, - {"read", doread}, - {"readonly",doreadonly}, - {"set", doset}, - {"shift", doshift}, - {"times", dotimes}, - {"trap", dotrap}, - {"umask", doumask}, - {"wait", dowait}, - {0,0} -}; - -/* Globals */ -extern char **environ; /* environment pointer */ -static char **dolv; -static int dolc; -static int exstat; -static char gflg; -static int interactive; /* Is this an interactive shell */ -static int execflg; -static int multiline; /* \n changed to ; */ -static struct op *outtree; /* result from parser */ -static xint *failpt; -static xint *errpt; -static struct brkcon *brklist; -static int isbreak; -static struct wdblock *wdlist; -static struct wdblock *iolist; -static char *trap[_NSIG+1]; -static char ourtrap[_NSIG+1]; -static int trapset; /* trap pending */ -static int yynerrs; /* yacc */ -static char line[LINELIM]; -static struct var *vlist; /* dictionary */ -static struct var *homedir; /* home directory */ -static struct var *prompt; /* main prompt */ -static struct var *cprompt; /* continuation prompt */ -static struct var *path; /* search path for commands */ -static struct var *shell; /* shell to interpret command files */ -static struct var *ifs; /* field separators */ -static struct ioarg ioargstack[NPUSH]; -static struct io iostack[NPUSH]; -static int areanum; /* current allocation area */ -static int intr; -static int inparse; -static char flags['z'-'a'+1]; -static char *flag = flags-'a'; -static char *elinep = line+sizeof(line)-5; -static char *null = ""; -static int heedint =1; -static struct env e ={line, iostack, iostack-1, (xint *)NULL, FDBASE, (struct env *)NULL}; -static void (*qflag)(int) = SIG_IGN; -static char shellname[] = "/bin/sh"; -static char search[] = ":/bin:/usr/bin"; -static int startl; -static int peeksym; -static int nlseen; -static int iounit = IODEFAULT; -static YYSTYPE yylval; -static struct iobuf sharedbuf = {AFID_NOBUF}; -static struct iobuf mainbuf = {AFID_NOBUF}; -static unsigned bufid = AFID_ID; /* buffer id counter */ -static struct ioarg temparg = {0, 0, 0, AFID_NOBUF, 0}; -static struct here *inhere; /* list of hear docs while parsing */ -static struct here *acthere; /* list of active here documents */ -static struct region *areabot; /* bottom of area */ -static struct region *areatop; /* top of area */ -static struct region *areanxt; /* starting point of scan */ -static void * brktop; -static void * brkaddr; - - -#ifdef BB_FEATURE_COMMAND_EDITING -static char * current_prompt; -#endif - - -/* -------- sh.c -------- */ -/* - * shell - */ - - -extern int msh_main(int argc, char **argv) -{ - register int f; - register char *s; - int cflag; - char *name, **ap; - int (*iof)(); - - initarea(); - if ((ap = environ) != NULL) { - while (*ap) - assign(*ap++, !COPYV); - for (ap = environ; *ap;) - export(lookup(*ap++)); - } - closeall(); - areanum = 1; - - shell = lookup("SHELL"); - if (shell->value == null) - setval(shell, shellname); - export(shell); - - homedir = lookup("HOME"); - if (homedir->value == null) - setval(homedir, "/"); - export(homedir); - - setval(lookup("$"), itoa(getpid(), 5)); - - path = lookup("PATH"); - if (path->value == null) - setval(path, search); - export(path); - - ifs = lookup("IFS"); - if (ifs->value == null) - setval(ifs, " \t\n"); - - prompt = lookup("PS1"); -#ifdef BB_FEATURE_SH_FANCY_PROMPT - if (prompt->value == null) -#endif - setval(prompt, "$ "); - if (geteuid() == 0) { - setval(prompt, "# "); - prompt->status &= ~EXPORT; - } - cprompt = lookup("PS2"); -#ifdef BB_FEATURE_SH_FANCY_PROMPT - if (cprompt->value == null) -#endif - setval(cprompt, "> "); - - iof = filechar; - cflag = 0; - name = *argv++; - if (--argc >= 1) { - if(argv[0][0] == '-' && argv[0][1] != '\0') { - for (s = argv[0]+1; *s; s++) - switch (*s) { - case 'c': - prompt->status &= ~EXPORT; - cprompt->status &= ~EXPORT; - setval(prompt, ""); - setval(cprompt, ""); - cflag = 1; - if (--argc > 0) - PUSHIO(aword, *++argv, iof = nlchar); - break; - - case 'q': - qflag = SIG_DFL; - break; - - case 's': - /* standard input */ - break; - - case 't': - prompt->status &= ~EXPORT; - setval(prompt, ""); - iof = linechar; - break; - - case 'i': - interactive++; - default: - if (*s>='a' && *s<='z') - flag[(int)*s]++; - } - } else { - argv--; - argc++; - } - if (iof == filechar && --argc > 0) { - setval(prompt, ""); - setval(cprompt, ""); - prompt->status &= ~EXPORT; - cprompt->status &= ~EXPORT; - if (newfile(name = *++argv)) - exit(1); - } - } - setdash(); - if (e.iop < iostack) { - PUSHIO(afile, 0, iof); - if (isatty(0) && isatty(1) && !cflag) { - interactive++; -#ifndef BB_FEATURE_SH_EXTRA_QUIET - printf( "\n\n" BB_BANNER " Built-in shell (msh)\n"); - printf( "Enter 'help' for a list of built-in commands.\n\n"); -#endif - } - } - signal(SIGQUIT, qflag); - if (name && name[0] == '-') { - interactive++; - if ((f = open(".profile", 0)) >= 0) - next(remap(f)); - if ((f = open("/etc/profile", 0)) >= 0) - next(remap(f)); - } - if (interactive) - signal(SIGTERM, sig); - if (signal(SIGINT, SIG_IGN) != SIG_IGN) - signal(SIGINT, onintr); - dolv = argv; - dolc = argc; - dolv[0] = name; - if (dolc > 1) { - for (ap = ++argv; --argc > 0;) { - if (assign(*ap = *argv++, !COPYV)) { - dolc--; /* keyword */ - } else { - ap++; - } - } - } - setval(lookup("#"), putn((--dolc < 0) ? (dolc = 0) : dolc)); - - for (;;) { - if (interactive && e.iop <= iostack) { -#ifdef BB_FEATURE_COMMAND_EDITING - current_prompt=prompt->value; -#else - prs(prompt->value); -#endif - } - onecommand(); - } -} - -static void -setdash() -{ - register char *cp; - register int c; - char m['z'-'a'+1]; - - cp = m; - for (c='a'; c<='z'; c++) - if (flag[c]) - *cp++ = c; - *cp = 0; - setval(lookup("-"), m); -} - -static int -newfile(s) -register char *s; -{ - register int f; - - if (strcmp(s, "-") != 0) { - f = open(s, 0); - if (f < 0) { - prs(s); - err(": cannot open"); - return(1); - } - } else - f = 0; - next(remap(f)); - return(0); -} - -static void -onecommand() -{ - register int i; - jmp_buf m1; - - while (e.oenv) - quitenv(); - areanum = 1; - freehere(areanum); - freearea(areanum); - garbage(); - wdlist = 0; - iolist = 0; - e.errpt = 0; - e.linep = line; - yynerrs = 0; - multiline = 0; - inparse = 1; - intr = 0; - execflg = 0; - setjmp(failpt = m1); /* Bruce Evans' fix */ - if (setjmp(failpt = m1) || yyparse() || intr) { - while (e.oenv) - quitenv(); - scraphere(); - if (!interactive && intr) - leave(); - inparse = 0; - intr = 0; - return; - } - inparse = 0; - brklist = 0; - intr = 0; - execflg = 0; - if (!flag['n']) - execute(outtree, NOPIPE, NOPIPE, 0); - if (!interactive && intr) { - execflg = 0; - leave(); - } - if ((i = trapset) != 0) { - trapset = 0; - runtrap(i); - } -} - -static void -fail() -{ - longjmp(failpt, 1); - /* NOTREACHED */ -} - -static void -leave() -{ - if (execflg) - fail(); - scraphere(); - freehere(1); - runtrap(0); - exit(exstat); - /* NOTREACHED */ -} - -static void -warn(s) -register char *s; -{ - if(*s) { - prs(s); - exstat = -1; - } - prs("\n"); - if (flag['e']) - leave(); -} - -static void -err(s) -char *s; -{ - warn(s); - if (flag['n']) - return; - if (!interactive) - leave(); - if (e.errpt) - longjmp(e.errpt, 1); - closeall(); - e.iop = e.iobase = iostack; -} - -static int -newenv(f) -int f; -{ - register struct env *ep; - - if (f) { - quitenv(); - return(1); - } - ep = (struct env *) space(sizeof(*ep)); - if (ep == NULL) { - while (e.oenv) - quitenv(); - fail(); - } - *ep = e; - e.oenv = ep; - e.errpt = errpt; - return(0); -} - -static void -quitenv() -{ - register struct env *ep; - register int fd; - - if ((ep = e.oenv) != NULL) { - fd = e.iofd; - e = *ep; - /* should close `'d files */ - DELETE(ep); - while (--fd >= e.iofd) - close(fd); - } -} - -/* - * Is any character from s1 in s2? - */ -static int -anys(s1, s2) -register char *s1, *s2; -{ - while (*s1) - if (any(*s1++, s2)) - return(1); - return(0); -} - -/* - * Is character c in s? - */ -static int -any(c, s) -register int c; -register char *s; -{ - while (*s) - if (*s++ == c) - return(1); - return(0); -} - -static char * -putn(n) -register int n; -{ - return(itoa(n, -1)); -} - -static char * -itoa(u, n) -register unsigned u; -int n; -{ - register char *cp; - static char s[20]; - int m; - - m = 0; - if (n < 0 && (int) u < 0) { - m++; - u = -u; - } - cp = s+sizeof(s); - *--cp = 0; - do { - *--cp = u%10 + '0'; - u /= 10; - } while (--n > 0 || u); - if (m) - *--cp = '-'; - return(cp); -} - -static void -next(f) -int f; -{ - PUSHIO(afile, f, filechar); -} - -static void -onintr(s) -int s; /* ANSI C requires a parameter */ -{ - signal(SIGINT, onintr); - intr = 1; - if (interactive) { - if (inparse) { - prs("\n"); - fail(); - } - } - else if (heedint) { - execflg = 0; - leave(); - } -} - -static char * -space(n) -int n; -{ - register char *cp; - - if ((cp = getcell(n)) == 0) - err("out of string space"); - return(cp); -} - -static char * -strsave(s, a) -register char *s; -int a; -{ - register char *cp, *xp; - - if ((cp = space(strlen(s)+1)) != NULL) { - setarea((char *)cp, a); - for (xp = cp; (*xp++ = *s++) != '\0';) - ; - return(cp); - } - return(""); -} - -/* - * trap handling - */ -static void -sig(i) -register int i; -{ - trapset = i; - signal(i, sig); -} - -static void runtrap(i) -int i; -{ - char *trapstr; - - if ((trapstr = trap[i]) == NULL) - return; - if (i == 0) - trap[i] = 0; - RUN(aword, trapstr, nlchar); -} - -/* -------- var.c -------- */ - -/* - * Find the given name in the dictionary - * and return its value. If the name was - * not previously there, enter it now and - * return a null value. - */ -static struct var * -lookup(n) -register char *n; -{ - register struct var *vp; - register char *cp; - register int c; - static struct var dummy; - - if (isdigit(*n)) { - dummy.name = n; - for (c = 0; isdigit(*n) && c < 1000; n++) - c = c*10 + *n-'0'; - dummy.status = RONLY; - dummy.value = c <= dolc? dolv[c]: null; - return(&dummy); - } - for (vp = vlist; vp; vp = vp->next) - if (eqname(vp->name, n)) - return(vp); - cp = findeq(n); - vp = (struct var *)space(sizeof(*vp)); - if (vp == 0 || (vp->name = space((int)(cp-n)+2)) == 0) { - dummy.name = dummy.value = ""; - return(&dummy); - } - for (cp = vp->name; (*cp = *n++) && *cp != '='; cp++) - ; - if (*cp == 0) - *cp = '='; - *++cp = 0; - setarea((char *)vp, 0); - setarea((char *)vp->name, 0); - vp->value = null; - vp->next = vlist; - vp->status = GETCELL; - vlist = vp; - return(vp); -} - -/* - * give variable at `vp' the value `val'. - */ -static void -setval(vp, val) -struct var *vp; -char *val; -{ - nameval(vp, val, (char *)NULL); -} - -/* - * if name is not NULL, it must be - * a prefix of the space `val', - * and end with `='. - * this is all so that exporting - * values is reasonably painless. - */ -static void -nameval(vp, val, name) -register struct var *vp; -char *val, *name; -{ - register char *cp, *xp; - char *nv; - int fl; - - if (vp->status & RONLY) { - for (xp = vp->name; *xp && *xp != '=';) - putc(*xp++, stderr); - err(" is read-only"); - return; - } - fl = 0; - if (name == NULL) { - xp = space(strlen(vp->name)+strlen(val)+2); - if (xp == 0) - return; - /* make string: name=value */ - setarea((char *)xp, 0); - name = xp; - for (cp = vp->name; (*xp = *cp++) && *xp!='='; xp++) - ; - if (*xp++ == 0) - xp[-1] = '='; - nv = xp; - for (cp = val; (*xp++ = *cp++) != '\0';) - ; - val = nv; - fl = GETCELL; - } - if (vp->status & GETCELL) - freecell(vp->name); /* form new string `name=value' */ - vp->name = name; - vp->value = val; - vp->status |= fl; -} - -static void -export(vp) -struct var *vp; -{ - vp->status |= EXPORT; -} - -static void -ronly(vp) -struct var *vp; -{ - if (isalpha(vp->name[0]) || vp->name[0] == '_') /* not an internal symbol */ - vp->status |= RONLY; -} - -static int -isassign(s) -register char *s; -{ - if (!isalpha((int)*s) && *s != '_') - return(0); - for (; *s != '='; s++) - if (*s == 0 || (!isalnum(*s) && *s != '_')) - return(0); - return(1); -} - -static int -assign(s, cf) -register char *s; -int cf; -{ - register char *cp; - struct var *vp; - - if (!isalpha(*s) && *s != '_') - return(0); - for (cp = s; *cp != '='; cp++) - if (*cp == 0 || (!isalnum(*cp) && *cp != '_')) - return(0); - vp = lookup(s); - nameval(vp, ++cp, cf == COPYV? (char *)NULL: s); - if (cf != COPYV) - vp->status &= ~GETCELL; - return(1); -} - -static int -checkname(cp) -register char *cp; -{ - if (!isalpha(*cp++) && *(cp-1) != '_') - return(0); - while (*cp) - if (!isalnum(*cp++) && *(cp-1) != '_') - return(0); - return(1); -} - -static void -putvlist(f, out) -register int f, out; -{ - register struct var *vp; - - for (vp = vlist; vp; vp = vp->next) - if (vp->status & f && (isalpha(*vp->name) || *vp->name == '_')) { - if (vp->status & EXPORT) - write(out, "export ", 7); - if (vp->status & RONLY) - write(out, "readonly ", 9); - write(out, vp->name, (int)(findeq(vp->name) - vp->name)); - write(out, "\n", 1); - } -} - -static int -eqname(n1, n2) -register char *n1, *n2; -{ - for (; *n1 != '=' && *n1 != 0; n1++) - if (*n2++ != *n1) - return(0); - return(*n2 == 0 || *n2 == '='); -} - -static char * -findeq(cp) -register char *cp; -{ - while (*cp != '\0' && *cp != '=') - cp++; - return(cp); -} - -/* -------- gmatch.c -------- */ -/* - * int gmatch(string, pattern) - * char *string, *pattern; - * - * Match a pattern as in sh(1). - */ - -#define CMASK 0377 -#define QUOTE 0200 -#define QMASK (CMASK&~QUOTE) -#define NOT '!' /* might use ^ */ - -static int -gmatch(s, p) -register char *s, *p; -{ - register int sc, pc; - - if (s == NULL || p == NULL) - return(0); - while ((pc = *p++ & CMASK) != '\0') { - sc = *s++ & QMASK; - switch (pc) { - case '[': - if ((p = cclass(p, sc)) == NULL) - return(0); - break; - - case '?': - if (sc == 0) - return(0); - break; - - case '*': - s--; - do { - if (*p == '\0' || gmatch(s, p)) - return(1); - } while (*s++ != '\0'); - return(0); - - default: - if (sc != (pc&~QUOTE)) - return(0); - } - } - return(*s == 0); -} - -static char * -cclass(p, sub) -register char *p; -register int sub; -{ - register int c, d, not, found; - - if ((not = *p == NOT) != 0) - p++; - found = not; - do { - if (*p == '\0') - return((char *)NULL); - c = *p & CMASK; - if (p[1] == '-' && p[2] != ']') { - d = p[2] & CMASK; - p++; - } else - d = c; - if (c == sub || (c <= sub && sub <= d)) - found = !not; - } while (*++p != ']'); - return(found? p+1: (char *)NULL); -} - - -/* -------- area.c -------- */ - -/* - * All memory between (char *)areabot and (char *)(areatop+1) is - * exclusively administered by the area management routines. - * It is assumed that sbrk() and brk() manipulate the high end. - */ - -#define sbrk(X) ({ void * __q = (void *)-1; if (brkaddr + (int)(X) < brktop) { __q = brkaddr; brkaddr+=(int)(X); } __q;}) - -static void -initarea() -{ - brkaddr = malloc(65000); - brktop = brkaddr + 65000; - - while ((int)sbrk(0) & ALIGN) - sbrk(1); - areabot = (struct region *)sbrk(REGSIZE); - - areabot->next = areabot; - areabot->area = BUSY; - areatop = areabot; - areanxt = areabot; -} - -char * -getcell(nbytes) -unsigned nbytes; -{ - register int nregio; - register struct region *p, *q; - register int i; - - if (nbytes == 0) { - puts("getcell(0)"); - abort(); - } /* silly and defeats the algorithm */ - /* - * round upwards and add administration area - */ - nregio = (nbytes+(REGSIZE-1))/REGSIZE + 1; - for (p = areanxt;;) { - if (p->area > areanum) { - /* - * merge free cells - */ - while ((q = p->next)->area > areanum && q != areanxt) - p->next = q->next; - /* - * exit loop if cell big enough - */ - if (q >= p + nregio) - goto found; - } - p = p->next; - if (p == areanxt) - break; - } - i = nregio >= GROWBY ? nregio : GROWBY; - p = (struct region *)sbrk(i * REGSIZE); - if (p == (struct region *)-1) - return((char *)NULL); - p--; - if (p != areatop) { - puts("not contig"); - abort(); /* allocated areas are contiguous */ - } - q = p + i; - p->next = q; - p->area = FREE; - q->next = areabot; - q->area = BUSY; - areatop = q; -found: - /* - * we found a FREE area big enough, pointed to by 'p', and up to 'q' - */ - areanxt = p + nregio; - if (areanxt < q) { - /* - * split into requested area and rest - */ - if (areanxt+1 > q) { - puts("OOM"); - abort(); /* insufficient space left for admin */ - } - areanxt->next = q; - areanxt->area = FREE; - p->next = areanxt; - } - p->area = areanum; - return((char *)(p+1)); -} - -static void -freecell(cp) -char *cp; -{ - register struct region *p; - - if ((p = (struct region *)cp) != NULL) { - p--; - if (p < areanxt) - areanxt = p; - p->area = FREE; - } -} - -static void -freearea(a) -register int a; -{ - register struct region *p, *top; - - top = areatop; - for (p = areabot; p != top; p = p->next) - if (p->area >= a) - p->area = FREE; -} - -static void -setarea(cp,a) -char *cp; -int a; -{ - register struct region *p; - - if ((p = (struct region *)cp) != NULL) - (p-1)->area = a; -} - -int -getarea(cp) -char *cp; -{ - return ((struct region*)cp-1)->area; -} - -static void -garbage() -{ - register struct region *p, *q, *top; - - top = areatop; - for (p = areabot; p != top; p = p->next) { - if (p->area > areanum) { - while ((q = p->next)->area > areanum) - p->next = q->next; - areanxt = p; - } - } -#ifdef SHRINKBY - if (areatop >= q + SHRINKBY && q->area > areanum) { - brk((char *)(q+1)); - q->next = areabot; - q->area = BUSY; - areatop = q; - } -#endif -} - -/* -------- csyn.c -------- */ -/* - * shell: syntax (C version) - */ - - -int -yyparse() -{ - startl = 1; - peeksym = 0; - yynerrs = 0; - outtree = c_list(); - musthave('\n', 0); - return(yynerrs!=0); -} - -static struct op * -pipeline(cf) -int cf; -{ - register struct op *t, *p; - register int c; - - t = command(cf); - if (t != NULL) { - while ((c = yylex(0)) == '|') { - if ((p = command(CONTIN)) == NULL) - SYNTAXERR; - if (t->type != TPAREN && t->type != TCOM) { - /* shell statement */ - t = block(TPAREN, t, NOBLOCK, NOWORDS); - } - t = block(TPIPE, t, p, NOWORDS); - } - peeksym = c; - } - return(t); -} - -static struct op * -andor() -{ - register struct op *t, *p; - register int c; - - t = pipeline(0); - if (t != NULL) { - while ((c = yylex(0)) == LOGAND || c == LOGOR) { - if ((p = pipeline(CONTIN)) == NULL) - SYNTAXERR; - t = block(c == LOGAND? TAND: TOR, t, p, NOWORDS); - } - peeksym = c; - } - return(t); -} - -static struct op * -c_list() -{ - register struct op *t, *p; - register int c; - - t = andor(); - if (t != NULL) { - if((peeksym = yylex(0)) == '&') - t = block(TASYNC, t, NOBLOCK, NOWORDS); - while ((c = yylex(0)) == ';' || c == '&' || (multiline && c == '\n')) { - if ((p = andor()) == NULL) - return(t); - if((peeksym = yylex(0)) == '&') - p = block(TASYNC, p, NOBLOCK, NOWORDS); - t = list(t, p); - } - peeksym = c; - } - return(t); -} - - -static int -synio(cf) -int cf; -{ - register struct ioword *iop; - register int i; - register int c; - - if ((c = yylex(cf)) != '<' && c != '>') { - peeksym = c; - return(0); - } - i = yylval.i; - musthave(WORD, 0); - iop = io(iounit, i, yylval.cp); - iounit = IODEFAULT; - if (i & IOHERE) - markhere(yylval.cp, iop); - return(1); -} - -static void -musthave(c, cf) -int c, cf; -{ - if ((peeksym = yylex(cf)) != c) - SYNTAXERR; - peeksym = 0; -} - -static struct op * -simple() -{ - register struct op *t; - - t = NULL; - for (;;) { - switch (peeksym = yylex(0)) { - case '<': - case '>': - (void) synio(0); - break; - - case WORD: - if (t == NULL) { - t = newtp(); - t->type = TCOM; - } - peeksym = 0; - word(yylval.cp); - break; - - default: - return(t); - } - } -} - -static struct op * -nested(type, mark) -int type, mark; -{ - register struct op *t; - - multiline++; - t = c_list(); - musthave(mark, 0); - multiline--; - return(block(type, t, NOBLOCK, NOWORDS)); -} - -static struct op * -command(cf) -int cf; -{ - register struct op *t; - struct wdblock *iosave; - register int c; - - iosave = iolist; - iolist = NULL; - if (multiline) - cf |= CONTIN; - while (synio(cf)) - cf = 0; - switch (c = yylex(cf)) { - default: - peeksym = c; - if ((t = simple()) == NULL) { - if (iolist == NULL) - return((struct op *)NULL); - t = newtp(); - t->type = TCOM; - } - break; - - case '(': - t = nested(TPAREN, ')'); - break; - - case '{': - t = nested(TBRACE, '}'); - break; - - case FOR: - t = newtp(); - t->type = TFOR; - musthave(WORD, 0); - startl = 1; - t->str = yylval.cp; - multiline++; - t->words = wordlist(); - if ((c = yylex(0)) != '\n' && c != ';') - peeksym = c; - t->left = dogroup(0); - multiline--; - break; - - case WHILE: - case UNTIL: - multiline++; - t = newtp(); - t->type = c == WHILE? TWHILE: TUNTIL; - t->left = c_list(); - t->right = dogroup(1); - t->words = NULL; - multiline--; - break; - - case CASE: - t = newtp(); - t->type = TCASE; - musthave(WORD, 0); - t->str = yylval.cp; - startl++; - multiline++; - musthave(IN, CONTIN); - startl++; - t->left = caselist(); - musthave(ESAC, 0); - multiline--; - break; - - case IF: - multiline++; - t = newtp(); - t->type = TIF; - t->left = c_list(); - t->right = thenpart(); - musthave(FI, 0); - multiline--; - break; - } - while (synio(0)) - ; - t = namelist(t); - iolist = iosave; - return(t); -} - -static struct op * -dogroup(onlydone) -int onlydone; -{ - register int c; - register struct op *mylist; - - c = yylex(CONTIN); - if (c == DONE && onlydone) - return((struct op *)NULL); - if (c != DO) - SYNTAXERR; - mylist = c_list(); - musthave(DONE, 0); - return(mylist); -} - -static struct op * -thenpart() -{ - register int c; - register struct op *t; - - if ((c = yylex(0)) != THEN) { - peeksym = c; - return((struct op *)NULL); - } - t = newtp(); - t->type = 0; - t->left = c_list(); - if (t->left == NULL) - SYNTAXERR; - t->right = elsepart(); - return(t); -} - -static struct op * -elsepart() -{ - register int c; - register struct op *t; - - switch (c = yylex(0)) { - case ELSE: - if ((t = c_list()) == NULL) - SYNTAXERR; - return(t); - - case ELIF: - t = newtp(); - t->type = TELIF; - t->left = c_list(); - t->right = thenpart(); - return(t); - - default: - peeksym = c; - return((struct op *)NULL); - } -} - -static struct op * -caselist() -{ - register struct op *t; - - t = NULL; - while ((peeksym = yylex(CONTIN)) != ESAC) - t = list(t, casepart()); - return(t); -} - -static struct op * -casepart() -{ - register struct op *t; - - t = newtp(); - t->type = TPAT; - t->words = pattern(); - musthave(')', 0); - t->left = c_list(); - if ((peeksym = yylex(CONTIN)) != ESAC) - musthave(BREAK, CONTIN); - return(t); -} - -static char ** -pattern() -{ - register int c, cf; - - cf = CONTIN; - do { - musthave(WORD, cf); - word(yylval.cp); - cf = 0; - } while ((c = yylex(0)) == '|'); - peeksym = c; - word(NOWORD); - return(copyw()); -} - -static char ** -wordlist() -{ - register int c; - - if ((c = yylex(0)) != IN) { - peeksym = c; - return((char **)NULL); - } - startl = 0; - while ((c = yylex(0)) == WORD) - word(yylval.cp); - word(NOWORD); - peeksym = c; - return(copyw()); -} - -/* - * supporting functions - */ -static struct op * -list(t1, t2) -register struct op *t1, *t2; -{ - if (t1 == NULL) - return(t2); - if (t2 == NULL) - return(t1); - return(block(TLIST, t1, t2, NOWORDS)); -} - -static struct op * -block(type, t1, t2, wp) -int type; -struct op *t1, *t2; -char **wp; -{ - register struct op *t; - - t = newtp(); - t->type = type; - t->left = t1; - t->right = t2; - t->words = wp; - return(t); -} - -static int -rlookup(n) -register char *n; -{ - register struct res *rp; - - for (rp = restab; rp->r_name; rp++) - if (strcmp(rp->r_name, n) == 0) - return(rp->r_val); - return(0); -} - -static struct op * -newtp() -{ - register struct op *t; - - t = (struct op *)tree(sizeof(*t)); - t->type = 0; - t->words = NULL; - t->ioact = NULL; - t->left = NULL; - t->right = NULL; - t->str = NULL; - return(t); -} - -static struct op * -namelist(t) -register struct op *t; -{ - if (iolist) { - iolist = addword((char *)NULL, iolist); - t->ioact = copyio(); - } else - t->ioact = NULL; - if (t->type != TCOM) { - if (t->type != TPAREN && t->ioact != NULL) { - t = block(TPAREN, t, NOBLOCK, NOWORDS); - t->ioact = t->left->ioact; - t->left->ioact = NULL; - } - return(t); - } - word(NOWORD); - t->words = copyw(); - return(t); -} - -static char ** -copyw() -{ - register char **wd; - - wd = getwords(wdlist); - wdlist = 0; - return(wd); -} - -static void -word(cp) -char *cp; -{ - wdlist = addword(cp, wdlist); -} - -static struct ioword ** -copyio() -{ - register struct ioword **iop; - - iop = (struct ioword **) getwords(iolist); - iolist = 0; - return(iop); -} - -static struct ioword * -io(u, f, cp) -int u; -int f; -char *cp; -{ - register struct ioword *iop; - - iop = (struct ioword *) tree(sizeof(*iop)); - iop->io_unit = u; - iop->io_flag = f; - iop->io_name = cp; - iolist = addword((char *)iop, iolist); - return(iop); -} - -static void -zzerr() -{ - yyerror("syntax error"); -} - -static void -yyerror(s) -char *s; -{ - yynerrs++; - if (interactive && e.iop <= iostack) { - multiline = 0; - while (eofc() == 0 && yylex(0) != '\n') - ; - } - err(s); - fail(); -} - -static int -yylex(cf) -int cf; -{ - register int c, c1; - int atstart; - - if ((c = peeksym) > 0) { - peeksym = 0; - if (c == '\n') - startl = 1; - return(c); - } - nlseen = 0; - e.linep = line; - atstart = startl; - startl = 0; - yylval.i = 0; - -loop: - while ((c = my_getc(0)) == ' ' || c == '\t') - ; - switch (c) { - default: - if (any(c, "0123456789")) { - unget(c1 = my_getc(0)); - if (c1 == '<' || c1 == '>') { - iounit = c - '0'; - goto loop; - } - *e.linep++ = c; - c = c1; - } - break; - - case '#': - while ((c = my_getc(0)) != 0 && c != '\n') - ; - unget(c); - goto loop; - - case 0: - return(c); - - case '$': - *e.linep++ = c; - if ((c = my_getc(0)) == '{') { - if ((c = collect(c, '}')) != '\0') - return(c); - goto pack; - } - break; - - case '`': - case '\'': - case '"': - if ((c = collect(c, c)) != '\0') - return(c); - goto pack; - - case '|': - case '&': - case ';': - if ((c1 = dual(c)) != '\0') { - startl = 1; - return(c1); - } - startl = 1; - return(c); - case '^': - startl = 1; - return('|'); - case '>': - case '<': - diag(c); - return(c); - - case '\n': - nlseen++; - gethere(); - startl = 1; - if (multiline || cf & CONTIN) { - if (interactive && e.iop <= iostack) { -#ifdef BB_FEATURE_COMMAND_EDITING - current_prompt=cprompt->value; -#else - prs(cprompt->value); -#endif - } - if (cf & CONTIN) - goto loop; - } - return(c); - - case '(': - case ')': - startl = 1; - return(c); - } - - unget(c); - -pack: - while ((c = my_getc(0)) != 0 && !any(c, "`$ '\"\t;&<>()|^\n")) - if (e.linep >= elinep) - err("word too long"); - else - *e.linep++ = c; - unget(c); - if(any(c, "\"'`$")) - goto loop; - *e.linep++ = '\0'; - if (atstart && (c = rlookup(line))!=0) { - startl = 1; - return(c); - } - yylval.cp = strsave(line, areanum); - return(WORD); -} - -static int -collect(c, c1) -register int c, c1; -{ - char s[2]; - - *e.linep++ = c; - while ((c = my_getc(c1)) != c1) { - if (c == 0) { - unget(c); - s[0] = c1; - s[1] = 0; - prs("no closing "); yyerror(s); - return(YYERRCODE); - } - if (interactive && c == '\n' && e.iop <= iostack) { -#ifdef BB_FEATURE_COMMAND_EDITING - current_prompt=cprompt->value; -#else - prs(cprompt->value); -#endif - } - *e.linep++ = c; - } - *e.linep++ = c; - return(0); -} - -static int -dual(c) -register int c; -{ - char s[3]; - register char *cp = s; - - *cp++ = c; - *cp++ = my_getc(0); - *cp = 0; - if ((c = rlookup(s)) == 0) - unget(*--cp); - return(c); -} - -static void -diag(ec) -register int ec; -{ - register int c; - - c = my_getc(0); - if (c == '>' || c == '<') { - if (c != ec) - zzerr(); - yylval.i = ec == '>'? IOWRITE|IOCAT: IOHERE; - c = my_getc(0); - } else - yylval.i = ec == '>'? IOWRITE: IOREAD; - if (c != '&' || yylval.i == IOHERE) - unget(c); - else - yylval.i |= IODUP; -} - -static char * -tree(size) -unsigned size; -{ - register char *t; - - if ((t = getcell(size)) == NULL) { - prs("command line too complicated\n"); - fail(); - /* NOTREACHED */ - } - return(t); -} - -/* VARARGS1 */ -/* ARGSUSED */ - -/* -------- exec.c -------- */ - -/* - * execute tree - */ - - -static int -execute(t, pin, pout, act) -register struct op *t; -int *pin, *pout; -int act; -{ - register struct op *t1; - volatile int i, rv, a; - char *cp, **wp, **wp2; - struct var *vp; - struct brkcon bc; - -#if __GNUC__ - /* Avoid longjmp clobbering */ - (void) ℘ -#endif - - - if (t == NULL) - return(0); - rv = 0; - a = areanum++; - wp = (wp2 = t->words) != NULL - ? eval(wp2, t->type == TCOM ? DOALL : DOALL & ~DOKEY) - : NULL; - - switch(t->type) { - case TPAREN: - case TCOM: - { - int child; - rv = forkexec(t, pin, pout, act, wp, &child); - if (child) { - exstat = rv; - leave(); - } - } - break; - - case TPIPE: - { - int pv[2]; - if ((rv = openpipe(pv)) < 0) - break; - pv[0] = remap(pv[0]); - pv[1] = remap(pv[1]); - (void) execute(t->left, pin, pv, 0); - rv = execute(t->right, pv, pout, 0); - } - break; - - case TLIST: - (void) execute(t->left, pin, pout, 0); - rv = execute(t->right, pin, pout, 0); - break; - - case TASYNC: - { - int hinteractive = interactive; - - i = vfork(); - if (i != 0) { - interactive = hinteractive; - if (i != -1) { - setval(lookup("!"), putn(i)); - if (pin != NULL) - closepipe(pin); - if (interactive) { - prs(putn(i)); - prs("\n"); - } - } else - rv = -1; - setstatus(rv); - } else { - signal(SIGINT, SIG_IGN); - signal(SIGQUIT, SIG_IGN); - if (interactive) - signal(SIGTERM, SIG_DFL); - interactive = 0; - if (pin == NULL) { - close(0); - open("/dev/null", 0); - } - exit(execute(t->left, pin, pout, FEXEC)); - } - } - break; - - case TOR: - case TAND: - rv = execute(t->left, pin, pout, 0); - if ((t1 = t->right)!=NULL && (rv == 0) == (t->type == TAND)) - rv = execute(t1, pin, pout, 0); - break; - - case TFOR: - if (wp == NULL) { - wp = dolv+1; - if ((i = dolc) < 0) - i = 0; - } else { - i = -1; - while (*wp++ != NULL) - ; - } - vp = lookup(t->str); - while (setjmp(bc.brkpt)) - if (isbreak) - goto broken; - brkset(&bc); - for (t1 = t->left; i-- && *wp != NULL;) { - setval(vp, *wp++); - rv = execute(t1, pin, pout, 0); - } - brklist = brklist->nextlev; - break; - - case TWHILE: - case TUNTIL: - while (setjmp(bc.brkpt)) - if (isbreak) - goto broken; - brkset(&bc); - t1 = t->left; - while ((execute(t1, pin, pout, 0) == 0) == (t->type == TWHILE)) - rv = execute(t->right, pin, pout, 0); - brklist = brklist->nextlev; - break; - - case TIF: - case TELIF: - if (t->right != NULL) { - rv = !execute(t->left, pin, pout, 0) ? - execute(t->right->left, pin, pout, 0): - execute(t->right->right, pin, pout, 0); - } - break; - - case TCASE: - if ((cp = evalstr(t->str, DOSUB|DOTRIM)) == 0) - cp = ""; - if ((t1 = findcase(t->left, cp)) != NULL) - rv = execute(t1, pin, pout, 0); - break; - - case TBRACE: -/* - if (iopp = t->ioact) - while (*iopp) - if (iosetup(*iopp++, pin!=NULL, pout!=NULL)) { - rv = -1; - break; - } -*/ - if (rv >= 0 && (t1 = t->left)) - rv = execute(t1, pin, pout, 0); - break; - } - -broken: - t->words = wp2; - isbreak = 0; - freehere(areanum); - freearea(areanum); - areanum = a; - if (interactive && intr) { - closeall(); - fail(); - } - if ((i = trapset) != 0) { - trapset = 0; - runtrap(i); - } - return(rv); -} - -static int -forkexec( register struct op *t, int *pin, int *pout, int act, char **wp, int *pforked) -{ - int i, rv; - int (*shcom)() = NULL; - register int f; - char *cp = NULL; - struct ioword **iopp; - int resetsig; - char **owp; - - int *hpin = pin; - int *hpout = pout; - int hforked; - char *hwp; - int hinteractive; - int hintr; - struct brkcon * hbrklist; - int hexecflg; - -#if __GNUC__ - /* Avoid longjmp clobbering */ - (void) &pin; - (void) &pout; - (void) ℘ - (void) &shcom; - (void) &cp; - (void) &resetsig; - (void) &owp; -#endif - - owp = wp; - resetsig = 0; - *pforked = 0; - rv = -1; /* system-detected error */ - if (t->type == TCOM) { - while ((cp = *wp++) != NULL) - ; - cp = *wp; - - /* strip all initial assignments */ - /* not correct wrt PATH=yyy command etc */ - if (flag['x']) - echo (cp ? wp: owp); - if (cp == NULL && t->ioact == NULL) { - while ((cp = *owp++) != NULL && assign(cp, COPYV)) - ; - return(setstatus(0)); - } - else if (cp != NULL) - shcom = inbuilt(cp); - } - t->words = wp; - f = act; - if (shcom == NULL && (f & FEXEC) == 0) { - - hpin = pin; - hpout = pout; - hforked = *pforked; - hwp = *wp; - hinteractive = interactive; - hintr = intr; - hbrklist = brklist; - hexecflg = execflg; - - i = vfork(); - if (i != 0) { - /* who wrote this crappy non vfork safe shit? */ - pin = hpin; - pout = hpout; - *pforked = hforked; - *wp = hwp; - interactive = hinteractive; - intr = hintr; - brklist = hbrklist; - execflg = hexecflg; - - *pforked = 0; - if (i == -1) - return(rv); - if (pin != NULL) - closepipe(pin); - return(pout==NULL? setstatus(waitfor(i,0)): 0); - } - - if (interactive) { - signal(SIGINT, SIG_IGN); - signal(SIGQUIT, SIG_IGN); - resetsig = 1; - } - interactive = 0; - intr = 0; - (*pforked)++; - brklist = 0; - execflg = 0; - } - if (owp != NULL) - while ((cp = *owp++) != NULL && assign(cp, COPYV)) - if (shcom == NULL) - export(lookup(cp)); -#ifdef COMPIPE - if ((pin != NULL || pout != NULL) && shcom != NULL && shcom != doexec) { - err("piping to/from shell builtins not yet done"); - return(-1); - } -#endif - if (pin != NULL) { - dup2(pin[0], 0); - closepipe(pin); - } - if (pout != NULL) { - dup2(pout[1], 1); - closepipe(pout); - } - if ((iopp = t->ioact) != NULL) { - if (shcom != NULL && shcom != doexec) { - prs(cp); - err(": cannot redirect shell command"); - return(-1); - } - while (*iopp) - if (iosetup(*iopp++, pin!=NULL, pout!=NULL)) - return(rv); - } - if (shcom) - return(setstatus((*shcom)(t))); - /* should use FIOCEXCL */ - for (i=FDBASE; itype == TPAREN) - exit(execute(t->left, NOPIPE, NOPIPE, FEXEC)); - if (wp[0] == NULL) - exit(0); - - cp = rexecve(wp[0], wp, makenv()); - prs(wp[0]); prs(": "); warn(cp); - if (!execflg) - trap[0] = NULL; - leave(); - /* NOTREACHED */ - exit(1); -} - -/* - * 0< 1> are ignored as required - * within pipelines. - */ -static int -iosetup(iop, pipein, pipeout) -register struct ioword *iop; -int pipein, pipeout; -{ - register int u = -1; - char *cp=NULL, *msg; - - if (iop->io_unit == IODEFAULT) /* take default */ - iop->io_unit = iop->io_flag&(IOREAD|IOHERE)? 0: 1; - if (pipein && iop->io_unit == 0) - return(0); - if (pipeout && iop->io_unit == 1) - return(0); - msg = iop->io_flag&(IOREAD|IOHERE)? "open": "create"; - if ((iop->io_flag & IOHERE) == 0) { - cp = iop->io_name; - if ((cp = evalstr(cp, DOSUB|DOTRIM)) == NULL) - return(1); - } - if (iop->io_flag & IODUP) { - if (cp[1] || (!isdigit(*cp) && *cp != '-')) { - prs(cp); - err(": illegal >& argument"); - return(1); - } - if (*cp == '-') - iop->io_flag = IOCLOSE; - iop->io_flag &= ~(IOREAD|IOWRITE); - } - switch (iop->io_flag) { - case IOREAD: - u = open(cp, 0); - break; - - case IOHERE: - case IOHERE|IOXHERE: - u = herein(iop->io_name, iop->io_flag&IOXHERE); - cp = "here file"; - break; - - case IOWRITE|IOCAT: - if ((u = open(cp, 1)) >= 0) { - lseek(u, (long)0, 2); - break; - } - case IOWRITE: - u = creat(cp, 0666); - break; - - case IODUP: - u = dup2(*cp-'0', iop->io_unit); - break; - - case IOCLOSE: - close(iop->io_unit); - return(0); - } - if (u < 0) { - prs(cp); - prs(": cannot "); - warn(msg); - return(1); - } else { - if (u != iop->io_unit) { - dup2(u, iop->io_unit); - close(u); - } - } - return(0); -} - -static void -echo(wp) -register char **wp; -{ - register int i; - - prs("+"); - for (i=0; wp[i]; i++) { - if (i) - prs(" "); - prs(wp[i]); - } - prs("\n"); -} - -static struct op ** -find1case(t, w) -struct op *t; -char *w; -{ - register struct op *t1; - struct op **tp; - register char **wp, *cp; - - if (t == NULL) - return((struct op **)NULL); - if (t->type == TLIST) { - if ((tp = find1case(t->left, w)) != NULL) - return(tp); - t1 = t->right; /* TPAT */ - } else - t1 = t; - for (wp = t1->words; *wp;) - if ((cp = evalstr(*wp++, DOSUB)) && gmatch(w, cp)) - return(&t1->left); - return((struct op **)NULL); -} - -static struct op * -findcase(t, w) -struct op *t; -char *w; -{ - register struct op **tp; - - return((tp = find1case(t, w)) != NULL? *tp: (struct op *)NULL); -} - -/* - * Enter a new loop level (marked for break/continue). - */ -static void -brkset(bc) -struct brkcon *bc; -{ - bc->nextlev = brklist; - brklist = bc; -} - -/* - * Wait for the last process created. - * Print a message for each process found - * that was killed by a signal. - * Ignore interrupt signals while waiting - * unless `canintr' is true. - */ -static int -waitfor(lastpid, canintr) -register int lastpid; -int canintr; -{ - register int pid, rv; - int s; - int oheedint = heedint; - - heedint = 0; - rv = 0; - do { - pid = wait(&s); - if (pid == -1) { - if (errno != EINTR || canintr) - break; - } else { - if ((rv = WAITSIG(s)) != 0) { - if (rv < NSIGNAL) { - if (signame[rv] != NULL) { - if (pid != lastpid) { - prn(pid); - prs(": "); - } - prs(signame[rv]); - } - } else { - if (pid != lastpid) { - prn(pid); - prs(": "); - } - prs("Signal "); prn(rv); prs(" "); - } - if (WAITCORE(s)) - prs(" - core dumped"); - if (rv >= NSIGNAL || signame[rv]) - prs("\n"); - rv = -1; - } else - rv = WAITVAL(s); - } - } while (pid != lastpid); - heedint = oheedint; - if (intr) { - if (interactive) { - if (canintr) - intr = 0; - } else { - if (exstat == 0) exstat = rv; - onintr(0); - } - } - return(rv); -} - -static int -setstatus(s) -register int s; -{ - exstat = s; - setval(lookup("?"), putn(s)); - return(s); -} - -/* - * PATH-searching interface to execve. - * If getenv("PATH") were kept up-to-date, - * execvp might be used. - */ -static char * -rexecve(c, v, envp) -char *c, **v, **envp; -{ - register int i; - register char *sp, *tp; - int eacces = 0, asis = 0; - -#ifdef BB_FEATURE_SH_STANDALONE_SHELL - char *name = c; -#ifdef BB_FEATURE_SH_APPLETS_ALWAYS_WIN - name = get_last_path_component(name); -#endif - optind = 1; - if (find_applet_by_name(name)) { - /* We have to exec here since we vforked. Running - * run_applet_by_name() won't work and bad things - * will happen. */ - execve("/proc/self/exe", v, envp); - execve("busybox", v, envp); - } -#endif - - sp = any('/', c)? "": path->value; - asis = *sp == '\0'; - while (asis || *sp != '\0') { - asis = 0; - tp = e.linep; - for (; *sp != '\0'; tp++) - if ((*tp = *sp++) == ':') { - asis = *sp == '\0'; - break; - } - if (tp != e.linep) - *tp++ = '/'; - for (i = 0; (*tp++ = c[i++]) != '\0';) - ; - - execve(e.linep, v, envp); - switch (errno) { - case ENOEXEC: - *v = e.linep; - tp = *--v; - *v = e.linep; - execve("/bin/sh", v, envp); - *v = tp; - return("no Shell"); - - case ENOMEM: - return("program too big"); - - case E2BIG: - return("argument list too long"); - - case EACCES: - eacces++; - break; - } - } - return(errno==ENOENT ? "not found" : "cannot execute"); -} - -/* - * Run the command produced by generator `f' - * applied to stream `arg'. - */ -static int -run(argp, f) -struct ioarg *argp; -int (*f)(); -{ - struct op *otree; - struct wdblock *swdlist; - struct wdblock *siolist; - jmp_buf ev, rt; - xint *ofail; - int rv; - -#if __GNUC__ - /* Avoid longjmp clobbering */ - (void) &rv; -#endif - - areanum++; - swdlist = wdlist; - siolist = iolist; - otree = outtree; - ofail = failpt; - rv = -1; - if (newenv(setjmp(errpt = ev)) == 0) { - wdlist = 0; - iolist = 0; - pushio(argp, f); - e.iobase = e.iop; - yynerrs = 0; - if (setjmp(failpt = rt) == 0 && yyparse() == 0) - rv = execute(outtree, NOPIPE, NOPIPE, 0); - quitenv(); - } - wdlist = swdlist; - iolist = siolist; - failpt = ofail; - outtree = otree; - freearea(areanum--); - return(rv); -} - -/* -------- do.c -------- */ - -/* - * built-in commands: doX - */ - -static int dohelp() -{ - int col; - const struct builtincmd *x; - - printf("\nBuilt-in commands:\n"); - printf("-------------------\n"); - - for (col=0, x = builtincmds; x->builtinfunc != NULL; x++) { - if (!x->name) - continue; - col += printf("%s%s", ((col == 0) ? "\t" : " "), x->name); - if (col > 60) { - printf("\n"); - col = 0; - } - } -#ifdef BB_FEATURE_SH_STANDALONE_SHELL - { - int i; - const struct BB_applet *applet; - extern const struct BB_applet applets[]; - extern const size_t NUM_APPLETS; - - for (i=0, applet = applets; i < NUM_APPLETS; applet++, i++) { - if (!applet->name) - continue; - - col += printf("%s%s", ((col == 0) ? "\t" : " "), - applet->name); - if (col > 60) { - printf("\n"); - col = 0; - } - } - } -#endif - printf("\n\n"); - return EXIT_SUCCESS; -} - - - -static int -dolabel() -{ - return(0); -} - -static int -dochdir(t) -register struct op *t; -{ - register char *cp, *er; - - if ((cp = t->words[1]) == NULL && (cp = homedir->value) == NULL) - er = ": no home directory"; - else if(chdir(cp) < 0) - er = ": bad directory"; - else - return(0); - prs(cp != NULL? cp: "cd"); - err(er); - return(1); -} - -static int -doshift(t) -register struct op *t; -{ - register int n; - - n = t->words[1]? getn(t->words[1]): 1; - if(dolc < n) { - err("nothing to shift"); - return(1); - } - dolv[n] = dolv[0]; - dolv += n; - dolc -= n; - setval(lookup("#"), putn(dolc)); - return(0); -} - -/* - * execute login and newgrp directly - */ -static int -dologin(t) -struct op *t; -{ - register char *cp; - - if (interactive) { - signal(SIGINT, SIG_DFL); - signal(SIGQUIT, SIG_DFL); - } - cp = rexecve(t->words[0], t->words, makenv()); - prs(t->words[0]); prs(": "); err(cp); - return(1); -} - -static int -doumask(t) -register struct op *t; -{ - register int i, n; - register char *cp; - - if ((cp = t->words[1]) == NULL) { - i = umask(0); - umask(i); - for (n=3*4; (n-=3) >= 0;) - putc('0'+((i>>n)&07), stderr); - putc('\n', stderr); - } else { - for (n=0; *cp>='0' && *cp<='9'; cp++) - n = n*8 + (*cp-'0'); - umask(n); - } - return(0); -} - -static int -doexec(t) -register struct op *t; -{ - register int i; - jmp_buf ex; - xint *ofail; - - t->ioact = NULL; - for(i = 0; (t->words[i]=t->words[i+1]) != NULL; i++) - ; - if (i == 0) - return(1); - execflg = 1; - ofail = failpt; - if (setjmp(failpt = ex) == 0) - execute(t, NOPIPE, NOPIPE, FEXEC); - failpt = ofail; - execflg = 0; - return(1); -} - -static int -dodot(t) -struct op *t; -{ - register int i; - register char *sp, *tp; - char *cp; - - if ((cp = t->words[1]) == NULL) - return(0); - sp = any('/', cp)? ":": path->value; - while (*sp) { - tp = e.linep; - while (*sp && (*tp = *sp++) != ':') - tp++; - if (tp != e.linep) - *tp++ = '/'; - for (i = 0; (*tp++ = cp[i++]) != '\0';) - ; - if ((i = open(e.linep, 0)) >= 0) { - exstat = 0; - next(remap(i)); - return(exstat); - } - } - prs(cp); - err(": not found"); - return(-1); -} - -static int -dowait(t) -struct op *t; -{ - register int i; - register char *cp; - - if ((cp = t->words[1]) != NULL) { - i = getn(cp); - if (i == 0) - return(0); - } else - i = -1; - setstatus(waitfor(i, 1)); - return(0); -} - -static int -doread(t) -struct op *t; -{ - register char *cp, **wp; - register int nb = 0; - register int nl = 0; - - if (t->words[1] == NULL) { - err("Usage: read name ..."); - return(1); - } - for (wp = t->words+1; *wp; wp++) { - for (cp = e.linep; !nl && cp < elinep-1; cp++) - if ((nb = read(0, cp, sizeof(*cp))) != sizeof(*cp) || - (nl = (*cp == '\n')) || - (wp[1] && any(*cp, ifs->value))) - break; - *cp = 0; - if (nb <= 0) - break; - setval(lookup(*wp), e.linep); - } - return(nb <= 0); -} - -static int -doeval(t) -register struct op *t; -{ - return(RUN(awordlist, t->words+1, wdchar)); -} - -static int -dotrap(t) -register struct op *t; -{ - register int n, i; - register int resetsig; - - if (t->words[1] == NULL) { - for (i=0; i<=_NSIG; i++) - if (trap[i]) { - prn(i); - prs(": "); - prs(trap[i]); - prs("\n"); - } - return(0); - } - resetsig = isdigit(*t->words[1]); - for (i = resetsig ? 1 : 2; t->words[i] != NULL; ++i) { - n = getsig(t->words[i]); - freecell(trap[n]); - trap[n] = 0; - if (!resetsig) { - if (*t->words[1] != '\0') { - trap[n] = strsave(t->words[1], 0); - setsig(n, sig); - } else - setsig(n, SIG_IGN); - } else { - if (interactive) - if (n == SIGINT) - setsig(n, onintr); - else - setsig(n, n == SIGQUIT ? SIG_IGN - : SIG_DFL); - else - setsig(n, SIG_DFL); - } - } - return(0); -} - -static int -getsig(s) -char *s; -{ - register int n; - - if ((n = getn(s)) < 0 || n > _NSIG) { - err("trap: bad signal number"); - n = 0; - } - return(n); -} - -static void -setsig( register int n, void (*f)(int)) -{ - if (n == 0) - return; - if (signal(n, SIG_IGN) != SIG_IGN || ourtrap[n]) { - ourtrap[n] = 1; - signal(n, f); - } -} - -static int -getn(as) -char *as; -{ - register char *s; - register int n, m; - - s = as; - m = 1; - if (*s == '-') { - m = -1; - s++; - } - for (n = 0; isdigit(*s); s++) - n = (n*10) + (*s-'0'); - if (*s) { - prs(as); - err(": bad number"); - } - return(n*m); -} - -static int -dobreak(t) -struct op *t; -{ - return(brkcontin(t->words[1], 1)); -} - -static int -docontinue(t) -struct op *t; -{ - return(brkcontin(t->words[1], 0)); -} - -static int -brkcontin(cp, val) -register char *cp; -int val; -{ - register struct brkcon *bc; - register int nl; - - nl = cp == NULL? 1: getn(cp); - if (nl <= 0) - nl = 999; - do { - if ((bc = brklist) == NULL) - break; - brklist = bc->nextlev; - } while (--nl); - if (nl) { - err("bad break/continue level"); - return(1); - } - isbreak = val; - longjmp(bc->brkpt, 1); - /* NOTREACHED */ -} - -static int -doexit(t) -struct op *t; -{ - register char *cp; - - execflg = 0; - if ((cp = t->words[1]) != NULL) - setstatus(getn(cp)); - leave(); - /* NOTREACHED */ - return(0); -} - -static int -doexport(t) -struct op *t; -{ - rdexp(t->words+1, export, EXPORT); - return(0); -} - -static int -doreadonly(t) -struct op *t; -{ - rdexp(t->words+1, ronly, RONLY); - return(0); -} - -static void -rdexp(wp, f, key) -register char **wp; -void (*f)(); -int key; -{ - if (*wp != NULL) { - for (; *wp != NULL; wp++) { - if (isassign(*wp)) { - char *cp; - assign(*wp, COPYV); - for (cp = *wp; *cp != '='; cp++) - ; - *cp = '\0'; - } - if (checkname(*wp)) - (*f)(lookup(*wp)); - else - badid(*wp); - } - } else - putvlist(key, 1); -} - -static void -badid(s) -register char *s; -{ - prs(s); - err(": bad identifier"); -} - -static int -doset(t) -register struct op *t; -{ - register struct var *vp; - register char *cp; - register int n; - - if ((cp = t->words[1]) == NULL) { - for (vp = vlist; vp; vp = vp->next) - varput(vp->name, 1); - return(0); - } - if (*cp == '-') { - /* bad: t->words++; */ - for(n = 0; (t->words[n]=t->words[n+1]) != NULL; n++) - ; - if (*++cp == 0) - flag['x'] = flag['v'] = 0; - else - for (; *cp; cp++) - switch (*cp) { - case 'e': - if (!interactive) - flag['e']++; - break; - - default: - if (*cp>='a' && *cp<='z') - flag[(int)*cp]++; - break; - } - setdash(); - } - if (t->words[1]) { - t->words[0] = dolv[0]; - for (n=1; t->words[n]; n++) - setarea((char *)t->words[n], 0); - dolc = n-1; - dolv = t->words; - setval(lookup("#"), putn(dolc)); - setarea((char *)(dolv-1), 0); - } - return(0); -} - -static void -varput(s, out) -register char *s; -int out; -{ - if (isalnum(*s) || *s == '_') { - write(out, s, strlen(s)); - write(out, "\n", 1); - } -} - - -/* - * Copyright (c) 1999 Herbert Xu - * This file contains code for the times builtin. - */ -static int dotimes () -{ - struct tms buf; - long int clk_tck = sysconf(_SC_CLK_TCK); - - times(&buf); - printf("%dm%fs %dm%fs\n%dm%fs %dm%fs\n", - (int) (buf.tms_utime / clk_tck / 60), - ((double) buf.tms_utime) / clk_tck, - (int) (buf.tms_stime / clk_tck / 60), - ((double) buf.tms_stime) / clk_tck, - (int) (buf.tms_cutime / clk_tck / 60), - ((double) buf.tms_cutime) / clk_tck, - (int) (buf.tms_cstime / clk_tck / 60), - ((double) buf.tms_cstime) / clk_tck); - return 0; -} - - -static int (*inbuilt(char *s))() -{ - const struct builtincmd *bp; - - for (bp = builtincmds; bp->name != NULL; bp++) - if (strcmp(bp->name, s) == 0) - return(bp->builtinfunc); - - return((int(*)())NULL); -} - -/* -------- eval.c -------- */ - -/* - * ${} - * `command` - * blank interpretation - * quoting - * glob - */ - -static char ** eval( char **ap, int f) -{ - struct wdblock *wb; - char **wp; - char **wf; - jmp_buf ev; - -#if __GNUC__ - /* Avoid longjmp clobbering */ - (void) ℘ - (void) ≈ -#endif - wp = NULL; - wb = NULL; - wf = NULL; - if (newenv(setjmp(errpt = ev)) == 0) { - while (*ap && isassign(*ap)) - expand(*ap++, &wb, f & ~DOGLOB); - if (flag['k']) { - for (wf = ap; *wf; wf++) { - if (isassign(*wf)) - expand(*wf, &wb, f & ~DOGLOB); - } - } - for (wb = addword((char *)0, wb); *ap; ap++) { - if (!flag['k'] || !isassign(*ap)) - expand(*ap, &wb, f & ~DOKEY); - } - wb = addword((char *)0, wb); - wp = getwords(wb); - quitenv(); - } else - gflg = 1; - return(gflg? (char **)NULL: wp); -} - -/* - * Make the exported environment from the exported - * names in the dictionary. Keyword assignments - * will already have been done. - */ -static char ** -makenv() - -{ - register struct wdblock *wb; - register struct var *vp; - - wb = NULL; - for (vp = vlist; vp; vp = vp->next) - if (vp->status & EXPORT) - wb = addword(vp->name, wb); - wb = addword((char *)0, wb); - return(getwords(wb)); -} - -static char * -evalstr(cp, f) -register char *cp; -int f; -{ - struct wdblock *wb; - - wb = NULL; - if (expand(cp, &wb, f)) { - if (wb == NULL || wb->w_nword == 0 || (cp = wb->w_words[0]) == NULL) - cp = ""; - DELETE(wb); - } else - cp = NULL; - return(cp); -} - -static int -expand( char *cp, register struct wdblock **wbp, int f) -{ - jmp_buf ev; - -#if __GNUC__ - /* Avoid longjmp clobbering */ - (void) &cp; -#endif - gflg = 0; - if (cp == NULL) - return(0); - if (!anys("$`'\"", cp) && - !anys(ifs->value, cp) && - ((f&DOGLOB)==0 || !anys("[*?", cp))) { - cp = strsave(cp, areanum); - if (f & DOTRIM) - unquote(cp); - *wbp = addword(cp, *wbp); - return(1); - } - if (newenv(setjmp(errpt = ev)) == 0) { - PUSHIO(aword, cp, strchar); - e.iobase = e.iop; - while ((cp = blank(f)) && gflg == 0) { - e.linep = cp; - cp = strsave(cp, areanum); - if ((f&DOGLOB) == 0) { - if (f & DOTRIM) - unquote(cp); - *wbp = addword(cp, *wbp); - } else - *wbp = glob(cp, *wbp); - } - quitenv(); - } else - gflg = 1; - return(gflg == 0); -} - -/* - * Blank interpretation and quoting - */ -static char * -blank(f) -int f; -{ - register int c, c1; - register char *sp; - int scanequals, foundequals; - - sp = e.linep; - scanequals = f & DOKEY; - foundequals = 0; - -loop: - switch (c = subgetc('"', foundequals)) { - case 0: - if (sp == e.linep) - return(0); - *e.linep++ = 0; - return(sp); - - default: - if (f & DOBLANK && any(c, ifs->value)) - goto loop; - break; - - case '"': - case '\'': - scanequals = 0; - if (INSUB()) - break; - for (c1 = c; (c = subgetc(c1, 1)) != c1;) { - if (c == 0) - break; - if (c == '\'' || !any(c, "$`\"")) - c |= QUOTE; - *e.linep++ = c; - } - c = 0; - } - unget(c); - if (!isalpha(c) && c != '_') - scanequals = 0; - for (;;) { - c = subgetc('"', foundequals); - if (c == 0 || - f & (DOBLANK && any(c, ifs->value)) || - (!INSUB() && any(c, "\"'"))) { - scanequals = 0; - unget(c); - if (any(c, "\"'")) - goto loop; - break; - } - if (scanequals) { - if (c == '=') { - foundequals = 1; - scanequals = 0; - } - else if (!isalnum(c) && c != '_') - scanequals = 0; - } - *e.linep++ = c; - } - *e.linep++ = 0; - return(sp); -} - -/* - * Get characters, substituting for ` and $ - */ -static int -subgetc(ec, quoted) -register int ec; -int quoted; -{ - register char c; - -again: - c = my_getc(ec); - if (!INSUB() && ec != '\'') { - if (c == '`') { - if (grave(quoted) == 0) - return(0); - e.iop->task = XGRAVE; - goto again; - } - if (c == '$' && (c = dollar(quoted)) == 0) { - e.iop->task = XDOLL; - goto again; - } - } - return(c); -} - -/* - * Prepare to generate the string returned by ${} substitution. - */ -static int -dollar(quoted) -int quoted; -{ - int otask; - struct io *oiop; - char *dolp; - register char *s, c, *cp=NULL; - struct var *vp; - - c = readc(); - s = e.linep; - if (c != '{') { - *e.linep++ = c; - if (isalpha(c) || c == '_') { - while ((c = readc())!=0 && (isalnum(c) || c == '_')) - if (e.linep < elinep) - *e.linep++ = c; - unget(c); - } - c = 0; - } else { - oiop = e.iop; - otask = e.iop->task; - e.iop->task = XOTHER; - while ((c = subgetc('"', 0))!=0 && c!='}' && c!='\n') - if (e.linep < elinep) - *e.linep++ = c; - if (oiop == e.iop) - e.iop->task = otask; - if (c != '}') { - err("unclosed ${"); - gflg++; - return(c); - } - } - if (e.linep >= elinep) { - err("string in ${} too long"); - gflg++; - e.linep -= 10; - } - *e.linep = 0; - if (*s) - for (cp = s+1; *cp; cp++) - if (any(*cp, "=-+?")) { - c = *cp; - *cp++ = 0; - break; - } - if (s[1] == 0 && (*s == '*' || *s == '@')) { - if (dolc > 1) { - /* currently this does not distinguish $* and $@ */ - /* should check dollar */ - e.linep = s; - PUSHIO(awordlist, dolv+1, dolchar); - return(0); - } else { /* trap the nasty ${=} */ - s[0] = '1'; - s[1] = 0; - } - } - vp = lookup(s); - if ((dolp = vp->value) == null) { - switch (c) { - case '=': - if (isdigit(*s)) { - err("cannot use ${...=...} with $n"); - gflg++; - break; - } - setval(vp, cp); - dolp = vp->value; - break; - - case '-': - dolp = strsave(cp, areanum); - break; - - case '?': - if (*cp == 0) { - prs("missing value for "); - err(s); - } else - err(cp); - gflg++; - break; - } - } else if (c == '+') - dolp = strsave(cp, areanum); - if (flag['u'] && dolp == null) { - prs("unset variable: "); - err(s); - gflg++; - } - e.linep = s; - PUSHIO(aword, dolp, quoted ? qstrchar : strchar); - return(0); -} - -/* - * Run the command in `...` and read its output. - */ -static int -grave(quoted) -int quoted; -{ - register int i; - char *cp; - int pf[2]; - -#if __GNUC__ - /* Avoid longjmp clobbering */ - (void) &cp; -#endif - for (cp = e.iop->argp->aword; *cp != '`'; cp++) - if (*cp == 0) { - err("no closing `"); - return(0); - } - if (openpipe(pf) < 0) - return(0); - if ((i = vfork()) == -1) { - closepipe(pf); - err("try again"); - return(0); - } - if (i != 0) { - e.iop->argp->aword = ++cp; - close(pf[1]); - PUSHIO(afile, remap(pf[0]), quoted? qgravechar: gravechar); - return(1); - } - *cp = 0; - /* allow trapped signals */ - for (i=0; i<=_NSIG; i++) - if (ourtrap[i] && signal(i, SIG_IGN) != SIG_IGN) - signal(i, SIG_DFL); - dup2(pf[1], 1); - closepipe(pf); - flag['e'] = 0; - flag['v'] = 0; - flag['n'] = 0; - cp = strsave(e.iop->argp->aword, 0); - areanum = 1; - freehere(areanum); - freearea(areanum); /* free old space */ - e.oenv = NULL; - e.iop = (e.iobase = iostack) - 1; - unquote(cp); - interactive = 0; - PUSHIO(aword, cp, nlchar); - onecommand(); - exit(1); -} - -static char * -unquote(as) -register char *as; -{ - register char *s; - - if ((s = as) != NULL) - while (*s) - *s++ &= ~QUOTE; - return(as); -} - -/* -------- glob.c -------- */ - -/* - * glob - */ - -#define scopy(x) strsave((x), areanum) -#define BLKSIZ 512 -#define NDENT ((BLKSIZ+sizeof(struct dirent)-1)/sizeof(struct dirent)) - -static struct wdblock *cl, *nl; -static char spcl[] = "[?*"; - -static struct wdblock * -glob(cp, wb) -char *cp; -struct wdblock *wb; -{ - register int i; - register char *pp; - - if (cp == 0) - return(wb); - i = 0; - for (pp = cp; *pp; pp++) - if (any(*pp, spcl)) - i++; - else if (!any(*pp & ~QUOTE, spcl)) - *pp &= ~QUOTE; - if (i != 0) { - for (cl = addword(scopy(cp), (struct wdblock *)0); anyspcl(cl); cl = nl) { - nl = newword(cl->w_nword*2); - for(i=0; iw_nword; i++) { /* for each argument */ - for (pp = cl->w_words[i]; *pp; pp++) - if (any(*pp, spcl)) { - globname(cl->w_words[i], pp); - break; - } - if (*pp == '\0') - nl = addword(scopy(cl->w_words[i]), nl); - } - for(i=0; iw_nword; i++) - DELETE(cl->w_words[i]); - DELETE(cl); - } - for(i=0; iw_nword; i++) - unquote(cl->w_words[i]); - glob0((char *)cl->w_words, cl->w_nword, sizeof(char *), xstrcmp); - if (cl->w_nword) { - for (i=0; iw_nword; i++) - wb = addword(cl->w_words[i], wb); - DELETE(cl); - return(wb); - } - } - wb = addword(unquote(cp), wb); - return(wb); -} - -static void -globname(we, pp) -char *we; -register char *pp; -{ - register char *np, *cp; - char *name, *gp, *dp; - int k; - DIR *dirp; - struct dirent *de; - char dname[NAME_MAX+1]; - struct stat dbuf; - - for (np = we; np != pp; pp--) - if (pp[-1] == '/') - break; - for (dp = cp = space((int)(pp-np)+3); np < pp;) - *cp++ = *np++; - *cp++ = '.'; - *cp = '\0'; - for (gp = cp = space(strlen(pp)+1); *np && *np != '/';) - *cp++ = *np++; - *cp = '\0'; - dirp = opendir(dp); - if (dirp == 0) { - DELETE(dp); - DELETE(gp); - return; - } - dname[NAME_MAX] = '\0'; - while ((de=readdir(dirp))!=NULL) { - /* XXX Hmmm... What this could be? (abial) */ - /* - if (ent[j].d_ino == 0) - continue; - */ - strncpy(dname, de->d_name, NAME_MAX); - if (dname[0] == '.') - if (*gp != '.') - continue; - for(k=0; kw_words; - for (i=0; iw_nword; i++) - if (anys(spcl, *wd++)) - return(1); - return(0); -} - -static int -xstrcmp(p1, p2) -char *p1, *p2; -{ - return(strcmp(*(char **)p1, *(char **)p2)); -} - -/* -------- word.c -------- */ - -static struct wdblock * -newword(nw) -register int nw; -{ - register struct wdblock *wb; - - wb = (struct wdblock *) space(sizeof(*wb) + nw*sizeof(char *)); - wb->w_bsize = nw; - wb->w_nword = 0; - return(wb); -} - -static struct wdblock * -addword(wd, wb) -char *wd; -register struct wdblock *wb; -{ - register struct wdblock *wb2; - register int nw; - - if (wb == NULL) - wb = newword(NSTART); - if ((nw = wb->w_nword) >= wb->w_bsize) { - wb2 = newword(nw * 2); - memcpy((char *)wb2->w_words, (char *)wb->w_words, nw*sizeof(char *)); - wb2->w_nword = nw; - DELETE(wb); - wb = wb2; - } - wb->w_words[wb->w_nword++] = wd; - return(wb); -} -static -char ** -getwords(wb) -register struct wdblock *wb; -{ - register char **wd; - register int nb; - - if (wb == NULL) - return((char **)NULL); - if (wb->w_nword == 0) { - DELETE(wb); - return((char **)NULL); - } - wd = (char **) space(nb = sizeof(*wd) * wb->w_nword); - memcpy((char *)wd, (char *)wb->w_words, nb); - DELETE(wb); /* perhaps should done by caller */ - return(wd); -} - -int (*func)(char *, char *); -int globv; - -static void -glob0(a0, a1, a2, a3) -char *a0; -unsigned a1; -int a2; -int (*a3) (char *, char *); -{ - func = a3; - globv = a2; - glob1(a0, a0 + a1 * a2); -} - -static void -glob1(base, lim) -char *base, *lim; -{ - register char *i, *j; - int v2; - char *lptr, *hptr; - int c; - unsigned n; - - - v2 = globv; - -top: - if ((n=(int)(lim-base)) <= v2) - return; - n = v2 * (n / (2*v2)); - hptr = lptr = base+n; - i = base; - j = lim-v2; - for(;;) { - if (i < lptr) { - if ((c = (*func)(i, lptr)) == 0) { - glob2(i, lptr -= v2); - continue; - } - if (c < 0) { - i += v2; - continue; - } - } - -begin: - if (j > hptr) { - if ((c = (*func)(hptr, j)) == 0) { - glob2(hptr += v2, j); - goto begin; - } - if (c > 0) { - if (i == lptr) { - glob3(i, hptr += v2, j); - i = lptr += v2; - goto begin; - } - glob2(i, j); - j -= v2; - i += v2; - continue; - } - j -= v2; - goto begin; - } - - - if (i == lptr) { - if (lptr-base >= lim-hptr) { - glob1(hptr+v2, lim); - lim = lptr; - } else { - glob1(base, lptr); - base = hptr+v2; - } - goto top; - } - - - glob3(j, lptr -= v2, i); - j = hptr -= v2; - } -} - -static void -glob2(i, j) -char *i, *j; -{ - register char *index1, *index2, c; - int m; - - m = globv; - index1 = i; - index2 = j; - do { - c = *index1; - *index1++ = *index2; - *index2++ = c; - } while(--m); -} - -static void -glob3(i, j, k) -char *i, *j, *k; -{ - register char *index1, *index2, *index3; - int c; - int m; - - m = globv; - index1 = i; - index2 = j; - index3 = k; - do { - c = *index1; - *index1++ = *index3; - *index3++ = *index2; - *index2++ = c; - } while(--m); -} - -/* -------- io.c -------- */ - -/* - * shell IO - */ - -static int my_getc( int ec) -{ - register int c; - - if(e.linep > elinep) { - while((c=readc()) != '\n' && c) - ; - err("input line too long"); - gflg++; - return(c); - } - c = readc(); - if (ec != '\'' && e.iop->task != XGRAVE) { - if(c == '\\') { - c = readc(); - if (c == '\n' && ec != '\"') - return(my_getc(ec)); - c |= QUOTE; - } - } - return(c); -} - -static void -unget(c) -int c; -{ - if (e.iop >= e.iobase) - e.iop->peekc = c; -} - -static int -eofc() - -{ - return e.iop < e.iobase || (e.iop->peekc == 0 && e.iop->prev == 0); -} - -static int -readc() -{ - register int c; - - for (; e.iop >= e.iobase; e.iop--) - if ((c = e.iop->peekc) != '\0') { - e.iop->peekc = 0; - return(c); - } - else { - if (e.iop->prev != 0) { - if ((c = (*e.iop->iofn)(e.iop->argp, e.iop)) != '\0') { - if (c == -1) { - e.iop++; - continue; - } - if (e.iop == iostack) - ioecho(c); - return(e.iop->prev = c); - } - else if (e.iop->task == XIO && e.iop->prev != '\n') { - e.iop->prev = 0; - if (e.iop == iostack) - ioecho('\n'); - return '\n'; - } - } - if (e.iop->task == XIO) { - if (multiline) - return e.iop->prev = 0; - if (interactive && e.iop == iostack+1) { -#ifdef BB_FEATURE_COMMAND_EDITING - current_prompt=prompt->value; -#else - prs(prompt->value); -#endif - } - } - } - if (e.iop >= iostack) - return(0); - leave(); - /* NOTREACHED */ - return(0); -} - -static void -ioecho(c) -char c; -{ - if (flag['v']) - write(2, &c, sizeof c); -} - -static void -pushio(argp, fn) -struct ioarg *argp; -int (*fn)(); -{ - if (++e.iop >= &iostack[NPUSH]) { - e.iop--; - err("Shell input nested too deeply"); - gflg++; - return; - } - e.iop->iofn = fn; - - if (argp->afid != AFID_NOBUF) - e.iop->argp = argp; - else { - e.iop->argp = ioargstack + (e.iop - iostack); - *e.iop->argp = *argp; - e.iop->argp->afbuf = e.iop == &iostack[0] ? &mainbuf : &sharedbuf; - if (isatty(e.iop->argp->afile) == 0 && - (e.iop == &iostack[0] || - lseek(e.iop->argp->afile, 0L, 1) != -1)) { - if (++bufid == AFID_NOBUF) - bufid = AFID_ID; - e.iop->argp->afid = bufid; - } - } - - e.iop->prev = ~'\n'; - e.iop->peekc = 0; - e.iop->xchar = 0; - e.iop->nlcount = 0; - if (fn == filechar || fn == linechar) - e.iop->task = XIO; - else if (fn == gravechar || fn == qgravechar) - e.iop->task = XGRAVE; - else - e.iop->task = XOTHER; -} - -static struct io * -setbase(ip) -struct io *ip; -{ - register struct io *xp; - - xp = e.iobase; - e.iobase = ip; - return(xp); -} - -/* - * Input generating functions - */ - -/* - * Produce the characters of a string, then a newline, then EOF. - */ -static int -nlchar(ap) -register struct ioarg *ap; -{ - register int c; - - if (ap->aword == NULL) - return(0); - if ((c = *ap->aword++) == 0) { - ap->aword = NULL; - return('\n'); - } - return(c); -} - -/* - * Given a list of words, produce the characters - * in them, with a space after each word. - */ -static int -wdchar(ap) -register struct ioarg *ap; -{ - register char c; - register char **wl; - - if ((wl = ap->awordlist) == NULL) - return(0); - if (*wl != NULL) { - if ((c = *(*wl)++) != 0) - return(c & 0177); - ap->awordlist++; - return(' '); - } - ap->awordlist = NULL; - return('\n'); -} - -/* - * Return the characters of a list of words, - * producing a space between them. - */ -static int -dolchar(ap) -register struct ioarg *ap; -{ - register char *wp; - - if ((wp = *ap->awordlist++) != NULL) { - PUSHIO(aword, wp, *ap->awordlist == NULL? strchar: xxchar); - return(-1); - } - return(0); -} - -static int -xxchar(ap) -register struct ioarg *ap; -{ - register int c; - - if (ap->aword == NULL) - return(0); - if ((c = *ap->aword++) == '\0') { - ap->aword = NULL; - return(' '); - } - return(c); -} - -/* - * Produce the characters from a single word (string). - */ -static int -strchar(ap) -register struct ioarg *ap; -{ - register int c; - - if (ap->aword == NULL || (c = *ap->aword++) == 0) - return(0); - return(c); -} - -/* - * Produce quoted characters from a single word (string). - */ -static int -qstrchar(ap) -register struct ioarg *ap; -{ - register int c; - - if (ap->aword == NULL || (c = *ap->aword++) == 0) - return(0); - return(c|QUOTE); -} - -/* - * Return the characters from a file. - */ -static int -filechar(ap) -register struct ioarg *ap; -{ - register int i; - char c; - struct iobuf *bp = ap->afbuf; - - if (ap->afid != AFID_NOBUF) { - if ((i = ap->afid != bp->id) || bp->bufp == bp->ebufp) { - if (i) - lseek(ap->afile, ap->afpos, 0); - i = safe_read(ap->afile, bp->buf, sizeof(bp->buf)); - if (i <= 0) { - closef(ap->afile); - return 0; - } - bp->id = ap->afid; - bp->ebufp = (bp->bufp = bp->buf) + i; - } - ap->afpos++; - return *bp->bufp++ & 0177; - } - -#ifdef BB_FEATURE_COMMAND_EDITING - if (interactive) { - static char mycommand[BUFSIZ]; - static int position = 0, size = 0; - - while (size == 0 || position >= size) { - cmdedit_read_input(current_prompt, mycommand); - size = strlen(mycommand); - position = 0; - } - c = mycommand[position]; - position++; - return(c); - } else -#endif - { - i = safe_read(ap->afile, &c, sizeof(c)); - return(i == sizeof(c)? c&0177: (closef(ap->afile), 0)); - } -} - -/* - * Return the characters from a here temp file. - */ -static int -herechar(ap) -register struct ioarg *ap; -{ - char c; - - - if (read(ap->afile, &c, sizeof(c)) != sizeof(c)) { - close(ap->afile); - c = 0; - } - return (c); - -} - -/* - * Return the characters produced by a process (`...`). - * Quote them if required, and remove any trailing newline characters. - */ -static int -gravechar(ap, iop) -struct ioarg *ap; -struct io *iop; -{ - register int c; - - if ((c = qgravechar(ap, iop)&~QUOTE) == '\n') - c = ' '; - return(c); -} - -static int -qgravechar(ap, iop) -register struct ioarg *ap; -struct io *iop; -{ - register int c; - - if (iop->xchar) { - if (iop->nlcount) { - iop->nlcount--; - return('\n'|QUOTE); - } - c = iop->xchar; - iop->xchar = 0; - } else if ((c = filechar(ap)) == '\n') { - iop->nlcount = 1; - while ((c = filechar(ap)) == '\n') - iop->nlcount++; - iop->xchar = c; - if (c == 0) - return(c); - iop->nlcount--; - c = '\n'; - } - return(c!=0? c|QUOTE: 0); -} - -/* - * Return a single command (usually the first line) from a file. - */ -static int -linechar(ap) -register struct ioarg *ap; -{ - register int c; - - if ((c = filechar(ap)) == '\n') { - if (!multiline) { - closef(ap->afile); - ap->afile = -1; /* illegal value */ - } - } - return(c); -} - -static void -prs(s) -register char *s; -{ - if (*s) - write(2, s, strlen(s)); -} - -static void -prn(u) -unsigned u; -{ - prs(itoa(u, 0)); -} - -static void -closef(i) -register int i; -{ - if (i > 2) - close(i); -} - -static void -closeall() -{ - register int u; - - for (u=NUFILE; u= 0 && fd < e.iofd); - for (i=0; ih_tag = evalstr(s, DOSUB); - if (h->h_tag == 0) - return; - h->h_iop = iop; - iop->io_name = 0; - h->h_next = NULL; - if (inhere == 0) - inhere = h; - else - for (lh = inhere; lh!=NULL; lh = lh->h_next) - if (lh->h_next == 0) { - lh->h_next = h; - break; - } - iop->io_flag |= IOHERE|IOXHERE; - for (s = h->h_tag; *s; s++) - if (*s & QUOTE) { - iop->io_flag &= ~ IOXHERE; - *s &= ~ QUOTE; - } - h->h_dosub = iop->io_flag & IOXHERE; -} - -static void -gethere() -{ - register struct here *h, *hp; - - /* Scan here files first leaving inhere list in place */ - for (hp = h = inhere; h != NULL; hp = h, h = h->h_next) - readhere(&h->h_iop->io_name, h->h_tag, h->h_dosub? 0: '\''); - - /* Make inhere list active - keep list intact for scraphere */ - if (hp != NULL) { - hp->h_next = acthere; - acthere = inhere; - inhere = NULL; - } -} - -static void -readhere(name, s, ec) -char **name; -register char *s; -int ec; -{ - int tf; - char tname[30] = ".msh_XXXXXX"; - register int c; - jmp_buf ev; - char myline [LINELIM+1]; - char *thenext; - - tf = mkstemp(tname); - if (tf < 0) - return; - *name = strsave(tname, areanum); - if (newenv(setjmp(errpt = ev)) != 0) - unlink(tname); - else { - pushio(e.iop->argp, e.iop->iofn); - e.iobase = e.iop; - for (;;) { - if (interactive && e.iop <= iostack) { -#ifdef BB_FEATURE_COMMAND_EDITING - current_prompt=cprompt->value; -#else - prs(cprompt->value); -#endif - } - thenext = myline; - while ((c = my_getc(ec)) != '\n' && c) { - if (ec == '\'') - c &= ~ QUOTE; - if (thenext >= &myline[LINELIM]) { - c = 0; - break; - } - *thenext++ = c; - } - *thenext = 0; - if (strcmp(s, myline) == 0 || c == 0) - break; - *thenext++ = '\n'; - write (tf, myline, (int)(thenext-myline)); - } - if (c == 0) { - prs("here document `"); prs(s); err("' unclosed"); - } - quitenv(); - } - close(tf); -} - -/* - * open here temp file. - * if unquoted here, expand here temp file into second temp file. - */ -static int -herein(hname, xdoll) -char *hname; -int xdoll; -{ - register int hf; - int tf; - -#if __GNUC__ - /* Avoid longjmp clobbering */ - (void) &tf; -#endif - if (hname == 0) - return(-1); - hf = open(hname, 0); - if (hf < 0) - return (-1); - if (xdoll) { - char c; - char tname[30] = ".msh_XXXXXX"; - jmp_buf ev; - - tf = mkstemp(tname); - if (tf < 0) - return (-1); - if (newenv(setjmp(errpt = ev)) == 0) { - PUSHIO(afile, hf, herechar); - setbase(e.iop); - while ((c = subgetc(0, 0)) != 0) { - c &= ~ QUOTE; - write(tf, &c, sizeof c); - } - quitenv(); - } else - unlink(tname); - close(tf); - tf = open(tname, 0); - unlink(tname); - return (tf); - } else - return (hf); -} - -static void -scraphere() -{ - register struct here *h; - - for (h = inhere; h != NULL; h = h->h_next) { - if (h->h_iop && h->h_iop->io_name) - unlink(h->h_iop->io_name); - } - inhere = NULL; -} - -/* unlink here temp files before a freearea(area) */ -static void -freehere(area) -int area; -{ - register struct here *h, *hl; - - hl = NULL; - for (h = acthere; h != NULL; h = h->h_next) - if (getarea((char *) h) >= area) { - if (h->h_iop->io_name != NULL) - unlink(h->h_iop->io_name); - if (hl == NULL) - acthere = h->h_next; - else - hl->h_next = h->h_next; - } else - hl = h; -} - - - -/* - * Copyright (c) 1987,1997, Prentice Hall - * All rights reserved. - * - * Redistribution and use of the MINIX operating system in source and - * binary forms, with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * Neither the name of Prentice Hall nor the names of the software - * authors or contributors may be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND - * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL PRENTICE HALL OR ANY AUTHORS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - diff --git a/mt.c b/mt.c deleted file mode 100644 index 49dc70ac6..000000000 --- a/mt.c +++ /dev/null @@ -1,121 +0,0 @@ -/* vi: set sw=4 ts=4: */ -#include -#include -#include -#include -#include -#include "busybox.h" - -struct mt_opcodes { - char *name; - short value; -}; - -/* missing: eod/seod, stoptions, stwrthreshold, densities */ -static const struct mt_opcodes opcodes[] = { - {"bsf", MTBSF}, - {"bsfm", MTBSFM}, - {"bsr", MTBSR}, - {"bss", MTBSS}, - {"datacompression", MTCOMPRESSION}, - {"eom", MTEOM}, - {"erase", MTERASE}, - {"fsf", MTFSF}, - {"fsfm", MTFSFM}, - {"fsr", MTFSR}, - {"fss", MTFSS}, - {"load", MTLOAD}, - {"lock", MTLOCK}, - {"mkpart", MTMKPART}, - {"nop", MTNOP}, - {"offline", MTOFFL}, - {"rewoffline", MTOFFL}, - {"ras1", MTRAS1}, - {"ras2", MTRAS2}, - {"ras3", MTRAS3}, - {"reset", MTRESET}, - {"retension", MTRETEN}, - {"rewind", MTREW}, - {"seek", MTSEEK}, - {"setblk", MTSETBLK}, - {"setdensity", MTSETDENSITY}, - {"drvbuffer", MTSETDRVBUFFER}, - {"setpart", MTSETPART}, - {"tell", MTTELL}, - {"wset", MTWSM}, - {"unload", MTUNLOAD}, - {"unlock", MTUNLOCK}, - {"eof", MTWEOF}, - {"weof", MTWEOF}, - {0, 0} -}; - -extern int mt_main(int argc, char **argv) -{ - const char *file = "/dev/tape"; - const struct mt_opcodes *code = opcodes; - struct mtop op; - struct mtpos position; - int fd, mode; - - if (argc < 2) { - show_usage(); - } - - if (strcmp(argv[1], "-f") == 0) { - if (argc < 4) { - show_usage(); - } - file = argv[2]; - argv += 2; - argc -= 2; - } - - while (code->name != 0) { - if (strcmp(code->name, argv[1]) == 0) - break; - code++; - } - - if (code->name == 0) { - error_msg("unrecognized opcode %s.", argv[1]); - return EXIT_FAILURE; - } - - op.mt_op = code->value; - if (argc >= 3) - op.mt_count = atoi(argv[2]); - else - op.mt_count = 1; /* One, not zero, right? */ - - switch (code->value) { - case MTWEOF: - case MTERASE: - case MTWSM: - case MTSETDRVBUFFER: - mode = O_WRONLY; - break; - - default: - mode = O_RDONLY; - break; - } - - if ((fd = open(file, mode, 0)) < 0) - perror_msg_and_die("%s", file); - - switch (code->value) { - case MTTELL: - if (ioctl(fd, MTIOCPOS, &position) < 0) - perror_msg_and_die("%s", file); - printf ("At block %d.\n", (int) position.mt_blkno); - break; - - default: - if (ioctl(fd, MTIOCTOP, &op) != 0) - perror_msg_and_die("%s", file); - break; - } - - return EXIT_SUCCESS; -} diff --git a/mv.c b/mv.c deleted file mode 100644 index 1c4a34788..000000000 --- a/mv.c +++ /dev/null @@ -1,168 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini mv implementation for busybox - * - * - * Copyright (C) 2000 by Matt Kraai - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include - -#include "busybox.h" - -static int flags; - -static int manual_rename(const char *source, const char *dest) -{ - struct stat source_stat; - struct stat dest_stat; - int source_exists = 1; - int dest_exists = 1; - - if (stat(source, &source_stat) < 0) { - if (errno != ENOENT) { - perror_msg("unable to stat `%s'", source); - return -1; - } - source_exists = 0; - } - - if (stat(dest, &dest_stat) < 0) { - if (errno != ENOENT) { - perror_msg("unable to stat `%s'", dest); - return -1; - } - dest_exists = 0; - } - - if (dest_exists) { - if (S_ISDIR(dest_stat.st_mode) && - (!source_exists || !S_ISDIR(source_stat.st_mode))) { - error_msg("cannot overwrite directory with non-directory"); - return -1; - } - - if (!S_ISDIR(dest_stat.st_mode) && source_exists && - S_ISDIR(source_stat.st_mode)) { - error_msg("cannot overwrite non-directory with directory"); - return -1; - } - - if (unlink(dest) < 0) { - perror_msg("cannot remove `%s'", dest); - return -1; - } - } - - if (copy_file(source, dest, - FILEUTILS_RECUR | FILEUTILS_PRESERVE_STATUS) < 0) - return -1; - - if (remove_file(source, FILEUTILS_RECUR | FILEUTILS_FORCE) < 0) - return -1; - - return 0; -} - -static int move_file(const char *source, const char *dest) -{ - struct stat dest_stat; - int dest_exists = 1; - - if (stat(dest, &dest_stat) < 0) { - if (errno != ENOENT) { - perror_msg("unable to stat `%s'", dest); - return -1; - } - dest_exists = 0; - } - - if (dest_exists && !(flags & FILEUTILS_FORCE) && - ((access(dest, W_OK) < 0 && isatty(0)) || - (flags & FILEUTILS_INTERACTIVE))) { - fprintf(stderr, "mv: overwrite `%s'? ", dest); - if (!ask_confirmation()) - return 0; - } - - if (rename(source, dest) < 0) { - if (errno == EXDEV) - return manual_rename(source, dest); - - perror_msg("unable to rename `%s'", source); - return -1; - } - - return 0; -} - -extern int mv_main(int argc, char **argv) -{ - int status = 0; - int opt; - int i; - - while ((opt = getopt(argc, argv, "fi")) != -1) - switch (opt) { - case 'f': - flags &= ~FILEUTILS_INTERACTIVE; - flags |= FILEUTILS_FORCE; - break; - case 'i': - flags &= ~FILEUTILS_FORCE; - flags |= FILEUTILS_INTERACTIVE; - break; - default: - show_usage(); - } - - if (optind + 2 > argc) - show_usage(); - - if (optind + 2 == argc) { - struct stat dest_stat; - int dest_exists = 1; - - if (stat(argv[optind + 1], &dest_stat) < 0) { - if (errno != ENOENT) - perror_msg_and_die("unable to stat `%s'", argv[optind + 1]); - dest_exists = 0; - } - - if (!dest_exists || !S_ISDIR(dest_stat.st_mode)) { - if (move_file(argv[optind], argv[optind + 1]) < 0) - status = 1; - return status; - } - } - - for (i = optind; i < argc - 1; i++) { - char *dest = concat_path_file(argv[argc - 1], - get_last_path_component(argv[i])); - if (move_file(argv[i], dest) < 0) - status = 1; - free(dest); - } - - return status; -} diff --git a/nc.c b/nc.c deleted file mode 100644 index 5335872e5..000000000 --- a/nc.c +++ /dev/null @@ -1,137 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* nc: mini-netcat - built from the ground up for LRP - Copyright (C) 1998 Charles P. Wright - - 0.0.1 6K It works. - 0.0.2 5K Smaller and you can also check the exit condition if you wish. - 0.0.3 Uses select() - - 19980918 Busy Boxed! Dave Cinege - 19990512 Uses Select. Charles P. Wright - 19990513 Fixes stdin stupidity and uses buffers. Charles P. Wright - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" - -int nc_main(int argc, char **argv) -{ - int do_listen = 0, lport = 0, tmpfd, opt, sfd; - char buf[BUFSIZ]; - - struct sockaddr_in address; - struct hostent *hostinfo; - - fd_set readfds, testfds; - - while ((opt = getopt(argc, argv, "lp:")) > 0) { - switch (opt) { - case 'l': - do_listen++; - break; - case 'p': - lport = atoi(optarg); - break; - default: - show_usage(); - } - } - - if ((do_listen && optind != argc) || (!do_listen && optind + 2 != argc)) - show_usage(); - - if ((sfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) - perror_msg_and_die("socket"); - - address.sin_family = AF_INET; - - if (lport != 0) { - memset(&address.sin_addr, 0, sizeof(address.sin_addr)); - address.sin_port = htons(lport); - - if (bind(sfd, (struct sockaddr *) &address, sizeof(address)) < 0) - perror_msg_and_die("bind"); - } - - if (do_listen) { - socklen_t addrlen = sizeof(address); - - if (listen(sfd, 1) < 0) - perror_msg_and_die("listen"); - - if ((tmpfd = accept(sfd, (struct sockaddr *) &address, &addrlen)) < 0) - perror_msg_and_die("accept"); - - close(sfd); - sfd = tmpfd; - } else { - hostinfo = xgethostbyname(argv[optind]); - - address.sin_addr = *(struct in_addr *) *hostinfo->h_addr_list; - address.sin_port = htons(atoi(argv[optind+1])); - - if (connect(sfd, (struct sockaddr *) &address, sizeof(address)) < 0) - perror_msg_and_die("connect"); - } - - FD_ZERO(&readfds); - FD_SET(sfd, &readfds); - FD_SET(STDIN_FILENO, &readfds); - - while (1) { - int fd; - int ofd; - int nread; - - testfds = readfds; - - if (select(FD_SETSIZE, &testfds, NULL, NULL, NULL) < 0) - perror_msg_and_die("select"); - - for (fd = 0; fd < FD_SETSIZE; fd++) { - if (FD_ISSET(fd, &testfds)) { - if ((nread = safe_read(fd, buf, sizeof(buf))) < 0) - perror_msg_and_die("read"); - - if (fd == sfd) { - if (nread == 0) - exit(0); - ofd = STDOUT_FILENO; - } else { - if (nread == 0) - shutdown(sfd, 1); - ofd = sfd; - } - - if (full_write(ofd, buf, nread) < 0) - perror_msg_and_die("write"); - } - } - } -} diff --git a/networking/Makefile b/networking/Makefile new file mode 100644 index 000000000..4dd0cdb56 --- /dev/null +++ b/networking/Makefile @@ -0,0 +1,45 @@ +# Makefile for busybox +# +# Copyright (C) 1999,2000,2001 by Erik Andersen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +TOPDIR :=.. +L_TARGET := networking.a + +obj-y := +obj-n := +obj- := + + +obj-$(CONFIG_HOSTNAME) += hostname.o +obj-$(CONFIG_IFCONFIG) += ifconfig.o +obj-$(CONFIG_NC) += nc.o +obj-$(CONFIG_NSLOOKUP) += nslookup.o +obj-$(CONFIG_PING) += ping.o +obj-$(CONFIG_ROUTE) += route.o +obj-$(CONFIG_TELNET) += telnet.o +obj-$(CONFIG_TFTP) += tftp.o +obj-$(CONFIG_TRACEROUTE) += traceroute.o +obj-$(CONFIG_WGET) += wget.o + + +# Hand off to toplevel Rules.mak +include $(TOPDIR)/Rules.mak + +clean: + rm -f $(L_TARGET) *.o core + diff --git a/networking/config.in b/networking/config.in new file mode 100644 index 000000000..577d925c3 --- /dev/null +++ b/networking/config.in @@ -0,0 +1,21 @@ +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +mainmenu_option next_comment +comment 'Networking Utilities' + +bool 'hostname' CONFIG_HOSTNAME +bool 'ifconfig' CONFIG_IFCONFIG +bool 'nc' CONFIG_NC +bool 'nslookup' CONFIG_NSLOOKUP +bool 'ping' CONFIG_PING +bool 'route' CONFIG_ROUTE +bool 'telnet' CONFIG_TELNET +bool 'tftp' CONFIG_TFTP +bool 'traceroute' CONFIG_TRACEROUTE +bool 'wget' CONFIG_WGET + +endmenu + diff --git a/networking/hostname.c b/networking/hostname.c index d87851509..7a26c1b2c 100644 --- a/networking/hostname.c +++ b/networking/hostname.c @@ -1,6 +1,6 @@ /* vi: set sw=4 ts=4: */ /* - * $Id: hostname.c,v 1.30 2001/06/26 02:06:08 bug1 Exp $ + * $Id: hostname.c,v 1.31 2001/10/24 04:59:56 andersen Exp $ * Mini hostname implementation for busybox * * Copyright (C) 1999 by Randolph Chung @@ -49,7 +49,7 @@ static void do_sethostname(char *s, int isfile) } else { f = xfopen(s, "r"); fgets(buf, 255, f); -#ifdef BB_FEATURE_CLEAN_UP +#ifdef CONFIG_FEATURE_CLEAN_UP fclose(f); #endif chomp(buf); diff --git a/networking/ifconfig.c b/networking/ifconfig.c index c77ea04b1..3beecaf3d 100644 --- a/networking/ifconfig.c +++ b/networking/ifconfig.c @@ -15,7 +15,7 @@ * Foundation; either version 2 of the License, or (at * your option) any later version. * - * $Id: ifconfig.c,v 1.12 2001/08/10 06:02:23 mjn3 Exp $ + * $Id: ifconfig.c,v 1.13 2001/10/24 04:59:56 andersen Exp $ * */ @@ -44,7 +44,7 @@ #include #include "busybox.h" -#ifdef BB_FEATURE_IFCONFIG_SLIP +#ifdef CONFIG_FEATURE_IFCONFIG_SLIP #include #endif @@ -173,7 +173,7 @@ static const struct arg1opt Arg1Opt[] = { {"SIOCSIFDSTADDR", SIOCSIFDSTADDR, ifreq_offsetof(ifr_dstaddr)}, {"SIOCSIFNETMASK", SIOCSIFNETMASK, ifreq_offsetof(ifr_netmask)}, {"SIOCSIFBRDADDR", SIOCSIFBRDADDR, ifreq_offsetof(ifr_broadaddr)}, -#ifdef BB_FEATURE_IFCONFIG_HW +#ifdef CONFIG_FEATURE_IFCONFIG_HW {"SIOCSIFHWADDR", SIOCSIFHWADDR, ifreq_offsetof(ifr_hwaddr)}, #endif {"SIOCSIFDSTADDR", SIOCSIFDSTADDR, ifreq_offsetof(ifr_dstaddr)}, @@ -183,7 +183,7 @@ static const struct arg1opt Arg1Opt[] = { #ifdef SIOCSOUTFILL {"SIOCSOUTFILL", SIOCSOUTFILL, ifreq_offsetof(ifr_data)}, #endif -#ifdef BB_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ +#ifdef CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ {"SIOCSIFMAP", SIOCSIFMAP, ifreq_offsetof(ifr_map.mem_start)}, {"SIOCSIFMAP", SIOCSIFMAP, ifreq_offsetof(ifr_map.base_addr)}, {"SIOCSIFMAP", SIOCSIFMAP, ifreq_offsetof(ifr_map.irq)}, @@ -199,7 +199,7 @@ static const struct options OptArray[] = { {"dstaddr", N_ARG, ARG_DSTADDR, 0}, {"netmask", N_ARG, ARG_NETMASK, 0}, {"broadcast", N_ARG | M_CLR, ARG_BROADCAST, IFF_BROADCAST}, -#ifdef BB_FEATURE_IFCONFIG_HW +#ifdef CONFIG_FEATURE_IFCONFIG_HW {"hw", N_ARG, ARG_HW, 0}, #endif {"pointopoint", N_ARG | M_CLR, ARG_POINTOPOINT, IFF_POINTOPOINT}, @@ -209,7 +209,7 @@ static const struct options OptArray[] = { #ifdef SIOCSOUTFILL {"outfill", N_ARG, ARG_OUTFILL, 0}, #endif -#ifdef BB_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ +#ifdef CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ {"mem_start", N_ARG, ARG_MEM_START, 0}, {"io_addr", N_ARG, ARG_IO_ADDR, 0}, {"irq", N_ARG, ARG_IRQ, 0}, @@ -229,11 +229,11 @@ static const struct options OptArray[] = { * A couple of prototypes. */ -#ifdef BB_FEATURE_IFCONFIG_HW +#ifdef CONFIG_FEATURE_IFCONFIG_HW static int in_ether(char *bufp, struct sockaddr *sap); #endif -#ifdef BB_FEATURE_IFCONFIG_STATUS +#ifdef CONFIG_FEATURE_IFCONFIG_STATUS extern int interface_opt_a; extern int display_interfaces(char *ifname); #endif @@ -246,7 +246,7 @@ int ifconfig_main(int argc, char **argv) { struct ifreq ifr; struct sockaddr_in sai; -#ifdef BB_FEATURE_IFCONFIG_HW +#ifdef CONFIG_FEATURE_IFCONFIG_HW struct sockaddr sa; #endif const struct arg1opt *a1op; @@ -266,7 +266,7 @@ int ifconfig_main(int argc, char **argv) ++argv; --argc; -#ifdef BB_FEATURE_IFCONFIG_STATUS +#ifdef CONFIG_FEATURE_IFCONFIG_STATUS if ((argc > 0) && (strcmp(*argv,"-a") == 0)) { interface_opt_a = 1; --argc; @@ -275,7 +275,7 @@ int ifconfig_main(int argc, char **argv) #endif if(argc <= 1) { -#ifdef BB_FEATURE_IFCONFIG_STATUS +#ifdef CONFIG_FEATURE_IFCONFIG_STATUS return display_interfaces(argc ? *argv : NULL); #else error_msg_and_die( "ifconfig was not compiled with interface status display support."); @@ -333,7 +333,7 @@ int ifconfig_main(int argc, char **argv) HOSTNAME: did_flags |= (mask & A_NETMASK); if (mask & A_CAST_HOST_COPY) { -#ifdef BB_FEATURE_IFCONFIG_HW +#ifdef CONFIG_FEATURE_IFCONFIG_HW if (mask & A_CAST_RESOLVE) { #endif safe_strncpy(host, *argv, (sizeof host)); @@ -348,7 +348,7 @@ int ifconfig_main(int argc, char **argv) continue; } p = (char *) &sai; -#ifdef BB_FEATURE_IFCONFIG_HW +#ifdef CONFIG_FEATURE_IFCONFIG_HW } else { /* A_CAST_HOST_COPY_IN_ETHER */ /* This is the "hw" arg case. */ if (strcmp("ether", *argv) || (*++argv == NULL)) { @@ -368,7 +368,7 @@ int ifconfig_main(int argc, char **argv) } else { unsigned int i = strtoul(*argv,NULL,0); p = ((char *)(&ifr)) + a1op->ifr_offset; -#ifdef BB_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ +#ifdef CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ if (mask & A_MAP_TYPE) { if (ioctl(sockfd, SIOCGIFMAP, &ifr) < 0) { ++goterr; @@ -446,7 +446,7 @@ int ifconfig_main(int argc, char **argv) return goterr; } -#ifdef BB_FEATURE_IFCONFIG_HW +#ifdef CONFIG_FEATURE_IFCONFIG_HW /* Input an Ethernet address and convert to binary. */ static int in_ether(char *bufp, struct sockaddr *sap) diff --git a/networking/nslookup.c b/networking/nslookup.c index 3e32ca9c0..a1a12d992 100644 --- a/networking/nslookup.c +++ b/networking/nslookup.c @@ -2,8 +2,8 @@ /* * Mini nslookup implementation for busybox * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by John Beppu + * Copyright (C) 1999,2000 by Lineo, inc. and John Beppu + * Copyright (C) 1999,2000,2001 by John Beppu * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -180,4 +180,4 @@ int nslookup_main(int argc, char **argv) return EXIT_SUCCESS; } -/* $Id: nslookup.c,v 1.25 2001/10/01 17:50:25 kraai Exp $ */ +/* $Id: nslookup.c,v 1.26 2001/10/24 04:59:56 andersen Exp $ */ diff --git a/networking/ping.c b/networking/ping.c index 5ca5dd9e0..476c15cea 100644 --- a/networking/ping.c +++ b/networking/ping.c @@ -1,6 +1,6 @@ /* vi: set sw=4 ts=4: */ /* - * $Id: ping.c,v 1.46 2001/07/17 01:12:36 andersen Exp $ + * $Id: ping.c,v 1.47 2001/10/24 04:59:56 andersen Exp $ * Mini ping implementation for busybox * * Copyright (C) 1999 by Randolph Chung @@ -174,7 +174,7 @@ static int in_cksum(unsigned short *buf, int sz) } /* simple version */ -#ifndef BB_FEATURE_FANCY_PING +#ifndef CONFIG_FEATURE_FANCY_PING static char *hostname = NULL; static void noresp(int ign) @@ -247,7 +247,7 @@ extern int ping_main(int argc, char **argv) return EXIT_SUCCESS; } -#else /* ! BB_FEATURE_FANCY_PING */ +#else /* ! CONFIG_FEATURE_FANCY_PING */ /* full(er) version */ static char *hostname = NULL; static struct sockaddr_in pingaddr; @@ -516,7 +516,7 @@ extern int ping_main(int argc, char **argv) ping(*argv); return EXIT_SUCCESS; } -#endif /* ! BB_FEATURE_FANCY_PING */ +#endif /* ! CONFIG_FEATURE_FANCY_PING */ /* * Copyright (c) 1989 The Regents of the University of California. diff --git a/networking/telnet.c b/networking/telnet.c index ce82a0ee8..57494089d 100644 --- a/networking/telnet.c +++ b/networking/telnet.c @@ -137,7 +137,7 @@ static int local_bind(int port); /* Some globals */ static int one = 1; -#ifdef BB_FEATURE_TELNET_TTYPE +#ifdef CONFIG_FEATURE_TELNET_TTYPE static char *ttype; #endif @@ -326,7 +326,7 @@ static void putiac1(byte c) } #endif -#ifdef BB_FEATURE_TELNET_TTYPE +#ifdef CONFIG_FEATURE_TELNET_TTYPE static void putiac_subopt(byte c, char *str) { int len = strlen(str) + 6; // ( 2 + 1 + 1 + strlen + 2 ) @@ -453,7 +453,7 @@ static inline void to_sga() return; } -#ifdef BB_FEATURE_TELNET_TTYPE +#ifdef CONFIG_FEATURE_TELNET_TTYPE static inline void to_ttype() { /* Tell server we will (or won't) do TTYPE */ @@ -473,7 +473,7 @@ static void telopt(byte c) { case TELOPT_ECHO: to_echo(c); break; case TELOPT_SGA: to_sga(c); break; -#ifdef BB_FEATURE_TELNET_TTYPE +#ifdef CONFIG_FEATURE_TELNET_TTYPE case TELOPT_TTYPE: to_ttype(c); break; #endif default: to_notsup(c); break; @@ -492,7 +492,7 @@ static int subneg(byte c) case TS_SUB1: if (c == IAC) G.telstate = TS_SUB2; -#ifdef BB_FEATURE_TELNET_TTYPE +#ifdef CONFIG_FEATURE_TELNET_TTYPE else if (c == TELOPT_TTYPE) putiac_subopt(TELOPT_TTYPE,ttype); @@ -537,7 +537,7 @@ extern int telnet_main(int argc, char** argv) int maxfd; #endif -#ifdef BB_FEATURE_TELNET_TTYPE +#ifdef CONFIG_FEATURE_TELNET_TTYPE ttype = getenv("TERM"); #endif diff --git a/networking/tftp.c b/networking/tftp.c index 530b3d134..38a6f81f0 100644 --- a/networking/tftp.c +++ b/networking/tftp.c @@ -46,7 +46,7 @@ #include "busybox.h" -//#define BB_FEATURE_TFTP_DEBUG +//#define CONFIG_FEATURE_TFTP_DEBUG #define TFTP_BLOCKSIZE_DEFAULT 512 /* according to RFC 1350, don't change */ #define TFTP_TIMEOUT 5 /* seconds */ @@ -74,7 +74,7 @@ static const char *tftp_error_msg[] = { const int tftp_cmd_get = 1; const int tftp_cmd_put = 2; -#ifdef BB_FEATURE_TFTP_BLOCKSIZE +#ifdef CONFIG_FEATURE_TFTP_BLOCKSIZE static int tftp_blocksize_check(int blocksize, int bufsize) { @@ -158,11 +158,11 @@ static inline int tftp(const int cmd, const struct hostent *host, int timeout = bb_tftp_num_retries; int block_nr = 1; -#ifdef BB_FEATURE_TFTP_BLOCKSIZE +#ifdef CONFIG_FEATURE_TFTP_BLOCKSIZE int want_option_ack = 0; #endif - RESERVE_BB_BUFFER(buf, tftp_bufsize + 4); /* Opcode + Block # + Data */ + RESERVE_CONFIG_BUFFER(buf, tftp_bufsize + 4); /* Opcode + Block # + Data */ tftp_bufsize += 4; @@ -230,7 +230,7 @@ static inline int tftp(const int cmd, const struct hostent *host, memcpy(cp, "octet", 6); cp += 6; -#ifdef BB_FEATURE_TFTP_BLOCKSIZE +#ifdef CONFIG_FEATURE_TFTP_BLOCKSIZE len = tftp_bufsize - 4; /* data block size */ @@ -290,7 +290,7 @@ static inline int tftp(const int cmd, const struct hostent *host, len = cp - buf; -#ifdef BB_FEATURE_TFTP_DEBUG +#ifdef CONFIG_FEATURE_TFTP_DEBUG printf("sending %u bytes\n", len); for (cp = buf; cp < &buf[len]; cp++) printf("%02x ", *cp); @@ -367,7 +367,7 @@ static inline int tftp(const int cmd, const struct hostent *host, opcode = ntohs(*((unsigned short *) buf)); tmp = ntohs(*((unsigned short *) &buf[2])); -#ifdef BB_FEATURE_TFTP_DEBUG +#ifdef CONFIG_FEATURE_TFTP_DEBUG printf("received %d bytes: %04x %04x\n", len, opcode, tmp); #endif @@ -390,7 +390,7 @@ static inline int tftp(const int cmd, const struct hostent *host, break; } -#ifdef BB_FEATURE_TFTP_BLOCKSIZE +#ifdef CONFIG_FEATURE_TFTP_BLOCKSIZE if (want_option_ack) { want_option_ack = 0; @@ -416,7 +416,7 @@ static inline int tftp(const int cmd, const struct hostent *host, else { opcode = TFTP_ACK; } -#ifdef BB_FEATURE_TFTP_DEBUG +#ifdef CONFIG_FEATURE_TFTP_DEBUG printf("using blksize %u\n"); #endif tftp_bufsize = foo + 4; @@ -470,10 +470,10 @@ static inline int tftp(const int cmd, const struct hostent *host, } } -#ifdef BB_FEATURE_CLEAN_UP +#ifdef CONFIG_FEATURE_CLEAN_UP close(socketfd); - RELEASE_BB_BUFFER(buf); + RELEASE_CONFIG_BUFFER(buf); #endif return finished ? EXIT_SUCCESS : EXIT_FAILURE; @@ -494,19 +494,19 @@ int tftp_main(int argc, char **argv) /* figure out what to pass to getopt */ -#ifdef BB_FEATURE_TFTP_BLOCKSIZE +#ifdef CONFIG_FEATURE_TFTP_BLOCKSIZE #define BS "b:" #else #define BS #endif -#ifdef BB_FEATURE_TFTP_GET +#ifdef CONFIG_FEATURE_TFTP_GET #define GET "g" #else #define GET #endif -#ifdef BB_FEATURE_TFTP_PUT +#ifdef CONFIG_FEATURE_TFTP_PUT #define PUT "p" #else #define PUT @@ -514,7 +514,7 @@ int tftp_main(int argc, char **argv) while ((opt = getopt(argc, argv, BS GET PUT "l:r:")) != -1) { switch (opt) { -#ifdef BB_FEATURE_TFTP_BLOCKSIZE +#ifdef CONFIG_FEATURE_TFTP_BLOCKSIZE case 'b': blocksize = atoi(optarg); if (!tftp_blocksize_check(blocksize, 0)) { @@ -522,13 +522,13 @@ int tftp_main(int argc, char **argv) } break; #endif -#ifdef BB_FEATURE_TFTP_GET +#ifdef CONFIG_FEATURE_TFTP_GET case 'g': cmd = tftp_cmd_get; flags = O_WRONLY | O_CREAT; break; #endif -#ifdef BB_FEATURE_TFTP_PUT +#ifdef CONFIG_FEATURE_TFTP_PUT case 'p': cmd = tftp_cmd_put; flags = O_RDONLY; @@ -558,7 +558,7 @@ int tftp_main(int argc, char **argv) port = atoi(argv[optind + 1]); } -#ifdef BB_FEATURE_TFTP_DEBUG +#ifdef CONFIG_FEATURE_TFTP_DEBUG printf("using server \"%s\", remotefile \"%s\", " "localfile \"%s\".\n", inet_ntoa(*((struct in_addr *) host->h_addr)), @@ -567,7 +567,7 @@ int tftp_main(int argc, char **argv) result = tftp(cmd, host, remotefile, fd, port, blocksize); -#ifdef BB_FEATURE_CLEAN_UP +#ifdef CONFIG_FEATURE_CLEAN_UP close(fd); #endif return(result); diff --git a/networking/traceroute.c b/networking/traceroute.c index a3abd0a00..e7d9725af 100644 --- a/networking/traceroute.c +++ b/networking/traceroute.c @@ -62,9 +62,9 @@ * Tue Dec 20 03:50:13 PST 1988 */ -#undef BB_FEATURE_TRACEROUTE_VERBOSE -//#define BB_FEATURE_TRACEROUTE_VERBOSE -#undef BB_FEATURE_TRACEROUTE_SO_DEBUG /* not in documentation man */ +#undef CONFIG_FEATURE_TRACEROUTE_VERBOSE +//#define CONFIG_FEATURE_TRACEROUTE_VERBOSE +#undef CONFIG_FEATURE_TRACEROUTE_SO_DEBUG /* not in documentation man */ #include #include @@ -213,7 +213,7 @@ static int max_ttl = 30; static u_short ident; static u_short port = 32768+666; /* start udp dest port # for probe packets */ -#ifdef BB_FEATURE_TRACEROUTE_VERBOSE +#ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE static int verbose; #endif static int waittime = 5; /* time to wait for response (in seconds) */ @@ -269,7 +269,7 @@ print(u_char *buf, int cc, struct sockaddr_in *from) cc -= hlen; inetname(from); -#ifdef BB_FEATURE_TRACEROUTE_VERBOSE +#ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE if (verbose) printf (" %d bytes to %s", cc, inet_ntoa (ip->ip_dst)); #endif @@ -319,7 +319,7 @@ wait_for_reply(int sock, struct sockaddr_in *from, int reset_timer) return(cc); } -#ifdef BB_FEATURE_TRACEROUTE_VERBOSE +#ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE /* * Convert an ICMP "type" field to a printable string. */ @@ -353,7 +353,7 @@ packet_ok(u_char *buf, int cc, struct sockaddr_in *from, int seq) ip = (struct ip *) buf; hlen = ip->ip_hl << 2; if (cc < hlen + ICMP_MINLEN) { -#ifdef BB_FEATURE_TRACEROUTE_VERBOSE +#ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE if (verbose) printf("packet too short (%d bytes) from %s\n", cc, inet_ntoa(from->sin_addr)); @@ -376,7 +376,7 @@ packet_ok(u_char *buf, int cc, struct sockaddr_in *from, int seq) up->dest == htons(port+seq)) return (type == ICMP_TIMXCEED? -1 : code+1); } -#ifdef BB_FEATURE_TRACEROUTE_VERBOSE +#ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE if (verbose) { int i; u_long *lp = (u_long *)&icp->icmp_ip; @@ -430,7 +430,7 @@ send_probe(int seq, int ttl) int -#ifndef BB_TRACEROUTE +#ifndef CONFIG_TRACEROUTE main(argc, argv) #else traceroute_main(argc, argv) @@ -454,7 +454,7 @@ traceroute_main(argc, argv) while ((ch = getopt(argc, argv, "dm:np:q:rs:t:w:v")) != EOF) switch(ch) { case 'd': -#ifdef BB_FEATURE_TRACEROUTE_SO_DEBUG +#ifdef CONFIG_FEATURE_TRACEROUTE_SO_DEBUG options |= SO_DEBUG; #endif break; @@ -492,7 +492,7 @@ traceroute_main(argc, argv) error_msg_and_die("tos must be 0 to 255."); break; case 'v': -#ifdef BB_FEATURE_TRACEROUTE_VERBOSE +#ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE verbose++; #endif break; @@ -537,7 +537,7 @@ traceroute_main(argc, argv) s = create_icmp_socket(); -#ifdef BB_FEATURE_TRACEROUTE_SO_DEBUG +#ifdef CONFIG_FEATURE_TRACEROUTE_SO_DEBUG if (options & SO_DEBUG) (void) setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof(on)); @@ -555,7 +555,7 @@ traceroute_main(argc, argv) sizeof(on)) < 0) perror_msg_and_die("IP_HDRINCL"); #endif IP_HDRINCL -#ifdef BB_FEATURE_TRACEROUTE_SO_DEBUG +#ifdef CONFIG_FEATURE_TRACEROUTE_SO_DEBUG if (options & SO_DEBUG) (void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof(on)); diff --git a/networking/wget.c b/networking/wget.c index 59373d1d9..41b4e30af 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -60,7 +60,7 @@ static int ftpcmd(char *s1, char *s2, FILE *fp, char *buf); /* Globals (can be accessed from signal handlers */ static off_t filesize = 0; /* content-length of the file */ static int chunked = 0; /* chunked transfer encoding */ -#ifdef BB_FEATURE_WGET_STATUSBAR +#ifdef CONFIG_FEATURE_WGET_STATUSBAR static void progressmeter(int flag); static char *curfile; /* Name of current file being transferred. */ static struct timeval start; /* Time a transfer started. */ @@ -126,7 +126,7 @@ static char *safe_fgets(char *s, int size, FILE *stream) error_msg_and_die(s); } -#ifdef BB_FEATURE_WGET_AUTHENTICATION +#ifdef CONFIG_FEATURE_WGET_AUTHENTICATION /* * Base64-encode character string * oops... isn't something similar in uuencode.c? @@ -245,20 +245,20 @@ int wget_main(int argc, char **argv) /* Guess an output filename */ if (!fname_out) { fname_out = -#ifdef BB_FEATURE_WGET_STATUSBAR +#ifdef CONFIG_FEATURE_WGET_STATUSBAR curfile = #endif get_last_path_component(target.path); if (fname_out==NULL || strlen(fname_out)<1) { fname_out = -#ifdef BB_FEATURE_WGET_STATUSBAR +#ifdef CONFIG_FEATURE_WGET_STATUSBAR curfile = #endif "index.html"; } if (dir_prefix != NULL) fname_out = concat_path_file(dir_prefix, fname_out); -#ifdef BB_FEATURE_WGET_STATUSBAR +#ifdef CONFIG_FEATURE_WGET_STATUSBAR } else { curfile = get_last_path_component(fname_out); #endif @@ -316,7 +316,7 @@ int wget_main(int argc, char **argv) fprintf(sfp, "Host: %s\r\nUser-Agent: Wget\r\n", target.host); -#ifdef BB_FEATURE_WGET_AUTHENTICATION +#ifdef CONFIG_FEATURE_WGET_AUTHENTICATION if (target.user) { fprintf(sfp, "Authorization: Basic %s\r\n", base64enc(target.user, buf, sizeof(buf))); @@ -475,14 +475,14 @@ read_response: if (fgets(buf, sizeof(buf), sfp) == NULL) fgets(buf, sizeof(buf), dfp); filesize = strtol(buf, (char **) NULL, 16); } -#ifdef BB_FEATURE_WGET_STATUSBAR +#ifdef CONFIG_FEATURE_WGET_STATUSBAR if (quiet_flag==FALSE) progressmeter(-1); #endif do { while ((filesize > 0 || !got_clen) && (n = safe_fread(buf, 1, chunked ? (filesize > sizeof(buf) ? sizeof(buf) : filesize) : sizeof(buf), dfp)) > 0) { safe_fwrite(buf, 1, n, output); -#ifdef BB_FEATURE_WGET_STATUSBAR +#ifdef CONFIG_FEATURE_WGET_STATUSBAR statbytes+=n; #endif if (got_clen) @@ -499,7 +499,7 @@ read_response: if (fgets(buf, sizeof(buf), sfp) == NULL) if (n == 0 && ferror(dfp)) perror_msg_and_die("network read error"); } while (chunked); -#ifdef BB_FEATURE_WGET_STATUSBAR +#ifdef CONFIG_FEATURE_WGET_STATUSBAR if (quiet_flag==FALSE) progressmeter(1); #endif @@ -645,7 +645,7 @@ static int ftpcmd(char *s1, char *s2, FILE *fp, char *buf) return atoi(buf); } -#ifdef BB_FEATURE_WGET_STATUSBAR +#ifdef CONFIG_FEATURE_WGET_STATUSBAR /* Stuff below is from BSD rcp util.c, as added to openshh. * Original copyright notice is retained at the end of this file. * @@ -782,7 +782,7 @@ progressmeter(int flag) } #endif -/* Original copyright notice which applies to the BB_FEATURE_WGET_STATUSBAR stuff, +/* Original copyright notice which applies to the CONFIG_FEATURE_WGET_STATUSBAR stuff, * much of which was blatently stolen from openssh. */ /*- @@ -817,7 +817,7 @@ progressmeter(int flag) * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: wget.c,v 1.45 2001/07/19 22:28:01 andersen Exp $ + * $Id: wget.c,v 1.46 2001/10/24 04:59:56 andersen Exp $ */ diff --git a/nfsmount.c b/nfsmount.c deleted file mode 100644 index cd722acc3..000000000 --- a/nfsmount.c +++ /dev/null @@ -1,977 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * nfsmount.c -- Linux NFS mount - * Copyright (C) 1993 Rick Sladkey - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * Wed Feb 8 12:51:48 1995, biro@yggdrasil.com (Ross Biro): allow all port - * numbers to be specified on the command line. - * - * Fri, 8 Mar 1996 18:01:39, Swen Thuemmler : - * Omit the call to connect() for Linux version 1.3.11 or later. - * - * Wed Oct 1 23:55:28 1997: Dick Streefland - * Implemented the "bg", "fg" and "retry" mount options for NFS. - * - * 1999-02-22 Arkadiusz Mi¶kiewicz - * - added Native Language Support - * - * Modified by Olaf Kirch and Trond Myklebust for new NFS code, - * plus NFSv3 stuff. - */ - -/* - * nfsmount.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" -#undef TRUE -#undef FALSE -#include -#include -#include -#include /* For the kernels nfs stuff */ -#include "nfsmount.h" - -#ifndef NFS_FHSIZE -static const int NFS_FHSIZE = 32; -#endif -#ifndef NFS_PORT -static const int NFS_PORT = 2049; -#endif - -/* Disable the nls stuff */ -# undef bindtextdomain -# define bindtextdomain(Domain, Directory) /* empty */ -# undef textdomain -# define textdomain(Domain) /* empty */ -# define _(Text) (Text) -# define N_(Text) (Text) - -static const int MS_MGC_VAL = 0xc0ed0000; /* Magic number indicatng "new" flags */ -static const int MS_RDONLY = 1; /* Mount read-only */ -static const int MS_NOSUID = 2; /* Ignore suid and sgid bits */ -static const int MS_NODEV = 4; /* Disallow access to device special files */ -static const int MS_NOEXEC = 8; /* Disallow program execution */ -static const int MS_SYNCHRONOUS = 16; /* Writes are synced at once */ -static const int MS_REMOUNT = 32; /* Alter flags of a mounted FS */ -static const int MS_MANDLOCK = 64; /* Allow mandatory locks on an FS */ -static const int S_QUOTA = 128; /* Quota initialized for file/directory/symlink */ -static const int S_APPEND = 256; /* Append-only file */ -static const int S_IMMUTABLE = 512; /* Immutable file */ -static const int MS_NOATIME = 1024; /* Do not update access times. */ -static const int MS_NODIRATIME = 2048; /* Do not update directory access times */ - - -/* - * We want to be able to compile mount on old kernels in such a way - * that the binary will work well on more recent kernels. - * Thus, if necessary we teach nfsmount.c the structure of new fields - * that will come later. - * - * Moreover, the new kernel includes conflict with glibc includes - * so it is easiest to ignore the kernel altogether (at compile time). - */ - -/* NOTE: Do not make this into a 'static const int' because the pre-processor - * needs to test this value in some #if statements. */ -#define NFS_MOUNT_VERSION 4 - -struct nfs2_fh { - char data[32]; -}; -struct nfs3_fh { - unsigned short size; - unsigned char data[64]; -}; - -struct nfs_mount_data { - int version; /* 1 */ - int fd; /* 1 */ - struct nfs2_fh old_root; /* 1 */ - int flags; /* 1 */ - int rsize; /* 1 */ - int wsize; /* 1 */ - int timeo; /* 1 */ - int retrans; /* 1 */ - int acregmin; /* 1 */ - int acregmax; /* 1 */ - int acdirmin; /* 1 */ - int acdirmax; /* 1 */ - struct sockaddr_in addr; /* 1 */ - char hostname[256]; /* 1 */ - int namlen; /* 2 */ - unsigned int bsize; /* 3 */ - struct nfs3_fh root; /* 4 */ -}; - -/* bits in the flags field */ - -static const int NFS_MOUNT_SOFT = 0x0001; /* 1 */ -static const int NFS_MOUNT_INTR = 0x0002; /* 1 */ -static const int NFS_MOUNT_SECURE = 0x0004; /* 1 */ -static const int NFS_MOUNT_POSIX = 0x0008; /* 1 */ -static const int NFS_MOUNT_NOCTO = 0x0010; /* 1 */ -static const int NFS_MOUNT_NOAC = 0x0020; /* 1 */ -static const int NFS_MOUNT_TCP = 0x0040; /* 2 */ -static const int NFS_MOUNT_VER3 = 0x0080; /* 3 */ -static const int NFS_MOUNT_KERBEROS = 0x0100; /* 3 */ -static const int NFS_MOUNT_NONLM = 0x0200; /* 3 */ - - -#define UTIL_LINUX_VERSION "2.10m" -#define util_linux_version "util-linux-2.10m" - -#define HAVE_inet_aton -#define HAVE_scsi_h -#define HAVE_blkpg_h -#define HAVE_kd_h -#define HAVE_termcap -#define HAVE_locale_h -#define HAVE_libintl_h -#define ENABLE_NLS -#define HAVE_langinfo_h -#define HAVE_progname -#define HAVE_openpty -#define HAVE_nanosleep -#define HAVE_personality -#define HAVE_tm_gmtoff - -static char *nfs_strerror(int status); - -#define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r)) -#define MAX_NFSPROT ((nfs_mount_version >= 4) ? 3 : 2) - -static const int EX_FAIL = 32; /* mount failure */ -static const int EX_BG = 256; /* retry in background (internal only) */ - - -/* - * nfs_mount_version according to the sources seen at compile time. - */ -static int nfs_mount_version; - -/* - * Unfortunately, the kernel prints annoying console messages - * in case of an unexpected nfs mount version (instead of - * just returning some error). Therefore we'll have to try - * and figure out what version the kernel expects. - * - * Variables: - * KERNEL_NFS_MOUNT_VERSION: kernel sources at compile time - * NFS_MOUNT_VERSION: these nfsmount sources at compile time - * nfs_mount_version: version this source and running kernel can handle - */ -static void -find_kernel_nfs_mount_version(void) -{ - static int kernel_version = 0; - - if (kernel_version) - return; - - nfs_mount_version = NFS_MOUNT_VERSION; /* default */ - - kernel_version = get_kernel_revision(); - if (kernel_version) { - if (kernel_version < MAKE_VERSION(2,1,32)) - nfs_mount_version = 1; - else if (kernel_version < MAKE_VERSION(2,2,18) || - (kernel_version >= MAKE_VERSION(2,3,0) && - kernel_version < MAKE_VERSION(2,3,99))) - nfs_mount_version = 3; - else - nfs_mount_version = 4; /* since 2.3.99pre4 */ - } - if (nfs_mount_version > NFS_MOUNT_VERSION) - nfs_mount_version = NFS_MOUNT_VERSION; -} - -static struct pmap * -get_mountport(struct sockaddr_in *server_addr, - long unsigned prog, - long unsigned version, - long unsigned proto, - long unsigned port) -{ -struct pmaplist *pmap; -static struct pmap p = {0, 0, 0, 0}; - -server_addr->sin_port = PMAPPORT; -pmap = pmap_getmaps(server_addr); - -if (version > MAX_NFSPROT) - version = MAX_NFSPROT; -if (!prog) - prog = MOUNTPROG; -p.pm_prog = prog; -p.pm_vers = version; -p.pm_prot = proto; -p.pm_port = port; - -while (pmap) { - if (pmap->pml_map.pm_prog != prog) - goto next; - if (!version && p.pm_vers > pmap->pml_map.pm_vers) - goto next; - if (version > 2 && pmap->pml_map.pm_vers != version) - goto next; - if (version && version <= 2 && pmap->pml_map.pm_vers > 2) - goto next; - if (pmap->pml_map.pm_vers > MAX_NFSPROT || - (proto && p.pm_prot && pmap->pml_map.pm_prot != proto) || - (port && pmap->pml_map.pm_port != port)) - goto next; - memcpy(&p, &pmap->pml_map, sizeof(p)); -next: - pmap = pmap->pml_next; -} -if (!p.pm_vers) - p.pm_vers = MOUNTVERS; -if (!p.pm_port) - p.pm_port = MOUNTPORT; -if (!p.pm_prot) - p.pm_prot = IPPROTO_TCP; -return &p; -} - -int nfsmount(const char *spec, const char *node, int *flags, - char **extra_opts, char **mount_opts, int running_bg) -{ - static char *prev_bg_host; - char hostdir[1024]; - CLIENT *mclient; - char *hostname; - char *pathname; - char *old_opts; - char *mounthost=NULL; - char new_opts[1024]; - struct timeval total_timeout; - enum clnt_stat clnt_stat; - static struct nfs_mount_data data; - char *opt, *opteq; - int val; - struct hostent *hp; - struct sockaddr_in server_addr; - struct sockaddr_in mount_server_addr; - struct pmap* pm_mnt; - int msock, fsock; - struct timeval retry_timeout; - union { - struct fhstatus nfsv2; - struct mountres3 nfsv3; - } status; - struct stat statbuf; - char *s; - int port; - int mountport; - int proto; - int bg; - int soft; - int intr; - int posix; - int nocto; - int noac; - int nolock; - int retry; - int tcp; - int mountprog; - int mountvers; - int nfsprog; - int nfsvers; - int retval; - time_t t; - time_t prevt; - time_t timeout; - - find_kernel_nfs_mount_version(); - - retval = EX_FAIL; - msock = fsock = -1; - mclient = NULL; - if (strlen(spec) >= sizeof(hostdir)) { - error_msg("excessively long host:dir argument"); - goto fail; - } - strcpy(hostdir, spec); - if ((s = strchr(hostdir, ':'))) { - hostname = hostdir; - pathname = s + 1; - *s = '\0'; - /* Ignore all but first hostname in replicated mounts - until they can be fully supported. (mack@sgi.com) */ - if ((s = strchr(hostdir, ','))) { - *s = '\0'; - error_msg("warning: multiple hostnames not supported"); - } - } else { - error_msg("directory to mount not in host:dir format"); - goto fail; - } - - server_addr.sin_family = AF_INET; -#ifdef HAVE_inet_aton - if (!inet_aton(hostname, &server_addr.sin_addr)) -#endif - { - if ((hp = gethostbyname(hostname)) == NULL) { - herror_msg("%s", hostname); - goto fail; - } else { - if (hp->h_length > sizeof(struct in_addr)) { - error_msg("got bad hp->h_length"); - hp->h_length = sizeof(struct in_addr); - } - memcpy(&server_addr.sin_addr, - hp->h_addr, hp->h_length); - } - } - - memcpy (&mount_server_addr, &server_addr, sizeof (mount_server_addr)); - - /* add IP address to mtab options for use when unmounting */ - - s = inet_ntoa(server_addr.sin_addr); - old_opts = *extra_opts; - if (!old_opts) - old_opts = ""; - if (strlen(old_opts) + strlen(s) + 10 >= sizeof(new_opts)) { - error_msg("excessively long option argument"); - goto fail; - } - sprintf(new_opts, "%s%saddr=%s", - old_opts, *old_opts ? "," : "", s); - *extra_opts = xstrdup(new_opts); - - /* Set default options. - * rsize/wsize (and bsize, for ver >= 3) are left 0 in order to - * let the kernel decide. - * timeo is filled in after we know whether it'll be TCP or UDP. */ - memset(&data, 0, sizeof(data)); - data.retrans = 3; - data.acregmin = 3; - data.acregmax = 60; - data.acdirmin = 30; - data.acdirmax = 60; -#if NFS_MOUNT_VERSION >= 2 - data.namlen = NAME_MAX; -#endif - - bg = 0; - soft = 0; - intr = 0; - posix = 0; - nocto = 0; - nolock = 0; - noac = 0; - retry = 10000; /* 10000 minutes ~ 1 week */ - tcp = 0; - - mountprog = MOUNTPROG; - mountvers = 0; - port = 0; - mountport = 0; - nfsprog = NFS_PROGRAM; - nfsvers = 0; - - /* parse options */ - - for (opt = strtok(old_opts, ","); opt; opt = strtok(NULL, ",")) { - if ((opteq = strchr(opt, '='))) { - val = atoi(opteq + 1); - *opteq = '\0'; - if (!strcmp(opt, "rsize")) - data.rsize = val; - else if (!strcmp(opt, "wsize")) - data.wsize = val; - else if (!strcmp(opt, "timeo")) - data.timeo = val; - else if (!strcmp(opt, "retrans")) - data.retrans = val; - else if (!strcmp(opt, "acregmin")) - data.acregmin = val; - else if (!strcmp(opt, "acregmax")) - data.acregmax = val; - else if (!strcmp(opt, "acdirmin")) - data.acdirmin = val; - else if (!strcmp(opt, "acdirmax")) - data.acdirmax = val; - else if (!strcmp(opt, "actimeo")) { - data.acregmin = val; - data.acregmax = val; - data.acdirmin = val; - data.acdirmax = val; - } - else if (!strcmp(opt, "retry")) - retry = val; - else if (!strcmp(opt, "port")) - port = val; - else if (!strcmp(opt, "mountport")) - mountport = val; - else if (!strcmp(opt, "mounthost")) - mounthost=xstrndup(opteq+1, - strcspn(opteq+1," \t\n\r,")); - else if (!strcmp(opt, "mountprog")) - mountprog = val; - else if (!strcmp(opt, "mountvers")) - mountvers = val; - else if (!strcmp(opt, "nfsprog")) - nfsprog = val; - else if (!strcmp(opt, "nfsvers") || - !strcmp(opt, "vers")) - nfsvers = val; - else if (!strcmp(opt, "proto")) { - if (!strncmp(opteq+1, "tcp", 3)) - tcp = 1; - else if (!strncmp(opteq+1, "udp", 3)) - tcp = 0; - else - printf(_("Warning: Unrecognized proto= option.\n")); - } else if (!strcmp(opt, "namlen")) { -#if NFS_MOUNT_VERSION >= 2 - if (nfs_mount_version >= 2) - data.namlen = val; - else -#endif - printf(_("Warning: Option namlen is not supported.\n")); - } else if (!strcmp(opt, "addr")) - /* ignore */; - else { - printf(_("unknown nfs mount parameter: " - "%s=%d\n"), opt, val); - goto fail; - } - } - else { - val = 1; - if (!strncmp(opt, "no", 2)) { - val = 0; - opt += 2; - } - if (!strcmp(opt, "bg")) - bg = val; - else if (!strcmp(opt, "fg")) - bg = !val; - else if (!strcmp(opt, "soft")) - soft = val; - else if (!strcmp(opt, "hard")) - soft = !val; - else if (!strcmp(opt, "intr")) - intr = val; - else if (!strcmp(opt, "posix")) - posix = val; - else if (!strcmp(opt, "cto")) - nocto = !val; - else if (!strcmp(opt, "ac")) - noac = !val; - else if (!strcmp(opt, "tcp")) - tcp = val; - else if (!strcmp(opt, "udp")) - tcp = !val; - else if (!strcmp(opt, "lock")) { - if (nfs_mount_version >= 3) - nolock = !val; - else - printf(_("Warning: option nolock is not supported.\n")); - } else { - printf(_("unknown nfs mount option: " - "%s%s\n"), val ? "" : "no", opt); - goto fail; - } - } - } - proto = (tcp) ? IPPROTO_TCP : IPPROTO_UDP; - - data.flags = (soft ? NFS_MOUNT_SOFT : 0) - | (intr ? NFS_MOUNT_INTR : 0) - | (posix ? NFS_MOUNT_POSIX : 0) - | (nocto ? NFS_MOUNT_NOCTO : 0) - | (noac ? NFS_MOUNT_NOAC : 0); -#if NFS_MOUNT_VERSION >= 2 - if (nfs_mount_version >= 2) - data.flags |= (tcp ? NFS_MOUNT_TCP : 0); -#endif -#if NFS_MOUNT_VERSION >= 3 - if (nfs_mount_version >= 3) - data.flags |= (nolock ? NFS_MOUNT_NONLM : 0); -#endif - if (nfsvers > MAX_NFSPROT) { - error_msg("NFSv%d not supported!", nfsvers); - return 0; - } - if (mountvers > MAX_NFSPROT) { - error_msg("NFSv%d not supported!", nfsvers); - return 0; - } - if (nfsvers && !mountvers) - mountvers = (nfsvers < 3) ? 1 : nfsvers; - if (nfsvers && nfsvers < mountvers) { - mountvers = nfsvers; - } - - /* Adjust options if none specified */ - if (!data.timeo) - data.timeo = tcp ? 70 : 7; - -#ifdef NFS_MOUNT_DEBUG - printf("rsize = %d, wsize = %d, timeo = %d, retrans = %d\n", - data.rsize, data.wsize, data.timeo, data.retrans); - printf("acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)\n", - data.acregmin, data.acregmax, data.acdirmin, data.acdirmax); - printf("port = %d, bg = %d, retry = %d, flags = %.8x\n", - port, bg, retry, data.flags); - printf("mountprog = %d, mountvers = %d, nfsprog = %d, nfsvers = %d\n", - mountprog, mountvers, nfsprog, nfsvers); - printf("soft = %d, intr = %d, posix = %d, nocto = %d, noac = %d\n", - (data.flags & NFS_MOUNT_SOFT) != 0, - (data.flags & NFS_MOUNT_INTR) != 0, - (data.flags & NFS_MOUNT_POSIX) != 0, - (data.flags & NFS_MOUNT_NOCTO) != 0, - (data.flags & NFS_MOUNT_NOAC) != 0); -#if NFS_MOUNT_VERSION >= 2 - printf("tcp = %d\n", - (data.flags & NFS_MOUNT_TCP) != 0); -#endif -#endif - - data.version = nfs_mount_version; - *mount_opts = (char *) &data; - - if (*flags & MS_REMOUNT) - return 0; - - /* - * If the previous mount operation on the same host was - * backgrounded, and the "bg" for this mount is also set, - * give up immediately, to avoid the initial timeout. - */ - if (bg && !running_bg && - prev_bg_host && strcmp(hostname, prev_bg_host) == 0) { - if (retry > 0) - retval = EX_BG; - return retval; - } - - /* create mount deamon client */ - /* See if the nfs host = mount host. */ - if (mounthost) { - if (mounthost[0] >= '0' && mounthost[0] <= '9') { - mount_server_addr.sin_family = AF_INET; - mount_server_addr.sin_addr.s_addr = inet_addr(hostname); - } else { - if ((hp = gethostbyname(mounthost)) == NULL) { - herror_msg("%s", mounthost); - goto fail; - } else { - if (hp->h_length > sizeof(struct in_addr)) { - error_msg("got bad hp->h_length?"); - hp->h_length = sizeof(struct in_addr); - } - mount_server_addr.sin_family = AF_INET; - memcpy(&mount_server_addr.sin_addr, - hp->h_addr, hp->h_length); - } - } - } - - /* - * The following loop implements the mount retries. On the first - * call, "running_bg" is 0. When the mount times out, and the - * "bg" option is set, the exit status EX_BG will be returned. - * For a backgrounded mount, there will be a second call by the - * child process with "running_bg" set to 1. - * - * The case where the mount point is not present and the "bg" - * option is set, is treated as a timeout. This is done to - * support nested mounts. - * - * The "retry" count specified by the user is the number of - * minutes to retry before giving up. - * - * Only the first error message will be displayed. - */ - retry_timeout.tv_sec = 3; - retry_timeout.tv_usec = 0; - total_timeout.tv_sec = 20; - total_timeout.tv_usec = 0; - timeout = time(NULL) + 60 * retry; - prevt = 0; - t = 30; - val = 1; - for (;;) { - if (bg && stat(node, &statbuf) == -1) { - if (running_bg) { - sleep(val); /* 1, 2, 4, 8, 16, 30, ... */ - val *= 2; - if (val > 30) - val = 30; - } - } else { - /* be careful not to use too many CPU cycles */ - if (t - prevt < 30) - sleep(30); - - pm_mnt = get_mountport(&mount_server_addr, - mountprog, - mountvers, - proto, - mountport); - - /* contact the mount daemon via TCP */ - mount_server_addr.sin_port = htons(pm_mnt->pm_port); - msock = RPC_ANYSOCK; - - switch (pm_mnt->pm_prot) { - case IPPROTO_UDP: - mclient = clntudp_create(&mount_server_addr, - pm_mnt->pm_prog, - pm_mnt->pm_vers, - retry_timeout, - &msock); - if (mclient) - break; - mount_server_addr.sin_port = htons(pm_mnt->pm_port); - msock = RPC_ANYSOCK; - case IPPROTO_TCP: - mclient = clnttcp_create(&mount_server_addr, - pm_mnt->pm_prog, - pm_mnt->pm_vers, - &msock, 0, 0); - break; - default: - mclient = 0; - } - if (mclient) { - /* try to mount hostname:pathname */ - mclient->cl_auth = authunix_create_default(); - - /* make pointers in xdr_mountres3 NULL so - * that xdr_array allocates memory for us - */ - memset(&status, 0, sizeof(status)); - - if (pm_mnt->pm_vers == 3) - clnt_stat = clnt_call(mclient, MOUNTPROC3_MNT, - (xdrproc_t) xdr_dirpath, - (caddr_t) &pathname, - (xdrproc_t) xdr_mountres3, - (caddr_t) &status, - total_timeout); - else - clnt_stat = clnt_call(mclient, MOUNTPROC_MNT, - (xdrproc_t) xdr_dirpath, - (caddr_t) &pathname, - (xdrproc_t) xdr_fhstatus, - (caddr_t) &status, - total_timeout); - - if (clnt_stat == RPC_SUCCESS) - break; /* we're done */ - if (errno != ECONNREFUSED) { - clnt_perror(mclient, "mount"); - goto fail; /* don't retry */ - } - if (!running_bg && prevt == 0) - clnt_perror(mclient, "mount"); - auth_destroy(mclient->cl_auth); - clnt_destroy(mclient); - mclient = 0; - close(msock); - } else { - if (!running_bg && prevt == 0) - clnt_pcreateerror("mount"); - } - prevt = t; - } - if (!bg) - goto fail; - if (!running_bg) { - prev_bg_host = xstrdup(hostname); - if (retry > 0) - retval = EX_BG; - goto fail; - } - t = time(NULL); - if (t >= timeout) - goto fail; - } - nfsvers = (pm_mnt->pm_vers < 2) ? 2 : pm_mnt->pm_vers; - - if (nfsvers == 2) { - if (status.nfsv2.fhs_status != 0) { - error_msg("%s:%s failed, reason given by server: %s", - hostname, pathname, - nfs_strerror(status.nfsv2.fhs_status)); - goto fail; - } - memcpy(data.root.data, - (char *) status.nfsv2.fhstatus_u.fhs_fhandle, - NFS_FHSIZE); -#if NFS_MOUNT_VERSION >= 4 - data.root.size = NFS_FHSIZE; - memcpy(data.old_root.data, - (char *) status.nfsv2.fhstatus_u.fhs_fhandle, - NFS_FHSIZE); -#endif - } else { -#if NFS_MOUNT_VERSION >= 4 - fhandle3 *my_fhandle; - if (status.nfsv3.fhs_status != 0) { - error_msg("%s:%s failed, reason given by server: %s", - hostname, pathname, - nfs_strerror(status.nfsv3.fhs_status)); - goto fail; - } - my_fhandle = &status.nfsv3.mountres3_u.mountinfo.fhandle; - memset(data.old_root.data, 0, NFS_FHSIZE); - memset(&data.root, 0, sizeof(data.root)); - data.root.size = my_fhandle->fhandle3_len; - memcpy(data.root.data, - (char *) my_fhandle->fhandle3_val, - my_fhandle->fhandle3_len); - - data.flags |= NFS_MOUNT_VER3; -#endif - } - - /* create nfs socket for kernel */ - - if (tcp) { - if (nfs_mount_version < 3) { - printf(_("NFS over TCP is not supported.\n")); - goto fail; - } - fsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - } else - fsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (fsock < 0) { - perror(_("nfs socket")); - goto fail; - } - if (bindresvport(fsock, 0) < 0) { - perror(_("nfs bindresvport")); - goto fail; - } - if (port == 0) { - server_addr.sin_port = PMAPPORT; - port = pmap_getport(&server_addr, nfsprog, nfsvers, - tcp ? IPPROTO_TCP : IPPROTO_UDP); - if (port == 0) - port = NFS_PORT; -#ifdef NFS_MOUNT_DEBUG - else - printf(_("used portmapper to find NFS port\n")); -#endif - } -#ifdef NFS_MOUNT_DEBUG - printf(_("using port %d for nfs deamon\n"), port); -#endif - server_addr.sin_port = htons(port); - /* - * connect() the socket for kernels 1.3.10 and below only, - * to avoid problems with multihomed hosts. - * --Swen - */ - if (get_kernel_revision() <= 66314 - && connect(fsock, (struct sockaddr *) &server_addr, - sizeof (server_addr)) < 0) { - perror(_("nfs connect")); - goto fail; - } - - /* prepare data structure for kernel */ - - data.fd = fsock; - memcpy((char *) &data.addr, (char *) &server_addr, sizeof(data.addr)); - strncpy(data.hostname, hostname, sizeof(data.hostname)); - - /* clean up */ - - auth_destroy(mclient->cl_auth); - clnt_destroy(mclient); - close(msock); - return 0; - - /* abort */ - -fail: - if (msock != -1) { - if (mclient) { - auth_destroy(mclient->cl_auth); - clnt_destroy(mclient); - } - close(msock); - } - if (fsock != -1) - close(fsock); - return retval; -} - -/* - * We need to translate between nfs status return values and - * the local errno values which may not be the same. - * - * Andreas Schwab : change errno: - * "after #include the symbol errno is reserved for any use, - * it cannot even be used as a struct tag or field name". - */ - -#ifndef EDQUOT -#define EDQUOT ENOSPC -#endif - -static struct { - enum nfs_stat stat; - int errnum; -} nfs_errtbl[] = { - { NFS_OK, 0 }, - { NFSERR_PERM, EPERM }, - { NFSERR_NOENT, ENOENT }, - { NFSERR_IO, EIO }, - { NFSERR_NXIO, ENXIO }, - { NFSERR_ACCES, EACCES }, - { NFSERR_EXIST, EEXIST }, - { NFSERR_NODEV, ENODEV }, - { NFSERR_NOTDIR, ENOTDIR }, - { NFSERR_ISDIR, EISDIR }, -#ifdef NFSERR_INVAL - { NFSERR_INVAL, EINVAL }, /* that Sun forgot */ -#endif - { NFSERR_FBIG, EFBIG }, - { NFSERR_NOSPC, ENOSPC }, - { NFSERR_ROFS, EROFS }, - { NFSERR_NAMETOOLONG, ENAMETOOLONG }, - { NFSERR_NOTEMPTY, ENOTEMPTY }, - { NFSERR_DQUOT, EDQUOT }, - { NFSERR_STALE, ESTALE }, -#ifdef EWFLUSH - { NFSERR_WFLUSH, EWFLUSH }, -#endif - /* Throw in some NFSv3 values for even more fun (HP returns these) */ - { 71, EREMOTE }, - - { -1, EIO } -}; - -static char *nfs_strerror(int status) -{ - int i; - static char buf[256]; - - for (i = 0; nfs_errtbl[i].stat != -1; i++) { - if (nfs_errtbl[i].stat == status) - return strerror(nfs_errtbl[i].errnum); - } - sprintf(buf, _("unknown nfs status return value: %d"), status); - return buf; -} - -static bool_t -xdr_fhandle (XDR *xdrs, fhandle objp) -{ - //register int32_t *buf; - - if (!xdr_opaque (xdrs, objp, FHSIZE)) - return FALSE; - return TRUE; -} - -bool_t -xdr_fhstatus (XDR *xdrs, fhstatus *objp) -{ - //register int32_t *buf; - - if (!xdr_u_int (xdrs, &objp->fhs_status)) - return FALSE; - switch (objp->fhs_status) { - case 0: - if (!xdr_fhandle (xdrs, objp->fhstatus_u.fhs_fhandle)) - return FALSE; - break; - default: - break; - } - return TRUE; -} - -bool_t -xdr_dirpath (XDR *xdrs, dirpath *objp) -{ - //register int32_t *buf; - - if (!xdr_string (xdrs, objp, MNTPATHLEN)) - return FALSE; - return TRUE; -} - -bool_t -xdr_fhandle3 (XDR *xdrs, fhandle3 *objp) -{ - //register int32_t *buf; - - if (!xdr_bytes (xdrs, (char **)&objp->fhandle3_val, (u_int *) &objp->fhandle3_len, FHSIZE3)) - return FALSE; - return TRUE; -} - -bool_t -xdr_mountres3_ok (XDR *xdrs, mountres3_ok *objp) -{ - //register int32_t *buf; - - if (!xdr_fhandle3 (xdrs, &objp->fhandle)) - return FALSE; - if (!xdr_array (xdrs, (char **)&objp->auth_flavours.auth_flavours_val, (u_int *) &objp->auth_flavours.auth_flavours_len, ~0, - sizeof (int), (xdrproc_t) xdr_int)) - return FALSE; - return TRUE; -} - -bool_t -xdr_mountstat3 (XDR *xdrs, mountstat3 *objp) -{ - //register int32_t *buf; - - if (!xdr_enum (xdrs, (enum_t *) objp)) - return FALSE; - return TRUE; -} - -bool_t -xdr_mountres3 (XDR *xdrs, mountres3 *objp) -{ - //register int32_t *buf; - - if (!xdr_mountstat3 (xdrs, &objp->fhs_status)) - return FALSE; - switch (objp->fhs_status) { - case MNT_OK: - if (!xdr_mountres3_ok (xdrs, &objp->mountres3_u.mountinfo)) - return FALSE; - break; - default: - break; - } - return TRUE; -} - diff --git a/nfsmount.h b/nfsmount.h deleted file mode 100644 index b3d5a51e6..000000000 --- a/nfsmount.h +++ /dev/null @@ -1,242 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * This file was originally generated using rpcgen. - * But now we edit it by hand as needed to make it - * shut up... - */ - -#ifndef _NFSMOUNT_H_RPCGEN -#define _NFSMOUNT_H_RPCGEN - -#include - - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Sun RPC is a product of Sun Microsystems, Inc. and is provided for - * unrestricted use provided that this legend is included on all tape - * media and as a part of the software program in whole or part. Users - * may copy or modify Sun RPC without charge, but are not authorized - * to license or distribute it to anyone else except as part of a product or - * program developed by the user or with the express written consent of - * Sun Microsystems, Inc. - * - * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE - * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR - * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - * - * Sun RPC is provided with no support and without any obligation on the - * part of Sun Microsystems, Inc. to assist in its use, correction, - * modification or enhancement. - * - * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE - * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC - * OR ANY PART THEREOF. - * - * In no event will Sun Microsystems, Inc. be liable for any lost revenue - * or profits or other special, indirect and consequential damages, even if - * Sun has been advised of the possibility of such damages. - * - * Sun Microsystems, Inc. - * 2550 Garcia Avenue - * Mountain View, California 94043 - */ -/* - * Copyright (c) 1985, 1990 by Sun Microsystems, Inc. - */ - -/* from @(#)mount.x 1.3 91/03/11 TIRPC 1.0 */ -#ifndef _rpcsvc_mount_h -#define _rpcsvc_mount_h -#include -#define MOUNTPORT 635 -#define MNTPATHLEN 1024 -#define MNTNAMLEN 255 -#define FHSIZE 32 -#define FHSIZE3 64 - -typedef char fhandle[FHSIZE]; - -typedef struct { - u_int fhandle3_len; - char *fhandle3_val; -} fhandle3; - -enum mountstat3 { - MNT_OK = 0, - MNT3ERR_PERM = 1, - MNT3ERR_NOENT = 2, - MNT3ERR_IO = 5, - MNT3ERR_ACCES = 13, - MNT3ERR_NOTDIR = 20, - MNT3ERR_INVAL = 22, - MNT3ERR_NAMETOOLONG = 63, - MNT3ERR_NOTSUPP = 10004, - MNT3ERR_SERVERFAULT = 10006, -}; -typedef enum mountstat3 mountstat3; - -struct fhstatus { - u_int fhs_status; - union { - fhandle fhs_fhandle; - } fhstatus_u; -}; -typedef struct fhstatus fhstatus; - -struct mountres3_ok { - fhandle3 fhandle; - struct { - u_int auth_flavours_len; - int *auth_flavours_val; - } auth_flavours; -}; -typedef struct mountres3_ok mountres3_ok; - -struct mountres3 { - mountstat3 fhs_status; - union { - mountres3_ok mountinfo; - } mountres3_u; -}; -typedef struct mountres3 mountres3; - -typedef char *dirpath; - -typedef char *name; - -typedef struct mountbody *mountlist; - -struct mountbody { - name ml_hostname; - dirpath ml_directory; - mountlist ml_next; -}; -typedef struct mountbody mountbody; - -typedef struct groupnode *groups; - -struct groupnode { - name gr_name; - groups gr_next; -}; -typedef struct groupnode groupnode; - -typedef struct exportnode *exports; - -struct exportnode { - dirpath ex_dir; - groups ex_groups; - exports ex_next; -}; -typedef struct exportnode exportnode; - -struct ppathcnf { - int pc_link_max; - short pc_max_canon; - short pc_max_input; - short pc_name_max; - short pc_path_max; - short pc_pipe_buf; - u_char pc_vdisable; - char pc_xxx; - short pc_mask[2]; -}; -typedef struct ppathcnf ppathcnf; -#endif /*!_rpcsvc_mount_h*/ - -#define MOUNTPROG 100005 -#define MOUNTVERS 1 - -#define MOUNTPROC_NULL 0 -extern void * mountproc_null_1(void *, CLIENT *); -extern void * mountproc_null_1_svc(void *, struct svc_req *); -#define MOUNTPROC_MNT 1 -extern fhstatus * mountproc_mnt_1(dirpath *, CLIENT *); -extern fhstatus * mountproc_mnt_1_svc(dirpath *, struct svc_req *); -#define MOUNTPROC_DUMP 2 -extern mountlist * mountproc_dump_1(void *, CLIENT *); -extern mountlist * mountproc_dump_1_svc(void *, struct svc_req *); -#define MOUNTPROC_UMNT 3 -extern void * mountproc_umnt_1(dirpath *, CLIENT *); -extern void * mountproc_umnt_1_svc(dirpath *, struct svc_req *); -#define MOUNTPROC_UMNTALL 4 -extern void * mountproc_umntall_1(void *, CLIENT *); -extern void * mountproc_umntall_1_svc(void *, struct svc_req *); -#define MOUNTPROC_EXPORT 5 -extern exports * mountproc_export_1(void *, CLIENT *); -extern exports * mountproc_export_1_svc(void *, struct svc_req *); -#define MOUNTPROC_EXPORTALL 6 -extern exports * mountproc_exportall_1(void *, CLIENT *); -extern exports * mountproc_exportall_1_svc(void *, struct svc_req *); -extern int mountprog_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t); - -#define MOUNTVERS_POSIX 2 - -extern void * mountproc_null_2(void *, CLIENT *); -extern void * mountproc_null_2_svc(void *, struct svc_req *); -extern fhstatus * mountproc_mnt_2(dirpath *, CLIENT *); -extern fhstatus * mountproc_mnt_2_svc(dirpath *, struct svc_req *); -extern mountlist * mountproc_dump_2(void *, CLIENT *); -extern mountlist * mountproc_dump_2_svc(void *, struct svc_req *); -extern void * mountproc_umnt_2(dirpath *, CLIENT *); -extern void * mountproc_umnt_2_svc(dirpath *, struct svc_req *); -extern void * mountproc_umntall_2(void *, CLIENT *); -extern void * mountproc_umntall_2_svc(void *, struct svc_req *); -extern exports * mountproc_export_2(void *, CLIENT *); -extern exports * mountproc_export_2_svc(void *, struct svc_req *); -extern exports * mountproc_exportall_2(void *, CLIENT *); -extern exports * mountproc_exportall_2_svc(void *, struct svc_req *); -#define MOUNTPROC_PATHCONF 7 -extern ppathcnf * mountproc_pathconf_2(dirpath *, CLIENT *); -extern ppathcnf * mountproc_pathconf_2_svc(dirpath *, struct svc_req *); -extern int mountprog_2_freeresult (SVCXPRT *, xdrproc_t, caddr_t); - -#define MOUNT_V3 3 - -#define MOUNTPROC3_NULL 0 -extern void * mountproc3_null_3(void *, CLIENT *); -extern void * mountproc3_null_3_svc(void *, struct svc_req *); -#define MOUNTPROC3_MNT 1 -extern mountres3 * mountproc3_mnt_3(dirpath *, CLIENT *); -extern mountres3 * mountproc3_mnt_3_svc(dirpath *, struct svc_req *); -#define MOUNTPROC3_DUMP 2 -extern mountlist * mountproc3_dump_3(void *, CLIENT *); -extern mountlist * mountproc3_dump_3_svc(void *, struct svc_req *); -#define MOUNTPROC3_UMNT 3 -extern void * mountproc3_umnt_3(dirpath *, CLIENT *); -extern void * mountproc3_umnt_3_svc(dirpath *, struct svc_req *); -#define MOUNTPROC3_UMNTALL 4 -extern void * mountproc3_umntall_3(void *, CLIENT *); -extern void * mountproc3_umntall_3_svc(void *, struct svc_req *); -#define MOUNTPROC3_EXPORT 5 -extern exports * mountproc3_export_3(void *, CLIENT *); -extern exports * mountproc3_export_3_svc(void *, struct svc_req *); -extern int mountprog_3_freeresult (SVCXPRT *, xdrproc_t, caddr_t); - -/* the xdr functions */ - -static bool_t xdr_fhandle (XDR *, fhandle); -extern bool_t xdr_fhandle3 (XDR *, fhandle3*); -extern bool_t xdr_mountstat3 (XDR *, mountstat3*); -extern bool_t xdr_fhstatus (XDR *, fhstatus*); -extern bool_t xdr_mountres3_ok (XDR *, mountres3_ok*); -extern bool_t xdr_mountres3 (XDR *, mountres3*); -extern bool_t xdr_dirpath (XDR *, dirpath*); -extern bool_t xdr_name (XDR *, name*); -extern bool_t xdr_mountlist (XDR *, mountlist*); -extern bool_t xdr_mountbody (XDR *, mountbody*); -extern bool_t xdr_groups (XDR *, groups*); -extern bool_t xdr_groupnode (XDR *, groupnode*); -extern bool_t xdr_exports (XDR *, exports*); -extern bool_t xdr_exportnode (XDR *, exportnode*); -extern bool_t xdr_ppathcnf (XDR *, ppathcnf*); - -#ifdef __cplusplus -} -#endif - -#endif /* !_NFSMOUNT_H_RPCGEN */ diff --git a/nslookup.c b/nslookup.c deleted file mode 100644 index 3e32ca9c0..000000000 --- a/nslookup.c +++ /dev/null @@ -1,183 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini nslookup implementation for busybox - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by John Beppu - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include "busybox.h" - -/* - | I'm only implementing non-interactive mode; - | I totally forgot nslookup even had an interactive mode. - | - | [ TODO ] - | + find out how to use non-default name servers - */ - -/* only works for IPv4 */ -static int addr_fprint(char *addr) -{ - u_int8_t split[4]; - u_int32_t ip; - u_int32_t *x = (u_int32_t *) addr; - - ip = ntohl(*x); - split[0] = (ip & 0xff000000) >> 24; - split[1] = (ip & 0x00ff0000) >> 16; - split[2] = (ip & 0x0000ff00) >> 8; - split[3] = (ip & 0x000000ff); - printf("%d.%d.%d.%d", split[0], split[1], split[2], split[3]); - return 0; -} - -/* takes the NULL-terminated array h_addr_list, and - * prints its contents appropriately - */ -static int addr_list_fprint(char **h_addr_list) -{ - int i, j; - char *addr_string = (h_addr_list[1]) - ? "Addresses: " : "Address: "; - - printf("%s ", addr_string); - for (i = 0, j = 0; h_addr_list[i]; i++, j++) { - addr_fprint(h_addr_list[i]); - - /* real nslookup does this */ - if (j == 4) { - if (h_addr_list[i + 1]) { - printf("\n "); - } - j = 0; - } else { - if (h_addr_list[i + 1]) { - printf(", "); - } - } - - } - printf("\n"); - return 0; -} - -/* print the results as nslookup would */ -static struct hostent *hostent_fprint(struct hostent *host) -{ - if (host) { - printf("Name: %s\n", host->h_name); - addr_list_fprint(host->h_addr_list); - } else { - printf("*** Unknown host\n"); - } - return host; -} - -/* changes a c-string matching the perl regex \d+\.\d+\.\d+\.\d+ - * into a u_int32_t - */ -static u_int32_t str_to_addr(const char *addr) -{ - u_int32_t split[4]; - u_int32_t ip; - - sscanf(addr, "%d.%d.%d.%d", - &split[0], &split[1], &split[2], &split[3]); - - /* assuming sscanf worked */ - ip = (split[0] << 24) | - (split[1] << 16) | (split[2] << 8) | (split[3]); - - return htonl(ip); -} - -/* gethostbyaddr wrapper */ -static struct hostent *gethostbyaddr_wrapper(const char *address) -{ - struct in_addr addr; - - addr.s_addr = str_to_addr(address); - return gethostbyaddr((char *) &addr, 4, AF_INET); /* IPv4 only for now */ -} - -#ifdef __UCLIBC__ -#warning FIXME after fixing uClibc to define struct _res -static inline void server_print(void) -{ - printf("Server: %s\n", "default"); - printf("Address: %s\n\n", "default"); -} -#else -/* lookup the default nameserver and display it */ -static inline void server_print(void) -{ - struct sockaddr_in def = _res.nsaddr_list[0]; - char *ip = inet_ntoa(def.sin_addr); - - hostent_fprint(gethostbyaddr_wrapper(ip)); - printf("\n"); -} -#endif - -/* naive function to check whether char *s is an ip address */ -static int is_ip_address(const char *s) -{ - while (*s) { - if ((isdigit(*s)) || (*s == '.')) { - s++; - continue; - } - return 0; - } - return 1; -} - -/* ________________________________________________________________________ */ -int nslookup_main(int argc, char **argv) -{ - struct hostent *host; - - if (argc < 2 || *argv[1]=='-') { - show_usage(); - } - - res_init(); - server_print(); - if (is_ip_address(argv[1])) { - host = gethostbyaddr_wrapper(argv[1]); - } else { - host = xgethostbyname(argv[1]); - } - hostent_fprint(host); - return EXIT_SUCCESS; -} - -/* $Id: nslookup.c,v 1.25 2001/10/01 17:50:25 kraai Exp $ */ diff --git a/pidof.c b/pidof.c deleted file mode 100644 index 50dffd387..000000000 --- a/pidof.c +++ /dev/null @@ -1,79 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * pidof implementation for busybox - * - * Copyright (C) 2001 by Lineo, inc. - * Written by Erik Andersen , - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" - - -extern int pidof_main(int argc, char **argv) -{ - int opt; - - - /* do normal option parsing */ - while ((opt = getopt(argc, argv, "ne:f:")) > 0) { - switch (opt) { -#if 0 - case 'g': - break; - case 'e': - break; -#endif - default: - show_usage(); - } - } - - /* if we didn't get a process name, then we need to choke and die here */ - if (argv[optind] == NULL) - show_usage(); - - /* Looks like everything is set to go. */ - while(optind < argc) { - pid_t* pidList; - - pidList = find_pid_by_name( argv[optind]); - if (!pidList || *pidList<=0) { - break; - } - - for(; pidList && *pidList!=0; pidList++) { - printf("%ld ", (long)*pidList); - } - /* Note that we don't bother to free the memory - * allocated in find_pid_by_name(). It will be freed - * upon exit, so we can save a byte or two */ - optind++; - } - printf("\n"); - - return EXIT_SUCCESS; -} diff --git a/ping.c b/ping.c deleted file mode 100644 index 5ca5dd9e0..000000000 --- a/ping.c +++ /dev/null @@ -1,555 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * $Id: ping.c,v 1.46 2001/07/17 01:12:36 andersen Exp $ - * Mini ping implementation for busybox - * - * Copyright (C) 1999 by Randolph Chung - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * This version of ping is adapted from the ping in netkit-base 0.10, - * which is: - * - * Copyright (c) 1989 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Muuss. - * - * Original copyright notice is retained at the end of this file. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" - - -/* It turns out that libc5 doesn't have proper icmp support - * built into it header files, so we have to supplement it */ -#if __GNU_LIBRARY__ < 5 -static const int ICMP_MINLEN = 8; /* abs minimum */ - -struct icmp_ra_addr -{ - u_int32_t ira_addr; - u_int32_t ira_preference; -}; - - -struct icmp -{ - u_int8_t icmp_type; /* type of message, see below */ - u_int8_t icmp_code; /* type sub code */ - u_int16_t icmp_cksum; /* ones complement checksum of struct */ - union - { - u_char ih_pptr; /* ICMP_PARAMPROB */ - struct in_addr ih_gwaddr; /* gateway address */ - struct ih_idseq /* echo datagram */ - { - u_int16_t icd_id; - u_int16_t icd_seq; - } ih_idseq; - u_int32_t ih_void; - - /* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */ - struct ih_pmtu - { - u_int16_t ipm_void; - u_int16_t ipm_nextmtu; - } ih_pmtu; - - struct ih_rtradv - { - u_int8_t irt_num_addrs; - u_int8_t irt_wpa; - u_int16_t irt_lifetime; - } ih_rtradv; - } icmp_hun; -#define icmp_pptr icmp_hun.ih_pptr -#define icmp_gwaddr icmp_hun.ih_gwaddr -#define icmp_id icmp_hun.ih_idseq.icd_id -#define icmp_seq icmp_hun.ih_idseq.icd_seq -#define icmp_void icmp_hun.ih_void -#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void -#define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu -#define icmp_num_addrs icmp_hun.ih_rtradv.irt_num_addrs -#define icmp_wpa icmp_hun.ih_rtradv.irt_wpa -#define icmp_lifetime icmp_hun.ih_rtradv.irt_lifetime - union - { - struct - { - u_int32_t its_otime; - u_int32_t its_rtime; - u_int32_t its_ttime; - } id_ts; - struct - { - struct ip idi_ip; - /* options and then 64 bits of data */ - } id_ip; - struct icmp_ra_addr id_radv; - u_int32_t id_mask; - u_int8_t id_data[1]; - } icmp_dun; -#define icmp_otime icmp_dun.id_ts.its_otime -#define icmp_rtime icmp_dun.id_ts.its_rtime -#define icmp_ttime icmp_dun.id_ts.its_ttime -#define icmp_ip icmp_dun.id_ip.idi_ip -#define icmp_radv icmp_dun.id_radv -#define icmp_mask icmp_dun.id_mask -#define icmp_data icmp_dun.id_data -}; -#endif - -static const int DEFDATALEN = 56; -static const int MAXIPLEN = 60; -static const int MAXICMPLEN = 76; -static const int MAXPACKET = 65468; -#define MAX_DUP_CHK (8 * 128) -static const int MAXWAIT = 10; -static const int PINGINTERVAL = 1; /* second */ - -#define O_QUIET (1 << 0) - -#define A(bit) rcvd_tbl[(bit)>>3] /* identify byte in array */ -#define B(bit) (1 << ((bit) & 0x07)) /* identify bit in byte */ -#define SET(bit) (A(bit) |= B(bit)) -#define CLR(bit) (A(bit) &= (~B(bit))) -#define TST(bit) (A(bit) & B(bit)) - -static void ping(const char *host); - -/* common routines */ -static int in_cksum(unsigned short *buf, int sz) -{ - int nleft = sz; - int sum = 0; - unsigned short *w = buf; - unsigned short ans = 0; - - while (nleft > 1) { - sum += *w++; - nleft -= 2; - } - - if (nleft == 1) { - *(unsigned char *) (&ans) = *(unsigned char *) w; - sum += ans; - } - - sum = (sum >> 16) + (sum & 0xFFFF); - sum += (sum >> 16); - ans = ~sum; - return (ans); -} - -/* simple version */ -#ifndef BB_FEATURE_FANCY_PING -static char *hostname = NULL; - -static void noresp(int ign) -{ - printf("No response from %s\n", hostname); - exit(0); -} - -static void ping(const char *host) -{ - struct hostent *h; - struct sockaddr_in pingaddr; - struct icmp *pkt; - int pingsock, c; - char packet[DEFDATALEN + MAXIPLEN + MAXICMPLEN]; - - pingsock = create_icmp_socket(); - - memset(&pingaddr, 0, sizeof(struct sockaddr_in)); - - pingaddr.sin_family = AF_INET; - h = xgethostbyname(host); - memcpy(&pingaddr.sin_addr, h->h_addr, sizeof(pingaddr.sin_addr)); - hostname = h->h_name; - - pkt = (struct icmp *) packet; - memset(pkt, 0, sizeof(packet)); - pkt->icmp_type = ICMP_ECHO; - pkt->icmp_cksum = in_cksum((unsigned short *) pkt, sizeof(packet)); - - c = sendto(pingsock, packet, sizeof(packet), 0, - (struct sockaddr *) &pingaddr, sizeof(struct sockaddr_in)); - - if (c < 0 || c != sizeof(packet)) - perror_msg_and_die("sendto"); - - signal(SIGALRM, noresp); - alarm(5); /* give the host 5000ms to respond */ - /* listen for replies */ - while (1) { - struct sockaddr_in from; - size_t fromlen = sizeof(from); - - if ((c = recvfrom(pingsock, packet, sizeof(packet), 0, - (struct sockaddr *) &from, &fromlen)) < 0) { - if (errno == EINTR) - continue; - perror_msg("recvfrom"); - continue; - } - if (c >= 76) { /* ip + icmp */ - struct iphdr *iphdr = (struct iphdr *) packet; - - pkt = (struct icmp *) (packet + (iphdr->ihl << 2)); /* skip ip hdr */ - if (pkt->icmp_type == ICMP_ECHOREPLY) - break; - } - } - printf("%s is alive!\n", hostname); - return; -} - -extern int ping_main(int argc, char **argv) -{ - argc--; - argv++; - if (argc < 1) - show_usage(); - ping(*argv); - return EXIT_SUCCESS; -} - -#else /* ! BB_FEATURE_FANCY_PING */ -/* full(er) version */ -static char *hostname = NULL; -static struct sockaddr_in pingaddr; -static int pingsock = -1; -static int datalen; /* intentionally uninitialized to work around gcc bug */ - -static long ntransmitted = 0, nreceived = 0, nrepeats = 0, pingcount = 0; -static int myid = 0, options = 0; -static unsigned long tmin = ULONG_MAX, tmax = 0, tsum = 0; -static char rcvd_tbl[MAX_DUP_CHK / 8]; - -static void sendping(int); -static void pingstats(int); -static void unpack(char *, int, struct sockaddr_in *); - -/**************************************************************************/ - -static void pingstats(int junk) -{ - int status; - - signal(SIGINT, SIG_IGN); - - printf("\n--- %s ping statistics ---\n", hostname); - printf("%ld packets transmitted, ", ntransmitted); - printf("%ld packets received, ", nreceived); - if (nrepeats) - printf("%ld duplicates, ", nrepeats); - if (ntransmitted) - printf("%ld%% packet loss\n", - (ntransmitted - nreceived) * 100 / ntransmitted); - if (nreceived) - printf("round-trip min/avg/max = %lu.%lu/%lu.%lu/%lu.%lu ms\n", - tmin / 10, tmin % 10, - (tsum / (nreceived + nrepeats)) / 10, - (tsum / (nreceived + nrepeats)) % 10, tmax / 10, tmax % 10); - if (nreceived != 0) - status = EXIT_SUCCESS; - else - status = EXIT_FAILURE; - exit(status); -} - -static void sendping(int junk) -{ - struct icmp *pkt; - int i; - char packet[datalen + 8]; - - pkt = (struct icmp *) packet; - - pkt->icmp_type = ICMP_ECHO; - pkt->icmp_code = 0; - pkt->icmp_cksum = 0; - pkt->icmp_seq = ntransmitted++; - pkt->icmp_id = myid; - CLR(pkt->icmp_seq % MAX_DUP_CHK); - - gettimeofday((struct timeval *) &packet[8], NULL); - pkt->icmp_cksum = in_cksum((unsigned short *) pkt, sizeof(packet)); - - i = sendto(pingsock, packet, sizeof(packet), 0, - (struct sockaddr *) &pingaddr, sizeof(struct sockaddr_in)); - - if (i < 0) - perror_msg_and_die("sendto"); - else if ((size_t)i != sizeof(packet)) - error_msg_and_die("ping wrote %d chars; %d expected", i, - (int)sizeof(packet)); - - signal(SIGALRM, sendping); - if (pingcount == 0 || ntransmitted < pingcount) { /* schedule next in 1s */ - alarm(PINGINTERVAL); - } else { /* done, wait for the last ping to come back */ - /* todo, don't necessarily need to wait so long... */ - signal(SIGALRM, pingstats); - alarm(MAXWAIT); - } -} - -static char *icmp_type_name (int id) -{ - switch (id) { - case ICMP_ECHOREPLY: return "Echo Reply"; - case ICMP_DEST_UNREACH: return "Destination Unreachable"; - case ICMP_SOURCE_QUENCH: return "Source Quench"; - case ICMP_REDIRECT: return "Redirect (change route)"; - case ICMP_ECHO: return "Echo Request"; - case ICMP_TIME_EXCEEDED: return "Time Exceeded"; - case ICMP_PARAMETERPROB: return "Parameter Problem"; - case ICMP_TIMESTAMP: return "Timestamp Request"; - case ICMP_TIMESTAMPREPLY: return "Timestamp Reply"; - case ICMP_INFO_REQUEST: return "Information Request"; - case ICMP_INFO_REPLY: return "Information Reply"; - case ICMP_ADDRESS: return "Address Mask Request"; - case ICMP_ADDRESSREPLY: return "Address Mask Reply"; - default: return "unknown ICMP type"; - } -} - -static void unpack(char *buf, int sz, struct sockaddr_in *from) -{ - struct icmp *icmppkt; - struct iphdr *iphdr; - struct timeval tv, *tp; - int hlen, dupflag; - unsigned long triptime; - - gettimeofday(&tv, NULL); - - /* check IP header */ - iphdr = (struct iphdr *) buf; - hlen = iphdr->ihl << 2; - /* discard if too short */ - if (sz < (datalen + ICMP_MINLEN)) - return; - - sz -= hlen; - icmppkt = (struct icmp *) (buf + hlen); - - if (icmppkt->icmp_id != myid) - return; /* not our ping */ - - if (icmppkt->icmp_type == ICMP_ECHOREPLY) { - ++nreceived; - tp = (struct timeval *) icmppkt->icmp_data; - - if ((tv.tv_usec -= tp->tv_usec) < 0) { - --tv.tv_sec; - tv.tv_usec += 1000000; - } - tv.tv_sec -= tp->tv_sec; - - triptime = tv.tv_sec * 10000 + (tv.tv_usec / 100); - tsum += triptime; - if (triptime < tmin) - tmin = triptime; - if (triptime > tmax) - tmax = triptime; - - if (TST(icmppkt->icmp_seq % MAX_DUP_CHK)) { - ++nrepeats; - --nreceived; - dupflag = 1; - } else { - SET(icmppkt->icmp_seq % MAX_DUP_CHK); - dupflag = 0; - } - - if (options & O_QUIET) - return; - - printf("%d bytes from %s: icmp_seq=%u", sz, - inet_ntoa(*(struct in_addr *) &from->sin_addr.s_addr), - icmppkt->icmp_seq); - printf(" ttl=%d", iphdr->ttl); - printf(" time=%lu.%lu ms", triptime / 10, triptime % 10); - if (dupflag) - printf(" (DUP!)"); - printf("\n"); - } else - if (icmppkt->icmp_type != ICMP_ECHO) - error_msg("Warning: Got ICMP %d (%s)", - icmppkt->icmp_type, icmp_type_name (icmppkt->icmp_type)); -} - -static void ping(const char *host) -{ - struct hostent *h; - char buf[MAXHOSTNAMELEN]; - char packet[datalen + MAXIPLEN + MAXICMPLEN]; - int sockopt; - - pingsock = create_icmp_socket(); - - memset(&pingaddr, 0, sizeof(struct sockaddr_in)); - - pingaddr.sin_family = AF_INET; - h = xgethostbyname(host); - if (h->h_addrtype != AF_INET) - error_msg_and_die("unknown address type; only AF_INET is currently supported."); - - memcpy(&pingaddr.sin_addr, h->h_addr, sizeof(pingaddr.sin_addr)); - strncpy(buf, h->h_name, sizeof(buf) - 1); - hostname = buf; - - /* enable broadcast pings */ - sockopt = 1; - setsockopt(pingsock, SOL_SOCKET, SO_BROADCAST, (char *) &sockopt, - sizeof(sockopt)); - - /* set recv buf for broadcast pings */ - sockopt = 48 * 1024; - setsockopt(pingsock, SOL_SOCKET, SO_RCVBUF, (char *) &sockopt, - sizeof(sockopt)); - - printf("PING %s (%s): %d data bytes\n", - hostname, - inet_ntoa(*(struct in_addr *) &pingaddr.sin_addr.s_addr), - datalen); - - signal(SIGINT, pingstats); - - /* start the ping's going ... */ - sendping(0); - - /* listen for replies */ - while (1) { - struct sockaddr_in from; - socklen_t fromlen = (socklen_t) sizeof(from); - int c; - - if ((c = recvfrom(pingsock, packet, sizeof(packet), 0, - (struct sockaddr *) &from, &fromlen)) < 0) { - if (errno == EINTR) - continue; - perror_msg("recvfrom"); - continue; - } - unpack(packet, c, &from); - if (pingcount > 0 && nreceived >= pingcount) - break; - } - pingstats(0); -} - -extern int ping_main(int argc, char **argv) -{ - char *thisarg; - - datalen = DEFDATALEN; /* initialized here rather than in global scope to work around gcc bug */ - - argc--; - argv++; - options = 0; - /* Parse any options */ - while (argc >= 1 && **argv == '-') { - thisarg = *argv; - thisarg++; - switch (*thisarg) { - case 'q': - options |= O_QUIET; - break; - case 'c': - if (--argc <= 0) - show_usage(); - argv++; - pingcount = atoi(*argv); - break; - case 's': - if (--argc <= 0) - show_usage(); - argv++; - datalen = atoi(*argv); - break; - default: - show_usage(); - } - argc--; - argv++; - } - if (argc < 1) - show_usage(); - - myid = getpid() & 0xFFFF; - ping(*argv); - return EXIT_SUCCESS; -} -#endif /* ! BB_FEATURE_FANCY_PING */ - -/* - * Copyright (c) 1989 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Muuss. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. - * - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ diff --git a/pivot_root.c b/pivot_root.c deleted file mode 100644 index ba26b9c58..000000000 --- a/pivot_root.c +++ /dev/null @@ -1,35 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * pivot_root.c - Change root file system. Based on util-linux 2.10s - * - * busyboxed by Evin Robertson - * pivot_root syscall stubbed by Erik Andersen, so it will compile - * regardless of the kernel being used. - */ -#include -#include -#include -#include "busybox.h" - -extern int pivot_root(const char * new_root,const char * put_old); - -int pivot_root_main(int argc, char **argv) -{ - if (argc != 3) - show_usage(); - - if (pivot_root(argv[1],argv[2]) < 0) - perror_msg_and_die("pivot_root"); - - return EXIT_SUCCESS; - -} - - -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ diff --git a/poweroff.c b/poweroff.c deleted file mode 100644 index db20a4572..000000000 --- a/poweroff.c +++ /dev/null @@ -1,41 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini poweroff implementation for busybox - * - * - * Copyright (C) 1995, 1996 by Bruce Perens . - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include "busybox.h" -#include - -extern int poweroff_main(int argc, char **argv) -{ -#ifdef BB_FEATURE_LINUXRC - /* don't assume init's pid == 1 */ - pid_t *pid = find_pid_by_name("init"); - if (!pid || *pid<=0) { - pid = find_pid_by_name("linuxrc"); - if (!pid || *pid<=0) - error_msg_and_die("no process killed"); - } - return(kill(*pid, SIGUSR2)); -#else - return(kill(1, SIGUSR2)); -#endif -} diff --git a/printf.c b/printf.c deleted file mode 100644 index d579a9b4e..000000000 --- a/printf.c +++ /dev/null @@ -1,455 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* printf - format and print data - Copyright (C) 90, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -/* Usage: printf format [argument...] - - A front end to the printf function that lets it be used from the shell. - - Backslash escapes: - - \" = double quote - \\ = backslash - \a = alert (bell) - \b = backspace - \c = produce no further output - \f = form feed - \n = new line - \r = carriage return - \t = horizontal tab - \v = vertical tab - \0ooo = octal number (ooo is 0 to 3 digits) - \xhhh = hexadecimal number (hhh is 1 to 3 digits) - - Additional directive: - - %b = print an argument string, interpreting backslash escapes - - The `format' argument is re-used as many times as necessary - to convert all of the given arguments. - - David MacKenzie */ - - -// 19990508 Busy Boxed! Dave Cinege - -#include -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" - - -#ifndef S_IFMT -static const int S_IFMT = 0170000; -#endif -#if !defined(S_ISBLK) && defined(S_IFBLK) -# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) -#endif -#if !defined(S_ISCHR) && defined(S_IFCHR) -# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) -#endif -#if !defined(S_ISDIR) && defined(S_IFDIR) -# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) -#endif -#if !defined(S_ISREG) && defined(S_IFREG) -# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) -#endif -#if !defined(S_ISFIFO) && defined(S_IFIFO) -# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) -#endif -#if !defined(S_ISLNK) && defined(S_IFLNK) -# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) -#endif -#if !defined(S_ISSOCK) && defined(S_IFSOCK) -# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) -#endif -#if !defined(S_ISMPB) && defined(S_IFMPB) /* V7 */ -# define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB) -# define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC) -#endif -#if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */ -# define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK) -#endif - -#define IN_CTYPE_DOMAIN(c) 1 - -#define ISXDIGIT(c) (IN_CTYPE_DOMAIN (c) && isxdigit (c)) -#define ISDIGIT_LOCALE(c) (IN_CTYPE_DOMAIN (c) && isdigit (c)) -#define ISDIGIT(c) (((unsigned char) (c)) - '0' <= 9) - -#define isodigit(c) ((c) >= '0' && (c) <= '7') -#define hextobin(c) ((c)>='a'&&(c)<='f' ? (c)-'a'+10 : (c)>='A'&&(c)<='F' ? (c)-'A'+10 : (c)-'0') -#define octtobin(c) ((c) - '0') - -static double xstrtod __P((char *s)); -static int print_esc __P((char *escstart)); -static int print_formatted __P((char *format, int argc, char **argv)); -static long xstrtol __P((char *s)); -static unsigned long xstrtoul __P((char *s)); -static void print_direc -__P( - - (char *start, size_t length, int field_width, int precision, - char *argument)); -static void print_esc_char __P((int c)); -static void print_esc_string __P((char *str)); -static void verify __P((char *s, char *end)); - -/* The value to return to the calling program. */ -static int exit_status; - -int printf_main(int argc, char **argv) -{ - char *format; - int args_used; - - exit_status = 0; - if (argc <= 1 || **(argv + 1) == '-') { - show_usage(); - } - - format = argv[1]; - argc -= 2; - argv += 2; - - do { - args_used = print_formatted(format, argc, argv); - argc -= args_used; - argv += args_used; - } - while (args_used > 0 && argc > 0); - -/* - if (argc > 0) - fprintf(stderr, "excess args ignored"); -*/ - - return(exit_status); -} - -/* Print the text in FORMAT, using ARGV (with ARGC elements) for - arguments to any `%' directives. - Return the number of elements of ARGV used. */ - -static int print_formatted(char *format, int argc, char **argv) -{ - int save_argc = argc; /* Preserve original value. */ - char *f; /* Pointer into `format'. */ - char *direc_start; /* Start of % directive. */ - size_t direc_length; /* Length of % directive. */ - int field_width; /* Arg to first '*', or -1 if none. */ - int precision; /* Arg to second '*', or -1 if none. */ - - for (f = format; *f; ++f) { - switch (*f) { - case '%': - direc_start = f++; - direc_length = 1; - field_width = precision = -1; - if (*f == '%') { - putchar('%'); - break; - } - if (*f == 'b') { - if (argc > 0) { - print_esc_string(*argv); - ++argv; - --argc; - } - break; - } - if (strchr("-+ #", *f)) { - ++f; - ++direc_length; - } - if (*f == '*') { - ++f; - ++direc_length; - if (argc > 0) { - field_width = xstrtoul(*argv); - ++argv; - --argc; - } else - field_width = 0; - } else - while (ISDIGIT(*f)) { - ++f; - ++direc_length; - } - if (*f == '.') { - ++f; - ++direc_length; - if (*f == '*') { - ++f; - ++direc_length; - if (argc > 0) { - precision = xstrtoul(*argv); - ++argv; - --argc; - } else - precision = 0; - } else - while (ISDIGIT(*f)) { - ++f; - ++direc_length; - } - } - if (*f == 'l' || *f == 'L' || *f == 'h') { - ++f; - ++direc_length; - } - /* - if (!strchr ("diouxXfeEgGcs", *f)) - fprintf(stderr, "%%%c: invalid directive", *f); - */ - ++direc_length; - if (argc > 0) { - print_direc(direc_start, direc_length, field_width, - precision, *argv); - ++argv; - --argc; - } else - print_direc(direc_start, direc_length, field_width, - precision, ""); - break; - - case '\\': - f += print_esc(f); - break; - - default: - putchar(*f); - } - } - - return save_argc - argc; -} - -/* Print a \ escape sequence starting at ESCSTART. - Return the number of characters in the escape sequence - besides the backslash. */ - -static int print_esc(char *escstart) -{ - register char *p = escstart + 1; - int esc_value = 0; /* Value of \nnn escape. */ - int esc_length; /* Length of \nnn escape. */ - - /* \0ooo and \xhhh escapes have maximum length of 3 chars. */ - if (*p == 'x') { - for (esc_length = 0, ++p; - esc_length < 3 && ISXDIGIT(*p); ++esc_length, ++p) - esc_value = esc_value * 16 + hextobin(*p); -/* if (esc_length == 0) - fprintf(stderr, "missing hex in esc"); -*/ - putchar(esc_value); - } else if (*p == '0') { - for (esc_length = 0, ++p; - esc_length < 3 && isodigit(*p); ++esc_length, ++p) - esc_value = esc_value * 8 + octtobin(*p); - putchar(esc_value); - } else if (strchr("\"\\abcfnrtv", *p)) - print_esc_char(*p++); -/* else - fprintf(stderr, "\\%c: invalid esc", *p); -*/ - return p - escstart - 1; -} - -/* Output a single-character \ escape. */ - -static void print_esc_char(int c) -{ - switch (c) { - case 'a': /* Alert. */ - putchar(7); - break; - case 'b': /* Backspace. */ - putchar(8); - break; - case 'c': /* Cancel the rest of the output. */ - exit(0); - break; - case 'f': /* Form feed. */ - putchar(12); - break; - case 'n': /* New line. */ - putchar(10); - break; - case 'r': /* Carriage return. */ - putchar(13); - break; - case 't': /* Horizontal tab. */ - putchar(9); - break; - case 'v': /* Vertical tab. */ - putchar(11); - break; - default: - putchar(c); - break; - } -} - -/* Print string STR, evaluating \ escapes. */ - -static void print_esc_string(char *str) -{ - for (; *str; str++) - if (*str == '\\') - str += print_esc(str); - else - putchar(*str); -} - -static void -print_direc(char *start, size_t length, int field_width, int precision, - char *argument) -{ - char *p; /* Null-terminated copy of % directive. */ - - p = xmalloc((unsigned) (length + 1)); - strncpy(p, start, length); - p[length] = 0; - - switch (p[length - 1]) { - case 'd': - case 'i': - if (field_width < 0) { - if (precision < 0) - printf(p, xstrtol(argument)); - else - printf(p, precision, xstrtol(argument)); - } else { - if (precision < 0) - printf(p, field_width, xstrtol(argument)); - else - printf(p, field_width, precision, xstrtol(argument)); - } - break; - - case 'o': - case 'u': - case 'x': - case 'X': - if (field_width < 0) { - if (precision < 0) - printf(p, xstrtoul(argument)); - else - printf(p, precision, xstrtoul(argument)); - } else { - if (precision < 0) - printf(p, field_width, xstrtoul(argument)); - else - printf(p, field_width, precision, xstrtoul(argument)); - } - break; - - case 'f': - case 'e': - case 'E': - case 'g': - case 'G': - if (field_width < 0) { - if (precision < 0) - printf(p, xstrtod(argument)); - else - printf(p, precision, xstrtod(argument)); - } else { - if (precision < 0) - printf(p, field_width, xstrtod(argument)); - else - printf(p, field_width, precision, xstrtod(argument)); - } - break; - - case 'c': - printf(p, *argument); - break; - - case 's': - if (field_width < 0) { - if (precision < 0) - printf(p, argument); - else - printf(p, precision, argument); - } else { - if (precision < 0) - printf(p, field_width, argument); - else - printf(p, field_width, precision, argument); - } - break; - } - - free(p); -} - -static unsigned long xstrtoul(char *s) -{ - char *end; - unsigned long val; - - errno = 0; - val = strtoul(s, &end, 0); - verify(s, end); - return val; -} - -static long xstrtol(char *s) -{ - char *end; - long val; - - errno = 0; - val = strtol(s, &end, 0); - verify(s, end); - return val; -} - -static double xstrtod(char *s) -{ - char *end; - double val; - - errno = 0; - val = strtod(s, &end); - verify(s, end); - return val; -} - -static void verify(char *s, char *end) -{ - if (errno) { - fprintf(stderr, "%s", s); - exit_status = 1; - } else if (*end) { - /* - if (s == end) - fprintf(stderr, "%s: expected numeric", s); - else - fprintf(stderr, "%s: not completely converted", s); - */ - exit_status = 1; - } -} diff --git a/pristine_setup.sh b/pristine_setup.sh deleted file mode 100755 index 9e638f96e..000000000 --- a/pristine_setup.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/sh -# -# To compile BusyBox without touching the original sources -# (as might be interesting for multi-target builds), create -# an empty directory, cd into it, and run this program by -# giving its explicit path (kind of like how you would run -# configure, if BusyBox had one). Then you should be ready -# to "make". Files in the build tree, in particular Config.h, -# will override those in the pristine source tree. -# -# If you use a ? in your path name, you lose, see sed command below. - -export LC_ALL=POSIX -export LC_CTYPE=POSIX - -DIR=${0%%/pristine_setup.sh} -if [ ! -d $DIR ]; then - echo "unexpected problem: $DIR is not a directory. Aborting pristine setup" - exit -fi - -echo " " - -if [ -e ./Config.h ]; then - echo "./Config.h already exists: not overwriting" - exit -fi - -if [ -e ./Makefile ]; then - echo "./Makefile already exists: not overwriting" -fi - -sed -e "s?BB_SRC_DIR =.*?BB_SRC_DIR = $DIR?" <$DIR/Makefile >Makefile || exit -cp $DIR/Config.h Config.h || exit -#mkdir -p pwd_grp - -if [ ! -r $DIR/sh.c ]; then - echo "Warning: no shell selected. You must make the symlink (sh.c to either" - echo "lash.c or hush.c) in $DIR, not here." -fi - -echo " " -echo "You may now type 'make' to build busybox in this directory" -echo "($PWD) using the pristine sources in $DIR" -echo " " - diff --git a/procps/Makefile b/procps/Makefile new file mode 100644 index 000000000..0e3bdc254 --- /dev/null +++ b/procps/Makefile @@ -0,0 +1,40 @@ +# Makefile for busybox +# +# Copyright (C) 1999,2000,2001 by Erik Andersen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +TOPDIR :=.. +L_TARGET := procps.a + +obj-y := +obj-n := +obj- := + +obj-$(CONFIG_FREE) += free.o +obj-$(CONFIG_KILL) += kill.o +obj-$(CONFIG_PIDOF) += pidof.o +obj-$(CONFIG_PS) += ps.o +obj-$(CONFIG_RENICE) += renice.o +obj-$(CONFIG_UPTIME) += uptime.o + + +# Hand off to toplevel Rules.mak +include $(TOPDIR)/Rules.mak + +clean: + rm -f $(L_TARGET) *.o core + diff --git a/procps/config.in b/procps/config.in new file mode 100644 index 000000000..0c9c35c06 --- /dev/null +++ b/procps/config.in @@ -0,0 +1,17 @@ +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +mainmenu_option next_comment +comment 'Process Utilities' + +bool 'free' CONFIG_FREE +bool 'kill' CONFIG_KILL +bool 'pidof' CONFIG_PIDOF +bool 'ps' CONFIG_PS +bool 'renice' CONFIG_RENICE +bool 'uptime' CONFIG_UPTIME + +endmenu + diff --git a/procps/free.c b/procps/free.c index 2e34a972c..cdc0d358c 100644 --- a/procps/free.c +++ b/procps/free.c @@ -2,8 +2,8 @@ /* * Mini free implementation for busybox * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , + * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/procps/kill.c b/procps/kill.c index 3884ebdf4..8b8a9922c 100644 --- a/procps/kill.c +++ b/procps/kill.c @@ -40,7 +40,7 @@ extern int kill_main(int argc, char **argv) int whichApp, sig = SIGTERM; const char *name; -#ifdef BB_KILLALL +#ifdef CONFIG_KILLALL /* Figure out what we are trying to do here */ whichApp = (strcmp(applet_name, "killall") == 0)? KILLALL : KILL; #else @@ -108,7 +108,7 @@ extern int kill_main(int argc, char **argv) argv++; } } -#ifdef BB_KILLALL +#ifdef CONFIG_KILLALL else { int all_found = TRUE; pid_t myPid=getpid(); diff --git a/procps/pidof.c b/procps/pidof.c index 50dffd387..5a40288dc 100644 --- a/procps/pidof.c +++ b/procps/pidof.c @@ -2,8 +2,8 @@ /* * pidof implementation for busybox * - * Copyright (C) 2001 by Lineo, inc. - * Written by Erik Andersen , + * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/procps/ps.c b/procps/ps.c index 9e96a5402..fcb605a6e 100644 --- a/procps/ps.c +++ b/procps/ps.c @@ -2,15 +2,8 @@ /* * Mini ps implementation(s) for busybox * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , - * - * - * This contains _two_ implementations of ps for Linux. One uses the - * traditional /proc virtual filesystem, and the other use the devps kernel - * driver (written by Erik Andersen to avoid using /proc thereby saving 100k+). - * - * + * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -25,7 +18,12 @@ * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place, Suite 330, Boston, MA 02111-1307 USA - * + */ + +/* + * This contains _two_ implementations of ps for Linux. One uses the + * traditional /proc virtual filesystem, and the other use the devps kernel + * driver (written by Erik Andersen to avoid using /proc thereby saving 100k+). */ #include @@ -44,7 +42,7 @@ static const int TERMINAL_WIDTH = 79; /* not 80 in case terminal has linefo -#if ! defined BB_FEATURE_USE_DEVPS_PATCH +#if ! defined CONFIG_FEATURE_USE_DEVPS_PATCH /* The following is the first ps implementation -- * the one using the /proc virtual filesystem. @@ -114,7 +112,7 @@ extern int ps_main(int argc, char **argv) char path[32], sbuf[512]; char uidName[9]; int len, i, c; -#ifdef BB_FEATURE_AUTOWIDTH +#ifdef CONFIG_FEATURE_AUTOWIDTH struct winsize win = { 0, 0, 0, 0 }; int terminal_width = TERMINAL_WIDTH; #else @@ -127,7 +125,7 @@ extern int ps_main(int argc, char **argv) if (!dir) error_msg_and_die("Can't open /proc"); -#ifdef BB_FEATURE_AUTOWIDTH +#ifdef CONFIG_FEATURE_AUTOWIDTH ioctl(fileno(stdout), TIOCGWINSZ, &win); if (win.ws_col > 0) terminal_width = win.ws_col - 1; @@ -169,7 +167,7 @@ extern int ps_main(int argc, char **argv) } -#else /* BB_FEATURE_USE_DEVPS_PATCH */ +#else /* CONFIG_FEATURE_USE_DEVPS_PATCH */ /* The following is the second ps implementation -- @@ -187,7 +185,7 @@ extern int ps_main(int argc, char **argv) pid_t* pid_array = NULL; struct pid_info info; char uidName[9]; -#ifdef BB_FEATURE_AUTOWIDTH +#ifdef CONFIG_FEATURE_AUTOWIDTH struct winsize win = { 0, 0, 0, 0 }; int terminal_width = TERMINAL_WIDTH; #else @@ -217,7 +215,7 @@ extern int ps_main(int argc, char **argv) if (ioctl (fd, DEVPS_GET_PID_LIST, pid_array)<0) perror_msg_and_die("\nDEVPS_GET_PID_LIST"); -#ifdef BB_FEATURE_AUTOWIDTH +#ifdef CONFIG_FEATURE_AUTOWIDTH ioctl(fileno(stdout), TIOCGWINSZ, &win); if (win.ws_col > 0) terminal_width = win.ws_col - 1; @@ -262,5 +260,5 @@ extern int ps_main(int argc, char **argv) exit (0); } -#endif /* BB_FEATURE_USE_DEVPS_PATCH */ +#endif /* CONFIG_FEATURE_USE_DEVPS_PATCH */ diff --git a/procps/uptime.c b/procps/uptime.c index 6758d959e..85ff2233c 100644 --- a/procps/uptime.c +++ b/procps/uptime.c @@ -2,8 +2,8 @@ /* * Mini uptime implementation for busybox * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , + * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,7 +24,7 @@ /* 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 BB_FEATURE_UTMP_SUPPORT #define + * of CONFIG_FEATURE_UTMP_SUPPORT #define */ /* getopt not needed */ diff --git a/ps.c b/ps.c deleted file mode 100644 index 9e96a5402..000000000 --- a/ps.c +++ /dev/null @@ -1,266 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini ps implementation(s) for busybox - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , - * - * - * This contains _two_ implementations of ps for Linux. One uses the - * traditional /proc virtual filesystem, and the other use the devps kernel - * driver (written by Erik Andersen to avoid using /proc thereby saving 100k+). - * - * - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" - -static const int TERMINAL_WIDTH = 79; /* not 80 in case terminal has linefold bug */ - - - -#if ! defined BB_FEATURE_USE_DEVPS_PATCH - -/* The following is the first ps implementation -- - * the one using the /proc virtual filesystem. - */ - -typedef struct proc_s { - char - cmd[16]; /* basename of executable file in call to exec(2) */ - int - ruid, /* real only (sorry) */ - pid, /* process id */ - ppid; /* pid of parent process */ - char - state; /* single-char code for process state (S=sleeping) */ -} proc_t; - - - -static int file2str(char *filename, char *ret, int cap) -{ - int fd, num_read; - - if ((fd = open(filename, O_RDONLY, 0)) == -1) - return -1; - if ((num_read = read(fd, ret, cap - 1)) <= 0) - return -1; - ret[num_read] = 0; - close(fd); - return num_read; -} - - -static void parse_proc_status(char *S, proc_t * P) -{ - char *tmp; - - memset(P->cmd, 0, sizeof P->cmd); - sscanf(S, "Name:\t%15c", P->cmd); - tmp = strchr(P->cmd, '\n'); - if (tmp) - *tmp = '\0'; - tmp = strstr(S, "State"); - sscanf(tmp, "State:\t%c", &P->state); - - tmp = strstr(S, "Pid:"); - if (tmp) - sscanf(tmp, "Pid:\t%d\n" "PPid:\t%d\n", &P->pid, &P->ppid); - else - error_msg("Internal error!"); - - /* For busybox, ignoring effective, saved, etc. */ - tmp = strstr(S, "Uid:"); - if (tmp) - sscanf(tmp, "Uid:\t%d", &P->ruid); - else - error_msg("Internal error!"); - - -} - -extern int ps_main(int argc, char **argv) -{ - proc_t p; - DIR *dir; - FILE *file; - struct dirent *entry; - char path[32], sbuf[512]; - char uidName[9]; - int len, i, c; -#ifdef BB_FEATURE_AUTOWIDTH - struct winsize win = { 0, 0, 0, 0 }; - int terminal_width = TERMINAL_WIDTH; -#else -#define terminal_width TERMINAL_WIDTH -#endif - - - - dir = opendir("/proc"); - if (!dir) - error_msg_and_die("Can't open /proc"); - -#ifdef BB_FEATURE_AUTOWIDTH - ioctl(fileno(stdout), TIOCGWINSZ, &win); - if (win.ws_col > 0) - terminal_width = win.ws_col - 1; -#endif - - printf(" PID Uid Stat Command\n"); - while ((entry = readdir(dir)) != NULL) { - if (!isdigit(*entry->d_name)) - continue; - sprintf(path, "/proc/%s/status", entry->d_name); - if ((file2str(path, sbuf, sizeof sbuf)) != -1) { - parse_proc_status(sbuf, &p); - } - - /* Make some adjustments as needed */ - my_getpwuid(uidName, p.ruid); - if (*uidName == '\0') - sprintf(uidName, "%d", p.ruid); - - sprintf(path, "/proc/%s/cmdline", entry->d_name); - file = fopen(path, "r"); - if (file == NULL) - continue; - i = 0; - len = printf("%5d %-8s %c ", p.pid, uidName, p.state); - while (((c = getc(file)) != EOF) && (i < (terminal_width-len))) { - i++; - if (c == '\0') - c = ' '; - putc(c, stdout); - } - fclose(file); - if (i == 0) - printf("[%s]", p.cmd); - putchar('\n'); - } - closedir(dir); - return EXIT_SUCCESS; -} - - -#else /* BB_FEATURE_USE_DEVPS_PATCH */ - - -/* The following is the second ps implementation -- - * this one uses the nifty new devps kernel device. - */ - -#include /* For Erik's nifty devps device driver */ - - -extern int ps_main(int argc, char **argv) -{ - char device[] = "/dev/ps"; - int i, j, len, fd; - pid_t num_pids; - pid_t* pid_array = NULL; - struct pid_info info; - char uidName[9]; -#ifdef BB_FEATURE_AUTOWIDTH - struct winsize win = { 0, 0, 0, 0 }; - int terminal_width = TERMINAL_WIDTH; -#else -#define terminal_width TERMINAL_WIDTH -#endif - - if (argc > 1 && **(argv + 1) == '-') - show_usage(); - - /* open device */ - fd = open(device, O_RDONLY); - if (fd < 0) - perror_msg_and_die( "open failed for `%s'", device); - - /* Find out how many processes there are */ - if (ioctl (fd, DEVPS_GET_NUM_PIDS, &num_pids)<0) - perror_msg_and_die( "\nDEVPS_GET_PID_LIST"); - - /* Allocate some memory -- grab a few extras just in case - * some new processes start up while we wait. The kernel will - * just ignore any extras if we give it too many, and will trunc. - * the list if we give it too few. */ - pid_array = (pid_t*) xcalloc( num_pids+10, sizeof(pid_t)); - pid_array[0] = num_pids+10; - - /* Now grab the pid list */ - if (ioctl (fd, DEVPS_GET_PID_LIST, pid_array)<0) - perror_msg_and_die("\nDEVPS_GET_PID_LIST"); - -#ifdef BB_FEATURE_AUTOWIDTH - ioctl(fileno(stdout), TIOCGWINSZ, &win); - if (win.ws_col > 0) - terminal_width = win.ws_col - 1; -#endif - - /* Print up a ps listing */ - printf(" PID Uid Stat Command\n"); - - for (i=1; i 1) { - for( j=0; j<(sizeof(info.command_line)-1) && j < (terminal_width-len); j++) { - if (*(info.command_line+j) == '\0' && *(info.command_line+j+1) != '\0') { - *(info.command_line+j) = ' '; - } - } - *(info.command_line+j) = '\0'; - puts(info.command_line); - } else { - printf("[%s]\n", info.name); - } - } - - /* Free memory */ - free( pid_array); - - /* close device */ - if (close (fd) != 0) - perror_msg_and_die("close failed for `%s'", device); - - exit (0); -} - -#endif /* BB_FEATURE_USE_DEVPS_PATCH */ - diff --git a/pwd.c b/pwd.c deleted file mode 100644 index f6a00bf1e..000000000 --- a/pwd.c +++ /dev/null @@ -1,44 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini pwd implementation for busybox - * - * - * Copyright (C) 1995, 1996 by Bruce Perens . - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* getopt not needed */ - -#include -#include -#include -#include -#include -#include "busybox.h" - -extern int pwd_main(int argc, char **argv) -{ - static char *buf; - - buf = xgetcwd(buf); - - if (buf != NULL) { - puts(buf); - return EXIT_SUCCESS; - } - return EXIT_FAILURE; -} diff --git a/rdate.c b/rdate.c deleted file mode 100644 index 04a76129a..000000000 --- a/rdate.c +++ /dev/null @@ -1,116 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * The Rdate command will ask a time server for the RFC 868 time - * and optionally set the system time. - * - * by Sterling Huxley - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" - - -static const int RFC_868_BIAS = 2208988800UL; - -static time_t askremotedate(const char *host) -{ - struct hostent *h; - struct sockaddr_in s_in; - struct servent *tserv; - unsigned long int nett, localt; - int fd; - - h = xgethostbyname(host); /* get the IP addr */ - memcpy(&s_in.sin_addr, h->h_addr, sizeof(s_in.sin_addr)); - - s_in.sin_port = htons(37); /* find port # */ - if ((tserv = getservbyname("time", "tcp")) != NULL) - s_in.sin_port = tserv->s_port; - - s_in.sin_family = AF_INET; - - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) /* get net connection */ - perror_msg_and_die("socket"); - - if (connect(fd, (struct sockaddr *)&s_in, sizeof(s_in)) < 0) /* connect to time server */ - perror_msg_and_die("%s", host); - - if (read(fd, (void *)&nett, 4) != 4) /* read time from server */ - error_msg_and_die("%s did not send the complete time", host); - - close(fd); - - /* convert from network byte order to local byte order. - * RFC 868 time is the number of seconds - * since 00:00 (midnight) 1 January 1900 GMT - * the RFC 868 time 2,208,988,800 corresponds to 00:00 1 Jan 1970 GMT - * Subtract the RFC 868 time to get Linux epoch - */ - localt= ntohl(nett) - RFC_868_BIAS; - - return(localt); -} - -int rdate_main(int argc, char **argv) -{ - time_t remote_time; - int opt; - int setdate = 1; - int printdate = 1; - - /* Interpret command line args */ - while ((opt = getopt(argc, argv, "sp")) > 0) { - switch (opt) { - case 's': - printdate = 0; - setdate = 1; - break; - case 'p': - printdate = 1; - setdate = 0; - break; - default: - show_usage(); - } - } - - if (optind == argc) - show_usage(); - - remote_time = askremotedate(argv[optind]); - - if (setdate) { - if (stime(&remote_time) < 0) - perror_msg_and_die("Could not set time of day"); - } - - if (printdate) - printf("%s", ctime(&remote_time)); - - return EXIT_SUCCESS; -} diff --git a/readlink.c b/readlink.c deleted file mode 100644 index c46ebd108..000000000 --- a/readlink.c +++ /dev/null @@ -1,48 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini readlink implementation for busybox - * - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Matt Kraai - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include "busybox.h" - -int readlink_main(int argc, char **argv) -{ - char *buf = NULL; - - /* no options, no getopt */ - - if (argc != 2) - show_usage(); - - buf = xreadlink(argv[1]); - if (!buf) - return EXIT_FAILURE; - puts(buf); -#ifdef BB_FEATURE_CLEAN_UP - free(buf); -#endif - - return EXIT_SUCCESS; -} diff --git a/reboot.c b/reboot.c deleted file mode 100644 index 35afd74ff..000000000 --- a/reboot.c +++ /dev/null @@ -1,49 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini reboot implementation for busybox - * - * - * Copyright (C) 1995, 1996 by Bruce Perens . - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include "busybox.h" -#include - -extern int reboot_main(int argc, char **argv) -{ -#ifdef BB_FEATURE_LINUXRC - /* don't assume init's pid == 1 */ - pid_t *pid = find_pid_by_name("init"); - if (!pid || *pid<=0) { - pid = find_pid_by_name("linuxrc"); - if (!pid || *pid<=0) - error_msg_and_die("no process killed"); - } - return(kill(*pid, SIGTERM)); -#else - return(kill(1, SIGTERM)); -#endif -} - -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ diff --git a/renice.c b/renice.c deleted file mode 100644 index ec35bdcde..000000000 --- a/renice.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Mini renice implementation for busybox - * - * - * Copyright (C) 2000 Dave 'Kill a Cop' Cinege - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include "busybox.h" - - -extern int renice_main(int argc, char **argv) -{ - int prio, status = EXIT_SUCCESS; - - if (argc < 3) show_usage(); - - prio = atoi(*++argv); - if (prio > 20) prio = 20; - if (prio < -20) prio = -20; - - while (*++argv) { - int ps = atoi(*argv); - int oldp = getpriority(PRIO_PROCESS, ps); - - if (setpriority(PRIO_PROCESS, ps, prio) == 0) { - printf("%d: old priority %d, new priority %d\n", ps, oldp, prio ); - } else { - perror_msg("%d: setpriority", ps); - status = EXIT_FAILURE; - } - } - - return status; -} diff --git a/reset.c b/reset.c deleted file mode 100644 index 755c4c335..000000000 --- a/reset.c +++ /dev/null @@ -1,35 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini reset implementation for busybox - * - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , - * and Kent Robotti - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include "busybox.h" - -extern int reset_main(int argc, char **argv) -{ - printf("\033c"); - return EXIT_SUCCESS; -} - diff --git a/rm.c b/rm.c deleted file mode 100644 index 51c9f4ceb..000000000 --- a/rm.c +++ /dev/null @@ -1,77 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini rm implementation for busybox - * - * - * Copyright (C) 2001 Matt Kraai - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" - -extern int rm_main(int argc, char **argv) -{ - int status = 0; - int opt; - int flags = 0; - int i; - - while ((opt = getopt(argc, argv, "fiRr")) != -1) { - switch (opt) { - case 'f': - flags &= ~FILEUTILS_INTERACTIVE; - flags |= FILEUTILS_FORCE; - break; - case 'i': - flags &= ~FILEUTILS_FORCE; - flags |= FILEUTILS_INTERACTIVE; - break; - case 'R': - case 'r': - flags |= FILEUTILS_RECUR; - break; - } - } - - if (!(flags & FILEUTILS_FORCE) && optind == argc) - show_usage(); - - for (i = optind; i < argc; i++) { - char *base = get_last_path_component(argv[i]); - - if (strcmp(base, ".") == 0 || strcmp(base, "..") == 0) { - error_msg("cannot remove `.' or `..'"); - status = 1; - continue; - } - - if (remove_file(argv[i], flags) < 0) - status = 1; - } - - return status; -} diff --git a/rmdir.c b/rmdir.c deleted file mode 100644 index cac27cac9..000000000 --- a/rmdir.c +++ /dev/null @@ -1,97 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini rmdir implementation for busybox - * - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include - -#include "busybox.h" - - -/* Return true if a path is composed of multiple components. */ - -static int -multiple_components_p (const char *path) -{ - const char *s = path; - - while (s[0] != '\0' && s[0] != '/') - s++; - - while (s[0] == '/') - s++; - - return (s[0] != '\0'); -} - - -/* Remove a directory. Returns 0 if successful, -1 on error. */ - -static int -remove_directory (char *path, int flags) -{ - if (!(flags & FILEUTILS_RECUR)) { - if (rmdir (path) < 0) { - perror_msg ("unable to remove `%s'", path); - return -1; - } - } else { - if (remove_directory (path, 0) < 0) - return -1; - - if (multiple_components_p (path)) - if (remove_directory (dirname (path), flags) < 0) - return -1; - } - - return 0; -} - - -extern int -rmdir_main (int argc, char **argv) -{ - int status = EXIT_SUCCESS; - int flags = 0; - int i, opt; - - while ((opt = getopt (argc, argv, "p")) != -1) - switch (opt) { - case 'p': - flags |= FILEUTILS_RECUR; - break; - - default: - show_usage (); - } - - if (optind == argc) - show_usage(); - - for (i = optind; i < argc; i++) - if (remove_directory (argv[i], flags) < 0) - status = EXIT_FAILURE; - - return status; -} diff --git a/rmmod.c b/rmmod.c deleted file mode 100644 index 7596d0232..000000000 --- a/rmmod.c +++ /dev/null @@ -1,62 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini rmmod implementation for busybox - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen , - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include "busybox.h" - -extern int delete_module(const char * name); - - -extern int rmmod_main(int argc, char **argv) -{ - int n, ret = EXIT_SUCCESS; - - /* Parse command line. */ - while ((n = getopt(argc, argv, "a")) != EOF) { - switch (n) { - case 'a': - /* Unload _all_ unused modules via NULL delete_module() call */ - if (delete_module(NULL)) - perror_msg_and_die("rmmod"); - return EXIT_SUCCESS; - default: - show_usage(); - } - } - - if (optind == argc) - show_usage(); - - for (n = optind; n < argc; n++) { - if (delete_module(argv[n]) < 0) { - perror_msg("%s", argv[n]); - ret = EXIT_FAILURE; - } - } - - return(ret); -} diff --git a/route.c b/route.c deleted file mode 100644 index ee3533100..000000000 --- a/route.c +++ /dev/null @@ -1,452 +0,0 @@ -/* route - * - * Similar to the standard Unix route, but with only the necessary - * parts for AF_INET - * - * Bjorn Wesen, Axis Communications AB - * - * Author of the original route: - * Fred N. van Kempen, - * (derived from FvK's 'route.c 1.70 01/04/94') - * - * This program is free software; you can redistribute it - * and/or modify it under the terms of the GNU General - * Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * $Id: route.c,v 1.13 2001/09/05 19:32:00 andersen Exp $ - * - * displayroute() code added by Vladimir N. Oleynik - * adjustments by Larry Doolittle - */ - -#include -#include -#include -#include -#include // HZ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "busybox.h" - -#define _(x) x - -#define RTACTION_ADD 1 -#define RTACTION_DEL 2 -#define RTACTION_HELP 3 -#define RTACTION_FLUSH 4 -#define RTACTION_SHOW 5 - -#define E_NOTFOUND 8 -#define E_SOCK 7 -#define E_LOOKUP 6 -#define E_VERSION 5 -#define E_USAGE 4 -#define E_OPTERR 3 -#define E_INTERN 2 -#define E_NOSUPP 1 - -/* resolve XXX.YYY.ZZZ.QQQ -> binary */ - -static int -INET_resolve(char *name, struct sockaddr *sa) -{ - struct sockaddr_in *s_in = (struct sockaddr_in *)sa; - - s_in->sin_family = AF_INET; - s_in->sin_port = 0; - - /* Default is special, meaning 0.0.0.0. */ - if (strcmp(name, "default")==0) { - s_in->sin_addr.s_addr = INADDR_ANY; - return 1; - } - /* Look to see if it's a dotted quad. */ - if (inet_aton(name, &s_in->sin_addr)) { - return 0; - } - /* guess not.. */ - return -1; -} - -#if defined (SIOCADDRTOLD) || defined (RTF_IRTT) /* route */ -#define HAVE_NEW_ADDRT 1 -#endif -#ifdef RTF_IRTT /* route */ -#define HAVE_RTF_IRTT 1 -#endif -#ifdef RTF_REJECT /* route */ -#define HAVE_RTF_REJECT 1 -#endif - -#if HAVE_NEW_ADDRT -#define mask_in_addr(x) (((struct sockaddr_in *)&((x).rt_genmask))->sin_addr.s_addr) -#define full_mask(x) (x) -#else -#define mask_in_addr(x) ((x).rt_genmask) -#define full_mask(x) (((struct sockaddr_in *)&(x))->sin_addr.s_addr) -#endif - -/* add or delete a route depending on action */ - -static int -INET_setroute(int action, int options, char **args) -{ - struct rtentry rt; - char target[128], gateway[128] = "NONE", netmask[128] = "default"; - int xflag, isnet; - int skfd; - - xflag = 0; - - if (*args == NULL) - show_usage(); - if (strcmp(*args, "-net")==0) { - xflag = 1; - args++; - } else if (strcmp(*args, "-host")==0) { - xflag = 2; - args++; - } - safe_strncpy(target, *args++, (sizeof target)); - - /* Clean out the RTREQ structure. */ - memset((char *) &rt, 0, sizeof(struct rtentry)); - - - if ((isnet = INET_resolve(target, &rt.rt_dst)) < 0) { - error_msg(_("can't resolve %s"), target); - return EXIT_FAILURE; /* XXX change to E_something */ - } - - switch (xflag) { - case 1: - isnet = 1; - break; - - case 2: - isnet = 0; - break; - - default: - break; - } - - /* Fill in the other fields. */ - rt.rt_flags = (RTF_UP | RTF_HOST); - if (isnet) - rt.rt_flags &= ~RTF_HOST; - - while (*args) { - if (strcmp(*args, "metric")==0) { - int metric; - - args++; - if (!*args || !isdigit(**args)) - show_usage(); - metric = atoi(*args); -#if HAVE_NEW_ADDRT - rt.rt_metric = metric + 1; -#else - ENOSUPP("inet_setroute", "NEW_ADDRT (metric)"); /* XXX Fixme */ -#endif - args++; - continue; - } - - if (strcmp(*args, "netmask")==0) { - struct sockaddr mask; - - args++; - if (!*args || mask_in_addr(rt)) - show_usage(); - safe_strncpy(netmask, *args, (sizeof netmask)); - if ((isnet = INET_resolve(netmask, &mask)) < 0) { - error_msg(_("can't resolve netmask %s"), netmask); - return E_LOOKUP; - } - rt.rt_genmask = full_mask(mask); - args++; - continue; - } - - if (strcmp(*args, "gw")==0 || strcmp(*args, "gateway")==0) { - args++; - if (!*args) - show_usage(); - if (rt.rt_flags & RTF_GATEWAY) - show_usage(); - safe_strncpy(gateway, *args, (sizeof gateway)); - if ((isnet = INET_resolve(gateway, &rt.rt_gateway)) < 0) { - error_msg(_("can't resolve gw %s"), gateway); - return E_LOOKUP; - } - if (isnet) { - error_msg( - _("%s: cannot use a NETWORK as gateway!"), - gateway); - return E_OPTERR; - } - rt.rt_flags |= RTF_GATEWAY; - args++; - continue; - } - - if (strcmp(*args, "mss")==0) { - args++; - rt.rt_flags |= RTF_MSS; - if (!*args) - show_usage(); - rt.rt_mss = atoi(*args); - args++; - if (rt.rt_mss < 64 || rt.rt_mss > 32768) { - error_msg(_("Invalid MSS.")); - return E_OPTERR; - } - continue; - } - - if (strcmp(*args, "window")==0) { - args++; - if (!*args) - show_usage(); - rt.rt_flags |= RTF_WINDOW; - rt.rt_window = atoi(*args); - args++; - if (rt.rt_window < 128) { - error_msg(_("Invalid window.")); - return E_OPTERR; - } - continue; - } - - if (strcmp(*args, "irtt")==0) { - args++; - if (!*args) - show_usage(); - args++; -#if HAVE_RTF_IRTT - rt.rt_flags |= RTF_IRTT; - rt.rt_irtt = atoi(*(args - 1)); - rt.rt_irtt *= (HZ / 100); /* FIXME */ -#if 0 /* FIXME: do we need to check anything of this? */ - if (rt.rt_irtt < 1 || rt.rt_irtt > (120 * HZ)) { - error_msg(_("Invalid initial rtt.")); - return E_OPTERR; - } -#endif -#else - ENOSUPP("inet_setroute", "RTF_IRTT"); /* XXX Fixme */ -#endif - continue; - } - - if (strcmp(*args, "reject")==0) { - args++; -#if HAVE_RTF_REJECT - rt.rt_flags |= RTF_REJECT; -#else - ENOSUPP("inet_setroute", "RTF_REJECT"); /* XXX Fixme */ -#endif - continue; - } - if (strcmp(*args, "mod")==0) { - args++; - rt.rt_flags |= RTF_MODIFIED; - continue; - } - if (strcmp(*args, "dyn")==0) { - args++; - rt.rt_flags |= RTF_DYNAMIC; - continue; - } - if (strcmp(*args, "reinstate")==0) { - args++; - rt.rt_flags |= RTF_REINSTATE; - continue; - } - if (strcmp(*args, "device")==0 || strcmp(*args, "dev")==0) { - args++; - if (rt.rt_dev || *args == NULL) - show_usage(); - rt.rt_dev = *args++; - continue; - } - /* nothing matches */ - if (!rt.rt_dev) { - rt.rt_dev = *args++; - if (*args) - show_usage(); /* must be last to catch typos */ - } else { - show_usage(); - } - } - -#if HAVE_RTF_REJECT - if ((rt.rt_flags & RTF_REJECT) && !rt.rt_dev) - rt.rt_dev = "lo"; -#endif - - /* sanity checks.. */ - if (mask_in_addr(rt)) { - unsigned long mask = mask_in_addr(rt); - mask = ~ntohl(mask); - if ((rt.rt_flags & RTF_HOST) && mask != 0xffffffff) { - error_msg( - _("netmask %.8x doesn't make sense with host route"), - (unsigned int)mask); - return E_OPTERR; - } - if (mask & (mask + 1)) { - error_msg(_("bogus netmask %s"), netmask); - return E_OPTERR; - } - mask = ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr; - if (mask & ~mask_in_addr(rt)) { - error_msg(_("netmask doesn't match route address")); - return E_OPTERR; - } - } - /* Fill out netmask if still unset */ - if ((action == RTACTION_ADD) && rt.rt_flags & RTF_HOST) - mask_in_addr(rt) = 0xffffffff; - - /* Create a socket to the INET kernel. */ - if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - perror("socket"); - return E_SOCK; - } - /* Tell the kernel to accept this route. */ - if (action == RTACTION_DEL) { - if (ioctl(skfd, SIOCDELRT, &rt) < 0) { - perror("SIOCDELRT"); - close(skfd); - return E_SOCK; - } - } else { - if (ioctl(skfd, SIOCADDRT, &rt) < 0) { - perror("SIOCADDRT"); - close(skfd); - return E_SOCK; - } - } - - /* Close the socket. */ - (void) close(skfd); - return EXIT_SUCCESS; -} - -#ifndef RTF_UP -/* Keep this in sync with /usr/src/linux/include/linux/route.h */ -#define RTF_UP 0x0001 /* route usable */ -#define RTF_GATEWAY 0x0002 /* destination is a gateway */ -#define RTF_HOST 0x0004 /* host entry (net otherwise) */ -#define RTF_REINSTATE 0x0008 /* reinstate route after tmout */ -#define RTF_DYNAMIC 0x0010 /* created dyn. (by redirect) */ -#define RTF_MODIFIED 0x0020 /* modified dyn. (by redirect) */ -#define RTF_MTU 0x0040 /* specific MTU for this route */ -#ifndef RTF_MSS -#define RTF_MSS RTF_MTU /* Compatibility :-( */ -#endif -#define RTF_WINDOW 0x0080 /* per route window clamping */ -#define RTF_IRTT 0x0100 /* Initial round trip time */ -#define RTF_REJECT 0x0200 /* Reject route */ -#endif - -static void displayroutes(void) -{ - char buff[256]; - int nl = 0 ; - struct in_addr dest; - struct in_addr gw; - struct in_addr mask; - int flgs, ref, use, metric; - char flags[64]; - unsigned long int d,g,m; - - char sdest[16], sgw[16]; - - - FILE *fp = xfopen("/proc/net/route", "r"); - - while( fgets(buff, sizeof(buff), fp) != NULL ) { - if(nl) { - int ifl = 0; - while(buff[ifl]!=' ' && buff[ifl]!='\t' && buff[ifl]!='\0') - ifl++; - buff[ifl]=0; /* interface */ - if(sscanf(buff+ifl+1, "%lx%lx%X%d%d%d%lx", - &d, &g, &flgs, &ref, &use, &metric, &m)!=7) { - error_msg_and_die( "Unsuported kernel route format\n"); - } - if(nl==1) - printf("Kernel IP routing table\n" - "Destination Gateway Genmask Flags Metric Ref Use Iface\n"); - - ifl = 0; /* parse flags */ - if(flgs&RTF_UP) { - if(flgs&RTF_REJECT) - flags[ifl++]='!'; - else - flags[ifl++]='U'; - if(flgs&RTF_GATEWAY) - flags[ifl++]='G'; - if(flgs&RTF_HOST) - flags[ifl++]='H'; - if(flgs&RTF_REINSTATE) - flags[ifl++]='R'; - if(flgs&RTF_DYNAMIC) - flags[ifl++]='D'; - if(flgs&RTF_MODIFIED) - flags[ifl++]='M'; - flags[ifl]=0; - dest.s_addr = d; - gw.s_addr = g; - mask.s_addr = m; - strcpy(sdest, (dest.s_addr==0 ? "default" : - inet_ntoa(dest))); - strcpy(sgw, (gw.s_addr==0 ? "*" : - inet_ntoa(gw))); - printf("%-16s%-16s%-16s%-6s%-6d %-2d %7d %s\n", - sdest, sgw, - inet_ntoa(mask), - flags, metric, ref, use, buff); - } - } - nl++; - } -} - -int route_main(int argc, char **argv) -{ - int what = 0; - - argc--; - argv++; - - if (*argv == NULL) { - displayroutes(); - return EXIT_SUCCESS; - } else { - /* check verb */ - if (strcmp(*argv, "add")==0) - what = RTACTION_ADD; - else if (strcmp(*argv, "del")==0 || strcmp(*argv, "delete")==0) - what = RTACTION_DEL; - else if (strcmp(*argv, "flush")==0) - what = RTACTION_FLUSH; - else - show_usage(); - } - - return INET_setroute(what, 0, ++argv); -} diff --git a/rpm2cpio.c b/rpm2cpio.c deleted file mode 100644 index 8d639d6ad..000000000 --- a/rpm2cpio.c +++ /dev/null @@ -1,91 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini rpm2cpio implementation for busybox - * - * Copyright (C) 2001 by Laurence Anderson - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "busybox.h" -#include /* For ntohl & htonl function */ -#include - -#define RPM_MAGIC "\355\253\356\333" -#define RPM_HEADER_MAGIC "\216\255\350" - -struct rpm_lead { - unsigned char magic[4]; - u_int8_t major, minor; - u_int16_t type; - u_int16_t archnum; - char name[66]; - u_int16_t osnum; - u_int16_t signature_type; - char reserved[16]; -}; - -struct rpm_header { - char magic[3]; /* 3 byte magic: 0x8e 0xad 0xe8 */ - u_int8_t version; /* 1 byte version number */ - u_int32_t reserved; /* 4 bytes reserved */ - u_int32_t entries; /* Number of entries in header (4 bytes) */ - u_int32_t size; /* Size of store (4 bytes) */ -}; - -void skip_header(FILE *rpmfile) -{ - struct rpm_header header; - - fread(&header, sizeof(struct rpm_header), 1, rpmfile); - if (strncmp((char *) &header.magic, RPM_HEADER_MAGIC, 3) != 0) error_msg_and_die("Invalid RPM header magic"); /* Invalid magic */ - if (header.version != 1) error_msg_and_die("Unsupported RPM header version"); /* This program only supports v1 headers */ - header.entries = ntohl(header.entries); - header.size = ntohl(header.size); - fseek (rpmfile, 16 * header.entries, SEEK_CUR); /* Seek past index entries */ - fseek (rpmfile, header.size, SEEK_CUR); /* Seek past store */ -} - -/* No getopt required */ -extern int rpm2cpio_main(int argc, char **argv) -{ - struct rpm_lead lead; - int gunzip_pid; - FILE *rpmfile, *cpiofile; - - if (argc == 1) { - rpmfile = stdin; - } else { - rpmfile = fopen(argv[1], "r"); - if (!rpmfile) perror_msg_and_die("Can't open rpm file"); - /* set the buffer size */ - setvbuf(rpmfile, NULL, _IOFBF, 0x8000); - } - - fread (&lead, sizeof(struct rpm_lead), 1, rpmfile); - if (strncmp((char *) &lead.magic, RPM_MAGIC, 4) != 0) error_msg_and_die("Invalid RPM magic"); /* Just check the magic, the rest is irrelevant */ - /* Skip the signature header */ - skip_header(rpmfile); - fseek(rpmfile, (8 - (ftell(rpmfile) % 8)) % 8, SEEK_CUR); /* Pad to 8 byte boundary */ - /* Skip the main header */ - skip_header(rpmfile); - - cpiofile = gz_open(rpmfile, &gunzip_pid); - - copyfd(fileno(cpiofile), fileno(stdout)); - gz_close(gunzip_pid); - fclose(rpmfile); - return 0; -} diff --git a/scripts/Configure b/scripts/Configure new file mode 100644 index 000000000..01637bdbe --- /dev/null +++ b/scripts/Configure @@ -0,0 +1,705 @@ +#! /bin/sh +# +# This script is used to configure BusyBox. +# +# It was inspired by the challenge in the original Configure script +# to ``do something better'', combined with the actual need to ``do +# something better'' because the old configure script wasn't flexible +# enough. +# +# Raymond Chen was the original author of Configure. +# Michael Elizabeth Chastain (mec@shout.net) is the current maintainer. +# +# 050793 - use IFS='@' to get around a bug in a pre-version of bash-1.13 +# with an empty IFS. +# +# 030995 (storner@osiris.ping.dk) - added support for tri-state answers, +# for selecting modules to compile. +# +# 180995 Bernhard Kaindl (bkaindl@ping.at) - added dummy functions for +# use with a config.in modified for make menuconfig. +# +# 301195 (boldt@math.ucsb.edu) - added help text support +# +# 281295 Paul Gortmaker - make tri_state functions collapse to boolean +# if module support is not enabled. +# +# 010296 Aaron Ucko (ucko@vax1.rockhurst.edu) - fix int and hex to accept +# arbitrary ranges +# +# 150296 Dick Streefland (dicks@tasking.nl) - report new configuration +# items and ask for a value even when doing a "make oldconfig" +# +# 200396 Tom Dyas (tdyas@eden.rutgers.edu) - when the module option is +# chosen for an item, define the macro _MODULE +# +# 090397 Axel Boldt (boldt@math.ucsb.edu) - avoid ? and + in regular +# expressions for GNU expr since version 1.15 and up use \? and \+. +# +# 300397 Phil Blundell (pjb27@cam.ac.uk) - added support for min/max +# arguments to "int", allow dep_tristate to take a list of dependencies +# rather than just one. +# +# 090398 Axel Boldt (boldt@math.ucsb.edu) - allow for empty lines in help +# texts. +# +# 102598 Michael Chastain (mec@shout.net) - put temporary files in +# current directory, not in /tmp. +# +# 24 January 1999, Michael Elizabeth Chastain, +# - Improve the exit message (Jeff Ronne). +# +# 7 October 2000, Ghozlane Toumi, +# added switches for "random" , "all yes" and "all modules" +# + +# +# Make sure we're really running bash. +# +# I would really have preferred to write this script in a language with +# better string handling, but alas, bash is the only scripting language +# that I can be reasonable sure everybody has on their linux machine. +# +[ -z "$BASH" ] && { echo "Configure requires bash" 1>&2; exit 1; } + +# Disable filename globbing once and for all. +# Enable function cacheing. +set -f -h + +# +# Dummy functions for use with a config.in modified for menuconf +# +function mainmenu_option () { + : +} +function mainmenu_name () { + : +} +function endmenu () { + : +} + +# +# returns a random number between 1 and $1 +# +function rnd () { + rnd=$[ $RANDOM % $1 + 1 ] +} + +# +# randomly chose a number in a config list (LIST_CONFIG_NAME) +# or in a range ( MIN_CONFIG_NAME MAX_CONFIG_NAME ) +# ONLY if there is no forced default (and we are in an "auto" mode) +# we are limited by the range of values taken by "$RANDOM" +# +# rndval CONFIG_NAME +# + +function rndval () { + [ "$AUTO" != "yes" -o -n "$old" ] && return + def_list=$(eval echo "\${LIST_$1}") + def_min=$(eval echo "\${MIN_$1}") + def_max=$(eval echo "\${MAX_$1}") + + if [ -n "$def_list" ]; then + set -- $(echo $def_list | sed 's/,/ /g') + rnd $# + while [ $rnd -le $# ] ; do + def=$1 + shift + done + return + fi + if [ -n "$def_min" -a -n "$def_max" ]; then + rnd $[ $def_max - $def_min ] + def=$[ $def_min + $rnd ] + fi +} + +# +# help prints the corresponding help text from Configure.help to stdout +# +# help variable +# +function help () { + if [ -f Documentation/Configure.help ] + then + #first escape regexp special characters in the argument: + var=$(echo "$1"|sed 's/[][\/.^$*]/\\&/g') + #now pick out the right help text: + text=$(sed -n "/^$var[ ]*\$/,\${ + /^$var[ ]*\$/c\\ +${var}:\\ + + /^#/b + /^[^ ]/q + /]*\\)>/s//\\1/g + p + }" Documentation/Configure.help) + if [ -z "$text" ] + then + echo; echo " Sorry, no help available for this option yet.";echo + else + (echo; echo "$text") | ${PAGER:-more} + fi + else + echo; + echo " Can't access the file Documentation/Configure.help which" + echo " should contain the help texts." + echo + fi +} + + +# +# readln reads a line into $ans. +# +# readln prompt default oldval +# +function readln () { + if [ "$AUTO" = "yes" ]; then + echo -n "$1" + ans=$2 + echo $ans + elif [ "$DEFAULT" = "-d" -a -n "$3" ]; then + echo "$1" + ans=$2 + else + echo -n "$1" + [ -z "$3" ] && echo -n "(NEW) " + IFS='@' read ans || exit 1 + [ -z "$ans" ] && ans=$2 + fi +} + +# +# comment does some pretty-printing +# +# comment 'xxx' +# +function comment () { + echo "*"; echo "* $1" ; echo "*" + (echo "" ; echo "#"; echo "# $1" ; echo "#") >>$CONFIG + (echo "" ; echo "/*"; echo " * $1" ; echo " */") >>$CONFIG_H +} + +# +# define_bool sets the value of a boolean argument +# +# define_bool define value +# +function define_bool () { + define_tristate $1 $2 +} + +function define_tristate () { + case "$2" in + "y") + echo "$1=y" >>$CONFIG + echo "#define $1 1" >>$CONFIG_H + ;; + + "m") + echo "$1=m" >>$CONFIG + echo "#undef $1" >>$CONFIG_H + echo "#define $1_MODULE 1" >>$CONFIG_H + ;; + + "n") + echo "# $1 is not set" >>$CONFIG + echo "#undef $1" >>$CONFIG_H + ;; + esac + eval "$1=$2" +} + +# +# bool processes a boolean argument +# +# bool question define +# +function bool () { + old=$(eval echo "\${$2}") + def=${old:-'n'} + if [ "$AUTO" = "yes" -a -z "$old" ]; then + if [ "$RND" = "-r" ]; then + rnd 2 + case $rnd in + "1") def="y" ;; + "2") def="n" ;; + esac + else + def=$DEF_ANS; + fi + fi + case "$def" in + "y" | "m") defprompt="Y/n/?" + def="y" + ;; + "n") defprompt="N/y/?" + ;; + esac + while :; do + readln "$1 ($2) [$defprompt] " "$def" "$old" + case "$ans" in + [yY] | [yY]es ) define_bool "$2" "y" + break;; + [nN] | [nN]o ) define_bool "$2" "n" + break;; + * ) help "$2" + ;; + esac + done +} + +# +# tristate processes a tristate argument +# +# tristate question define +# +function tristate () { + if [ "$CONFIG_MODULES" != "y" ]; then + bool "$1" "$2" + else + old=$(eval echo "\${$2}") + def=${old:-'n'} + if [ "$AUTO" = "yes" -a -z "$old" ]; then + if [ "$RND" = "-r" ]; then + rnd 3 + case $rnd in + "1") def="y" ;; + "2") def="n" ;; + "3") def="m" ;; + esac + else + def=$DEF_ANS + fi + fi + case "$def" in + "y") defprompt="Y/m/n/?" + ;; + "m") defprompt="M/n/y/?" + ;; + "n") defprompt="N/y/m/?" + ;; + esac + while :; do + readln "$1 ($2) [$defprompt] " "$def" "$old" + case "$ans" in + [yY] | [yY]es ) define_tristate "$2" "y" + break ;; + [nN] | [nN]o ) define_tristate "$2" "n" + break ;; + [mM] ) define_tristate "$2" "m" + break ;; + * ) help "$2" + ;; + esac + done + fi +} + +# +# dep_tristate processes a tristate argument that depends upon +# another option or options. If any of the options we depend upon is a +# module, then the only allowable options are M or N. If all are Y, then +# this is a normal tristate. This is used in cases where modules +# are nested, and one module requires the presence of something +# else in the kernel. +# +# dep_tristate question define default ... +# +function dep_tristate () { + old=$(eval echo "\${$2}") + def=${old:-'n'} + ques=$1 + var=$2 + need_module=0 + shift 2 + while [ $# -gt 0 ]; do + case "$1" in + n) + define_tristate "$var" "n" + return + ;; + m) + need_module=1 + ;; + esac + shift + done + + if [ $need_module = 1 ]; then + if [ "$CONFIG_MODULES" = "y" ]; then + if [ "$AUTO" = "yes" -a -z "$old" ]; then + if [ "$RND" = "-r" ]; then + rnd 2 + case $rnd in + "1") def="m" ;; + "2") def="n" ;; + esac + else + def=$DEF_ANS + fi + fi + case "$def" in + "y" | "m") defprompt="M/n/?" + def="m" + ;; + "n") defprompt="N/m/?" + ;; + esac + while :; do + readln "$ques ($var) [$defprompt] " "$def" "$old" + case "$ans" in + [nN] | [nN]o ) define_tristate "$var" "n" + break ;; + [mM] ) define_tristate "$var" "m" + break ;; + [yY] | [yY]es ) echo + echo " This answer is not allowed, because it is not consistent with" + echo " your other choices." + echo " This driver depends on another one which you chose to compile" + echo " as a module. This means that you can either compile this one" + echo " as a module as well (with M) or leave it out altogether (N)." + echo + ;; + * ) help "$var" + ;; + esac + done + fi + else + tristate "$ques" "$var" + fi +} + +function dep_bool () { + ques=$1 + var=$2 + shift 2 + while [ $# -gt 0 ]; do + case "$1" in + m | n) + define_bool "$var" "n" + return + ;; + esac + shift + done + + bool "$ques" "$var" +} + +function dep_mbool () { + ques=$1 + var=$2 + shift 2 + while [ $# -gt 0 ]; do + case "$1" in + n) + define_bool "$var" "n" + return + ;; + esac + shift + done + + bool "$ques" "$var" +} + +# +# define_int sets the value of a integer argument +# +# define_int define value +# +function define_int () { + echo "$1=$2" >>$CONFIG + echo "#define $1 ($2)" >>$CONFIG_H + eval "$1=$2" +} + +# +# int processes an integer argument with optional limits +# +# int question define default [min max] +# +function int () { + old=$(eval echo "\${$2}") + def=${old:-$3} + if [ $# -gt 3 ]; then + min=$4 + else + min=-10000000 # !! + fi + if [ $# -gt 4 ]; then + max=$5 + else + max=10000000 # !! + fi + rndval $2 + while :; do + readln "$1 ($2) [$def] " "$def" "$old" + if expr \( \( $ans + 0 \) \>= $min \) \& \( $ans \<= $max \) >/dev/null 2>&1 ; then + define_int "$2" "$ans" + break + else + help "$2" + fi + done +} + +# +# define_hex sets the value of a hexadecimal argument +# +# define_hex define value +# +function define_hex () { + echo "$1=$2" >>$CONFIG + echo "#define $1 0x${2#*[x,X]}" >>$CONFIG_H + eval "$1=$2" +} + +# +# hex processes an hexadecimal argument +# +# hex question define default +# +function hex () { + old=$(eval echo "\${$2}") + def=${old:-$3} + def=${def#*[x,X]} + rndval $2 + while :; do + readln "$1 ($2) [$def] " "$def" "$old" + ans=${ans#*[x,X]} + if expr "$ans" : '[0-9a-fA-F][0-9a-fA-F]*$' > /dev/null; then + define_hex "$2" "$ans" + break + else + help "$2" + fi + done +} + +# +# define_string sets the value of a string argument +# +# define_string define value +# +function define_string () { + echo "$1=\"$2\"" >>$CONFIG + echo "#define $1 \"$2\"" >>$CONFIG_H + eval "$1=\"$2\"" +} + +# +# string processes a string argument +# +# string question define default +# +function string () { + old=$(eval echo "\${$2}") + def=${old:-$3} + while :; do + if [ "$old" = "?" ]; then + readln "$1 ($2) [$def] " "$def" "" + else + readln "$1 ($2) [$def] " "$def" "$old" + fi + if [ "$ans" = "?" ]; then + help "$2" + else + break + fi + done + define_string "$2" "$ans" +} +# +# choice processes a choice list (1-out-of-n) +# +# choice question choice-list default +# +# The choice list has a syntax of: +# NAME WHITESPACE VALUE { WHITESPACE NAME WHITESPACE VALUE } +# The user may enter any unique prefix of one of the NAMEs and +# choice will define VALUE as if it were a boolean option. +# VALUE must be in all uppercase. Normally, VALUE is of the +# form CONFIG_. Thus, if the user selects , +# the CPP symbol CONFIG_ will be defined and the +# shell variable CONFIG_ will be set to "y". +# +function choice () { + question="$1" + choices="$2" + old= + def=$3 + + # determine default answer: + names="" + set -- $choices + firstvar=$2 + while [ -n "$2" ]; do + if [ -n "$names" ]; then + names="$names, $1" + else + names="$1" + fi + if [ "$(eval echo \"\${$2}\")" = "y" ]; then + old=$1 + def=$1 + fi + shift; shift + done + + if [ "$RND" = "-r" -a -z "$old" ] ; then + set -- $choices + rnd $# + while [ $rnd -le $# ] ; do + def=$1 + shift ; shift + done + fi + + val="" + while [ -z "$val" ]; do + ambg=n + readln "$question ($names) [$def] " "$def" "$old" + ans=$(echo $ans | tr a-z A-Z) + set -- $choices + while [ -n "$1" ]; do + name=$(echo $1 | tr a-z A-Z) + case "$name" in + "$ans"* | */"$ans"* ) + case "$name" in + "$ans" | */"$ans"/* | \ + "$ans"/* | */"$ans" ) + val="$2" + break # exact match + ;; + esac + if [ -n "$val" ]; then + echo;echo \ + " Sorry, \"$ans\" is ambiguous; please enter a longer string." + echo + val="" + ambg=y + break + else + val="$2" + fi;; + esac + shift; shift + done + if [ "$val" = "" -a "$ambg" = "n" ]; then + help "$firstvar" + fi + done + set -- $choices + while [ -n "$2" ]; do + if [ "$2" = "$val" ]; then + echo " defined $val" + define_bool "$2" "y" + else + define_bool "$2" "n" + fi + shift; shift + done +} + +CONFIG=.tmpconfig +CONFIG_H=.tmpconfig.h +FORCE_DEFAULT=.force_default +trap "rm -f $CONFIG $CONFIG_H ; exit 1" 1 2 + +# +# Make sure we start out with a clean slate. +# +echo "#" > $CONFIG +echo "# Automatically generated make config: don't edit" >> $CONFIG +echo "#" >> $CONFIG + +echo "/*" > $CONFIG_H +echo " * Automatically generated C config: don't edit" >> $CONFIG_H +echo " */" >> $CONFIG_H +echo "#define AUTOCONF_INCLUDED" >> $CONFIG_H + +DEFAULT="" +if [ "$1" = "-d" ] ; then + DEFAULT="-d" + shift +fi + +RND="" +DEF_ANS="" +AUTO="" +case "$1" in + -r) RND="-r" ; AUTO="yes" ; shift ;; + -y) DEF_ANS="y" ; AUTO="yes" ; shift ;; + -m) DEF_ANS="m" ; AUTO="yes" ; shift ;; + -n) DEF_ANS="n" ; AUTO="yes" ; shift ;; +esac + +CONFIG_IN=./config.in +if [ "$1" != "" ] ; then + CONFIG_IN=$1 +fi + +DEFAULTS=sysdeps/$TARGET_OS/defconfig +if [ -f .config ]; then + DEFAULTS=.config +fi + +if [ "$AUTO" != "yes" ]; then + if [ -f $DEFAULTS ]; then + echo "#" + echo "# Using defaults found in" $DEFAULTS + echo "#" + . $DEFAULTS + sed -e 's/# \(CONFIG_[^ ]*\) is not.*/\1=n/' <$DEFAULTS >.config-is-not.$$ + . .config-is-not.$$ + rm .config-is-not.$$ + else + echo "#" + echo "# No defaults found" + echo "#" + fi +else + if [ -f $FORCE_DEFAULT ]; then + echo "#" + echo "# Forcing defaults found in $FORCE_DEFAULT" + echo "#" + sed -e ' +s/# \(CONFIG_[^ ]*\) is not.*/\1=n/; +s/# range \(CONFIG_[^ ]*\) \([^ ][^ ]*\) \([^ ][^ ]*\)/MIN_\1=\2; MAX_\1=\3/; +s/# list \(CONFIG_[^ ]*\) \([^ ][^ ]*\)/LIST_\1=\2/ +' <$FORCE_DEFAULT >.default_val.$$ + . .default_val.$$ + rm .default_val.$$ + else + echo "#" + echo "# No defaults found" + echo "#" + fi +fi + +. $CONFIG_IN + +rm -f .config.old +if [ -f .config ]; then + mv .config .config.old +fi +mv .tmpconfig .config +mv .tmpconfig.h include/config.h + +echo +echo "*** End of BusyBox configuration." +echo "*** Check the top-level Makefile for additional configuration." +if [ ! -f .hdepend -o "$CONFIG_MODVERSIONS" = "y" ] ; then + echo "*** Next, you must run 'make dep'." +else + echo "*** Next, you may run 'make bzImage', 'make bzdisk', or 'make install'." +fi +echo + +exit 0 diff --git a/scripts/Menuconfig b/scripts/Menuconfig new file mode 100644 index 000000000..5d4cdce6b --- /dev/null +++ b/scripts/Menuconfig @@ -0,0 +1,1285 @@ +#! /bin/sh +# +# This script is used to configure BusyBox. +# +# It was inspired by a desire to not have to hit 9 million times +# or startup the X server just to change a single kernel parameter. +# +# This script attempts to parse the configuration files, which are +# scattered throughout the kernel source tree, and creates a temporary +# set of mini scripts which are in turn used to create nested menus and +# radiolists. +# +# It uses a very modified/mutilated version of the "dialog" utility +# written by Savio Lam (lam836@cs.cuhk.hk). Savio is not responsible +# for this script or the version of dialog used by this script. +# Please do not contact him with questions. The official version of +# dialog is available at sunsite.unc.edu or a sunsite mirror. +# +# Portions of this script were borrowed from the original Configure +# script. +# +# William Roadcap was the original author of Menuconfig. +# Michael Elizabeth Chastain (mec@shout.net) is the current maintainer. +# +# 070497 Bernhard Kaindl (bkaindl@netway.at) - get default values for +# new bool, tristate and dep_tristate parameters from the defconfig file. +# new configuration parameters are marked with '(NEW)' as in make config. +# +# 180697 Bernhard Kaindl (bkaindl@netway.at) - added the needed support +# for string options. They are handled like the int and hex options. +# +# 081297 Pavel Machek (pavel@atrey.karlin.mff.cuni.cz) - better error +# handling +# +# 131197 Michael Chastain (mec@shout.net) - output all lines for a +# choice list, not just the selected one. This makes the output +# the same as Configure output, which is important for smart config +# dependencies. +# +# 101297 Michael Chastain (mec@shout.net) - remove sound driver cruft. +# +# 221297 Michael Chastain (mec@shout.net) - make define_bool actually +# define its arguments so that later tests on them work right. +# +# 160198 Michael Chastain (mec@shout.net) - fix bug with 'c' command +# (complement existing value) when used on virgin uninitialized variables. +# +# 090398 Axel Boldt (boldt@math.ucsb.edu) - allow for empty lines in help +# texts. +# +# 12 Dec 1998, Michael Elizabeth Chastain (mec@shout.net) +# Remove a /tmp security hole in get_def (also makes it faster). +# Give uninitialized variables canonical values rather than null value. +# Change a lot of places to call set_x_info uniformly. +# Take out message about preparing version (old sound driver cruft). +# +# 13 Dec 1998, Riley H Williams +# When an error occurs, actually display the error message as well as +# our comments thereon. +# +# 31 Dec 1998, Michael Elizabeth Chastain (mec@shout.net) +# Fix mod_bool to honor $CONFIG_MODULES. +# Fix dep_tristate to call define_bool when dependency is "n". +# +# 02 January 1999, Michael Elizabeth Chastain (mec@shout.net) +# Blow away lxdialog.scrltmp on entry to activate_menu. This protects +# against people who use commands like ' ' to select menus. +# +# 24 January 1999, Michael Elizabeth Chastain, +# - Improve the exit message (Jeff Ronne). +# +# 06 July 1999, Andrzej M. Krzysztofowicz, +# - Support for multiple conditions in dep_tristate(). +# - Implemented new functions: define_tristate(), define_int(), define_hex(), +# define_string(), dep_bool(). +# +# 22 October 2001, Erik Andersen +# - Adjusted for busybox (modified hard coded kernel specific paths, +# and everything to do with modules (tristates, modbools, etc). + + +# +# Change this to TRUE if you prefer all options listed +# in a single menu rather than the standard menu hierarchy. +# +single_menu_mode= + +# +# Make sure we're really running bash. +# +[ -z "$BASH" ] && { echo "Menuconfig requires bash" 1>&2; exit 1; } + +# +# Cache function definitions, turn off posix compliance +# +set -h +o posix + + + +# Given a configuration variable, set the global variable $x to its value, +# and the global variable $info to the string " (NEW)" if this is a new +# variable. +# +# This function looks for: (1) the current value, or (2) the default value +# from the arch-dependent defconfig file, or (3) a default passed by the caller. + +function set_x_info () { + eval x=\$$1 + if [ -z "$x" ]; then + eval `sed -n -e 's/# \(.*\) is not set.*/\1=n/' -e "/^$1=/p" sysdeps/$TARGET_OS/defconfig` + eval x=\${$1:-"$2"} + eval $1=$x + eval INFO_$1="' (NEW)'" + fi + eval info="\$INFO_$1" +} + +# +# Load the functions used by the config.in files. +# +# I do this because these functions must be redefined depending +# on whether they are being called for interactive use or for +# saving a configuration to a file. +# +# Thank the heavens bash supports nesting function definitions. +# +load_functions () { + +# +# Additional comments +# +function comment () { + comment_ctr=$[ comment_ctr + 1 ] + echo -ne "': $comment_ctr' '--- $1' " >>MCmenu +} + +# +# Define a boolean to a specific value. +# +function define_bool () { + eval $1=$2 +} + +function define_hex () { + eval $1=$2 +} + +function define_int () { + eval $1=$2 +} + +function define_string () { + eval $1="$2" +} + +# +# Create a boolean (Yes/No) function for our current menu +# which calls our local bool function. +# +function bool () { + set_x_info "$2" "n" + + case $x in + y|m) flag="*" ;; + n) flag=" " ;; + esac + + echo -ne "'$2' '[$flag] $1$info' " >>MCmenu + + echo -e "function $2 () { l_bool '$2' \"\$1\" ;}\n" >>MCradiolists +} + +# +# Same as above, but now only Y and N are allowed as dependency +# (i.e. third and next arguments). +# +function dep_bool () { + ques="$1" + var="$2" + dep=y + shift 2 + while [ $# -gt 0 ]; do + if [ "$1" = y ]; then + shift + else + dep=n + shift $# + fi + done + if [ "$dep" = y ]; then + bool "$ques" "$var" + else + define_bool "$var" n + fi +} + +function dep_mbool () { + ques="$1" + var="$2" + dep=y + shift 2 + while [ $# -gt 0 ]; do + if [ "$1" = y -o "$1" = m ]; then + shift + else + dep=n + shift $# + fi + done + if [ "$dep" = y ]; then + bool "$ques" "$var" + else + define_bool "$var" n + fi +} + +# +# Add a menu item which will call our local int function. +# +function int () { + set_x_info "$2" "$3" + + echo -ne "'$2' '($x) $1$info' " >>MCmenu + + echo -e "function $2 () { l_int '$1' '$2' '$3' '$x' ;}" >>MCradiolists +} + +# +# Add a menu item which will call our local hex function. +# +function hex () { + set_x_info "$2" "$3" + x=${x##*[x,X]} + + echo -ne "'$2' '($x) $1$info' " >>MCmenu + + echo -e "function $2 () { l_hex '$1' '$2' '$3' '$x' ;}" >>MCradiolists +} + +# +# Add a menu item which will call our local string function. +# +function string () { + set_x_info "$2" "$3" + + echo -ne "'$2' ' $1: \"$x\"$info' " >>MCmenu + + echo -e "function $2 () { l_string '$1' '$2' '$3' '$x' ;}" >>MCradiolists +} + +# +# Add a menu item which will call our local One-of-Many choice list. +# +function choice () { + # + # Need to remember params cause they're gonna get reset. + # + title=$1 + choices=$2 + default=$3 + current= + + # + # Find out if one of the choices is already set. + # If it's not then make it the default. + # + set -- $choices + firstchoice=$2 + + while [ -n "$2" ] + do + if eval [ "_\$$2" = "_y" ] + then + current=$1 + break + fi + shift ; shift + done + + : ${current:=$default} + + echo -ne "'$firstchoice' '($current) $title' " >>MCmenu + + echo -e " + function $firstchoice () \ + { l_choice '$title' \"$choices\" \"$current\" ;}" >>MCradiolists +} + +} # END load_functions() + + + + + +# +# Extract available help for an option from Configure.help +# and send it to standard output. +# +# Most of this function was borrowed from the original kernel +# Configure script. +# +function extract_help () { + if [ -f docs/Configure.help ] + then + #first escape regexp special characters in the argument: + var=$(echo "$1"|sed 's/[][\/.^$*]/\\&/g') + #now pick out the right help text: + text=$(sed -n "/^$var[ ]*\$/,\${ + /^$var[ ]*\$/c\\ +${var}:\\ + + /^#/b + /^[^ ]/q + s/^ // + /]*\\)>/s//\\1/g + p + }" docs/Configure.help) + + if [ -z "$text" ] + then + echo "There is no help available for this option." + return 1 + else + echo "$text" + fi + else + echo "There is no help available for this option." + return 1 + fi +} + +# +# Activate a help dialog. +# +function help () { + if extract_help $1 >help.out + then + $DIALOG --backtitle "$backtitle" --title "$2"\ + --textbox help.out $ROWS $COLS + else + $DIALOG --backtitle "$backtitle" \ + --textbox help.out $ROWS $COLS + fi + rm -f help.out +} + +# +# Show the README file. +# +function show_readme () { + $DIALOG --backtitle "$backtitle" \ + --textbox scripts/README.Menuconfig $ROWS $COLS +} + +# +# Begin building the dialog menu command and Initialize the +# Radiolist function file. +# +function menu_name () { + echo -ne "$DIALOG --title '$1'\ + --backtitle '$backtitle' \ + --menu '$menu_instructions' \ + $ROWS $COLS $((ROWS-10)) \ + '$default' " >MCmenu + >MCradiolists +} + +# +# Add a submenu option to the menu currently under construction. +# +function submenu () { + echo -ne "'activate_menu $2' '$1 --->' " >>MCmenu +} + +# +# Handle a boolean (Yes/No) option. +# +function l_bool () { + if [ -n "$2" ] + then + case "$2" in + y|m) eval $1=y ;; + c) eval x=\$$1 + case $x in + y) eval $1=n ;; + n) eval $1=y ;; + *) eval $1=y ;; + esac ;; + *) eval $1=n ;; + esac + else + echo -ne "\007" + fi +} + +# +# Create a dialog for entering an integer into a option. +# +function l_int () { + while true + do + if $DIALOG --title "$1" \ + --backtitle "$backtitle" \ + --inputbox "$inputbox_instructions_int" \ + 10 75 "$4" 2>MCdialog.out + then + answer="`cat MCdialog.out`" + answer="${answer:-$3}" + + # Semantics of + and ? in GNU expr changed, so + # we avoid them: + if expr "$answer" : '0$' '|' "$answer" : '[1-9][0-9]*$' '|' "$answer" : '-[1-9][0-9]*$' >/dev/null + then + eval $2="$answer" + else + eval $2="$3" + echo -en "\007" + ${DIALOG} --backtitle "$backtitle" \ + --infobox "You have made an invalid entry." 3 43 + sleep 2 + fi + + break + fi + + help "$2" "$1" + done +} + +# +# Create a dialog for entering a hexadecimal into an option. +# +function l_hex () { + while true + do + if $DIALOG --title "$1" \ + --backtitle "$backtitle" \ + --inputbox "$inputbox_instructions_hex" \ + 10 75 "$4" 2>MCdialog.out + then + answer="`cat MCdialog.out`" + answer="${answer:-$3}" + answer="${answer##*[x,X]}" + + if expr "$answer" : '[0-9a-fA-F][0-9a-fA-F]*$' >/dev/null + then + eval $2="$answer" + else + eval $2="$3" + echo -en "\007" + ${DIALOG} --backtitle "$backtitle" \ + --infobox "You have made an invalid entry." 3 43 + sleep 2 + fi + + break + fi + + help "$2" "$1" + done +} + +# +# Create a dialog for entering a string into an option. +# +function l_string () { + while true + do + if $DIALOG --title "$1" \ + --backtitle "$backtitle" \ + --inputbox "$inputbox_instructions_string" \ + 10 75 "$4" 2>MCdialog.out + then + answer="`cat MCdialog.out`" + answer="${answer:-$3}" + + # + # Someone may add a nice check for the entered + # string here... + # + eval $2=\"$answer\" + + break + fi + + help "$2" "$1" + done +} + + +# +# Handle a one-of-many choice list. +# +function l_choice () { + # + # Need to remember params cause they're gonna get reset. + # + title="$1" + choices="$2" + current="$3" + chosen= + + # + # Scan current value of choices and set radiolist switches. + # + list= + set -- $choices + firstchoice=$2 + while [ -n "$2" ] + do + case "$1" in + "$current"*) if [ -z "$chosen" ]; then + list="$list $2 $1 ON " + chosen=1 + else + list="$list $2 $1 OFF " + fi ;; + *) list="$list $2 $1 OFF " ;; + esac + + shift ; shift + done + + while true + do + if $DIALOG --title "$title" \ + --backtitle "$backtitle" \ + --radiolist "$radiolist_instructions" \ + 15 70 6 $list 2>MCdialog.out + then + choice=`cat MCdialog.out` + break + fi + + help "$firstchoice" "$title" + done + + # + # Now set the boolean value of each option based on + # the selection made from the radiolist. + # + set -- $choices + while [ -n "$2" ] + do + if [ "$2" = "$choice" ] + then + eval $2="y" + else + eval $2="n" + fi + + shift ; shift + done +} + +# +# Call awk, and watch for error codes, etc. +# +function callawk () { +awk "$1" || echo "Awk died with error code $?. Giving up." || exit 1 +} + +# +# A faster awk based recursive parser. (I hope) +# +function parser1 () { +callawk ' +BEGIN { + menu_no = 0 + comment_is_option = 0 + parser("'$CONFIG_IN'","MCmenu0") +} + +function parser(ifile,menu) { + + while (getline >menu + + newmenu = sprintf("MCmenu%d", menu_no); + printf( "function MCmenu%s () {\n"\ + "default=$1\n"\ + "menu_name %s\n",\ + menu_no, $0) >newmenu + + parser(ifile, newmenu) + } + else if ($0 ~ /^#|\$MAKE|mainmenu_name/) { + printf("") >>menu + } + else if ($1 ~ "endmenu") { + printf("}\n") >>menu + return + } + else if ($1 == "source") { + parser($2,menu) + } + else { + print >>menu + } + } +}' +} + +# +# Secondary parser for single menu mode. +# +function parser2 () { +callawk ' +BEGIN { + parser("'$CONFIG_IN'","MCmenu0") +} + +function parser(ifile,menu) { + + while (getline >menu + } + else if ($1 ~ /mainmenu_option|endmenu/) { + printf("") >>menu + } + else if ($1 == "source") { + parser($2,menu) + } + else { + print >>menu + } + } +}' +} + +# +# Parse all the config.in files into mini scripts. +# +function parse_config_files () { + rm -f MCmenu* + + echo "function MCmenu0 () {" >MCmenu0 + echo 'default=$1' >>MCmenu0 + echo "menu_name 'Main Menu'" >>MCmenu0 + + if [ "_$single_menu_mode" = "_TRUE" ] + then + parser2 + else + parser1 + fi + + echo "comment ''" >>MCmenu0 + echo "g_alt_config" >>MCmenu0 + echo "s_alt_config" >>MCmenu0 + + echo "}" >>MCmenu0 + + # + # These mini scripts must be sourced into the current + # environment in order for all of this to work. Leaving + # them on the disk as executables screws up the recursion + # in activate_menu(), among other things. Once they are + # sourced we can discard them. + # + for i in MCmenu* + do + echo -n "." + source ./$i + done + rm -f MCmenu* +} + +# +# This is the menu tree's bootstrap. +# +# Executes the parsed menus on demand and creates a set of functions, +# one per configuration option. These functions will in turn execute +# dialog commands or recursively call other menus. +# +function activate_menu () { + rm -f lxdialog.scrltmp + while true + do + comment_ctr=0 #So comment lines get unique tags + + $1 "$default" 2> MCerror #Create the lxdialog menu & functions + + if [ "$?" != "0" ] + then + clear + cat < /' MCerror + cat <. You may also +send a problem report to . + +Please indicate the BusyBox version you are trying to configure and +which menu you were trying to enter when this error occurred. + +EOM + cleanup + exit 1 + fi + rm -f MCerror + + . ./MCradiolists #Source the menu's functions + + . ./MCmenu 2>MCdialog.out #Activate the lxdialog menu + ret=$? + + read selection "*|*"alt_config"*) + show_readme ;; + *) + eval help $selection ;; + esac + ;; + 255|1) + break + ;; + 139) + stty sane + clear + cat < or post a message to + for additional assistance. + +EOM + cleanup + exit 139 + ;; + esac + done +} + +# +# Create a menu item to load an alternate configuration file. +# +g_alt_config () { + echo -n "get_alt_config 'Load an Alternate Configuration File' "\ + >>MCmenu +} + +# +# Get alternate config file name and load the +# configuration from it. +# +get_alt_config () { + set -f ## Switch file expansion OFF + + while true + do + ALT_CONFIG="${ALT_CONFIG:-$DEFAULTS}" + + $DIALOG --backtitle "$backtitle" \ + --inputbox "\ +Enter the name of the configuration file you wish to load. \ +Accept the name shown to restore the configuration you \ +last retrieved. Leave blank to abort."\ + 11 55 "$ALT_CONFIG" 2>MCdialog.out + + if [ "$?" = "0" ] + then + ALT_CONFIG=`cat MCdialog.out` + + [ "_" = "_$ALT_CONFIG" ] && break + + if eval [ -r "$ALT_CONFIG" ] + then + eval load_config_file "$ALT_CONFIG" + break + else + echo -ne "\007" + $DIALOG --backtitle "$backtitle" \ + --infobox "File does not exist!" 3 38 + sleep 2 + fi + else + cat <help.out + +For various reasons, one may wish to keep several different BusyBox +configurations available on a single machine. + +If you have saved a previous configuration in a file other than the +busybox default, entering the name of the file here will allow you +to modify that configuration. + +If you are uncertain, then you have probably never used alternate +configuration files. You should therefor leave this blank to abort. + +EOM + $DIALOG --backtitle "$backtitle"\ + --title "Load Alternate Configuration"\ + --textbox help.out $ROWS $COLS + fi + done + + set +f ## Switch file expansion ON + rm -f help.out MCdialog.out +} + +# +# Create a menu item to store an alternate config file. +# +s_alt_config () { + echo -n "save_alt_config 'Save Configuration to an Alternate File' "\ + >>MCmenu +} + +# +# Get an alternate config file name and save the current +# configuration to it. +# +save_alt_config () { + set -f ## Switch file expansion OFF + + while true + do + $DIALOG --backtitle "$backtitle" \ + --inputbox "\ +Enter a filename to which this configuration should be saved \ +as an alternate. Leave blank to abort."\ + 10 55 "$ALT_CONFIG" 2>MCdialog.out + + if [ "$?" = "0" ] + then + ALT_CONFIG=`cat MCdialog.out` + + [ "_" = "_$ALT_CONFIG" ] && break + + if eval touch $ALT_CONFIG 2>/dev/null + then + eval save_configuration $ALT_CONFIG + load_functions ## RELOAD + break + else + echo -ne "\007" + $DIALOG --backtitle "$backtitle" \ + --infobox "Can't create file! Probably a nonexistent directory." 3 60 + sleep 2 + fi + else + cat <help.out + +For various reasons, one may wish to keep different BusyBox +configurations available on a single machine. + +Entering a file name here will allow you to later retrieve, modify +and use the current configuration as an alternate to whatever +configuration options you have selected at that time. + +If you are uncertain what all this means then you should probably +leave this blank. +EOM + $DIALOG --backtitle "$backtitle"\ + --title "Save Alternate Configuration"\ + --textbox help.out $ROWS $COLS + fi + done + + set +f ## Switch file expansion ON + rm -f help.out MCdialog.out +} + +# +# Load config options from a file. +# Converts all "# OPTION is not set" lines to "OPTION=n" lines +# +function load_config_file () { + awk ' + /# .* is not set.*/ { printf("%s=n\n", $2) } + ! /# .* is not set.*/ { print } + ' $1 >.tmpconfig + + source ./.tmpconfig + rm -f .tmpconfig +} + +# +# Just what it says. +# +save_configuration () { + echo + echo -n "Saving your BusyBox configuration." + + # + # Now, let's redefine the configuration functions for final + # output to the config files. + # + # Nested function definitions, YIPEE! + # + function bool () { + set_x_info "$2" "n" + eval define_bool "$2" "$x" + } + + function dep_bool () { + set_x_info "$2" "n" + var="$2" + shift 2 + while [ $# -gt 0 ]; do + if [ "$1" = y ]; then + shift + else + x=n; shift $# + fi + done + define_bool "$var" "$x" + } + + function int () { + set_x_info "$2" "$3" + echo "$2=$x" >>$CONFIG + echo "#define $2 ($x)" >>$CONFIG_H + } + + function hex () { + set_x_info "$2" "$3" + echo "$2=$x" >>$CONFIG + echo "#define $2 0x${x##*[x,X]}" >>$CONFIG_H + } + + function string () { + set_x_info "$2" "$3" + echo "$2=\"$x\"" >>$CONFIG + echo "#define $2 \"$x\"" >>$CONFIG_H + } + + function define_hex () { + eval $1="$2" + echo "$1=$2" >>$CONFIG + echo "#define $1 0x${2##*[x,X]}" >>$CONFIG_H + } + + function define_int () { + eval $1="$2" + echo "$1=$2" >>$CONFIG + echo "#define $1 ($2)" >>$CONFIG_H + } + + function define_string () { + eval $1="$2" + echo "$1=\"$2\"" >>$CONFIG + echo "#define $1 \"$2\"" >>$CONFIG_H + } + + function define_bool () { + define_tristate "$1" "$2" + } + + function define_tristate () { + eval $1="$2" + + case "$2" in + y) + echo "$1=y" >>$CONFIG + echo "#define $1 1" >>$CONFIG_H + ;; + + n) + echo "# $1 is not set" >>$CONFIG + echo "#undef $1" >>$CONFIG_H + ;; + esac + } + + function choice () { + # + # Find the first choice that's already set to 'y' + # + choices="$2" + default="$3" + current= + chosen= + + set -- $choices + while [ -n "$2" ] + do + if eval [ "_\$$2" = "_y" ] + then + current=$1 + break + fi + shift ; shift + done + + # + # Use the default if none were set. + # + : ${current:=$default} + + # + # Output all choices (to be compatible with other configs). + # + set -- $choices + while [ -n "$2" ] + do + case "$1" in + "$current"*) if [ -z "$chosen" ]; then + define_bool "$2" "y" + chosen=1 + else + define_bool "$2" "n" + fi ;; + *) define_bool "$2" "n" ;; + esac + shift ; shift + done + } + + function mainmenu_name () { + : + } + + function mainmenu_option () { + comment_is_option=TRUE + } + + function endmenu () { + : + } + + function comment () { + if [ "$comment_is_option" ] + then + comment_is_option= + echo >>$CONFIG + echo "#" >>$CONFIG + echo "# $1" >>$CONFIG + echo "#" >>$CONFIG + + echo >>$CONFIG_H + echo "/*" >>$CONFIG_H + echo " * $1" >>$CONFIG_H + echo " */" >>$CONFIG_H + fi + } + + echo -n "." + + DEF_CONFIG="${1:-.config}" + DEF_CONFIG_H="include/config.h" + + CONFIG=.tmpconfig + CONFIG_H=.tmpconfig.h + + echo "#" >$CONFIG + echo "# Automatically generated by make menuconfig: don't edit" >>$CONFIG + echo "#" >>$CONFIG + + echo "/*" >$CONFIG_H + echo " * Automatically generated by make menuconfig: don't edit" >>$CONFIG_H + echo " */" >>$CONFIG_H + echo "#define AUTOCONF_INCLUDED" >> $CONFIG_H + + echo -n "." + if . $CONFIG_IN >>.menuconfig.log 2>&1 + then + if [ "$DEF_CONFIG" = ".config" ] + then + mv $CONFIG_H $DEF_CONFIG_H + fi + + if [ -f "$DEF_CONFIG" ] + then + rm -f ${DEF_CONFIG}.old + mv $DEF_CONFIG ${DEF_CONFIG}.old + fi + + mv $CONFIG $DEF_CONFIG + + return 0 + else + return 1 + fi +} + +# +# Remove temporary files +# +cleanup () { + cleanup1 + cleanup2 +} + +cleanup1 () { + rm -f MCmenu* MCradiolists MCdialog.out help.out +} + +cleanup2 () { + rm -f .tmpconfig .tmpconfig.h +} + +set_geometry () { + # Some distributions export these with incorrect values + # which can really screw up some ncurses programs. + LINES= COLUMNS= + + ROWS=${1:-24} COLS=${2:-80} + + # Just in case the nasty rlogin bug returns. + # + [ $ROWS = 0 ] && ROWS=24 + [ $COLS = 0 ] && COLS=80 + + if [ $ROWS -lt 19 -o $COLS -lt 80 ] + then + echo -e "\n\007Your display is too small to run Menuconfig!" + echo "It must be at least 19 lines by 80 columns." + exit 1 + fi + + ROWS=$((ROWS-4)) COLS=$((COLS-5)) +} + + +set_geometry `stty size 2>/dev/null` + +menu_instructions="\ +Arrow keys navigate the menu. \ +Pressing selects submenus --->. \ +Highlighted letters are hotkeys. \ +Pressing includes, and excludes. \ +Press to exit, for Help. \ +Legend: [*] built-in [ ] excluded " + +radiolist_instructions="\ +Use the arrow keys to navigate this window or \ +press the hotkey of the item you wish to select \ +followed by the . +Press for additional information about this option." + +inputbox_instructions_int="\ +Please enter a decimal value. \ +Fractions will not be accepted. \ +Use the key to move from the input field to the buttons below it." + +inputbox_instructions_hex="\ +Please enter a hexadecimal value. \ +Use the key to move from the input field to the buttons below it." + +inputbox_instructions_string="\ +Please enter a string value. \ +Use the key to move from the input field to the buttons below it." + +DIALOG="./scripts/lxdialog/lxdialog" + +bb_version="${VERSION}" +backtitle="BusyBox v$bb_version Configuration" + +trap "cleanup ; exit 1" 1 2 15 + + +# +# Locate default files. +# +CONFIG_IN=./config.in +if [ "$1" != "" ] ; then + CONFIG_IN=$1 +fi + +DEFAULTS=sysdeps/$TARGET_OS/defconfig +if [ -f .config ]; then + DEFAULTS=.config +fi + +if [ -f $DEFAULTS ] +then + echo "Using defaults found in" $DEFAULTS + load_config_file $DEFAULTS +else + echo "No defaults found" +fi + + +# Fresh new log. +>.menuconfig.log + +# Load the functions used by the config.in files. +echo -n "Preparing scripts: functions" +load_functions + +if [ ! -e $CONFIG_IN ] +then + echo "Your main config.in file ($CONFIG_IN) does not exist" + exit 1 +fi + +if [ ! -x $DIALOG ] +then + echo "Your lxdialog utility does not exist" + exit 1 +fi + +# +# Read config.in files and parse them into one shell function per menu. +# +echo -n ", parsing" +parse_config_files $CONFIG_IN + +echo "done." +# +# Start the ball rolling from the top. +# +activate_menu MCmenu0 + +# +# All done! +# +cleanup1 + +# +# Confirm and Save +# +if $DIALOG --backtitle "$backtitle" \ + --yesno "Do you wish to save your new BusyBox configuration?" 5 60 +then + save_configuration + echo + echo + echo "*** End of BusyBox configuration." + echo "*** Check the top-level Makefile for additional configuration." + if [ ! -f .hdepend ] ; then + echo "*** Next, you must run 'make dep'." + else + echo "*** Next, you should run 'make' or 'make install'." + fi + echo +else + echo + echo + echo Your BusyBox configuration changes were NOT saved. + echo +fi + +# Remove log if empty. +if [ ! -s .menuconfig.log ] ; then + rm -f .menuconfig.log +fi + +exit 0 diff --git a/scripts/depmod.pl b/scripts/depmod.pl deleted file mode 100755 index e65f07b68..000000000 --- a/scripts/depmod.pl +++ /dev/null @@ -1,227 +0,0 @@ -#!/usr/bin/perl -w -# vi: set ts=4: -# Copyright (c) 2001 David Schleef -# Copyright (c) 2001 Erik Andersen -# Copyright (c) 2001 Stuart Hughes -# This program is free software; you can redistribute it and/or modify it -# under the same terms as Perl itself. - -# TODO -- use strict mode... -#use strict; - -use Getopt::Long; -use File::Find; - - -# Set up some default values - -my $basedir=""; -my $kernel; -my $kernelsyms; -my $stdout=1; -my $verbose=0; - - -# get command-line options - -my %opt; - -GetOptions( - \%opt, - "help|h", - "basedir|b=s" => \$basedir, - "kernel|k=s" => \$kernel, - "kernelsyms|F=s" => \$kernelsyms, - "stdout|n" => \$stdout, - "verbose|v" => \$verbose, -); - -if (defined $opt{help}) { - print - "$0 [OPTION]... [basedir]\n", - "\t-h --help\t\tShow this help screen\n", - "\t-b --basedir\t\tModules base directory (defaults to /lib/modules)\n", - "\t-k --kernel\t\tKernel binary for the target\n", - "\t-F --kernelsyms\t\tKernel symbol file\n", - "\t-n --stdout\t\tWrite to stdout instead of modules.dep\n", - "\t-v --verbose\t\tPrint out lots of debugging stuff\n", - ; - exit 1; -} - -if($basedir !~ m-/lib/modules-) { - warn "WARNING: base directory does not match ..../lib/modules\n"; -} - -# Find the list of .o files living under $basedir -#if ($verbose) { printf "Locating all modules\n"; } -my($file) = ""; -my(@liblist) = (); -find sub { - if ( -f $_ && ! -d $_ ) { - $file = $File::Find::name; - if ( $file =~ /.o$/ ) { - push(@liblist, $file); - if ($verbose) { printf "$file\n"; } - } - } -}, $basedir; -if ($verbose) { printf "Finished locating modules\n"; } - -foreach $obj ( @liblist, $kernel ){ - # turn the input file name into a target tag name - # vmlinux is a special that is only used to resolve symbols - if($obj =~ /vmlinux/) { - $tgtname = "vmlinux"; - } else { - ($tgtname) = $obj =~ m-(/lib/modules/.*)$-; - } - - warn "MODULE = $tgtname\n" if $verbose; - - # get a list of symbols - @output=`nm $obj`; - $ksymtab=grep m/ __ksymtab/, @output; - - # gather the exported symbols - if($ksymtab){ - # explicitly exported - foreach ( @output ) { - / __ksymtab_(.*)$/ and do { - warn "sym = $1\n" if $verbose; - $exp->{$1} = $tgtname; - }; - } - } else { - # exporting all symbols - foreach ( @output) { - / [ABCDGRST] (.*)$/ and do { - warn "syma = $1\n" if $verbose; - $exp->{$1} = $tgtname; - }; - } - } - # gather the unresolved symbols - foreach ( @output ) { - !/ __this_module/ && / U (.*)$/ and do { - warn "und = $1\n" if $verbose; - push @{$dep->{$tgtname}}, $1; - }; - } -} - - -# reduce dependancies: remove unresolvable and resolved from vmlinux -# remove duplicates -foreach $module (keys %$dep) { - $mod->{$module} = {}; - foreach (@{$dep->{$module}}) { - if( $exp->{$_} ) { - warn "resolved symbol $_ in file $exp->{$_}\n" if $verbose; - next if $exp->{$_} =~ /vmlinux/; - $mod->{$module}{$exp->{$_}} = 1; - } else { - warn "unresolved symbol $_ in file $module\n"; - } - } -} - -# resolve the dependancies for each module -foreach $module ( keys %$mod ) { - print "$module:\t"; - @sorted = sort bydep keys %{$mod->{$module}}; - print join(" \\\n\t",@sorted); -# foreach $m (@sorted ) { -# print "\t$m\n"; -# } - print "\n\n"; -} - -sub bydep -{ - foreach my $f ( keys %{$mod->{$b}} ) { - if($f eq $a) { - return 1; - } - } - return -1; -} - - - -__END__ - -=head1 NAME - -depmod.pl - a cross platform script to generate kernel module dependency - lists which can then be used by modprobe. - -=head1 SYNOPSIS - -depmod.pl [OPTION]... [FILE]... - -Example: - - depmod.pl -F linux/System.map target/lib/modules - -=head1 DESCRIPTION - -The purpose of this script is to automagically generate a list of of kernel -module dependancies. This script produces dependancy lists that should be -identical to the depmod program from the modutils package. Unlike the depmod -binary, however, depmod.pl is designed to be run on your host system, not -on your target system. - -This script was written by David Schleef to be used in -conjunction with the BusyBox modprobe applet. - -=head1 OPTIONS - -=over 4 - -=item B<-h --help> - -This displays the help message. - -=item B<-b --basedir> - -The base directory uner which the target's modules will be found. This -defaults to the /lib/modules directory. - -=item B<-k --kernel> - -Kernel binary for the target. You must either supply a kernel binary -or a kernel symbol file (using the -F option). - -=item B<-F --kernelsyms> - -Kernel symbol file for the target. You must supply either a kernel symbol file -kernel binary for the target (using the -k option). - -=item B<-n --stdout> - -Write to stdout instead of modules.dep. This is currently hard coded... -kernel binary for the target (using the -k option). - -=item B<--verbose> - -Be verbose (not implemented) - -=back - -=head1 COPYRIGHT - -Copyright (c) 2001 David Schleef -Copyright (c) 2001 Erik Andersen -Copyright (c) 2001 Stuart Hughes -This program is free software; you can redistribute it and/or modify it -under the same terms as Perl itself. - -=head1 AUTHOR - -David Schleef - -=cut - -# $Id: depmod.pl,v 1.1 2001/07/30 19:32:03 andersen Exp $ - diff --git a/scripts/inittab b/scripts/inittab deleted file mode 100644 index 8e7e945b3..000000000 --- a/scripts/inittab +++ /dev/null @@ -1,86 +0,0 @@ -# /etc/inittab init(8) configuration for BusyBox -# -# Copyright (C) 1999 by Lineo, inc. Written by Erik Andersen -# , -# -# -# Note, BusyBox init doesn't support runlevels. The runlevels field is -# completely ignored by BusyBox init. If you want runlevels, use sysvinit. -# -# -# Format for each entry: ::: -# -# : WARNING: This field has a non-traditional meaning for BusyBox init! -# -# The id field is used by BusyBox init to specify the controlling tty for -# the specified process to run on. The contents of this field are -# appended to "/dev/" and used as-is. There is no need for this field to -# be unique, although if it isn't you may have strange results. If this -# field is left blank, it is completely ignored. Also note that if -# BusyBox detects that a serial console is in use, then all entries -# containing non-empty id fields will _not_ be run. BusyBox init does -# nothing with utmp. We don't need no stinkin' utmp. -# -# : The runlevels field is completely ignored. -# -# : Valid actions include: sysinit, respawn, askfirst, wait, once, -# ctrlaltdel, and shutdown. -# -# Note: askfirst acts just like respawn, but before running the specified -# process it displays the line "Please press Enter to activate this -# console." and then waits for the user to press enter before starting -# the specified process. -# -# Note: unrecognised actions (like initdefault) will cause init to emit -# an error message, and then go along with its business. -# -# : Specifies the process to be executed and it's command line. -# -# Note: BusyBox init works just fine without an inittab. If no inittab is -# found, it has the following default behavior: -# ::sysinit:/etc/init.d/rcS -# ::askfirst:/bin/sh -# ::ctrlaltdel:/sbin/reboot -# ::shutdown:/sbin/swapoff -a -# ::shutdown:/bin/umount -a -r -# if it detects that /dev/console is _not_ a serial console, it will -# also run: -# tty2::askfirst:/bin/sh -# tty3::askfirst:/bin/sh -# tty4::askfirst:/bin/sh -# -# Boot-time system configuration/initialization script. -# This is run first except when booting in single-user mode. -# -::sysinit:/etc/init.d/rcS - -# /bin/sh invocations on selected ttys -# -# Note below that we prefix the shell commands with a "-" to indicate to the -# shell that it is supposed to be a login shell. Normally this is handled by -# login, but since we are bypassing login in this case, BusyBox lets you do -# this yourself... -# -# Start an "askfirst" shell on the console (whatever that may be) -::askfirst:-/bin/sh -# Start an "askfirst" shell on /dev/tty2-4 -tty2::askfirst:-/bin/sh -tty3::askfirst:-/bin/sh -tty4::askfirst:-/bin/sh - -# /sbin/getty invocations for selected ttys -tty4::respawn:/sbin/getty 38400 tty5 -tty5::respawn:/sbin/getty 38400 tty6 - -# Example of how to put a getty on a serial line (for a terminal) -#::respawn:/sbin/getty -L ttyS0 9600 vt100 -#::respawn:/sbin/getty -L ttyS1 9600 vt100 -# -# Example how to put a getty on a modem line. -#::respawn:/sbin/getty 57600 ttyS2 - -# Stuff to do before rebooting -::ctrlaltdel:/sbin/reboot -::shutdown:/bin/umount -a -r -::shutdown:/sbin/swapoff -a - diff --git a/scripts/lxdialog/BIG.FAT.WARNING b/scripts/lxdialog/BIG.FAT.WARNING new file mode 100644 index 000000000..a8999d82b --- /dev/null +++ b/scripts/lxdialog/BIG.FAT.WARNING @@ -0,0 +1,4 @@ +This is NOT the official version of dialog. This version has been +significantly modified from the original. It is for use by the Linux +kernel configuration script. Please do not bother Savio Lam with +questions about this program. diff --git a/scripts/lxdialog/Makefile b/scripts/lxdialog/Makefile new file mode 100644 index 000000000..ed8d17c37 --- /dev/null +++ b/scripts/lxdialog/Makefile @@ -0,0 +1,46 @@ +HOSTCFLAGS += -DLOCALE +LIBS = -lncurses + +ifeq (/usr/include/ncurses/ncurses.h, $(wildcard /usr/include/ncurses/ncurses.h)) + HOSTCFLAGS += -I/usr/include/ncurses -DCURSES_LOC="" +else +ifeq (/usr/include/ncurses/curses.h, $(wildcard /usr/include/ncurses/curses.h)) + HOSTCFLAGS += -I/usr/include/ncurses -DCURSES_LOC="" +else +ifeq (/usr/include/ncurses.h, $(wildcard /usr/include/ncurses.h)) + HOSTCFLAGS += -DCURSES_LOC="" +else + HOSTCFLAGS += -DCURSES_LOC="" +endif +endif +endif + + +OBJS = checklist.o menubox.o textbox.o yesno.o inputbox.o \ + util.o lxdialog.o msgbox.o + +%.o: %.c + $(HOSTCC) $(HOSTCFLAGS) -c -o $@ $< + +all: ncurses lxdialog + +lxdialog: $(OBJS) + $(HOSTCC) -o lxdialog $(OBJS) $(LIBS) + +ncurses: + @echo "main() {}" > lxtemp.c + @if $(HOSTCC) -lncurses lxtemp.c ; then \ + rm -f lxtemp.c a.out; \ + else \ + rm -f lxtemp.c; \ + echo -e "\007" ;\ + echo ">> Unable to find the Ncurses libraries." ;\ + echo ">>" ;\ + echo ">> You must have Ncurses installed in order" ;\ + echo ">> to use 'make menuconfig'" ;\ + echo ;\ + exit 1 ;\ + fi + +clean: + rm -f core *.o *~ lxdialog diff --git a/scripts/lxdialog/Makefile-2.5 b/scripts/lxdialog/Makefile-2.5 new file mode 100644 index 000000000..665205200 --- /dev/null +++ b/scripts/lxdialog/Makefile-2.5 @@ -0,0 +1,71 @@ +lxdialog-hostcflags += -DLOCALE +lxdialog-libs = -lncurses + +ifeq (/usr/include/ncurses/ncurses.h, $(wildcard /usr/include/ncurses/ncurses.h)) + lxdialog-hostcflags += -I/usr/include/ncurses -DCURSES_LOC="" +else +ifeq (/usr/include/ncurses/curses.h, $(wildcard /usr/include/ncurses/curses.h)) + lxdialog-hostcflags += -I/usr/include/ncurses -DCURSES_LOC="" +else +ifeq (/usr/include/ncurses.h, $(wildcard /usr/include/ncurses.h)) + lxdialog-hostcflags += -DCURSES_LOC="" +else + lxdialog-hostcflags += -DCURSES_LOC="" +endif +endif +endif + +$(tmp_config)lxdialog-ncurses: + @mkdir -p $(lxdialog-objtree) + @( \ + cd $(lxdialog-objtree) && \ + echo "main() {}" > lxtemp.c && \ + if $(HOSTCC) -lncurses lxtemp.c ; then \ + rm -f lxtemp.c a.out && \ + mkdir -p $(@D) && \ + touch $@; \ + else \ + rm -f lxtemp.c; \ + echo -e "\007" ;\ + echo ">> Unable to find the Ncurses libraries." ;\ + echo ">>" ;\ + echo ">> You must have Ncurses installed in order" ;\ + echo ">> to use 'make menuconfig'" ;\ + echo ;\ + exit 1 ;\ + fi ; \ + ) + +lxdialog-objs := $(lxdialog-objtree)checklist.o $(lxdialog-objtree)menubox.o \ + $(lxdialog-objtree)textbox.o $(lxdialog-objtree)yesno.o \ + $(lxdialog-objtree)inputbox.o $(lxdialog-objtree)util.o \ + $(lxdialog-objtree)lxdialog.o $(lxdialog-objtree)msgbox.o + +$(lxdialog-objtree)checklist.o: $(lxdialog-srctree)checklist.c $(tmp_config)lxdialog-ncurses + $(HOSTCC) $(HOSTCFLAGS) $(lxdialog-hostcflags) -c -o $@ $< + +$(lxdialog-objtree)menubox.o: $(lxdialog-srctree)menubox.c $(tmp_config)lxdialog-ncurses + $(HOSTCC) $(HOSTCFLAGS) $(lxdialog-hostcflags) -c -o $@ $< + +$(lxdialog-objtree)textbox.o: $(lxdialog-srctree)textbox.c $(tmp_config)lxdialog-ncurses + $(HOSTCC) $(HOSTCFLAGS) $(lxdialog-hostcflags) -c -o $@ $< + +$(lxdialog-objtree)yesno.o: $(lxdialog-srctree)yesno.c $(tmp_config)lxdialog-ncurses + $(HOSTCC) $(HOSTCFLAGS) $(lxdialog-hostcflags) -c -o $@ $< + +$(lxdialog-objtree)inputbox.o: $(lxdialog-srctree)inputbox.c $(tmp_config)lxdialog-ncurses + $(HOSTCC) $(HOSTCFLAGS) $(lxdialog-hostcflags) -c -o $@ $< + +$(lxdialog-objtree)util.o: $(lxdialog-srctree)util.c $(tmp_config)lxdialog-ncurses + $(HOSTCC) $(HOSTCFLAGS) $(lxdialog-hostcflags) -c -o $@ $< + +$(lxdialog-objtree)lxdialog.o: $(lxdialog-srctree)lxdialog.c $(tmp_config)lxdialog-ncurses + $(HOSTCC) $(HOSTCFLAGS) $(lxdialog-hostcflags) -c -o $@ $< + +$(lxdialog-objtree)msgbox.o: $(lxdialog-srctree)msgbox.c $(tmp_config)lxdialog-ncurses + $(HOSTCC) $(HOSTCFLAGS) $(lxdialog-hostcflags) -c -o $@ $< + +$(lxdialog-objtree)lxdialog: $(lxdialog-objs) + $(HOSTCC) -o $@ $(lxdialog-objs) $(lxdialog-libs) + +MRPROPER += $(lxdialog-objtree)lxdialog diff --git a/scripts/lxdialog/checklist.c b/scripts/lxdialog/checklist.c new file mode 100644 index 000000000..4f78688ed --- /dev/null +++ b/scripts/lxdialog/checklist.c @@ -0,0 +1,369 @@ +/* + * checklist.c -- implements the checklist box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension + * Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +static int list_width, check_x, item_x, checkflag; + +/* + * Print list item + */ +static void +print_item (WINDOW * win, const char *item, int status, + int choice, int selected) +{ + int i; + + /* Clear 'residue' of last item */ + wattrset (win, menubox_attr); + wmove (win, choice, 0); + for (i = 0; i < list_width; i++) + waddch (win, ' '); + + wmove (win, choice, check_x); + wattrset (win, selected ? check_selected_attr : check_attr); + if (checkflag == FLAG_CHECK) + wprintw (win, "[%c]", status ? 'X' : ' '); + else + wprintw (win, "(%c)", status ? 'X' : ' '); + + wattrset (win, selected ? tag_selected_attr : tag_attr); + mvwaddch(win, choice, item_x, item[0]); + wattrset (win, selected ? item_selected_attr : item_attr); + waddstr (win, (char *)item+1); + if (selected) { + wmove (win, choice, check_x+1); + wrefresh (win); + } +} + +/* + * Print the scroll indicators. + */ +static void +print_arrows (WINDOW * win, int choice, int item_no, int scroll, + int y, int x, int height) +{ + wmove(win, y, x); + + if (scroll > 0) { + wattrset (win, uarrow_attr); + waddch (win, ACS_UARROW); + waddstr (win, "(-)"); + } + else { + wattrset (win, menubox_attr); + waddch (win, ACS_HLINE); + waddch (win, ACS_HLINE); + waddch (win, ACS_HLINE); + waddch (win, ACS_HLINE); + } + + y = y + height + 1; + wmove(win, y, x); + + if ((height < item_no) && (scroll + choice < item_no - 1)) { + wattrset (win, darrow_attr); + waddch (win, ACS_DARROW); + waddstr (win, "(+)"); + } + else { + wattrset (win, menubox_border_attr); + waddch (win, ACS_HLINE); + waddch (win, ACS_HLINE); + waddch (win, ACS_HLINE); + waddch (win, ACS_HLINE); + } +} + +/* + * Display the termination buttons + */ +static void +print_buttons( WINDOW *dialog, int height, int width, int selected) +{ + int x = width / 2 - 11; + int y = height - 2; + + print_button (dialog, "Select", y, x, selected == 0); + print_button (dialog, " Help ", y, x + 14, selected == 1); + + wmove(dialog, y, x+1 + 14*selected); + wrefresh (dialog); +} + +/* + * Display a dialog box with a list of options that can be turned on or off + * The `flag' parameter is used to select between radiolist and checklist. + */ +int +dialog_checklist (const char *title, const char *prompt, int height, int width, + int list_height, int item_no, const char * const * items, int flag) + +{ + int i, x, y, box_x, box_y; + int key = 0, button = 0, choice = 0, scroll = 0, max_choice, *status; + WINDOW *dialog, *list; + + checkflag = flag; + + /* Allocate space for storing item on/off status */ + if ((status = malloc (sizeof (int) * item_no)) == NULL) { + endwin (); + fprintf (stderr, + "\nCan't allocate memory in dialog_checklist().\n"); + exit (-1); + } + + /* Initializes status */ + for (i = 0; i < item_no; i++) { + status[i] = !strcasecmp (items[i * 3 + 2], "on"); + if (!choice && status[i]) + choice = i; + } + + max_choice = MIN (list_height, item_no); + + /* center dialog box on screen */ + x = (COLS - width) / 2; + y = (LINES - height) / 2; + + draw_shadow (stdscr, y, x, height, width); + + dialog = newwin (height, width, y, x); + keypad (dialog, TRUE); + + draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr); + wattrset (dialog, border_attr); + mvwaddch (dialog, height-3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch (dialog, ACS_HLINE); + wattrset (dialog, dialog_attr); + waddch (dialog, ACS_RTEE); + + if (title != NULL && strlen(title) >= width-2 ) { + /* truncate long title -- mec */ + char * title2 = malloc(width-2+1); + memcpy( title2, title, width-2 ); + title2[width-2] = '\0'; + title = title2; + } + + if (title != NULL) { + wattrset (dialog, title_attr); + mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' '); + waddstr (dialog, (char *)title); + waddch (dialog, ' '); + } + + wattrset (dialog, dialog_attr); + print_autowrap (dialog, prompt, width - 2, 1, 3); + + list_width = width - 6; + box_y = height - list_height - 5; + box_x = (width - list_width) / 2 - 1; + + /* create new window for the list */ + list = subwin (dialog, list_height, list_width, y+box_y+1, x+box_x+1); + + keypad (list, TRUE); + + /* draw a box around the list items */ + draw_box (dialog, box_y, box_x, list_height + 2, list_width + 2, + menubox_border_attr, menubox_attr); + + /* Find length of longest item in order to center checklist */ + check_x = 0; + for (i = 0; i < item_no; i++) + check_x = MAX (check_x, + strlen (items[i * 3 + 1]) + 4); + + check_x = (list_width - check_x) / 2; + item_x = check_x + 4; + + if (choice >= list_height) { + scroll = choice - list_height + 1; + choice -= scroll; + } + + /* Print the list */ + for (i = 0; i < max_choice; i++) { + print_item (list, items[(scroll+i) * 3 + 1], + status[i+scroll], i, i == choice); + } + + print_arrows(dialog, choice, item_no, scroll, + box_y, box_x + check_x + 5, list_height); + + print_buttons(dialog, height, width, 0); + + wnoutrefresh (list); + wnoutrefresh (dialog); + doupdate (); + + while (key != ESC) { + key = wgetch (dialog); + + for (i = 0; i < max_choice; i++) + if (toupper(key) == toupper(items[(scroll+i)*3+1][0])) + break; + + + if ( i < max_choice || key == KEY_UP || key == KEY_DOWN || + key == '+' || key == '-' ) { + if (key == KEY_UP || key == '-') { + if (!choice) { + if (!scroll) + continue; + /* Scroll list down */ + if (list_height > 1) { + /* De-highlight current first item */ + print_item (list, items[scroll * 3 + 1], + status[scroll], 0, FALSE); + scrollok (list, TRUE); + wscrl (list, -1); + scrollok (list, FALSE); + } + scroll--; + print_item (list, items[scroll * 3 + 1], + status[scroll], 0, TRUE); + wnoutrefresh (list); + + print_arrows(dialog, choice, item_no, scroll, + box_y, box_x + check_x + 5, list_height); + + wrefresh (dialog); + + continue; /* wait for another key press */ + } else + i = choice - 1; + } else if (key == KEY_DOWN || key == '+') { + if (choice == max_choice - 1) { + if (scroll + choice >= item_no - 1) + continue; + /* Scroll list up */ + if (list_height > 1) { + /* De-highlight current last item before scrolling up */ + print_item (list, items[(scroll + max_choice - 1) * 3 + 1], + status[scroll + max_choice - 1], + max_choice - 1, FALSE); + scrollok (list, TRUE); + scroll (list); + scrollok (list, FALSE); + } + scroll++; + print_item (list, items[(scroll + max_choice - 1) * 3 + 1], + status[scroll + max_choice - 1], + max_choice - 1, TRUE); + wnoutrefresh (list); + + print_arrows(dialog, choice, item_no, scroll, + box_y, box_x + check_x + 5, list_height); + + wrefresh (dialog); + + continue; /* wait for another key press */ + } else + i = choice + 1; + } + if (i != choice) { + /* De-highlight current item */ + print_item (list, items[(scroll + choice) * 3 + 1], + status[scroll + choice], choice, FALSE); + /* Highlight new item */ + choice = i; + print_item (list, items[(scroll + choice) * 3 + 1], + status[scroll + choice], choice, TRUE); + wnoutrefresh (list); + wrefresh (dialog); + } + continue; /* wait for another key press */ + } + switch (key) { + case 'H': + case 'h': + case '?': + delwin (dialog); + free (status); + return 1; + case TAB: + case KEY_LEFT: + case KEY_RIGHT: + button = ((key == KEY_LEFT ? --button : ++button) < 0) + ? 1 : (button > 1 ? 0 : button); + + print_buttons(dialog, height, width, button); + wrefresh (dialog); + break; + case 'S': + case 's': + case ' ': + case '\n': + if (!button) { + if (flag == FLAG_CHECK) { + status[scroll + choice] = !status[scroll + choice]; + wmove (list, choice, check_x); + wattrset (list, check_selected_attr); + wprintw (list, "[%c]", status[scroll + choice] ? 'X' : ' '); + } else { + if (!status[scroll + choice]) { + for (i = 0; i < item_no; i++) + status[i] = 0; + status[scroll + choice] = 1; + for (i = 0; i < max_choice; i++) + print_item (list, items[(scroll + i) * 3 + 1], + status[scroll + i], i, i == choice); + } + } + wnoutrefresh (list); + wrefresh (dialog); + + for (i = 0; i < item_no; i++) { + if (status[i]) { + if (flag == FLAG_CHECK) { + fprintf (stderr, "\"%s\" ", items[i * 3]); + } else { + fprintf (stderr, "%s", items[i * 3]); + } + + } + } + } + delwin (dialog); + free (status); + return button; + case 'X': + case 'x': + key = ESC; + case ESC: + break; + } + + /* Now, update everything... */ + doupdate (); + } + + + delwin (dialog); + free (status); + return -1; /* ESC pressed */ +} diff --git a/scripts/lxdialog/colors.h b/scripts/lxdialog/colors.h new file mode 100644 index 000000000..d34dd37c6 --- /dev/null +++ b/scripts/lxdialog/colors.h @@ -0,0 +1,161 @@ +/* + * colors.h -- color attribute definitions + * + * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +/* + * Default color definitions + * + * *_FG = foreground + * *_BG = background + * *_HL = highlight? + */ +#define SCREEN_FG COLOR_CYAN +#define SCREEN_BG COLOR_BLUE +#define SCREEN_HL TRUE + +#define SHADOW_FG COLOR_BLACK +#define SHADOW_BG COLOR_BLACK +#define SHADOW_HL TRUE + +#define DIALOG_FG COLOR_BLACK +#define DIALOG_BG COLOR_WHITE +#define DIALOG_HL FALSE + +#define TITLE_FG COLOR_YELLOW +#define TITLE_BG COLOR_WHITE +#define TITLE_HL TRUE + +#define BORDER_FG COLOR_WHITE +#define BORDER_BG COLOR_WHITE +#define BORDER_HL TRUE + +#define BUTTON_ACTIVE_FG COLOR_WHITE +#define BUTTON_ACTIVE_BG COLOR_BLUE +#define BUTTON_ACTIVE_HL TRUE + +#define BUTTON_INACTIVE_FG COLOR_BLACK +#define BUTTON_INACTIVE_BG COLOR_WHITE +#define BUTTON_INACTIVE_HL FALSE + +#define BUTTON_KEY_ACTIVE_FG COLOR_WHITE +#define BUTTON_KEY_ACTIVE_BG COLOR_BLUE +#define BUTTON_KEY_ACTIVE_HL TRUE + +#define BUTTON_KEY_INACTIVE_FG COLOR_RED +#define BUTTON_KEY_INACTIVE_BG COLOR_WHITE +#define BUTTON_KEY_INACTIVE_HL FALSE + +#define BUTTON_LABEL_ACTIVE_FG COLOR_YELLOW +#define BUTTON_LABEL_ACTIVE_BG COLOR_BLUE +#define BUTTON_LABEL_ACTIVE_HL TRUE + +#define BUTTON_LABEL_INACTIVE_FG COLOR_BLACK +#define BUTTON_LABEL_INACTIVE_BG COLOR_WHITE +#define BUTTON_LABEL_INACTIVE_HL TRUE + +#define INPUTBOX_FG COLOR_BLACK +#define INPUTBOX_BG COLOR_WHITE +#define INPUTBOX_HL FALSE + +#define INPUTBOX_BORDER_FG COLOR_BLACK +#define INPUTBOX_BORDER_BG COLOR_WHITE +#define INPUTBOX_BORDER_HL FALSE + +#define SEARCHBOX_FG COLOR_BLACK +#define SEARCHBOX_BG COLOR_WHITE +#define SEARCHBOX_HL FALSE + +#define SEARCHBOX_TITLE_FG COLOR_YELLOW +#define SEARCHBOX_TITLE_BG COLOR_WHITE +#define SEARCHBOX_TITLE_HL TRUE + +#define SEARCHBOX_BORDER_FG COLOR_WHITE +#define SEARCHBOX_BORDER_BG COLOR_WHITE +#define SEARCHBOX_BORDER_HL TRUE + +#define POSITION_INDICATOR_FG COLOR_YELLOW +#define POSITION_INDICATOR_BG COLOR_WHITE +#define POSITION_INDICATOR_HL TRUE + +#define MENUBOX_FG COLOR_BLACK +#define MENUBOX_BG COLOR_WHITE +#define MENUBOX_HL FALSE + +#define MENUBOX_BORDER_FG COLOR_WHITE +#define MENUBOX_BORDER_BG COLOR_WHITE +#define MENUBOX_BORDER_HL TRUE + +#define ITEM_FG COLOR_BLACK +#define ITEM_BG COLOR_WHITE +#define ITEM_HL FALSE + +#define ITEM_SELECTED_FG COLOR_WHITE +#define ITEM_SELECTED_BG COLOR_BLUE +#define ITEM_SELECTED_HL TRUE + +#define TAG_FG COLOR_YELLOW +#define TAG_BG COLOR_WHITE +#define TAG_HL TRUE + +#define TAG_SELECTED_FG COLOR_YELLOW +#define TAG_SELECTED_BG COLOR_BLUE +#define TAG_SELECTED_HL TRUE + +#define TAG_KEY_FG COLOR_YELLOW +#define TAG_KEY_BG COLOR_WHITE +#define TAG_KEY_HL TRUE + +#define TAG_KEY_SELECTED_FG COLOR_YELLOW +#define TAG_KEY_SELECTED_BG COLOR_BLUE +#define TAG_KEY_SELECTED_HL TRUE + +#define CHECK_FG COLOR_BLACK +#define CHECK_BG COLOR_WHITE +#define CHECK_HL FALSE + +#define CHECK_SELECTED_FG COLOR_WHITE +#define CHECK_SELECTED_BG COLOR_BLUE +#define CHECK_SELECTED_HL TRUE + +#define UARROW_FG COLOR_GREEN +#define UARROW_BG COLOR_WHITE +#define UARROW_HL TRUE + +#define DARROW_FG COLOR_GREEN +#define DARROW_BG COLOR_WHITE +#define DARROW_HL TRUE + +/* End of default color definitions */ + +#define C_ATTR(x,y) ((x ? A_BOLD : 0) | COLOR_PAIR((y))) +#define COLOR_NAME_LEN 10 +#define COLOR_COUNT 8 + +/* + * Global variables + */ + +typedef struct { + char name[COLOR_NAME_LEN]; + int value; +} color_names_st; + +extern color_names_st color_names[]; +extern int color_table[][3]; diff --git a/scripts/lxdialog/dialog.h b/scripts/lxdialog/dialog.h new file mode 100644 index 000000000..0e30d00d0 --- /dev/null +++ b/scripts/lxdialog/dialog.h @@ -0,0 +1,184 @@ + +/* + * dialog.h -- common declarations for all dialog modules + * + * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + +#include CURSES_LOC + +/* + * Colors in ncurses 1.9.9e do not work properly since foreground and + * background colors are OR'd rather than separately masked. This version + * of dialog was hacked to work with ncurses 1.9.9e, making it incompatible + * with standard curses. The simplest fix (to make this work with standard + * curses) uses the wbkgdset() function, not used in the original hack. + * Turn it off if we're building with 1.9.9e, since it just confuses things. + */ +#if defined(NCURSES_VERSION) && defined(_NEED_WRAP) && !defined(GCC_PRINTFLIKE) +#define OLD_NCURSES 1 +#undef wbkgdset +#define wbkgdset(w,p) /*nothing*/ +#else +#define OLD_NCURSES 0 +#endif + +#define TR(params) _tracef params + +#define ESC 27 +#define TAB 9 +#define MAX_LEN 2048 +#define BUF_SIZE (10*1024) +#define MIN(x,y) (x < y ? x : y) +#define MAX(x,y) (x > y ? x : y) + + +#ifndef ACS_ULCORNER +#define ACS_ULCORNER '+' +#endif +#ifndef ACS_LLCORNER +#define ACS_LLCORNER '+' +#endif +#ifndef ACS_URCORNER +#define ACS_URCORNER '+' +#endif +#ifndef ACS_LRCORNER +#define ACS_LRCORNER '+' +#endif +#ifndef ACS_HLINE +#define ACS_HLINE '-' +#endif +#ifndef ACS_VLINE +#define ACS_VLINE '|' +#endif +#ifndef ACS_LTEE +#define ACS_LTEE '+' +#endif +#ifndef ACS_RTEE +#define ACS_RTEE '+' +#endif +#ifndef ACS_UARROW +#define ACS_UARROW '^' +#endif +#ifndef ACS_DARROW +#define ACS_DARROW 'v' +#endif + +/* + * Attribute names + */ +#define screen_attr attributes[0] +#define shadow_attr attributes[1] +#define dialog_attr attributes[2] +#define title_attr attributes[3] +#define border_attr attributes[4] +#define button_active_attr attributes[5] +#define button_inactive_attr attributes[6] +#define button_key_active_attr attributes[7] +#define button_key_inactive_attr attributes[8] +#define button_label_active_attr attributes[9] +#define button_label_inactive_attr attributes[10] +#define inputbox_attr attributes[11] +#define inputbox_border_attr attributes[12] +#define searchbox_attr attributes[13] +#define searchbox_title_attr attributes[14] +#define searchbox_border_attr attributes[15] +#define position_indicator_attr attributes[16] +#define menubox_attr attributes[17] +#define menubox_border_attr attributes[18] +#define item_attr attributes[19] +#define item_selected_attr attributes[20] +#define tag_attr attributes[21] +#define tag_selected_attr attributes[22] +#define tag_key_attr attributes[23] +#define tag_key_selected_attr attributes[24] +#define check_attr attributes[25] +#define check_selected_attr attributes[26] +#define uarrow_attr attributes[27] +#define darrow_attr attributes[28] + +/* number of attributes */ +#define ATTRIBUTE_COUNT 29 + +/* + * Global variables + */ +extern bool use_colors; +extern bool use_shadow; + +extern chtype attributes[]; + +extern const char *backtitle; + +/* + * Function prototypes + */ +extern void create_rc (const char *filename); +extern int parse_rc (void); + + +void init_dialog (void); +void end_dialog (void); +void attr_clear (WINDOW * win, int height, int width, chtype attr); +void dialog_clear (void); +void color_setup (void); +void print_autowrap (WINDOW * win, const char *prompt, int width, int y, int x); +void print_button (WINDOW * win, const char *label, int y, int x, int selected); +void draw_box (WINDOW * win, int y, int x, int height, int width, chtype box, + chtype border); +void draw_shadow (WINDOW * win, int y, int x, int height, int width); + +int first_alpha (const char *string, const char *exempt); +int dialog_yesno (const char *title, const char *prompt, int height, int width); +int dialog_msgbox (const char *title, const char *prompt, int height, + int width, int pause); +int dialog_textbox (const char *title, const char *file, int height, int width); +int dialog_menu (const char *title, const char *prompt, int height, int width, + int menu_height, const char *choice, int item_no, + const char * const * items); +int dialog_checklist (const char *title, const char *prompt, int height, + int width, int list_height, int item_no, + const char * const * items, int flag); +extern unsigned char dialog_input_result[]; +int dialog_inputbox (const char *title, const char *prompt, int height, + int width, const char *init); + +/* + * This is the base for fictitious keys, which activate + * the buttons. + * + * Mouse-generated keys are the following: + * -- the first 32 are used as numbers, in addition to '0'-'9' + * -- the lowercase are used to signal mouse-enter events (M_EVENT + 'o') + * -- uppercase chars are used to invoke the button (M_EVENT + 'O') + */ +#define M_EVENT (KEY_MAX+1) + + +/* + * The `flag' parameter in checklist is used to select between + * radiolist and checklist + */ +#define FLAG_CHECK 1 +#define FLAG_RADIO 0 diff --git a/scripts/lxdialog/inputbox.c b/scripts/lxdialog/inputbox.c new file mode 100644 index 000000000..fa7bebc69 --- /dev/null +++ b/scripts/lxdialog/inputbox.c @@ -0,0 +1,240 @@ +/* + * inputbox.c -- implements the input box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +unsigned char dialog_input_result[MAX_LEN + 1]; + +/* + * Print the termination buttons + */ +static void +print_buttons(WINDOW *dialog, int height, int width, int selected) +{ + int x = width / 2 - 11; + int y = height - 2; + + print_button (dialog, " Ok ", y, x, selected==0); + print_button (dialog, " Help ", y, x + 14, selected==1); + + wmove(dialog, y, x+1+14*selected); + wrefresh(dialog); +} + +/* + * Display a dialog box for inputing a string + */ +int +dialog_inputbox (const char *title, const char *prompt, int height, int width, + const char *init) +{ + int i, x, y, box_y, box_x, box_width; + int input_x = 0, scroll = 0, key = 0, button = -1; + unsigned char *instr = dialog_input_result; + WINDOW *dialog; + + /* center dialog box on screen */ + x = (COLS - width) / 2; + y = (LINES - height) / 2; + + + draw_shadow (stdscr, y, x, height, width); + + dialog = newwin (height, width, y, x); + keypad (dialog, TRUE); + + draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr); + wattrset (dialog, border_attr); + mvwaddch (dialog, height-3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch (dialog, ACS_HLINE); + wattrset (dialog, dialog_attr); + waddch (dialog, ACS_RTEE); + + if (title != NULL && strlen(title) >= width-2 ) { + /* truncate long title -- mec */ + char * title2 = malloc(width-2+1); + memcpy( title2, title, width-2 ); + title2[width-2] = '\0'; + title = title2; + } + + if (title != NULL) { + wattrset (dialog, title_attr); + mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' '); + waddstr (dialog, (char *)title); + waddch (dialog, ' '); + } + + wattrset (dialog, dialog_attr); + print_autowrap (dialog, prompt, width - 2, 1, 3); + + /* Draw the input field box */ + box_width = width - 6; + getyx (dialog, y, x); + box_y = y + 2; + box_x = (width - box_width) / 2; + draw_box (dialog, y + 1, box_x - 1, 3, box_width + 2, + border_attr, dialog_attr); + + print_buttons(dialog, height, width, 0); + + /* Set up the initial value */ + wmove (dialog, box_y, box_x); + wattrset (dialog, inputbox_attr); + + if (!init) + instr[0] = '\0'; + else + strcpy (instr, init); + + input_x = strlen (instr); + + if (input_x >= box_width) { + scroll = input_x - box_width + 1; + input_x = box_width - 1; + for (i = 0; i < box_width - 1; i++) + waddch (dialog, instr[scroll + i]); + } else + waddstr (dialog, instr); + + wmove (dialog, box_y, box_x + input_x); + + wrefresh (dialog); + + while (key != ESC) { + key = wgetch (dialog); + + if (button == -1) { /* Input box selected */ + switch (key) { + case TAB: + case KEY_UP: + case KEY_DOWN: + break; + case KEY_LEFT: + continue; + case KEY_RIGHT: + continue; + case KEY_BACKSPACE: + case 127: + if (input_x || scroll) { + wattrset (dialog, inputbox_attr); + if (!input_x) { + scroll = scroll < box_width - 1 ? + 0 : scroll - (box_width - 1); + wmove (dialog, box_y, box_x); + for (i = 0; i < box_width; i++) + waddch (dialog, instr[scroll + input_x + i] ? + instr[scroll + input_x + i] : ' '); + input_x = strlen (instr) - scroll; + } else + input_x--; + instr[scroll + input_x] = '\0'; + mvwaddch (dialog, box_y, input_x + box_x, ' '); + wmove (dialog, box_y, input_x + box_x); + wrefresh (dialog); + } + continue; + default: + if (key < 0x100 && isprint (key)) { + if (scroll + input_x < MAX_LEN) { + wattrset (dialog, inputbox_attr); + instr[scroll + input_x] = key; + instr[scroll + input_x + 1] = '\0'; + if (input_x == box_width - 1) { + scroll++; + wmove (dialog, box_y, box_x); + for (i = 0; i < box_width - 1; i++) + waddch (dialog, instr[scroll + i]); + } else { + wmove (dialog, box_y, input_x++ + box_x); + waddch (dialog, key); + } + wrefresh (dialog); + } else + flash (); /* Alarm user about overflow */ + continue; + } + } + } + switch (key) { + case 'O': + case 'o': + delwin (dialog); + return 0; + case 'H': + case 'h': + delwin (dialog); + return 1; + case KEY_UP: + case KEY_LEFT: + switch (button) { + case -1: + button = 1; /* Indicates "Cancel" button is selected */ + print_buttons(dialog, height, width, 1); + break; + case 0: + button = -1; /* Indicates input box is selected */ + print_buttons(dialog, height, width, 0); + wmove (dialog, box_y, box_x + input_x); + wrefresh (dialog); + break; + case 1: + button = 0; /* Indicates "OK" button is selected */ + print_buttons(dialog, height, width, 0); + break; + } + break; + case TAB: + case KEY_DOWN: + case KEY_RIGHT: + switch (button) { + case -1: + button = 0; /* Indicates "OK" button is selected */ + print_buttons(dialog, height, width, 0); + break; + case 0: + button = 1; /* Indicates "Cancel" button is selected */ + print_buttons(dialog, height, width, 1); + break; + case 1: + button = -1; /* Indicates input box is selected */ + print_buttons(dialog, height, width, 0); + wmove (dialog, box_y, box_x + input_x); + wrefresh (dialog); + break; + } + break; + case ' ': + case '\n': + delwin (dialog); + return (button == -1 ? 0 : button); + case 'X': + case 'x': + key = ESC; + case ESC: + break; + } + } + + delwin (dialog); + return -1; /* ESC pressed */ +} diff --git a/scripts/lxdialog/lxdialog.c b/scripts/lxdialog/lxdialog.c new file mode 100644 index 000000000..6f4c1fd4e --- /dev/null +++ b/scripts/lxdialog/lxdialog.c @@ -0,0 +1,226 @@ +/* + * dialog - Display simple dialog boxes from shell scripts + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +static void Usage (const char *name); + +typedef int (jumperFn) (const char *title, int argc, const char * const * argv); + +struct Mode { + char *name; + int argmin, argmax, argmod; + jumperFn *jumper; +}; + +jumperFn j_menu, j_checklist, j_radiolist, j_yesno, j_textbox, j_inputbox; +jumperFn j_msgbox, j_infobox; + +static struct Mode modes[] = +{ + {"--menu", 9, 0, 3, j_menu}, + {"--checklist", 9, 0, 3, j_checklist}, + {"--radiolist", 9, 0, 3, j_radiolist}, + {"--yesno", 5,5,1, j_yesno}, + {"--textbox", 5,5,1, j_textbox}, + {"--inputbox", 5, 6, 1, j_inputbox}, + {"--msgbox", 5, 5, 1, j_msgbox}, + {"--infobox", 5, 5, 1, j_infobox}, + {NULL, 0, 0, 0, NULL} +}; + +static struct Mode *modePtr; + +#ifdef LOCALE +#include +#endif + +int +main (int argc, const char * const * argv) +{ + int offset = 0, clear_screen = 0, end_common_opts = 0, retval; + const char *title = NULL; + +#ifdef LOCALE + (void) setlocale (LC_ALL, ""); +#endif + +#ifdef TRACE + trace(TRACE_CALLS|TRACE_UPDATE); +#endif + if (argc < 2) { + Usage (argv[0]); + exit (-1); + } + + while (offset < argc - 1 && !end_common_opts) { /* Common options */ + if (!strcmp (argv[offset + 1], "--title")) { + if (argc - offset < 3 || title != NULL) { + Usage (argv[0]); + exit (-1); + } else { + title = argv[offset + 2]; + offset += 2; + } + } else if (!strcmp (argv[offset + 1], "--backtitle")) { + if (backtitle != NULL) { + Usage (argv[0]); + exit (-1); + } else { + backtitle = argv[offset + 2]; + offset += 2; + } + } else if (!strcmp (argv[offset + 1], "--clear")) { + if (clear_screen) { /* Hey, "--clear" can't appear twice! */ + Usage (argv[0]); + exit (-1); + } else if (argc == 2) { /* we only want to clear the screen */ + init_dialog (); + refresh (); /* init_dialog() will clear the screen for us */ + end_dialog (); + return 0; + } else { + clear_screen = 1; + offset++; + } + } else /* no more common options */ + end_common_opts = 1; + } + + if (argc - 1 == offset) { /* no more options */ + Usage (argv[0]); + exit (-1); + } + /* use a table to look for the requested mode, to avoid code duplication */ + + for (modePtr = modes; modePtr->name; modePtr++) /* look for the mode */ + if (!strcmp (argv[offset + 1], modePtr->name)) + break; + + if (!modePtr->name) + Usage (argv[0]); + if (argc - offset < modePtr->argmin) + Usage (argv[0]); + if (modePtr->argmax && argc - offset > modePtr->argmax) + Usage (argv[0]); + + + + init_dialog (); + retval = (*(modePtr->jumper)) (title, argc - offset, argv + offset); + + if (clear_screen) { /* clear screen before exit */ + attr_clear (stdscr, LINES, COLS, screen_attr); + refresh (); + } + end_dialog(); + + exit (retval); +} + +/* + * Print program usage + */ +static void +Usage (const char *name) +{ + fprintf (stderr, "\ +\ndialog, by Savio Lam (lam836@cs.cuhk.hk).\ +\n patched by Stuart Herbert (S.Herbert@shef.ac.uk)\ +\n modified/gutted for use as a Linux kernel config tool by \ +\n William Roadcap (roadcapw@cfw.com)\ +\n\ +\n* Display dialog boxes from shell scripts *\ +\n\ +\nUsage: %s --clear\ +\n %s [--title ] [--backtitle <backtitle>] --clear <Box options>\ +\n\ +\nBox options:\ +\n\ +\n --menu <text> <height> <width> <menu height> <tag1> <item1>...\ +\n --checklist <text> <height> <width> <list height> <tag1> <item1> <status1>...\ +\n --radiolist <text> <height> <width> <list height> <tag1> <item1> <status1>...\ +\n --textbox <file> <height> <width>\ +\n --inputbox <text> <height> <width> [<init>]\ +\n --yesno <text> <height> <width>\ +\n", name, name); + exit (-1); +} + +/* + * These are the program jumpers + */ + +int +j_menu (const char *t, int ac, const char * const * av) +{ + return dialog_menu (t, av[2], atoi (av[3]), atoi (av[4]), + atoi (av[5]), av[6], (ac - 6) / 2, av + 7); +} + +int +j_checklist (const char *t, int ac, const char * const * av) +{ + return dialog_checklist (t, av[2], atoi (av[3]), atoi (av[4]), + atoi (av[5]), (ac - 6) / 3, av + 6, FLAG_CHECK); +} + +int +j_radiolist (const char *t, int ac, const char * const * av) +{ + return dialog_checklist (t, av[2], atoi (av[3]), atoi (av[4]), + atoi (av[5]), (ac - 6) / 3, av + 6, FLAG_RADIO); +} + +int +j_textbox (const char *t, int ac, const char * const * av) +{ + return dialog_textbox (t, av[2], atoi (av[3]), atoi (av[4])); +} + +int +j_yesno (const char *t, int ac, const char * const * av) +{ + return dialog_yesno (t, av[2], atoi (av[3]), atoi (av[4])); +} + +int +j_inputbox (const char *t, int ac, const char * const * av) +{ + int ret = dialog_inputbox (t, av[2], atoi (av[3]), atoi (av[4]), + ac == 6 ? av[5] : (char *) NULL); + if (ret == 0) + fprintf(stderr, dialog_input_result); + return ret; +} + +int +j_msgbox (const char *t, int ac, const char * const * av) +{ + return dialog_msgbox (t, av[2], atoi (av[3]), atoi (av[4]), 1); +} + +int +j_infobox (const char *t, int ac, const char * const * av) +{ + return dialog_msgbox (t, av[2], atoi (av[3]), atoi (av[4]), 0); +} + diff --git a/scripts/lxdialog/menubox.c b/scripts/lxdialog/menubox.c new file mode 100644 index 000000000..a234e9f3b --- /dev/null +++ b/scripts/lxdialog/menubox.c @@ -0,0 +1,443 @@ +/* + * menubox.c -- implements the menu box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * Changes by Clifford Wolf (god@clifford.at) + * + * [ 1998-06-13 ] + * + * *) A bugfix for the Page-Down problem + * + * *) Formerly when I used Page Down and Page Up, the cursor would be set + * to the first position in the menu box. Now lxdialog is a bit + * smarter and works more like other menu systems (just have a look at + * it). + * + * *) Formerly if I selected something my scrolling would be broken because + * lxdialog is re-invoked by the Menuconfig shell script, can't + * remember the last scrolling position, and just sets it so that the + * cursor is at the bottom of the box. Now it writes the temporary file + * lxdialog.scrltmp which contains this information. The file is + * deleted by lxdialog if the user leaves a submenu or enters a new + * one, but it would be nice if Menuconfig could make another "rm -f" + * just to be sure. Just try it out - you will recognise a difference! + * + * [ 1998-06-14 ] + * + * *) Now lxdialog is crash-safe against broken "lxdialog.scrltmp" files + * and menus change their size on the fly. + * + * *) If for some reason the last scrolling position is not saved by + * lxdialog, it sets the scrolling so that the selected item is in the + * middle of the menu box, not at the bottom. + * + * 02 January 1999, Michael Elizabeth Chastain (mec@shout.net) + * Reset 'scroll' to 0 if the value from lxdialog.scrltmp is bogus. + * This fixes a bug in Menuconfig where using ' ' to descend into menus + * would leave mis-synchronized lxdialog.scrltmp files lying around, + * fscanf would read in 'scroll', and eventually that value would get used. + */ + +#include "dialog.h" + +static int menu_width, item_x; + +/* + * Print menu item + */ +static void +print_item (WINDOW * win, const char *item, int choice, int selected, int hotkey) +{ + int j; + char menu_item[menu_width+1]; + + strncpy(menu_item, item, menu_width); + menu_item[menu_width] = 0; + j = first_alpha(menu_item, "YyNnMm"); + + /* Clear 'residue' of last item */ + wattrset (win, menubox_attr); + wmove (win, choice, 0); +#if OLD_NCURSES + { + int i; + for (i = 0; i < menu_width; i++) + waddch (win, ' '); + } +#else + wclrtoeol(win); +#endif + wattrset (win, selected ? item_selected_attr : item_attr); + mvwaddstr (win, choice, item_x, menu_item); + if (hotkey) { + wattrset (win, selected ? tag_key_selected_attr : tag_key_attr); + mvwaddch(win, choice, item_x+j, menu_item[j]); + } + if (selected) { + wmove (win, choice, item_x+1); + wrefresh (win); + } +} + +/* + * Print the scroll indicators. + */ +static void +print_arrows (WINDOW * win, int item_no, int scroll, + int y, int x, int height) +{ + int cur_y, cur_x; + + getyx(win, cur_y, cur_x); + + wmove(win, y, x); + + if (scroll > 0) { + wattrset (win, uarrow_attr); + waddch (win, ACS_UARROW); + waddstr (win, "(-)"); + } + else { + wattrset (win, menubox_attr); + waddch (win, ACS_HLINE); + waddch (win, ACS_HLINE); + waddch (win, ACS_HLINE); + waddch (win, ACS_HLINE); + } + + y = y + height + 1; + wmove(win, y, x); + + if ((height < item_no) && (scroll + height < item_no)) { + wattrset (win, darrow_attr); + waddch (win, ACS_DARROW); + waddstr (win, "(+)"); + } + else { + wattrset (win, menubox_border_attr); + waddch (win, ACS_HLINE); + waddch (win, ACS_HLINE); + waddch (win, ACS_HLINE); + waddch (win, ACS_HLINE); + } + + wmove(win, cur_y, cur_x); +} + +/* + * Display the termination buttons. + */ +static void +print_buttons (WINDOW *win, int height, int width, int selected) +{ + int x = width / 2 - 16; + int y = height - 2; + + print_button (win, "Select", y, x, selected == 0); + print_button (win, " Exit ", y, x + 12, selected == 1); + print_button (win, " Help ", y, x + 24, selected == 2); + + wmove(win, y, x+1+12*selected); + wrefresh (win); +} + +/* + * Display a menu for choosing among a number of options + */ +int +dialog_menu (const char *title, const char *prompt, int height, int width, + int menu_height, const char *current, int item_no, + const char * const * items) + +{ + int i, j, x, y, box_x, box_y; + int key = 0, button = 0, scroll = 0, choice = 0, first_item = 0, max_choice; + WINDOW *dialog, *menu; + FILE *f; + + max_choice = MIN (menu_height, item_no); + + /* center dialog box on screen */ + x = (COLS - width) / 2; + y = (LINES - height) / 2; + + draw_shadow (stdscr, y, x, height, width); + + dialog = newwin (height, width, y, x); + keypad (dialog, TRUE); + + draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr); + wattrset (dialog, border_attr); + mvwaddch (dialog, height - 3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch (dialog, ACS_HLINE); + wattrset (dialog, dialog_attr); + wbkgdset (dialog, dialog_attr & A_COLOR); + waddch (dialog, ACS_RTEE); + + if (title != NULL && strlen(title) >= width-2 ) { + /* truncate long title -- mec */ + char * title2 = malloc(width-2+1); + memcpy( title2, title, width-2 ); + title2[width-2] = '\0'; + title = title2; + } + + if (title != NULL) { + wattrset (dialog, title_attr); + mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' '); + waddstr (dialog, (char *)title); + waddch (dialog, ' '); + } + + wattrset (dialog, dialog_attr); + print_autowrap (dialog, prompt, width - 2, 1, 3); + + menu_width = width - 6; + box_y = height - menu_height - 5; + box_x = (width - menu_width) / 2 - 1; + + /* create new window for the menu */ + menu = subwin (dialog, menu_height, menu_width, + y + box_y + 1, x + box_x + 1); + keypad (menu, TRUE); + + /* draw a box around the menu items */ + draw_box (dialog, box_y, box_x, menu_height + 2, menu_width + 2, + menubox_border_attr, menubox_attr); + + /* + * Find length of longest item in order to center menu. + * Set 'choice' to default item. + */ + item_x = 0; + for (i = 0; i < item_no; i++) { + item_x = MAX (item_x, MIN(menu_width, strlen (items[i * 2 + 1]) + 2)); + if (strcmp(current, items[i*2]) == 0) choice = i; + } + + item_x = (menu_width - item_x) / 2; + + /* get the scroll info from the temp file */ + if ( (f=fopen("lxdialog.scrltmp","r")) != NULL ) { + if ( (fscanf(f,"%d\n",&scroll) == 1) && (scroll <= choice) && + (scroll+max_choice > choice) && (scroll >= 0) && + (scroll+max_choice <= item_no) ) { + first_item = scroll; + choice = choice - scroll; + fclose(f); + } else { + scroll=0; + remove("lxdialog.scrltmp"); + fclose(f); + f=NULL; + } + } + if ( (choice >= max_choice) || (f==NULL && choice >= max_choice/2) ) { + if (choice >= item_no-max_choice/2) + scroll = first_item = item_no-max_choice; + else + scroll = first_item = choice - max_choice/2; + choice = choice - scroll; + } + + /* Print the menu */ + for (i=0; i < max_choice; i++) { + print_item (menu, items[(first_item + i) * 2 + 1], i, i == choice, + (items[(first_item + i)*2][0] != ':')); + } + + wnoutrefresh (menu); + + print_arrows(dialog, item_no, scroll, + box_y, box_x+item_x+1, menu_height); + + print_buttons (dialog, height, width, 0); + wmove (menu, choice, item_x+1); + wrefresh (menu); + + while (key != ESC) { + key = wgetch(menu); + + if (key < 256 && isalpha(key)) key = tolower(key); + + if (strchr("ynm", key)) + i = max_choice; + else { + for (i = choice+1; i < max_choice; i++) { + j = first_alpha(items[(scroll+i)*2+1], "YyNnMm"); + if (key == tolower(items[(scroll+i)*2+1][j])) + break; + } + if (i == max_choice) + for (i = 0; i < max_choice; i++) { + j = first_alpha(items[(scroll+i)*2+1], "YyNnMm"); + if (key == tolower(items[(scroll+i)*2+1][j])) + break; + } + } + + if (i < max_choice || + key == KEY_UP || key == KEY_DOWN || + key == '-' || key == '+' || + key == KEY_PPAGE || key == KEY_NPAGE) { + + print_item (menu, items[(scroll+choice)*2+1], choice, FALSE, + (items[(scroll+choice)*2][0] != ':')); + + if (key == KEY_UP || key == '-') { + if (choice < 2 && scroll) { + /* Scroll menu down */ + scrollok (menu, TRUE); + wscrl (menu, -1); + scrollok (menu, FALSE); + + scroll--; + + print_item (menu, items[scroll * 2 + 1], 0, FALSE, + (items[scroll*2][0] != ':')); + } else + choice = MAX(choice - 1, 0); + + } else if (key == KEY_DOWN || key == '+') { + + print_item (menu, items[(scroll+choice)*2+1], choice, FALSE, + (items[(scroll+choice)*2][0] != ':')); + + if ((choice > max_choice-3) && + (scroll + max_choice < item_no) + ) { + /* Scroll menu up */ + scrollok (menu, TRUE); + scroll (menu); + scrollok (menu, FALSE); + + scroll++; + + print_item (menu, items[(scroll+max_choice-1)*2+1], + max_choice-1, FALSE, + (items[(scroll+max_choice-1)*2][0] != ':')); + } else + choice = MIN(choice+1, max_choice-1); + + } else if (key == KEY_PPAGE) { + scrollok (menu, TRUE); + for (i=0; (i < max_choice); i++) { + if (scroll > 0) { + wscrl (menu, -1); + scroll--; + print_item (menu, items[scroll * 2 + 1], 0, FALSE, + (items[scroll*2][0] != ':')); + } else { + if (choice > 0) + choice--; + } + } + scrollok (menu, FALSE); + + } else if (key == KEY_NPAGE) { + for (i=0; (i < max_choice); i++) { + if (scroll+max_choice < item_no) { + scrollok (menu, TRUE); + scroll(menu); + scrollok (menu, FALSE); + scroll++; + print_item (menu, items[(scroll+max_choice-1)*2+1], + max_choice-1, FALSE, + (items[(scroll+max_choice-1)*2][0] != ':')); + } else { + if (choice+1 < max_choice) + choice++; + } + } + + } else + choice = i; + + print_item (menu, items[(scroll+choice)*2+1], choice, TRUE, + (items[(scroll+choice)*2][0] != ':')); + + print_arrows(dialog, item_no, scroll, + box_y, box_x+item_x+1, menu_height); + + wnoutrefresh (dialog); + wrefresh (menu); + + continue; /* wait for another key press */ + } + + switch (key) { + case KEY_LEFT: + case TAB: + case KEY_RIGHT: + button = ((key == KEY_LEFT ? --button : ++button) < 0) + ? 2 : (button > 2 ? 0 : button); + + print_buttons(dialog, height, width, button); + wrefresh (menu); + break; + case ' ': + case 's': + case 'y': + case 'n': + case 'm': + /* save scroll info */ + if ( (f=fopen("lxdialog.scrltmp","w")) != NULL ) { + fprintf(f,"%d\n",scroll); + fclose(f); + } + delwin (dialog); + fprintf(stderr, "%s\n", items[(scroll + choice) * 2]); + switch (key) { + case 's': return 3; + case 'y': return 3; + case 'n': return 4; + case 'm': return 5; + case ' ': return 6; + } + return 0; + case 'h': + case '?': + button = 2; + case '\n': + delwin (dialog); + if (button == 2) + fprintf(stderr, "%s \"%s\"\n", + items[(scroll + choice) * 2], + items[(scroll + choice) * 2 + 1] + + first_alpha(items[(scroll + choice) * 2 + 1],"")); + else + fprintf(stderr, "%s\n", items[(scroll + choice) * 2]); + + remove("lxdialog.scrltmp"); + return button; + case 'e': + case 'x': + key = ESC; + case ESC: + break; + } + } + + delwin (dialog); + remove("lxdialog.scrltmp"); + return -1; /* ESC pressed */ +} diff --git a/scripts/lxdialog/msgbox.c b/scripts/lxdialog/msgbox.c new file mode 100644 index 000000000..93692e1fb --- /dev/null +++ b/scripts/lxdialog/msgbox.c @@ -0,0 +1,85 @@ +/* + * msgbox.c -- implements the message box and info box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +/* + * Display a message box. Program will pause and display an "OK" button + * if the parameter 'pause' is non-zero. + */ +int +dialog_msgbox (const char *title, const char *prompt, int height, int width, + int pause) +{ + int i, x, y, key = 0; + WINDOW *dialog; + + /* center dialog box on screen */ + x = (COLS - width) / 2; + y = (LINES - height) / 2; + + draw_shadow (stdscr, y, x, height, width); + + dialog = newwin (height, width, y, x); + keypad (dialog, TRUE); + + draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr); + + if (title != NULL && strlen(title) >= width-2 ) { + /* truncate long title -- mec */ + char * title2 = malloc(width-2+1); + memcpy( title2, title, width-2 ); + title2[width-2] = '\0'; + title = title2; + } + + if (title != NULL) { + wattrset (dialog, title_attr); + mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' '); + waddstr (dialog, (char *)title); + waddch (dialog, ' '); + } + wattrset (dialog, dialog_attr); + print_autowrap (dialog, prompt, width - 2, 1, 2); + + if (pause) { + wattrset (dialog, border_attr); + mvwaddch (dialog, height - 3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch (dialog, ACS_HLINE); + wattrset (dialog, dialog_attr); + waddch (dialog, ACS_RTEE); + + print_button (dialog, " Ok ", + height - 2, width / 2 - 4, TRUE); + + wrefresh (dialog); + while (key != ESC && key != '\n' && key != ' ' && + key != 'O' && key != 'o' && key != 'X' && key != 'x') + key = wgetch (dialog); + } else { + key = '\n'; + wrefresh (dialog); + } + + delwin (dialog); + return key == ESC ? -1 : 0; +} diff --git a/scripts/lxdialog/textbox.c b/scripts/lxdialog/textbox.c new file mode 100644 index 000000000..ecf55410e --- /dev/null +++ b/scripts/lxdialog/textbox.c @@ -0,0 +1,556 @@ +/* + * textbox.c -- implements the text box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +static void back_lines (int n); +static void print_page (WINDOW * win, int height, int width); +static void print_line (WINDOW * win, int row, int width); +static char *get_line (void); +static void print_position (WINDOW * win, int height, int width); + +static int hscroll = 0, fd, file_size, bytes_read; +static int begin_reached = 1, end_reached = 0, page_length; +static char *buf, *page; + +/* + * Display text from a file in a dialog box. + */ +int +dialog_textbox (const char *title, const char *file, int height, int width) +{ + int i, x, y, cur_x, cur_y, fpos, key = 0; + int passed_end; + char search_term[MAX_LEN + 1]; + WINDOW *dialog, *text; + + search_term[0] = '\0'; /* no search term entered yet */ + + /* Open input file for reading */ + if ((fd = open (file, O_RDONLY)) == -1) { + endwin (); + fprintf (stderr, + "\nCan't open input file in dialog_textbox().\n"); + exit (-1); + } + /* Get file size. Actually, 'file_size' is the real file size - 1, + since it's only the last byte offset from the beginning */ + if ((file_size = lseek (fd, 0, SEEK_END)) == -1) { + endwin (); + fprintf (stderr, "\nError getting file size in dialog_textbox().\n"); + exit (-1); + } + /* Restore file pointer to beginning of file after getting file size */ + if (lseek (fd, 0, SEEK_SET) == -1) { + endwin (); + fprintf (stderr, "\nError moving file pointer in dialog_textbox().\n"); + exit (-1); + } + /* Allocate space for read buffer */ + if ((buf = malloc (BUF_SIZE + 1)) == NULL) { + endwin (); + fprintf (stderr, "\nCan't allocate memory in dialog_textbox().\n"); + exit (-1); + } + if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) { + endwin (); + fprintf (stderr, "\nError reading file in dialog_textbox().\n"); + exit (-1); + } + buf[bytes_read] = '\0'; /* mark end of valid data */ + page = buf; /* page is pointer to start of page to be displayed */ + + /* center dialog box on screen */ + x = (COLS - width) / 2; + y = (LINES - height) / 2; + + + draw_shadow (stdscr, y, x, height, width); + + dialog = newwin (height, width, y, x); + keypad (dialog, TRUE); + + /* Create window for text region, used for scrolling text */ + text = subwin (dialog, height - 4, width - 2, y + 1, x + 1); + wattrset (text, dialog_attr); + wbkgdset (text, dialog_attr & A_COLOR); + + keypad (text, TRUE); + + /* register the new window, along with its borders */ + draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr); + + wattrset (dialog, border_attr); + mvwaddch (dialog, height-3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch (dialog, ACS_HLINE); + wattrset (dialog, dialog_attr); + wbkgdset (dialog, dialog_attr & A_COLOR); + waddch (dialog, ACS_RTEE); + + if (title != NULL && strlen(title) >= width-2 ) { + /* truncate long title -- mec */ + char * title2 = malloc(width-2+1); + memcpy( title2, title, width-2 ); + title2[width-2] = '\0'; + title = title2; + } + + if (title != NULL) { + wattrset (dialog, title_attr); + mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' '); + waddstr (dialog, (char *)title); + waddch (dialog, ' '); + } + print_button (dialog, " Exit ", height - 2, width / 2 - 4, TRUE); + wnoutrefresh (dialog); + getyx (dialog, cur_y, cur_x); /* Save cursor position */ + + /* Print first page of text */ + attr_clear (text, height - 4, width - 2, dialog_attr); + print_page (text, height - 4, width - 2); + print_position (dialog, height, width); + wmove (dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh (dialog); + + while ((key != ESC) && (key != '\n')) { + key = wgetch (dialog); + switch (key) { + case 'E': /* Exit */ + case 'e': + case 'X': + case 'x': + delwin (dialog); + free (buf); + close (fd); + return 0; + case 'g': /* First page */ + case KEY_HOME: + if (!begin_reached) { + begin_reached = 1; + /* First page not in buffer? */ + if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) { + endwin (); + fprintf (stderr, + "\nError moving file pointer in dialog_textbox().\n"); + exit (-1); + } + if (fpos > bytes_read) { /* Yes, we have to read it in */ + if (lseek (fd, 0, SEEK_SET) == -1) { + endwin (); + fprintf (stderr, "\nError moving file pointer in " + "dialog_textbox().\n"); + exit (-1); + } + if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) { + endwin (); + fprintf (stderr, + "\nError reading file in dialog_textbox().\n"); + exit (-1); + } + buf[bytes_read] = '\0'; + } + page = buf; + print_page (text, height - 4, width - 2); + print_position (dialog, height, width); + wmove (dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh (dialog); + } + break; + case 'G': /* Last page */ + case KEY_END: + + end_reached = 1; + /* Last page not in buffer? */ + if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) { + endwin (); + fprintf (stderr, + "\nError moving file pointer in dialog_textbox().\n"); + exit (-1); + } + if (fpos < file_size) { /* Yes, we have to read it in */ + if (lseek (fd, -BUF_SIZE, SEEK_END) == -1) { + endwin (); + fprintf (stderr, + "\nError moving file pointer in dialog_textbox().\n"); + exit (-1); + } + if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) { + endwin (); + fprintf (stderr, + "\nError reading file in dialog_textbox().\n"); + exit (-1); + } + buf[bytes_read] = '\0'; + } + page = buf + bytes_read; + back_lines (height - 4); + print_page (text, height - 4, width - 2); + print_position (dialog, height, width); + wmove (dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh (dialog); + break; + case 'K': /* Previous line */ + case 'k': + case KEY_UP: + if (!begin_reached) { + back_lines (page_length + 1); + + /* We don't call print_page() here but use scrolling to ensure + faster screen update. However, 'end_reached' and + 'page_length' should still be updated, and 'page' should + point to start of next page. This is done by calling + get_line() in the following 'for' loop. */ + scrollok (text, TRUE); + wscrl (text, -1); /* Scroll text region down one line */ + scrollok (text, FALSE); + page_length = 0; + passed_end = 0; + for (i = 0; i < height - 4; i++) { + if (!i) { + /* print first line of page */ + print_line (text, 0, width - 2); + wnoutrefresh (text); + } else + /* Called to update 'end_reached' and 'page' */ + get_line (); + if (!passed_end) + page_length++; + if (end_reached && !passed_end) + passed_end = 1; + } + + print_position (dialog, height, width); + wmove (dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh (dialog); + } + break; + case 'B': /* Previous page */ + case 'b': + case KEY_PPAGE: + if (begin_reached) + break; + back_lines (page_length + height - 4); + print_page (text, height - 4, width - 2); + print_position (dialog, height, width); + wmove (dialog, cur_y, cur_x); + wrefresh (dialog); + break; + case 'J': /* Next line */ + case 'j': + case KEY_DOWN: + if (!end_reached) { + begin_reached = 0; + scrollok (text, TRUE); + scroll (text); /* Scroll text region up one line */ + scrollok (text, FALSE); + print_line (text, height - 5, width - 2); + wnoutrefresh (text); + print_position (dialog, height, width); + wmove (dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh (dialog); + } + break; + case KEY_NPAGE: /* Next page */ + case ' ': + if (end_reached) + break; + + begin_reached = 0; + print_page (text, height - 4, width - 2); + print_position (dialog, height, width); + wmove (dialog, cur_y, cur_x); + wrefresh (dialog); + break; + case '0': /* Beginning of line */ + case 'H': /* Scroll left */ + case 'h': + case KEY_LEFT: + if (hscroll <= 0) + break; + + if (key == '0') + hscroll = 0; + else + hscroll--; + /* Reprint current page to scroll horizontally */ + back_lines (page_length); + print_page (text, height - 4, width - 2); + wmove (dialog, cur_y, cur_x); + wrefresh (dialog); + break; + case 'L': /* Scroll right */ + case 'l': + case KEY_RIGHT: + if (hscroll >= MAX_LEN) + break; + hscroll++; + /* Reprint current page to scroll horizontally */ + back_lines (page_length); + print_page (text, height - 4, width - 2); + wmove (dialog, cur_y, cur_x); + wrefresh (dialog); + break; + case ESC: + break; + } + } + + delwin (dialog); + free (buf); + close (fd); + return -1; /* ESC pressed */ +} + +/* + * Go back 'n' lines in text file. Called by dialog_textbox(). + * 'page' will be updated to point to the desired line in 'buf'. + */ +static void +back_lines (int n) +{ + int i, fpos; + + begin_reached = 0; + /* We have to distinguish between end_reached and !end_reached + since at end of file, the line is not ended by a '\n'. + The code inside 'if' basically does a '--page' to move one + character backward so as to skip '\n' of the previous line */ + if (!end_reached) { + /* Either beginning of buffer or beginning of file reached? */ + if (page == buf) { + if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) { + endwin (); + fprintf (stderr, "\nError moving file pointer in " + "back_lines().\n"); + exit (-1); + } + if (fpos > bytes_read) { /* Not beginning of file yet */ + /* We've reached beginning of buffer, but not beginning of + file yet, so read previous part of file into buffer. + Note that we only move backward for BUF_SIZE/2 bytes, + but not BUF_SIZE bytes to avoid re-reading again in + print_page() later */ + /* Really possible to move backward BUF_SIZE/2 bytes? */ + if (fpos < BUF_SIZE / 2 + bytes_read) { + /* No, move less then */ + if (lseek (fd, 0, SEEK_SET) == -1) { + endwin (); + fprintf (stderr, "\nError moving file pointer in " + "back_lines().\n"); + exit (-1); + } + page = buf + fpos - bytes_read; + } else { /* Move backward BUF_SIZE/2 bytes */ + if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), SEEK_CUR) + == -1) { + endwin (); + fprintf (stderr, "\nError moving file pointer " + "in back_lines().\n"); + exit (-1); + } + page = buf + BUF_SIZE / 2; + } + if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) { + endwin (); + fprintf (stderr, "\nError reading file in back_lines().\n"); + exit (-1); + } + buf[bytes_read] = '\0'; + } else { /* Beginning of file reached */ + begin_reached = 1; + return; + } + } + if (*(--page) != '\n') { /* '--page' here */ + /* Something's wrong... */ + endwin (); + fprintf (stderr, "\nInternal error in back_lines().\n"); + exit (-1); + } + } + /* Go back 'n' lines */ + for (i = 0; i < n; i++) + do { + if (page == buf) { + if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) { + endwin (); + fprintf (stderr, + "\nError moving file pointer in back_lines().\n"); + exit (-1); + } + if (fpos > bytes_read) { + /* Really possible to move backward BUF_SIZE/2 bytes? */ + if (fpos < BUF_SIZE / 2 + bytes_read) { + /* No, move less then */ + if (lseek (fd, 0, SEEK_SET) == -1) { + endwin (); + fprintf (stderr, "\nError moving file pointer " + "in back_lines().\n"); + exit (-1); + } + page = buf + fpos - bytes_read; + } else { /* Move backward BUF_SIZE/2 bytes */ + if (lseek (fd, -(BUF_SIZE / 2 + bytes_read), + SEEK_CUR) == -1) { + endwin (); + fprintf (stderr, "\nError moving file pointer" + " in back_lines().\n"); + exit (-1); + } + page = buf + BUF_SIZE / 2; + } + if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) { + endwin (); + fprintf (stderr, "\nError reading file in " + "back_lines().\n"); + exit (-1); + } + buf[bytes_read] = '\0'; + } else { /* Beginning of file reached */ + begin_reached = 1; + return; + } + } + } while (*(--page) != '\n'); + page++; +} + +/* + * Print a new page of text. Called by dialog_textbox(). + */ +static void +print_page (WINDOW * win, int height, int width) +{ + int i, passed_end = 0; + + page_length = 0; + for (i = 0; i < height; i++) { + print_line (win, i, width); + if (!passed_end) + page_length++; + if (end_reached && !passed_end) + passed_end = 1; + } + wnoutrefresh (win); +} + +/* + * Print a new line of text. Called by dialog_textbox() and print_page(). + */ +static void +print_line (WINDOW * win, int row, int width) +{ + int y, x; + char *line; + + line = get_line (); + line += MIN (strlen (line), hscroll); /* Scroll horizontally */ + wmove (win, row, 0); /* move cursor to correct line */ + waddch (win, ' '); + waddnstr (win, line, MIN (strlen (line), width - 2)); + + getyx (win, y, x); + /* Clear 'residue' of previous line */ +#if OLD_NCURSES + { + int i; + for (i = 0; i < width - x; i++) + waddch (win, ' '); + } +#else + wclrtoeol(win); +#endif +} + +/* + * Return current line of text. Called by dialog_textbox() and print_line(). + * 'page' should point to start of current line before calling, and will be + * updated to point to start of next line. + */ +static char * +get_line (void) +{ + int i = 0, fpos; + static char line[MAX_LEN + 1]; + + end_reached = 0; + while (*page != '\n') { + if (*page == '\0') { + /* Either end of file or end of buffer reached */ + if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) { + endwin (); + fprintf (stderr, "\nError moving file pointer in " + "get_line().\n"); + exit (-1); + } + if (fpos < file_size) { /* Not end of file yet */ + /* We've reached end of buffer, but not end of file yet, + so read next part of file into buffer */ + if ((bytes_read = read (fd, buf, BUF_SIZE)) == -1) { + endwin (); + fprintf (stderr, "\nError reading file in get_line().\n"); + exit (-1); + } + buf[bytes_read] = '\0'; + page = buf; + } else { + if (!end_reached) + end_reached = 1; + break; + } + } else if (i < MAX_LEN) + line[i++] = *(page++); + else { + /* Truncate lines longer than MAX_LEN characters */ + if (i == MAX_LEN) + line[i++] = '\0'; + page++; + } + } + if (i <= MAX_LEN) + line[i] = '\0'; + if (!end_reached) + page++; /* move pass '\n' */ + + return line; +} + +/* + * Print current position + */ +static void +print_position (WINDOW * win, int height, int width) +{ + int fpos, percent; + + if ((fpos = lseek (fd, 0, SEEK_CUR)) == -1) { + endwin (); + fprintf (stderr, "\nError moving file pointer in print_position().\n"); + exit (-1); + } + wattrset (win, position_indicator_attr); + wbkgdset (win, position_indicator_attr & A_COLOR); + percent = !file_size ? + 100 : ((fpos - bytes_read + page - buf) * 100) / file_size; + wmove (win, height - 3, width - 9); + wprintw (win, "(%3d%%)", percent); +} diff --git a/scripts/lxdialog/util.c b/scripts/lxdialog/util.c new file mode 100644 index 000000000..b3a7af9d2 --- /dev/null +++ b/scripts/lxdialog/util.c @@ -0,0 +1,359 @@ +/* + * util.c + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + + +/* use colors by default? */ +bool use_colors = 1; + +const char *backtitle = NULL; + +const char *dialog_result; + +/* + * Attribute values, default is for mono display + */ +chtype attributes[] = +{ + A_NORMAL, /* screen_attr */ + A_NORMAL, /* shadow_attr */ + A_NORMAL, /* dialog_attr */ + A_BOLD, /* title_attr */ + A_NORMAL, /* border_attr */ + A_REVERSE, /* button_active_attr */ + A_DIM, /* button_inactive_attr */ + A_REVERSE, /* button_key_active_attr */ + A_BOLD, /* button_key_inactive_attr */ + A_REVERSE, /* button_label_active_attr */ + A_NORMAL, /* button_label_inactive_attr */ + A_NORMAL, /* inputbox_attr */ + A_NORMAL, /* inputbox_border_attr */ + A_NORMAL, /* searchbox_attr */ + A_BOLD, /* searchbox_title_attr */ + A_NORMAL, /* searchbox_border_attr */ + A_BOLD, /* position_indicator_attr */ + A_NORMAL, /* menubox_attr */ + A_NORMAL, /* menubox_border_attr */ + A_NORMAL, /* item_attr */ + A_REVERSE, /* item_selected_attr */ + A_BOLD, /* tag_attr */ + A_REVERSE, /* tag_selected_attr */ + A_BOLD, /* tag_key_attr */ + A_REVERSE, /* tag_key_selected_attr */ + A_BOLD, /* check_attr */ + A_REVERSE, /* check_selected_attr */ + A_BOLD, /* uarrow_attr */ + A_BOLD /* darrow_attr */ +}; + + +#include "colors.h" + +/* + * Table of color values + */ +int color_table[][3] = +{ + {SCREEN_FG, SCREEN_BG, SCREEN_HL}, + {SHADOW_FG, SHADOW_BG, SHADOW_HL}, + {DIALOG_FG, DIALOG_BG, DIALOG_HL}, + {TITLE_FG, TITLE_BG, TITLE_HL}, + {BORDER_FG, BORDER_BG, BORDER_HL}, + {BUTTON_ACTIVE_FG, BUTTON_ACTIVE_BG, BUTTON_ACTIVE_HL}, + {BUTTON_INACTIVE_FG, BUTTON_INACTIVE_BG, BUTTON_INACTIVE_HL}, + {BUTTON_KEY_ACTIVE_FG, BUTTON_KEY_ACTIVE_BG, BUTTON_KEY_ACTIVE_HL}, + {BUTTON_KEY_INACTIVE_FG, BUTTON_KEY_INACTIVE_BG, BUTTON_KEY_INACTIVE_HL}, + {BUTTON_LABEL_ACTIVE_FG, BUTTON_LABEL_ACTIVE_BG, BUTTON_LABEL_ACTIVE_HL}, + {BUTTON_LABEL_INACTIVE_FG, BUTTON_LABEL_INACTIVE_BG, + BUTTON_LABEL_INACTIVE_HL}, + {INPUTBOX_FG, INPUTBOX_BG, INPUTBOX_HL}, + {INPUTBOX_BORDER_FG, INPUTBOX_BORDER_BG, INPUTBOX_BORDER_HL}, + {SEARCHBOX_FG, SEARCHBOX_BG, SEARCHBOX_HL}, + {SEARCHBOX_TITLE_FG, SEARCHBOX_TITLE_BG, SEARCHBOX_TITLE_HL}, + {SEARCHBOX_BORDER_FG, SEARCHBOX_BORDER_BG, SEARCHBOX_BORDER_HL}, + {POSITION_INDICATOR_FG, POSITION_INDICATOR_BG, POSITION_INDICATOR_HL}, + {MENUBOX_FG, MENUBOX_BG, MENUBOX_HL}, + {MENUBOX_BORDER_FG, MENUBOX_BORDER_BG, MENUBOX_BORDER_HL}, + {ITEM_FG, ITEM_BG, ITEM_HL}, + {ITEM_SELECTED_FG, ITEM_SELECTED_BG, ITEM_SELECTED_HL}, + {TAG_FG, TAG_BG, TAG_HL}, + {TAG_SELECTED_FG, TAG_SELECTED_BG, TAG_SELECTED_HL}, + {TAG_KEY_FG, TAG_KEY_BG, TAG_KEY_HL}, + {TAG_KEY_SELECTED_FG, TAG_KEY_SELECTED_BG, TAG_KEY_SELECTED_HL}, + {CHECK_FG, CHECK_BG, CHECK_HL}, + {CHECK_SELECTED_FG, CHECK_SELECTED_BG, CHECK_SELECTED_HL}, + {UARROW_FG, UARROW_BG, UARROW_HL}, + {DARROW_FG, DARROW_BG, DARROW_HL}, +}; /* color_table */ + +/* + * Set window to attribute 'attr' + */ +void +attr_clear (WINDOW * win, int height, int width, chtype attr) +{ + int i, j; + + wattrset (win, attr); + for (i = 0; i < height; i++) { + wmove (win, i, 0); + for (j = 0; j < width; j++) + waddch (win, ' '); + } + touchwin (win); +} + +void dialog_clear (void) +{ + attr_clear (stdscr, LINES, COLS, screen_attr); + /* Display background title if it exists ... - SLH */ + if (backtitle != NULL) { + int i; + + wattrset (stdscr, screen_attr); + mvwaddstr (stdscr, 0, 1, (char *)backtitle); + wmove (stdscr, 1, 1); + for (i = 1; i < COLS - 1; i++) + waddch (stdscr, ACS_HLINE); + } + wnoutrefresh (stdscr); +} + +/* + * Do some initialization for dialog + */ +void +init_dialog (void) +{ + initscr (); /* Init curses */ + keypad (stdscr, TRUE); + cbreak (); + noecho (); + + + if (use_colors) /* Set up colors */ + color_setup (); + + + dialog_clear (); +} + +/* + * Setup for color display + */ +void +color_setup (void) +{ + int i; + + if (has_colors ()) { /* Terminal supports color? */ + start_color (); + + /* Initialize color pairs */ + for (i = 0; i < ATTRIBUTE_COUNT; i++) + init_pair (i + 1, color_table[i][0], color_table[i][1]); + + /* Setup color attributes */ + for (i = 0; i < ATTRIBUTE_COUNT; i++) + attributes[i] = C_ATTR (color_table[i][2], i + 1); + } +} + +/* + * End using dialog functions. + */ +void +end_dialog (void) +{ + endwin (); +} + + +/* + * Print a string of text in a window, automatically wrap around to the + * next line if the string is too long to fit on one line. Newline + * characters '\n' are replaced by spaces. We start on a new line + * if there is no room for at least 4 nonblanks following a double-space. + */ +void +print_autowrap (WINDOW * win, const char *prompt, int width, int y, int x) +{ + int newl, cur_x, cur_y; + int i, prompt_len, room, wlen; + char tempstr[MAX_LEN + 1], *word, *sp, *sp2; + + strcpy (tempstr, prompt); + + prompt_len = strlen(tempstr); + + /* + * Remove newlines + */ + for(i=0; i<prompt_len; i++) { + if(tempstr[i] == '\n') tempstr[i] = ' '; + } + + if (prompt_len <= width - x * 2) { /* If prompt is short */ + wmove (win, y, (width - prompt_len) / 2); + waddstr (win, tempstr); + } else { + cur_x = x; + cur_y = y; + newl = 1; + word = tempstr; + while (word && *word) { + sp = index(word, ' '); + if (sp) + *sp++ = 0; + + /* Wrap to next line if either the word does not fit, + or it is the first word of a new sentence, and it is + short, and the next word does not fit. */ + room = width - cur_x; + wlen = strlen(word); + if (wlen > room || + (newl && wlen < 4 && sp && wlen+1+strlen(sp) > room + && (!(sp2 = index(sp, ' ')) || wlen+1+(sp2-sp) > room))) { + cur_y++; + cur_x = x; + } + wmove (win, cur_y, cur_x); + waddstr (win, word); + getyx (win, cur_y, cur_x); + cur_x++; + if (sp && *sp == ' ') { + cur_x++; /* double space */ + while (*++sp == ' '); + newl = 1; + } else + newl = 0; + word = sp; + } + } +} + +/* + * Print a button + */ +void +print_button (WINDOW * win, const char *label, int y, int x, int selected) +{ + int i, temp; + + wmove (win, y, x); + wattrset (win, selected ? button_active_attr : button_inactive_attr); + waddstr (win, "<"); + temp = strspn (label, " "); + label += temp; + wattrset (win, selected ? button_label_active_attr + : button_label_inactive_attr); + for (i = 0; i < temp; i++) + waddch (win, ' '); + wattrset (win, selected ? button_key_active_attr + : button_key_inactive_attr); + waddch (win, label[0]); + wattrset (win, selected ? button_label_active_attr + : button_label_inactive_attr); + waddstr (win, (char *)label + 1); + wattrset (win, selected ? button_active_attr : button_inactive_attr); + waddstr (win, ">"); + wmove (win, y, x + temp + 1); +} + +/* + * Draw a rectangular box with line drawing characters + */ +void +draw_box (WINDOW * win, int y, int x, int height, int width, + chtype box, chtype border) +{ + int i, j; + + wattrset (win, 0); + for (i = 0; i < height; i++) { + wmove (win, y + i, x); + for (j = 0; j < width; j++) + if (!i && !j) + waddch (win, border | ACS_ULCORNER); + else if (i == height - 1 && !j) + waddch (win, border | ACS_LLCORNER); + else if (!i && j == width - 1) + waddch (win, box | ACS_URCORNER); + else if (i == height - 1 && j == width - 1) + waddch (win, box | ACS_LRCORNER); + else if (!i) + waddch (win, border | ACS_HLINE); + else if (i == height - 1) + waddch (win, box | ACS_HLINE); + else if (!j) + waddch (win, border | ACS_VLINE); + else if (j == width - 1) + waddch (win, box | ACS_VLINE); + else + waddch (win, box | ' '); + } +} + +/* + * Draw shadows along the right and bottom edge to give a more 3D look + * to the boxes + */ +void +draw_shadow (WINDOW * win, int y, int x, int height, int width) +{ + int i; + + if (has_colors ()) { /* Whether terminal supports color? */ + wattrset (win, shadow_attr); + wmove (win, y + height, x + 2); + for (i = 0; i < width; i++) + waddch (win, winch (win) & A_CHARTEXT); + for (i = y + 1; i < y + height + 1; i++) { + wmove (win, i, x + width); + waddch (win, winch (win) & A_CHARTEXT); + waddch (win, winch (win) & A_CHARTEXT); + } + wnoutrefresh (win); + } +} + +/* + * Return the position of the first alphabetic character in a string. + */ +int +first_alpha(const char *string, const char *exempt) +{ + int i, in_paren=0, c; + + for (i = 0; i < strlen(string); i++) { + c = tolower(string[i]); + + if (strchr("<[(", c)) ++in_paren; + if (strchr(">])", c)) --in_paren; + + if ((! in_paren) && isalpha(c) && + strchr(exempt, c) == 0) + return i; + } + + return 0; +} diff --git a/scripts/lxdialog/yesno.c b/scripts/lxdialog/yesno.c new file mode 100644 index 000000000..11fcc25f5 --- /dev/null +++ b/scripts/lxdialog/yesno.c @@ -0,0 +1,118 @@ +/* + * yesno.c -- implements the yes/no box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +/* + * Display termination buttons + */ +static void +print_buttons(WINDOW *dialog, int height, int width, int selected) +{ + int x = width / 2 - 10; + int y = height - 2; + + print_button (dialog, " Yes ", y, x, selected == 0); + print_button (dialog, " No ", y, x + 13, selected == 1); + + wmove(dialog, y, x+1 + 13*selected ); + wrefresh (dialog); +} + +/* + * Display a dialog box with two buttons - Yes and No + */ +int +dialog_yesno (const char *title, const char *prompt, int height, int width) +{ + int i, x, y, key = 0, button = 0; + WINDOW *dialog; + + /* center dialog box on screen */ + x = (COLS - width) / 2; + y = (LINES - height) / 2; + + draw_shadow (stdscr, y, x, height, width); + + dialog = newwin (height, width, y, x); + keypad (dialog, TRUE); + + draw_box (dialog, 0, 0, height, width, dialog_attr, border_attr); + wattrset (dialog, border_attr); + mvwaddch (dialog, height-3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch (dialog, ACS_HLINE); + wattrset (dialog, dialog_attr); + waddch (dialog, ACS_RTEE); + + if (title != NULL && strlen(title) >= width-2 ) { + /* truncate long title -- mec */ + char * title2 = malloc(width-2+1); + memcpy( title2, title, width-2 ); + title2[width-2] = '\0'; + title = title2; + } + + if (title != NULL) { + wattrset (dialog, title_attr); + mvwaddch (dialog, 0, (width - strlen(title))/2 - 1, ' '); + waddstr (dialog, (char *)title); + waddch (dialog, ' '); + } + + wattrset (dialog, dialog_attr); + print_autowrap (dialog, prompt, width - 2, 1, 3); + + print_buttons(dialog, height, width, 0); + + while (key != ESC) { + key = wgetch (dialog); + switch (key) { + case 'Y': + case 'y': + delwin (dialog); + return 0; + case 'N': + case 'n': + delwin (dialog); + return 1; + + case TAB: + case KEY_LEFT: + case KEY_RIGHT: + button = ((key == KEY_LEFT ? --button : ++button) < 0) + ? 1 : (button > 1 ? 0 : button); + + print_buttons(dialog, height, width, button); + wrefresh (dialog); + break; + case ' ': + case '\n': + delwin (dialog); + return button; + case ESC: + break; + } + } + + delwin (dialog); + return -1; /* ESC pressed */ +} diff --git a/scripts/mk2knr.pl b/scripts/mk2knr.pl deleted file mode 100755 index aaf4963b1..000000000 --- a/scripts/mk2knr.pl +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/perl -w -# -# @(#) mk2knr.pl - generates a perl script that converts lexemes to K&R-style -# -# How to use this script: -# - In the busybox directory type 'scripts/mk2knr.pl files-you-want-to-convert' -# - Review the 'convertme.pl' script generated and remove / edit any of the -# substitutions in there (please especially check for false positives) -# - Type './convertme.pl same-files-as-before' -# - Compile and see if it works -# -# BUGS: This script does not ignore strings inside comments or strings inside -# quotes (it probably should). - -# set this to something else if you want -$convertme = 'convertme.pl'; - -# internal-use variables (don't touch) -$convert = 0; -%converted = (); - -# if no files were specified, print usage -die "usage: $0 file.c | file.h\n" if scalar(@ARGV) == 0; - -# prepare the "convert me" file -open(CM, ">$convertme") or die "convertme.pl $!"; -print CM "#!/usr/bin/perl -p -i\n\n"; - -# process each file passed on the cmd line -while (<>) { - - # if the line says "getopt" in it anywhere, we don't want to muck with it - # because option lists tend to include strings like "cxtzvOf:" which get - # matched by the "check for mixed case" regexps below - next if /getopt/; - - # tokenize the string into just the variables - while (/([a-zA-Z_][a-zA-Z0-9_]*)/g) { - $var = $1; - - # ignore the word "BusyBox" - next if ($var =~ /BusyBox/); - - # this checks for javaStyle or szHungarianNotation - $convert++ if ($var =~ /^[a-z]+[A-Z][a-z]+/); - - # this checks for PascalStyle - $convert++ if ($var =~ /^[A-Z][a-z]+[A-Z][a-z]+/); - - # if we want to add more checks, we can add 'em here, but the above - # checks catch "just enough" and not too much, so prolly not. - - if ($convert) { - $convert = 0; - - # skip ahead if we've already dealt with this one - next if ($converted{$var}); - - # record that we've dealt with this var - $converted{$var} = 1; - - print CM "s/\\b$var\\b/"; # more to come in just a minute - - # change the first letter to lower-case - $var = lcfirst($var); - - # put underscores before all remaining upper-case letters - $var =~ s/([A-Z])/_$1/g; - - # now change the remaining characters to lower-case - $var = lc($var); - - print CM "$var/g;\n"; - } - } -} - -# tidy up and make the $convertme script executable -close(CM); -chmod 0755, $convertme; - -# print a helpful help message -print "Done. Scheduled name changes are in $convertme.\n"; -print "Please review/modify it and then type ./$convertme to do the search & replace.\n"; diff --git a/scripts/mkdep.c b/scripts/mkdep.c new file mode 100644 index 000000000..c3e94bfae --- /dev/null +++ b/scripts/mkdep.c @@ -0,0 +1,628 @@ +/* + * Originally by Linus Torvalds. + * Smart CONFIG_* processing by Werner Almesberger, Michael Chastain. + * + * Usage: mkdep cflags -- file ... + * + * Read source files and output makefile dependency lines for them. + * I make simple dependency lines for #include <*.h> and #include "*.h". + * I also find instances of CONFIG_FOO and generate dependencies + * like include/config/foo.h. + * + * 1 August 1999, Michael Elizabeth Chastain, <mec@shout.net> + * - Keith Owens reported a bug in smart config processing. There used + * to be an optimization for "#define CONFIG_FOO ... #ifdef CONFIG_FOO", + * so that the file would not depend on CONFIG_FOO because the file defines + * this symbol itself. But this optimization is bogus! Consider this code: + * "#if 0 \n #define CONFIG_FOO \n #endif ... #ifdef CONFIG_FOO". Here + * the definition is inactivated, but I still used it. It turns out this + * actually happens a few times in the kernel source. The simple way to + * fix this problem is to remove this particular optimization. + * + * 2.3.99-pre1, Andrew Morton <andrewm@uow.edu.au> + * - Changed so that 'filename.o' depends upon 'filename.[cS]'. This is so that + * missing source files are noticed, rather than silently ignored. + * + * 2.4.2-pre3, Keith Owens <kaos@ocs.com.au> + * - Accept cflags followed by '--' followed by filenames. mkdep extracts -I + * options from cflags and looks in the specified directories as well as the + * defaults. Only -I is supported, no attempt is made to handle -idirafter, + * -isystem, -I- etc. + */ + +#include <ctype.h> +#include <fcntl.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <sys/fcntl.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/types.h> + + + +char __depname[512] = "\n\t@touch "; +#define depname (__depname+9) +int hasdep; + +struct path_struct { + int len; + char *buffer; +}; +struct path_struct *path_array; +int paths; + + +/* Current input file */ +static const char *g_filename; + +/* + * This records all the configuration options seen. + * In perl this would be a hash, but here it's a long string + * of values separated by newlines. This is simple and + * extremely fast. + */ +char * str_config = NULL; +int size_config = 0; +int len_config = 0; + +static void +do_depname(void) +{ + if (!hasdep) { + hasdep = 1; + printf("%s:", depname); + if (g_filename) + printf(" %s", g_filename); + } +} + +/* + * Grow the configuration string to a desired length. + * Usually the first growth is plenty. + */ +void grow_config(int len) +{ + while (len_config + len > size_config) { + if (size_config == 0) + size_config = 2048; + str_config = realloc(str_config, size_config *= 2); + if (str_config == NULL) + { perror("malloc config"); exit(1); } + } +} + + + +/* + * Lookup a value in the configuration string. + */ +int is_defined_config(const char * name, int len) +{ + const char * pconfig; + const char * plast = str_config + len_config - len; + for ( pconfig = str_config + 1; pconfig < plast; pconfig++ ) { + if (pconfig[ -1] == '\n' + && pconfig[len] == '\n' + && !memcmp(pconfig, name, len)) + return 1; + } + return 0; +} + + + +/* + * Add a new value to the configuration string. + */ +void define_config(const char * name, int len) +{ + grow_config(len + 1); + + memcpy(str_config+len_config, name, len); + len_config += len; + str_config[len_config++] = '\n'; +} + + + +/* + * Clear the set of configuration strings. + */ +void clear_config(void) +{ + len_config = 0; + define_config("", 0); +} + + + +/* + * This records all the precious .h filenames. No need for a hash, + * it's a long string of values enclosed in tab and newline. + */ +char * str_precious = NULL; +int size_precious = 0; +int len_precious = 0; + + + +/* + * Grow the precious string to a desired length. + * Usually the first growth is plenty. + */ +void grow_precious(int len) +{ + while (len_precious + len > size_precious) { + if (size_precious == 0) + size_precious = 2048; + str_precious = realloc(str_precious, size_precious *= 2); + if (str_precious == NULL) + { perror("malloc"); exit(1); } + } +} + + + +/* + * Add a new value to the precious string. + */ +void define_precious(const char * filename) +{ + int len = strlen(filename); + grow_precious(len + 4); + *(str_precious+len_precious++) = '\t'; + memcpy(str_precious+len_precious, filename, len); + len_precious += len; + memcpy(str_precious+len_precious, " \\\n", 3); + len_precious += 3; +} + + + +/* + * Handle an #include line. + */ +void handle_include(int start, const char * name, int len) +{ + struct path_struct *path; + int i; + + if (len == 14 && !memcmp(name, "include/config.h", len)) + return; + + if (len >= 7 && !memcmp(name, "config/", 7)) + define_config(name+7, len-7-2); + + for (i = start, path = path_array+start; i < paths; ++i, ++path) { + memcpy(path->buffer+path->len, name, len); + path->buffer[path->len+len] = '\0'; + if (access(path->buffer, F_OK) == 0) { + do_depname(); + printf(" \\\n %s", path->buffer); + return; + } + } + +} + + + +/* + * Add a path to the list of include paths. + */ +void add_path(const char * name) +{ + struct path_struct *path; + char resolved_path[PATH_MAX+1]; + const char *name2; + + if (strcmp(name, ".")) { + name2 = realpath(name, resolved_path); + if (!name2) { + fprintf(stderr, "realpath(%s) failed, %m\n", name); + exit(1); + } + } + else { + name2 = ""; + } + + path_array = realloc(path_array, (++paths)*sizeof(*path_array)); + if (!path_array) { + fprintf(stderr, "cannot expand path_arry\n"); + exit(1); + } + + path = path_array+paths-1; + path->len = strlen(name2); + path->buffer = malloc(path->len+1+256+1); + if (!path->buffer) { + fprintf(stderr, "cannot allocate path buffer\n"); + exit(1); + } + strcpy(path->buffer, name2); + if (path->len && *(path->buffer+path->len-1) != '/') { + *(path->buffer+path->len) = '/'; + *(path->buffer+(++(path->len))) = '\0'; + } +} + + + +/* + * Record the use of a CONFIG_* word. + */ +void use_config(const char * name, int len) +{ + char *pc; + int i; + + pc = path_array[paths-1].buffer + path_array[paths-1].len; + memcpy(pc, "config/", 7); + pc += 7; + + for (i = 0; i < len; i++) { + char c = name[i]; + if (isupper(c)) c = tolower(c); + if (c == '_') c = '/'; + pc[i] = c; + } + pc[len] = '\0'; + + if (is_defined_config(pc, len)) + return; + + define_config(pc, len); + + do_depname(); + printf(" \\\n $(wildcard %s.h)", path_array[paths-1].buffer); +} + + + +/* + * Macros for stunningly fast map-based character access. + * __buf is a register which holds the current word of the input. + * Thus, there is one memory access per sizeof(unsigned long) characters. + */ + +#if defined(__alpha__) || defined(__i386__) || defined(__ia64__) || defined(__x86_64__) || defined(__MIPSEL__) \ + || defined(__arm__) +#define LE_MACHINE +#endif + +#ifdef LE_MACHINE +#define next_byte(x) (x >>= 8) +#define current ((unsigned char) __buf) +#else +#define next_byte(x) (x <<= 8) +#define current (__buf >> 8*(sizeof(unsigned long)-1)) +#endif + +#define GETNEXT { \ + next_byte(__buf); \ + if ((unsigned long) next % sizeof(unsigned long) == 0) { \ + if (next >= end) \ + break; \ + __buf = * (unsigned long *) next; \ + } \ + next++; \ +} + +/* + * State machine macros. + */ +#define CASE(c,label) if (current == c) goto label +#define NOTCASE(c,label) if (current != c) goto label + +/* + * Yet another state machine speedup. + */ +#define MAX2(a,b) ((a)>(b)?(a):(b)) +#define MIN2(a,b) ((a)<(b)?(a):(b)) +#define MAX5(a,b,c,d,e) (MAX2(a,MAX2(b,MAX2(c,MAX2(d,e))))) +#define MIN5(a,b,c,d,e) (MIN2(a,MIN2(b,MIN2(c,MIN2(d,e))))) + + + +/* + * The state machine looks for (approximately) these Perl regular expressions: + * + * m|\/\*.*?\*\/| + * m|\/\/.*| + * m|'.*?'| + * m|".*?"| + * m|#\s*include\s*"(.*?)"| + * m|#\s*include\s*<(.*?>"| + * m|#\s*(?define|undef)\s*CONFIG_(\w*)| + * m|(?!\w)CONFIG_| + * + * About 98% of the CPU time is spent here, and most of that is in + * the 'start' paragraph. Because the current characters are + * in a register, the start loop usually eats 4 or 8 characters + * per memory read. The MAX5 and MIN5 tests dispose of most + * input characters with 1 or 2 comparisons. + */ +void state_machine(const char * map, const char * end) +{ + const char * next = map; + const char * map_dot; + unsigned long __buf = 0; + + for (;;) { +start: + GETNEXT +__start: + if (current > MAX5('/','\'','"','#','C')) goto start; + if (current < MIN5('/','\'','"','#','C')) goto start; + CASE('/', slash); + CASE('\'', squote); + CASE('"', dquote); + CASE('#', pound); + CASE('C', cee); + goto start; + +/* // */ +slash_slash: + GETNEXT + CASE('\n', start); + NOTCASE('\\', slash_slash); + GETNEXT + goto slash_slash; + +/* / */ +slash: + GETNEXT + CASE('/', slash_slash); + NOTCASE('*', __start); +slash_star_dot_star: + GETNEXT +__slash_star_dot_star: + NOTCASE('*', slash_star_dot_star); + GETNEXT + NOTCASE('/', __slash_star_dot_star); + goto start; + +/* '.*?' */ +squote: + GETNEXT + CASE('\'', start); + NOTCASE('\\', squote); + GETNEXT + goto squote; + +/* ".*?" */ +dquote: + GETNEXT + CASE('"', start); + NOTCASE('\\', dquote); + GETNEXT + goto dquote; + +/* #\s* */ +pound: + GETNEXT + CASE(' ', pound); + CASE('\t', pound); + CASE('i', pound_i); + CASE('d', pound_d); + CASE('u', pound_u); + goto __start; + +/* #\s*i */ +pound_i: + GETNEXT NOTCASE('n', __start); + GETNEXT NOTCASE('c', __start); + GETNEXT NOTCASE('l', __start); + GETNEXT NOTCASE('u', __start); + GETNEXT NOTCASE('d', __start); + GETNEXT NOTCASE('e', __start); + goto pound_include; + +/* #\s*include\s* */ +pound_include: + GETNEXT + CASE(' ', pound_include); + CASE('\t', pound_include); + map_dot = next; + CASE('"', pound_include_dquote); + CASE('<', pound_include_langle); + goto __start; + +/* #\s*include\s*"(.*)" */ +pound_include_dquote: + GETNEXT + CASE('\n', start); + NOTCASE('"', pound_include_dquote); + handle_include(0, map_dot, next - map_dot - 1); + goto start; + +/* #\s*include\s*<(.*)> */ +pound_include_langle: + GETNEXT + CASE('\n', start); + NOTCASE('>', pound_include_langle); + handle_include(1, map_dot, next - map_dot - 1); + goto start; + +/* #\s*d */ +pound_d: + GETNEXT NOTCASE('e', __start); + GETNEXT NOTCASE('f', __start); + GETNEXT NOTCASE('i', __start); + GETNEXT NOTCASE('n', __start); + GETNEXT NOTCASE('e', __start); + goto pound_define_undef; + +/* #\s*u */ +pound_u: + GETNEXT NOTCASE('n', __start); + GETNEXT NOTCASE('d', __start); + GETNEXT NOTCASE('e', __start); + GETNEXT NOTCASE('f', __start); + goto pound_define_undef; + +/* + * #\s*(define|undef)\s*CONFIG_(\w*) + * + * this does not define the word, because it could be inside another + * conditional (#if 0). But I do parse the word so that this instance + * does not count as a use. -- mec + */ +pound_define_undef: + GETNEXT + CASE(' ', pound_define_undef); + CASE('\t', pound_define_undef); + + NOTCASE('C', __start); + GETNEXT NOTCASE('O', __start); + GETNEXT NOTCASE('N', __start); + GETNEXT NOTCASE('F', __start); + GETNEXT NOTCASE('I', __start); + GETNEXT NOTCASE('G', __start); + GETNEXT NOTCASE('_', __start); + + map_dot = next; +pound_define_undef_CONFIG_word: + GETNEXT + if (isalnum(current) || current == '_') + goto pound_define_undef_CONFIG_word; + goto __start; + +/* \<CONFIG_(\w*) */ +cee: + if (next >= map+2 && (isalnum(next[-2]) || next[-2] == '_')) + goto start; + GETNEXT NOTCASE('O', __start); + GETNEXT NOTCASE('N', __start); + GETNEXT NOTCASE('F', __start); + GETNEXT NOTCASE('I', __start); + GETNEXT NOTCASE('G', __start); + GETNEXT NOTCASE('_', __start); + + map_dot = next; +cee_CONFIG_word: + GETNEXT + if (isalnum(current) || current == '_') + goto cee_CONFIG_word; + use_config(map_dot, next - map_dot - 1); + goto __start; + } +} + + + +/* + * Generate dependencies for one file. + */ +void do_depend(const char * filename, const char * command) +{ + int mapsize; + int pagesizem1 = getpagesize()-1; + int fd; + struct stat st; + char * map; + + fd = open(filename, O_RDONLY); + if (fd < 0) { + perror(filename); + return; + } + + fstat(fd, &st); + if (st.st_size == 0) { + fprintf(stderr,"%s is empty\n",filename); + close(fd); + return; + } + + mapsize = st.st_size; + mapsize = (mapsize+pagesizem1) & ~pagesizem1; + map = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0); + if ((long) map == -1) { + perror("mkdep: mmap"); + close(fd); + return; + } + if ((unsigned long) map % sizeof(unsigned long) != 0) + { + fprintf(stderr, "do_depend: map not aligned\n"); + exit(1); + } + + hasdep = 0; + clear_config(); + state_machine(map, map+st.st_size); + if (hasdep) { + puts(command); + if (*command) + define_precious(filename); + } + + munmap(map, mapsize); + close(fd); +} + + + +/* + * Generate dependencies for all files. + */ +int main(int argc, char **argv) +{ + int len; + const char *hpath; + + hpath = getenv("TOPDIR"); + if (!hpath) { + fputs("mkdep: TOPDIR not set in environment. " + "Don't bypass the top level Makefile.\n", stderr); + return 1; + } + + add_path("."); /* for #include "..." */ + + while (++argv, --argc > 0) { + if (strncmp(*argv, "-I", 2) == 0) { + if (*((*argv)+2)) { + add_path((*argv)+2); + } + else { + ++argv; + --argc; + add_path(*argv); + } + } + else if (strcmp(*argv, "--") == 0) { + break; + } + } + + add_path(hpath); /* must be last entry, for config files */ + + while (--argc > 0) { + const char * filename = *++argv; + const char * command = __depname; + g_filename = 0; + len = strlen(filename); + memcpy(depname, filename, len+1); + if (len > 2 && filename[len-2] == '.') { + if (filename[len-1] == 'c' || filename[len-1] == 'S') { + depname[len-1] = 'o'; + g_filename = filename; + command = ""; + } + } + do_depend(filename, command); + } + if (len_precious) { + *(str_precious+len_precious) = '\0'; + printf(".PRECIOUS:%s\n", str_precious); + } + return 0; +} diff --git a/scripts/split-include.c b/scripts/split-include.c new file mode 100644 index 000000000..3ab9fed87 --- /dev/null +++ b/scripts/split-include.c @@ -0,0 +1,226 @@ +/* + * split-include.c + * + * Copyright abandoned, Michael Chastain, <mailto:mec@shout.net>. + * This is a C version of syncdep.pl by Werner Almesberger. + * + * This program takes autoconf.h as input and outputs a directory full + * of one-line include files, merging onto the old values. + * + * Think of the configuration options as key-value pairs. Then there + * are five cases: + * + * key old value new value action + * + * KEY-1 VALUE-1 VALUE-1 leave file alone + * KEY-2 VALUE-2A VALUE-2B write VALUE-2B into file + * KEY-3 - VALUE-3 write VALUE-3 into file + * KEY-4 VALUE-4 - write an empty file + * KEY-5 (empty) - leave old empty file alone + */ + +#include <sys/stat.h> +#include <sys/types.h> + +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define ERROR_EXIT(strExit) \ + { \ + const int errnoSave = errno; \ + fprintf(stderr, "%s: ", str_my_name); \ + errno = errnoSave; \ + perror((strExit)); \ + exit(1); \ + } + + + +int main(int argc, const char * argv []) +{ + const char * str_my_name; + const char * str_file_autoconf; + const char * str_dir_config; + + FILE * fp_config; + FILE * fp_target; + FILE * fp_find; + + int buffer_size; + + char * line; + char * old_line; + char * list_target; + char * ptarget; + + struct stat stat_buf; + + /* Check arg count. */ + if (argc != 3) + { + fprintf(stderr, "%s: wrong number of arguments.\n", argv[0]); + exit(1); + } + + str_my_name = argv[0]; + str_file_autoconf = argv[1]; + str_dir_config = argv[2]; + + /* Find a buffer size. */ + if (stat(str_file_autoconf, &stat_buf) != 0) + ERROR_EXIT(str_file_autoconf); + buffer_size = 2 * stat_buf.st_size + 4096; + + /* Allocate buffers. */ + if ( (line = malloc(buffer_size)) == NULL + || (old_line = malloc(buffer_size)) == NULL + || (list_target = malloc(buffer_size)) == NULL ) + ERROR_EXIT(str_file_autoconf); + + /* Open autoconfig file. */ + if ((fp_config = fopen(str_file_autoconf, "r")) == NULL) + ERROR_EXIT(str_file_autoconf); + + /* Make output directory if needed. */ + if (stat(str_dir_config, &stat_buf) != 0) + { + if (mkdir(str_dir_config, 0755) != 0) + ERROR_EXIT(str_dir_config); + } + + /* Change to output directory. */ + if (chdir(str_dir_config) != 0) + ERROR_EXIT(str_dir_config); + + /* Put initial separator into target list. */ + ptarget = list_target; + *ptarget++ = '\n'; + + /* Read config lines. */ + while (fgets(line, buffer_size, fp_config)) + { + const char * str_config; + int is_same; + int itarget; + + if (line[0] != '#') + continue; + if ((str_config = strstr(line, "CONFIG_")) == NULL) + continue; + + /* Make the output file name. */ + str_config += sizeof("CONFIG_") - 1; + for (itarget = 0; !isspace(str_config[itarget]); itarget++) + { + char c = str_config[itarget]; + if (isupper(c)) c = tolower(c); + if (c == '_') c = '/'; + ptarget[itarget] = c; + } + ptarget[itarget++] = '.'; + ptarget[itarget++] = 'h'; + ptarget[itarget++] = '\0'; + + /* Check for existing file. */ + is_same = 0; + if ((fp_target = fopen(ptarget, "r")) != NULL) + { + fgets(old_line, buffer_size, fp_target); + if (fclose(fp_target) != 0) + ERROR_EXIT(ptarget); + if (!strcmp(line, old_line)) + is_same = 1; + } + + if (!is_same) + { + /* Auto-create directories. */ + int islash; + for (islash = 0; islash < itarget; islash++) + { + if (ptarget[islash] == '/') + { + ptarget[islash] = '\0'; + if (stat(ptarget, &stat_buf) != 0 + && mkdir(ptarget, 0755) != 0) + ERROR_EXIT( ptarget ); + ptarget[islash] = '/'; + } + } + + /* Write the file. */ + if ((fp_target = fopen(ptarget, "w" )) == NULL) + ERROR_EXIT(ptarget); + fputs(line, fp_target); + if (ferror(fp_target) || fclose(fp_target) != 0) + ERROR_EXIT(ptarget); + } + + /* Update target list */ + ptarget += itarget; + *(ptarget-1) = '\n'; + } + + /* + * Close autoconfig file. + * Terminate the target list. + */ + if (fclose(fp_config) != 0) + ERROR_EXIT(str_file_autoconf); + *ptarget = '\0'; + + /* + * Fix up existing files which have no new value. + * This is Case 4 and Case 5. + * + * I re-read the tree and filter it against list_target. + * This is crude. But it avoids data copies. Also, list_target + * is compact and contiguous, so it easily fits into cache. + * + * Notice that list_target contains strings separated by \n, + * with a \n before the first string and after the last. + * fgets gives the incoming names a terminating \n. + * So by having an initial \n, strstr will find exact matches. + */ + + fp_find = popen("find * -type f -name \"*.h\" -print", "r"); + if (fp_find == 0) + ERROR_EXIT( "find" ); + + line[0] = '\n'; + while (fgets(line+1, buffer_size, fp_find)) + { + if (strstr(list_target, line) == NULL) + { + /* + * This is an old file with no CONFIG_* flag in autoconf.h. + */ + + /* First strip the \n. */ + line[strlen(line)-1] = '\0'; + + /* Grab size. */ + if (stat(line+1, &stat_buf) != 0) + ERROR_EXIT(line); + + /* If file is not empty, make it empty and give it a fresh date. */ + if (stat_buf.st_size != 0) + { + if ((fp_target = fopen(line+1, "w")) == NULL) + ERROR_EXIT(line); + if (fclose(fp_target) != 0) + ERROR_EXIT(line); + } + } + } + + if (pclose(fp_find) != 0) + ERROR_EXIT("find"); + + return 0; +} diff --git a/scripts/undeb b/scripts/undeb deleted file mode 100644 index a72e1e2ba..000000000 --- a/scripts/undeb +++ /dev/null @@ -1,53 +0,0 @@ -#!/bin/sh -# -# This should work with the GNU version of tar and gzip! -# This should work with the bash or ash shell! -# Requires the programs (ar, tar, gzip, and the pager more or less). -# -usage() { -echo "Usage: undeb -c package.deb <Print control file info>" -echo " undeb -l package.deb <List contents of deb package>" -echo " undeb -x package.deb /foo/boo <Extract deb package to this directory," -echo " put . for current directory>" -exit -} - -deb=$2 - -exist() { -if [ "$deb" = "" ]; then -usage -elif [ ! -s "$deb" ]; then -echo "Can't find $deb!" -exit -fi -} - -if [ "$1" = "" ]; then -usage -elif [ "$1" = "-l" ]; then -exist -type more >/dev/null 2>&1 && pager=more -type less >/dev/null 2>&1 && pager=less -[ "$pager" = "" ] && echo "No pager found!" && exit -(ar -p $deb control.tar.gz | tar -xzO *control ; echo -e "\nPress enter to scroll, q to Quit!\n" ; ar -p $deb data.tar.gz | tar -tzv) | $pager -exit -elif [ "$1" = "-c" ]; then -exist -ar -p $deb control.tar.gz | tar -xzO *control -exit -elif [ "$1" = "-x" ]; then -exist -if [ "$3" = "" ]; then -usage -elif [ ! -d "$3" ]; then -echo "No such directory $3!" -exit -fi -ar -p $deb data.tar.gz | tar -xzvpf - -C $3 || exit -echo -echo "Extracted $deb to $3!" -exit -else -usage -fi diff --git a/scripts/unrpm b/scripts/unrpm deleted file mode 100644 index 376286a6f..000000000 --- a/scripts/unrpm +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/sh -# -# This should work with the GNU version of cpio and gzip! -# This should work with the bash or ash shell! -# Requires the programs (cpio, gzip, and the pager more or less). -# -usage() { -echo "Usage: unrpm -l package.rpm <List contents of rpm package>" -echo " unrpm -x package.rpm /foo/boo <Extract rpm package to this directory," -echo " put . for current directory>" -exit -} - -rpm=$2 - -exist() { -if [ "$rpm" = "" ]; then -usage -elif [ ! -s "$rpm" ]; then -echo "Can't find $rpm!" -exit -fi -} - -if [ "$1" = "" ]; then -usage -elif [ "$1" = "-l" ]; then -exist -type more >/dev/null 2>&1 && pager=more -type less >/dev/null 2>&1 && pager=less -[ "$pager" = "" ] && echo "No pager found!" && exit -(echo -e "\nPress enter to scroll, q to Quit!\n" ; rpm2cpio $rpm | cpio -tv --quiet) | $pager -exit -elif [ "$1" = "-x" ]; then -exist -if [ "$3" = "" ]; then -usage -elif [ ! -d "$3" ]; then -echo "No such directory $3!" -exit -fi -rpm2cpio $rpm | (umask 0 ; cd $3 ; cpio -idmuv) || exit -echo -echo "Extracted $rpm to $3!" -exit -else -usage -fi diff --git a/sed.c b/sed.c deleted file mode 100644 index 709fb13a8..000000000 --- a/sed.c +++ /dev/null @@ -1,850 +0,0 @@ -/* - * sed.c - very minimalist version of sed - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Mark Whitley <markw@lineo.com>, <markw@codepoet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* - Supported features and commands in this version of sed: - - - comments ('#') - - address matching: num|/matchstr/[,num|/matchstr/|$]command - - commands: (p)rint, (d)elete, (s)ubstitue (with g & I flags) - - edit commands: (a)ppend, (i)nsert, (c)hange - - file commands: (r)ead - - backreferences in substitution expressions (\1, \2...\9) - - (Note: Specifying an address (range) to match is *optional*; commands - default to the whole pattern space if no specific address match was - requested.) - - Unsupported features: - - - transliteration (y/source-chars/dest-chars/) (use 'tr') - - no pattern space hold space storing / swapping (x, etc.) - - no labels / branching (: label, b, t, and friends) - - and lots, lots more. -*/ - -#include <stdio.h> -#include <unistd.h> /* for getopt() */ -#include <regex.h> -#include <string.h> /* for strdup() */ -#include <errno.h> -#include <ctype.h> /* for isspace() */ -#include <stdlib.h> -#include "busybox.h" - -/* externs */ -extern void xregcomp(regex_t *preg, const char *regex, int cflags); -extern int optind; /* in unistd.h */ -extern char *optarg; /* ditto */ - -/* options */ -static int be_quiet = 0; - - -struct sed_cmd { - - - /* GENERAL FIELDS */ - char delimiter; /* The delimiter used to separate regexps */ - - /* address storage */ - int beg_line; /* 'sed 1p' 0 == no begining line, apply commands to all lines */ - int end_line; /* 'sed 1,3p' 0 == no end line, use only beginning. -1 == $ */ - regex_t *beg_match; /* sed -e '/match/cmd' */ - regex_t *end_match; /* sed -e '/match/,/end_match/cmd' */ - - /* the command */ - char cmd; /* p,d,s (add more at your leisure :-) */ - - - /* SUBSTITUTION COMMAND SPECIFIC FIELDS */ - - /* sed -e 's/sub_match/replace/' */ - regex_t *sub_match; - char *replace; - unsigned int num_backrefs:4; /* how many back references (\1..\9) */ - /* Note: GNU/POSIX sed does not save more than nine backrefs, so - * we only use 4 bits to hold the number */ - unsigned int sub_g:1; /* sed -e 's/foo/bar/g' (global) */ - unsigned int sub_p:2; /* sed -e 's/foo/bar/p' (print substitution) */ - - - /* EDIT COMMAND (a,i,c) SPEICIFIC FIELDS */ - - char *editline; - - - /* FILE COMMAND (r) SPEICIFIC FIELDS */ - - char *filename; -}; - -/* globals */ -static struct sed_cmd *sed_cmds = NULL; /* growable arrary holding a sequence of sed cmds */ -static int ncmds = 0; /* number of sed commands */ - -/*static char *cur_file = NULL;*/ /* file currently being processed XXX: do I need this? */ - -#ifdef BB_FEATURE_CLEAN_UP -static void destroy_cmd_strs() -{ - if (sed_cmds == NULL) - return; - - /* destroy all the elements in the array */ - while (--ncmds >= 0) { - - if (sed_cmds[ncmds].beg_match) { - regfree(sed_cmds[ncmds].beg_match); - free(sed_cmds[ncmds].beg_match); - } - if (sed_cmds[ncmds].end_match) { - regfree(sed_cmds[ncmds].end_match); - free(sed_cmds[ncmds].end_match); - } - if (sed_cmds[ncmds].sub_match) { - regfree(sed_cmds[ncmds].sub_match); - free(sed_cmds[ncmds].sub_match); - } - if (sed_cmds[ncmds].replace) - free(sed_cmds[ncmds].replace); - } - - /* destroy the array */ - free(sed_cmds); - sed_cmds = NULL; -} -#endif - - -/* - * index_of_next_unescaped_regexp_delim - walks left to right through a string - * beginning at a specified index and returns the index of the next regular - * expression delimiter (typically a forward * slash ('/')) not preceeded by - * a backslash ('\'). - */ -static int index_of_next_unescaped_regexp_delim(struct sed_cmd *sed_cmd, const char *str, int idx) -{ - int bracket = -1; - int escaped = 0; - - for ( ; str[idx]; idx++) { - if (bracket != -1) { - if (str[idx] == ']' && !(bracket == idx - 1 || - (bracket == idx - 2 && str[idx-1] == '^'))) - bracket = -1; - } else if (escaped) - escaped = 0; - else if (str[idx] == '\\') - escaped = 1; - else if (str[idx] == '[') - bracket = idx; - else if (str[idx] == sed_cmd->delimiter) - return idx; - } - - /* if we make it to here, we've hit the end of the string */ - return -1; -} - -/* - * returns the index in the string just past where the address ends. - */ -static int get_address(struct sed_cmd *sed_cmd, const char *str, int *linenum, regex_t **regex) -{ - char *my_str = strdup(str); - int idx = 0; - char olddelimiter; - olddelimiter = sed_cmd->delimiter; - sed_cmd->delimiter = '/'; - - if (isdigit(my_str[idx])) { - do { - idx++; - } while (isdigit(my_str[idx])); - my_str[idx] = 0; - *linenum = atoi(my_str); - } - else if (my_str[idx] == '$') { - *linenum = -1; - idx++; - } - else if (my_str[idx] == '/') { - idx = index_of_next_unescaped_regexp_delim(sed_cmd, my_str, ++idx); - if (idx == -1) - error_msg_and_die("unterminated match expression"); - my_str[idx] = '\0'; - *regex = (regex_t *)xmalloc(sizeof(regex_t)); - xregcomp(*regex, my_str+1, REG_NEWLINE); - idx++; /* so it points to the next character after the last '/' */ - } - else { - error_msg("get_address: no address found in string\n" - "\t(you probably didn't check the string you passed me)"); - idx = -1; - } - - free(my_str); - sed_cmd->delimiter = olddelimiter; - return idx; -} - -static int parse_subst_cmd(struct sed_cmd *sed_cmd, const char *substr) -{ - int oldidx, cflags = REG_NEWLINE; - char *match; - int idx = 0; - int j; - - /* - * the string that gets passed to this function should look like this: - * s/match/replace/gIp - * || | ||| - * mandatory optional - * - * (all three of the '/' slashes are mandatory) - */ - - /* verify that the 's' is followed by something. That something - * (typically a 'slash') is now our regexp delimiter... */ - if (!substr[++idx]) - error_msg_and_die("bad format in substitution expression"); - else - sed_cmd->delimiter=substr[idx]; - - /* save the match string */ - oldidx = idx+1; - idx = index_of_next_unescaped_regexp_delim(sed_cmd, substr, ++idx); - if (idx == -1) - error_msg_and_die("bad format in substitution expression"); - match = xstrndup(substr + oldidx, idx - oldidx); - - /* determine the number of back references in the match string */ - /* Note: we compute this here rather than in the do_subst_command() - * function to save processor time, at the expense of a little more memory - * (4 bits) per sed_cmd */ - - /* sed_cmd->num_backrefs = 0; */ /* XXX: not needed? --apparently not */ - for (j = 0; match[j]; j++) { - /* GNU/POSIX sed does not save more than nine backrefs */ - if (match[j] == '\\' && match[j+1] == '(' && sed_cmd->num_backrefs <= 9) - sed_cmd->num_backrefs++; - } - - /* save the replacement string */ - oldidx = idx+1; - idx = index_of_next_unescaped_regexp_delim(sed_cmd, substr, ++idx); - if (idx == -1) - error_msg_and_die("bad format in substitution expression"); - sed_cmd->replace = xstrndup(substr + oldidx, idx - oldidx); - - /* process the flags */ - while (substr[++idx]) { - switch (substr[idx]) { - case 'g': - sed_cmd->sub_g = 1; - break; - case 'I': - cflags |= REG_ICASE; - break; - case 'p': - sed_cmd->sub_p = 1; - break; - default: - /* any whitespace or semicolon trailing after a s/// is ok */ - if (strchr("; \t\v\n\r", substr[idx])) - goto out; - /* else */ - error_msg_and_die("bad option in substitution expression"); - } - } - -out: - /* compile the match string into a regex */ - sed_cmd->sub_match = (regex_t *)xmalloc(sizeof(regex_t)); - xregcomp(sed_cmd->sub_match, match, cflags); - free(match); - - return idx; -} - -static int parse_edit_cmd(struct sed_cmd *sed_cmd, const char *editstr) -{ - int idx = 0; - int slashes_eaten = 0; - char *ptr; /* shorthand */ - - /* - * the string that gets passed to this function should look like this: - * - * need one of these - * | - * | this backslash (immediately following the edit command) is mandatory - * | | - * [aic]\ - * TEXT1\ - * TEXT2\ - * TEXTN - * - * as soon as we hit a TEXT line that has no trailing '\', we're done. - * this means a command like: - * - * i\ - * INSERTME - * - * is a-ok. - * - */ - - if (editstr[1] != '\\' && (editstr[2] != '\n' || editstr[2] != '\r')) - error_msg_and_die("bad format in edit expression"); - - /* store the edit line text */ - /* make editline big enough to accomodate the extra '\n' we will tack on - * to the end */ - sed_cmd->editline = xmalloc(strlen(&editstr[3]) + 2); - strcpy(sed_cmd->editline, &editstr[3]); - ptr = sed_cmd->editline; - - /* now we need to go through * and: s/\\[\r\n]$/\n/g on the edit line */ - while (ptr[idx]) { - while (ptr[idx] != '\\' || (ptr[idx+1] != '\n' && ptr[idx+1] != '\r')) { - idx++; - if (!ptr[idx]) { - goto out; - } - } - /* move the newline over the '\' before it (effectively eats the '\') */ - memmove(&ptr[idx], &ptr[idx+1], strlen(&ptr[idx+1])); - ptr[strlen(ptr)-1] = 0; - slashes_eaten++; - /* substitue \r for \n if needed */ - if (ptr[idx] == '\r') - ptr[idx] = '\n'; - } - -out: - /* this accounts for discrepancies between the modified string and the - * original string passed in to this function */ - idx += slashes_eaten; - - /* figure out if we need to add a newline */ - if (ptr[idx-1] != '\n') { - ptr[idx] = '\n'; - idx++; - } - - /* terminate string */ - ptr[idx]= 0; - /* adjust for opening 2 chars [aic]\ */ - idx += 2; - - return idx; -} - - -static int parse_file_cmd(struct sed_cmd *sed_cmd, const char *filecmdstr) -{ - int idx = 0; - int filenamelen = 0; - - /* - * the string that gets passed to this function should look like this: - * '[ ]filename' - * | | - * | a filename - * | - * optional whitespace - - * re: the file to be read, the GNU manual says the following: "Note that - * if filename cannot be read, it is treated as if it were an empty file, - * without any error indication." Thus, all of the following commands are - * perfectly leagal: - * - * sed -e '1r noexist' - * sed -e '1r ;' - * sed -e '1r' - */ - - /* the file command may be followed by whitespace; move past it. */ - while (isspace(filecmdstr[++idx])) - { ; } - - /* the first non-whitespace we get is a filename. the filename ends when we - * hit a normal sed command terminator or end of string */ - filenamelen = strcspn(&filecmdstr[idx], "; \n\r\t\v\0"); - sed_cmd->filename = xmalloc(filenamelen + 1); - safe_strncpy(sed_cmd->filename, &filecmdstr[idx], filenamelen + 1); - - return idx + filenamelen; -} - - -static char *parse_cmd_str(struct sed_cmd *sed_cmd, const char *cmdstr) -{ - int idx = 0; - - /* parse the command - * format is: [addr][,addr]cmd - * |----||-----||-| - * part1 part2 part3 - */ - - /* first part (if present) is an address: either a number or a /regex/ */ - if (isdigit(cmdstr[idx]) || cmdstr[idx] == '/') - idx = get_address(sed_cmd, cmdstr, &sed_cmd->beg_line, &sed_cmd->beg_match); - - /* second part (if present) will begin with a comma */ - if (cmdstr[idx] == ',') - idx += get_address(sed_cmd, &cmdstr[++idx], &sed_cmd->end_line, &sed_cmd->end_match); - - /* last part (mandatory) will be a command */ - if (cmdstr[idx] == '\0') - error_msg_and_die("missing command"); - sed_cmd->cmd = cmdstr[idx]; - - /* if it was a single-letter command that takes no arguments (such as 'p' - * or 'd') all we need to do is increment the index past that command */ - if (strchr("pd", cmdstr[idx])) { - idx++; - } - /* handle (s)ubstitution command */ - else if (sed_cmd->cmd == 's') { - idx += parse_subst_cmd(sed_cmd, &cmdstr[idx]); - } - /* handle edit cmds: (a)ppend, (i)nsert, and (c)hange */ - else if (strchr("aic", sed_cmd->cmd)) { - if ((sed_cmd->end_line || sed_cmd->end_match) && sed_cmd->cmd != 'c') - error_msg_and_die("only a beginning address can be specified for edit commands"); - idx += parse_edit_cmd(sed_cmd, &cmdstr[idx]); - } - /* handle file cmds: (r)ead */ - else if (sed_cmd->cmd == 'r') { - if (sed_cmd->end_line || sed_cmd->end_match) - error_msg_and_die("Command only uses one address"); - idx += parse_file_cmd(sed_cmd, &cmdstr[idx]); - } - else { - error_msg_and_die("invalid command"); - } - - /* give back whatever's left over */ - return (char *)&cmdstr[idx]; -} - -static void add_cmd_str(const char *cmdstr) -{ - char *mystr = (char *)cmdstr; - - do { - - /* trim leading whitespace and semicolons */ - memmove(mystr, &mystr[strspn(mystr, "; \n\r\t\v")], strlen(mystr)); - /* if we ate the whole thing, that means there was just trailing - * whitespace or a final / no-op semicolon. either way, get out */ - if (strlen(mystr) == 0) - return; - /* if this is a comment, jump past it and keep going */ - if (mystr[0] == '#') { - mystr = strpbrk(mystr, ";\n\r"); - continue; - } - /* grow the array */ - sed_cmds = xrealloc(sed_cmds, sizeof(struct sed_cmd) * (++ncmds)); - /* zero new element */ - memset(&sed_cmds[ncmds-1], 0, sizeof(struct sed_cmd)); - /* load command string into new array element, get remainder */ - mystr = parse_cmd_str(&sed_cmds[ncmds-1], mystr); - - } while (mystr && strlen(mystr)); -} - - -static void load_cmd_file(char *filename) -{ - FILE *cmdfile; - char *line; - char *nextline; - - cmdfile = xfopen(filename, "r"); - - while ((line = get_line_from_file(cmdfile)) != NULL) { - /* if a line ends with '\' it needs the next line appended to it */ - while (line[strlen(line)-2] == '\\' && - (nextline = get_line_from_file(cmdfile)) != NULL) { - line = xrealloc(line, strlen(line) + strlen(nextline) + 1); - strcat(line, nextline); - free(nextline); - } - /* eat trailing newline (if any) --if I don't do this, edit commands - * (aic) will print an extra newline */ - chomp(line); - add_cmd_str(line); - free(line); - } -} - -#define PIPE_MAGIC 0x7f -#define PIPE_GROW 64 -#define pipeputc(c) \ -{ if (pipeline[pipeline_idx] == PIPE_MAGIC) { \ - pipeline = xrealloc(pipeline, pipeline_len+PIPE_GROW); \ - memset(pipeline+pipeline_len, 0, PIPE_GROW); \ - pipeline_len += PIPE_GROW; \ - pipeline[pipeline_len-1] = PIPE_MAGIC; } \ - pipeline[pipeline_idx++] = (c); } - -static void print_subst_w_backrefs(const char *line, const char *replace, - regmatch_t *regmatch, char **pipeline_p, int *pipeline_idx_p, - int *pipeline_len_p, int matches) -{ - char *pipeline = *pipeline_p; - int pipeline_idx = *pipeline_idx_p; - int pipeline_len = *pipeline_len_p; - int i; - - /* go through the replacement string */ - for (i = 0; replace[i]; i++) { - /* if we find a backreference (\1, \2, etc.) print the backref'ed * text */ - if (replace[i] == '\\' && isdigit(replace[i+1])) { - int j; - char tmpstr[2]; - int backref; - ++i; /* i now indexes the backref number, instead of the leading slash */ - tmpstr[0] = replace[i]; - tmpstr[1] = 0; - backref = atoi(tmpstr); - /* print out the text held in regmatch[backref] */ - if (backref <= matches && regmatch[backref].rm_so != -1) - for (j = regmatch[backref].rm_so; j < regmatch[backref].rm_eo; j++) - pipeputc(line[j]); - } - - /* if we find a backslash escaped character, print the character */ - else if (replace[i] == '\\') { - ++i; - pipeputc(replace[i]); - } - - /* if we find an unescaped '&' print out the whole matched text. - * fortunately, regmatch[0] contains the indicies to the whole matched - * expression (kinda seems like it was designed for just such a - * purpose...) */ - else if (replace[i] == '&' && replace[i-1] != '\\') { - int j; - for (j = regmatch[0].rm_so; j < regmatch[0].rm_eo; j++) - pipeputc(line[j]); - } - /* nothing special, just print this char of the replacement string to stdout */ - else - pipeputc(replace[i]); - } - *pipeline_p = pipeline; - *pipeline_idx_p = pipeline_idx; - *pipeline_len_p = pipeline_len; -} - -static int do_subst_command(const struct sed_cmd *sed_cmd, char **line) -{ - char *hackline = *line; - char *pipeline = 0; - int pipeline_idx = 0; - int pipeline_len = 0; - int altered = 0; - regmatch_t *regmatch = NULL; - - /* we only proceed if the substitution 'search' expression matches */ - if (regexec(sed_cmd->sub_match, hackline, 0, NULL, 0) == REG_NOMATCH) - return 0; - - /* whaddaya know, it matched. get the number of back references */ - regmatch = xmalloc(sizeof(regmatch_t) * (sed_cmd->num_backrefs+1)); - - /* allocate more PIPE_GROW bytes - if replaced string is larger than original */ - pipeline_len = strlen(hackline)+PIPE_GROW; - pipeline = xmalloc(pipeline_len); - memset(pipeline, 0, pipeline_len); - /* buffer magic */ - pipeline[pipeline_len-1] = PIPE_MAGIC; - - /* and now, as long as we've got a line to try matching and if we can match - * the search string, we make substitutions */ - while ((*hackline || !altered) && (regexec(sed_cmd->sub_match, hackline, - sed_cmd->num_backrefs+1, regmatch, 0) != REG_NOMATCH) ) { - int i; - - /* print everything before the match */ - for (i = 0; i < regmatch[0].rm_so; i++) - pipeputc(hackline[i]); - - /* then print the substitution string */ - print_subst_w_backrefs(hackline, sed_cmd->replace, regmatch, - &pipeline, &pipeline_idx, &pipeline_len, - sed_cmd->num_backrefs); - - /* advance past the match */ - hackline += regmatch[0].rm_eo; - /* flag that something has changed */ - altered++; - - /* if we're not doing this globally, get out now */ - if (!sed_cmd->sub_g) - break; - } - - for (; *hackline; hackline++) pipeputc(*hackline); - if (pipeline[pipeline_idx] == PIPE_MAGIC) pipeline[pipeline_idx] = 0; - - /* cleanup */ - free(regmatch); - - free(*line); - *line = pipeline; - return altered; -} - - -static void process_file(FILE *file) -{ - char *line = NULL; - static int linenum = 0; /* GNU sed does not restart counting lines at EOF */ - unsigned int still_in_range = 0; - int altered; - int i; - - /* go through every line in the file */ - while ((line = get_line_from_file(file)) != NULL) { - - chomp(line); - linenum++; - altered = 0; - - /* for every line, go through all the commands */ - for (i = 0; i < ncmds; i++) { - - - /* - * entry point into sedding... - */ - if ( - /* no range necessary */ - (sed_cmds[i].beg_line == 0 && sed_cmds[i].end_line == 0 && - sed_cmds[i].beg_match == NULL && - sed_cmds[i].end_match == NULL) || - /* this line number is the first address we're looking for */ - (sed_cmds[i].beg_line && (sed_cmds[i].beg_line == linenum)) || - /* this line matches our first address regex */ - (sed_cmds[i].beg_match && (regexec(sed_cmds[i].beg_match, line, 0, NULL, 0) == 0)) || - /* we are currently within the beginning & ending address range */ - still_in_range - ) { - - /* - * actual sedding - */ - switch (sed_cmds[i].cmd) { - - case 'p': - puts(line); - break; - - case 'd': - altered++; - break; - - case 's': - - /* - * Some special cases for 's' printing to make it compliant with - * GNU sed printing behavior (aka "The -n | s///p Matrix"): - * - * -n ONLY = never print anything regardless of any successful - * substitution - * - * s///p ONLY = always print successful substitutions, even if - * the line is going to be printed anyway (line will be printed - * twice). - * - * -n AND s///p = print ONLY a successful substitution ONE TIME; - * no other lines are printed - this is the reason why the 'p' - * flag exists in the first place. - */ - - /* if the user specified that they didn't want anything printed (i.e., a -n - * flag and no 'p' flag after the s///), then there's really no point doing - * anything here. */ - if (be_quiet && !sed_cmds[i].sub_p) - break; - - /* we print the line once, unless we were told to be quiet */ - if (!be_quiet) - altered |= do_subst_command(&sed_cmds[i], &line); - - /* we also print the line if we were given the 'p' flag - * (this is quite possibly the second printing) */ - if (sed_cmds[i].sub_p) - altered |= do_subst_command(&sed_cmds[i], &line); - if (altered && (i+1 >= ncmds || sed_cmds[i+1].cmd != 's')) - puts(line); - - break; - - case 'a': - puts(line); - fputs(sed_cmds[i].editline, stdout); - altered++; - break; - - case 'i': - fputs(sed_cmds[i].editline, stdout); - break; - - case 'c': - /* single-address case */ - if (sed_cmds[i].end_match == NULL && sed_cmds[i].end_line == 0) { - fputs(sed_cmds[i].editline, stdout); - } - /* multi-address case */ - else { - /* matching text */ - if (sed_cmds[i].end_match && (regexec(sed_cmds[i].end_match, line, 0, NULL, 0) == 0)) - fputs(sed_cmds[i].editline, stdout); - /* matching line numbers */ - if (sed_cmds[i].end_line > 0 && sed_cmds[i].end_line == linenum) - fputs(sed_cmds[i].editline, stdout); - } - altered++; - - break; - - case 'r': { - FILE *outfile; - puts(line); - outfile = fopen(sed_cmds[i].filename, "r"); - if (outfile) - print_file(outfile); - /* else if we couldn't open the output file, - * no biggie, just don't print anything */ - altered++; - } - break; - } - - /* - * exit point from sedding... - */ - if ( - /* this is a single-address command or... */ - (sed_cmds[i].end_line == 0 && sed_cmds[i].end_match == NULL) || ( - /* we were in the middle of our address range (this - * isn't the first time through) and.. */ - (still_in_range == 1) && ( - /* this line number is the last address we're looking for or... */ - (sed_cmds[i].end_line && (sed_cmds[i].end_line == linenum)) || - /* this line matches our last address regex */ - (sed_cmds[i].end_match && (regexec(sed_cmds[i].end_match, line, 0, NULL, 0) == 0)) - ) - ) - ) { - /* we're out of our address range */ - still_in_range = 0; - } - - /* didn't hit the exit? then we're still in the middle of an address range */ - else { - still_in_range = 1; - } - } - } - - /* we will print the line unless we were told to be quiet or if the - * line was altered (via a 'd'elete or 's'ubstitution), in which case - * the altered line was already printed */ - if (!be_quiet && !altered) - puts(line); - - free(line); - } -} - -extern int sed_main(int argc, char **argv) -{ - int opt; - -#ifdef BB_FEATURE_CLEAN_UP - /* destroy command strings on exit */ - if (atexit(destroy_cmd_strs) == -1) - perror_msg_and_die("atexit"); -#endif - - /* do normal option parsing */ - while ((opt = getopt(argc, argv, "ne:f:")) > 0) { - switch (opt) { - case 'n': - be_quiet++; - break; - case 'e': - add_cmd_str(optarg); - break; - case 'f': - load_cmd_file(optarg); - break; - default: - show_usage(); - } - } - - /* if we didn't get a pattern from a -e and no command file was specified, - * argv[optind] should be the pattern. no pattern, no worky */ - if (ncmds == 0) { - if (argv[optind] == NULL) - show_usage(); - else { - add_cmd_str(argv[optind]); - optind++; - } - } - - - /* argv[(optind)..(argc-1)] should be names of file to process. If no - * files were specified or '-' was specified, take input from stdin. - * Otherwise, we process all the files specified. */ - if (argv[optind] == NULL || (strcmp(argv[optind], "-") == 0)) { - process_file(stdin); - } - else { - int i; - FILE *file; - for (i = optind; i < argc; i++) { - file = fopen(argv[i], "r"); - if (file == NULL) { - perror_msg("%s", argv[i]); - } else { - process_file(file); - fclose(file); - } - } - } - - return 0; -} diff --git a/setkeycodes.c b/setkeycodes.c deleted file mode 100644 index c3c7e09aa..000000000 --- a/setkeycodes.c +++ /dev/null @@ -1,72 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * setkeycodes - * - * Copyright (C) 1994-1998 Andries E. Brouwer <aeb@cwi.nl> - * - * Adjusted for BusyBox by Erik Andersen <andersee@debian.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <stdio.h> -#include <stdlib.h> -#include <fcntl.h> -#include <sys/ioctl.h> -#include "busybox.h" - - -/* From <linux/kd.h> */ -struct kbkeycode { - unsigned int scancode, keycode; -}; -static const int KDSETKEYCODE = 0x4B4D; /* write kernel keycode table entry */ - -extern int -setkeycodes_main(int argc, char** argv) -{ - char *ep; - int fd, sc; - struct kbkeycode a; - - if (argc % 2 != 1 || argc < 2) { - show_usage(); - } - - fd = get_console_fd("/dev/console"); - - while (argc > 2) { - a.keycode = atoi(argv[2]); - a.scancode = sc = strtol(argv[1], &ep, 16); - if (*ep) { - error_msg_and_die("error reading SCANCODE: '%s'", argv[1]); - } - if (a.scancode > 127) { - a.scancode -= 0xe000; - a.scancode += 128; - } - if (a.scancode > 255 || a.keycode > 127) { - error_msg_and_die("SCANCODE or KEYCODE outside bounds"); - } - if (ioctl(fd,KDSETKEYCODE,&a)) { - perror("KDSETKEYCODE"); - error_msg_and_die("failed to set SCANCODE %x to KEYCODE %d", sc, a.keycode); - } - argc -= 2; - argv += 2; - } - return EXIT_SUCCESS; -} diff --git a/shell/Makefile b/shell/Makefile new file mode 100644 index 000000000..e0229973e --- /dev/null +++ b/shell/Makefile @@ -0,0 +1,40 @@ +# Makefile for busybox +# +# Copyright (C) 1999,2000,2001 by Erik Andersen <andersee@debian.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +TOPDIR :=.. +L_TARGET := shell.a +EXTRA_CFLAGS = -DBB_VER='"$(VERSION)"' -DBB_BT='"$(BUILDTIME)"' + +obj-y := +obj-n := +obj- := + +obj-$(CONFIG_ASH) += ash.o +obj-$(CONFIG_HUSH) += hush.o +obj-$(CONFIG_LASH) += lash.o +obj-$(CONFIG_MSH) += msh.o +obj-$(CONFIG_FEATURE_COMMAND_EDITING) += cmdedit.o + + +# Hand off to toplevel Rules.mak +include $(TOPDIR)/Rules.mak + +clean: + rm -f $(L_TARGET) *.o core + diff --git a/shell/ash.c b/shell/ash.c index 486386a25..9cc2208ab 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -265,7 +265,7 @@ union align { #define ALIGN(nbytes) (((nbytes) + sizeof(union align) - 1) & ~(sizeof(union align) - 1)) #endif -#ifdef BB_LOCALE_SUPPORT +#ifdef CONFIG_LOCALE_SUPPORT #include <locale.h> static void change_lc_all(const char *value); static void change_lc_ctype(const char *value); @@ -1218,7 +1218,7 @@ static struct var vpath; static struct var vps1; static struct var vps2; static struct var voptind; -#ifdef BB_LOCALE_SUPPORT +#ifdef CONFIG_LOCALE_SUPPORT static struct var vlc_all; static struct var vlc_ctype; #endif @@ -1261,7 +1261,7 @@ static const struct varinit varinit[] = { NULL }, { &voptind, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset }, -#ifdef BB_LOCALE_SUPPORT +#ifdef CONFIG_LOCALE_SUPPORT { &vlc_all, VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL=", change_lc_all }, { &vlc_ctype, VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE=", @@ -1556,7 +1556,7 @@ static int hashcmd (int, char **); static int helpcmd (int, char **); static int jobscmd (int, char **); static int localcmd (int, char **); -#ifndef BB_PWD +#ifndef CONFIG_PWD static int pwdcmd (int, char **); #endif static int readcmd (int, char **); @@ -1582,7 +1582,7 @@ static int typecmd (int, char **); static int getoptscmd (int, char **); #endif -#ifndef BB_TRUE_FALSE +#ifndef CONFIG_TRUE_FALSE static int true_main (int, char **); static int false_main (int, char **); #endif @@ -1653,7 +1653,7 @@ static const struct builtincmd builtincmds[] = { { BUILTIN_REGULAR "let", letcmd }, #endif { BUILTIN_ASSIGN "local", localcmd }, -#ifndef BB_PWD +#ifndef CONFIG_PWD { BUILTIN_NOSPEC "pwd", pwdcmd }, #endif { BUILTIN_REGULAR "read", readcmd }, @@ -1938,7 +1938,7 @@ updatepwd(const char *dir) } -#ifndef BB_PWD +#ifndef CONFIG_PWD static int pwdcmd(argc, argv) int argc; @@ -3182,7 +3182,7 @@ returncmd(argc, argv) } -#ifndef BB_TRUE_FALSE +#ifndef CONFIG_TRUE_FALSE static int false_main(argc, argv) int argc; @@ -3224,7 +3224,7 @@ setinteractive(int on) is_interactive = on; if (do_banner==0 && is_interactive) { /* Looks like they want an interactive shell */ -#ifndef BB_FEATURE_SH_EXTRA_QUIET +#ifndef CONFIG_FEATURE_SH_EXTRA_QUIET printf( "\n\n" BB_BANNER " Built-in shell (ash)\n"); printf( "Enter 'help' for a list of built-in commands.\n\n"); #endif @@ -3535,11 +3535,11 @@ tryexec(char *cmd, char **argv, char **envp) { int e; -#ifdef BB_FEATURE_SH_STANDALONE_SHELL +#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL char *name = cmd; char** argv_l=argv; int argc_l; -#ifdef BB_FEATURE_SH_APPLETS_ALWAYS_WIN +#ifdef CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN name = get_last_path_component(name); #endif argv_l=envp; @@ -3766,7 +3766,7 @@ static int helpcmd(int argc, char** argv) col = 0; } } -#ifdef BB_FEATURE_SH_STANDALONE_SHELL +#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL { extern const struct BB_applet applets[]; extern const size_t NUM_APPLETS; @@ -6023,7 +6023,7 @@ reset(void) { * This file implements the input routines used by the parser. */ -#ifdef BB_FEATURE_COMMAND_EDITING +#ifdef CONFIG_FEATURE_COMMAND_EDITING static const char * cmdedit_prompt; static inline void putprompt(const char *s) { cmdedit_prompt = s; @@ -6090,7 +6090,7 @@ preadfd(void) parsenextc = buf; retry: -#ifdef BB_FEATURE_COMMAND_EDITING +#ifdef CONFIG_FEATURE_COMMAND_EDITING { if (!iflag || parsefile->fd) nr = safe_read(parsefile->fd, buf, BUFSIZ - 1); @@ -7718,7 +7718,7 @@ ash_main(argc, argv) EXECCMD = find_builtin("exec"); EVALCMD = find_builtin("eval"); -#ifndef BB_FEATURE_SH_FANCY_PROMPT +#ifndef CONFIG_FEATURE_SH_FANCY_PROMPT unsetenv("PS1"); unsetenv("PS2"); #endif @@ -9331,7 +9331,7 @@ getoptsreset(const char *value) shellparam.optoff = -1; } -#ifdef BB_LOCALE_SUPPORT +#ifdef CONFIG_LOCALE_SUPPORT static void change_lc_all(const char *value) { if(value != 0 && *value != 0) @@ -12730,7 +12730,7 @@ findvar(struct var **vpp, const char *name) /* * Copyright (c) 1999 Herbert Xu <herbert@debian.org> * This file contains code for the times builtin. - * $Id: ash.c,v 1.28 2001/10/19 00:22:22 andersen Exp $ + * $Id: ash.c,v 1.29 2001/10/24 05:00:16 andersen Exp $ */ static int timescmd (int argc, char **argv) { diff --git a/shell/cmdedit.c b/shell/cmdedit.c index 16ec2f823..d1b9111ea 100644 --- a/shell/cmdedit.c +++ b/shell/cmdedit.c @@ -43,7 +43,7 @@ #include "busybox.h" -#ifdef BB_LOCALE_SUPPORT +#ifdef CONFIG_LOCALE_SUPPORT #define Isprint(c) isprint((c)) #else #define Isprint(c) ( (c) >= ' ' && (c) != ((unsigned char)'\233') ) @@ -55,32 +55,32 @@ #else -#define BB_FEATURE_COMMAND_EDITING -#define BB_FEATURE_COMMAND_TAB_COMPLETION -#define BB_FEATURE_COMMAND_USERNAME_COMPLETION -#define BB_FEATURE_NONPRINTABLE_INVERSE_PUT -#define BB_FEATURE_CLEAN_UP +#define CONFIG_FEATURE_COMMAND_EDITING +#define CONFIG_FEATURE_COMMAND_TAB_COMPLETION +#define CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION +#define CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT +#define CONFIG_FEATURE_CLEAN_UP #define D(x) x #endif /* TEST */ -#ifdef BB_FEATURE_COMMAND_TAB_COMPLETION +#ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION #include <dirent.h> #include <sys/stat.h> #endif -#ifdef BB_FEATURE_COMMAND_EDITING +#ifdef CONFIG_FEATURE_COMMAND_EDITING -#ifndef BB_FEATURE_COMMAND_TAB_COMPLETION -#undef BB_FEATURE_COMMAND_USERNAME_COMPLETION +#ifndef CONFIG_FEATURE_COMMAND_TAB_COMPLETION +#undef CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION #endif -#if defined(BB_FEATURE_COMMAND_USERNAME_COMPLETION) || defined(BB_FEATURE_SH_FANCY_PROMPT) -#define BB_FEATURE_GETUSERNAME_AND_HOMEDIR +#if defined(CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION) || defined(CONFIG_FEATURE_SH_FANCY_PROMPT) +#define CONFIG_FEATURE_GETUSERNAME_AND_HOMEDIR #endif -#ifdef BB_FEATURE_GETUSERNAME_AND_HOMEDIR +#ifdef CONFIG_FEATURE_GETUSERNAME_AND_HOMEDIR # ifndef TEST # include "pwd_grp/pwd.h" # else @@ -136,33 +136,33 @@ static int cursor; /* required global for signal handler */ static int len; /* --- "" - - "" - -"- --""-- --""--- */ static char *command_ps; /* --- "" - - "" - -"- --""-- --""--- */ static -#ifndef BB_FEATURE_SH_FANCY_PROMPT +#ifndef CONFIG_FEATURE_SH_FANCY_PROMPT const #endif char *cmdedit_prompt; /* --- "" - - "" - -"- --""-- --""--- */ -#ifdef BB_FEATURE_GETUSERNAME_AND_HOMEDIR +#ifdef CONFIG_FEATURE_GETUSERNAME_AND_HOMEDIR static char *user_buf = ""; static char *home_pwd_buf = ""; static int my_euid; #endif -#ifdef BB_FEATURE_SH_FANCY_PROMPT +#ifdef CONFIG_FEATURE_SH_FANCY_PROMPT static char *hostname_buf = ""; static int num_ok_lines = 1; #endif -#ifdef BB_FEATURE_COMMAND_TAB_COMPLETION +#ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION -#ifndef BB_FEATURE_GETUSERNAME_AND_HOMEDIR +#ifndef CONFIG_FEATURE_GETUSERNAME_AND_HOMEDIR static int my_euid; #endif static int my_uid; static int my_gid; -#endif /* BB_FEATURE_COMMAND_TAB_COMPLETION */ +#endif /* CONFIG_FEATURE_COMMAND_TAB_COMPLETION */ /* It seems that libc5 doesn't know what a sighandler_t is... */ #if (__GLIBC__ <= 2) && (__GLIBC_MINOR__ < 1) @@ -207,7 +207,7 @@ static void cmdedit_reset_term(void) handlers_sets &= ~SET_WCHG_HANDLERS; } fflush(stdout); -#ifdef BB_FEATURE_CLEAN_UP +#ifdef CONFIG_FEATURE_CLEAN_UP if (his_front) { struct history *n; @@ -230,7 +230,7 @@ static void cmdedit_set_out_char(int next_char) if (c == 0) c = ' '; /* destroy end char? */ -#ifdef BB_FEATURE_NONPRINTABLE_INVERSE_PUT +#ifdef CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT if (!Isprint(c)) { /* Inverse put non-printable characters */ if (c >= 128) c -= 128; @@ -321,7 +321,7 @@ static void put_prompt(void) cmdedit_y = 0; /* new quasireal y */ } -#ifndef BB_FEATURE_SH_FANCY_PROMPT +#ifndef CONFIG_FEATURE_SH_FANCY_PROMPT static void parse_prompt(const char *prmt_ptr) { cmdedit_prompt = prmt_ptr; @@ -359,7 +359,7 @@ static void parse_prompt(const char *prmt_ptr) break; c = *prmt_ptr++; switch (c) { -#ifdef BB_FEATURE_GETUSERNAME_AND_HOMEDIR +#ifdef CONFIG_FEATURE_GETUSERNAME_AND_HOMEDIR case 'u': pbuf = user_buf; break; @@ -382,7 +382,7 @@ static void parse_prompt(const char *prmt_ptr) case '$': c = my_euid == 0 ? '#' : '$'; break; -#ifdef BB_FEATURE_GETUSERNAME_AND_HOMEDIR +#ifdef CONFIG_FEATURE_GETUSERNAME_AND_HOMEDIR case 'w': pbuf = pwd_buf; l = strlen(home_pwd_buf); @@ -526,7 +526,7 @@ static void cmdedit_init(void) } if ((handlers_sets & SET_ATEXIT) == 0) { -#ifdef BB_FEATURE_GETUSERNAME_AND_HOMEDIR +#ifdef CONFIG_FEATURE_GETUSERNAME_AND_HOMEDIR struct passwd *entry; my_euid = geteuid(); @@ -537,20 +537,20 @@ static void cmdedit_init(void) } #endif -#ifdef BB_FEATURE_COMMAND_TAB_COMPLETION +#ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION -#ifndef BB_FEATURE_GETUSERNAME_AND_HOMEDIR +#ifndef CONFIG_FEATURE_GETUSERNAME_AND_HOMEDIR my_euid = geteuid(); #endif my_uid = getuid(); my_gid = getgid(); -#endif /* BB_FEATURE_COMMAND_TAB_COMPLETION */ +#endif /* CONFIG_FEATURE_COMMAND_TAB_COMPLETION */ handlers_sets |= SET_ATEXIT; atexit(cmdedit_reset_term); /* be sure to do this only once */ } } -#ifdef BB_FEATURE_COMMAND_TAB_COMPLETION +#ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION static int is_execute(const struct stat *st) { @@ -561,7 +561,7 @@ static int is_execute(const struct stat *st) return FALSE; } -#ifdef BB_FEATURE_COMMAND_USERNAME_COMPLETION +#ifdef CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION static char **username_tab_completion(char *ud, int *num_matches) { @@ -623,7 +623,7 @@ static char **username_tab_completion(char *ud, int *num_matches) return (matches); } } -#endif /* BB_FEATURE_COMMAND_USERNAME_COMPLETION */ +#endif /* CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION */ enum { FIND_EXE_ONLY = 0, @@ -720,7 +720,7 @@ static char **exe_n_cwd_tab_completion(char *command, int *num_matches, strcpy(dirbuf, command); /* set dir only */ dirbuf[(pfind - command) + 1] = 0; -#ifdef BB_FEATURE_COMMAND_USERNAME_COMPLETION +#ifdef CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION if (dirbuf[0] == '~') /* ~/... or ~user/... */ username_tab_completion(dirbuf, 0); #endif @@ -826,12 +826,12 @@ static int find_match(char *matchBuf, int *len_with_quotes) collapse_pos(j, j + 1); int_buf[j] |= QUOT; i++; -#ifdef BB_FEATURE_NONPRINTABLE_INVERSE_PUT +#ifdef CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT if (matchBuf[i] == '\t') /* algorithm equivalent */ int_buf[j] = ' ' | QUOT; #endif } -#ifdef BB_FEATURE_NONPRINTABLE_INVERSE_PUT +#ifdef CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT else if (matchBuf[i] == '\t') int_buf[j] = ' '; #endif @@ -1000,7 +1000,7 @@ static void input_tab(int *lastWasTab) /* Free up any memory already allocated */ input_tab(0); -#ifdef BB_FEATURE_COMMAND_USERNAME_COMPLETION +#ifdef CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION /* If the word starts with `~' and there is no slash in the word, * then try completing this word as a username. */ @@ -1119,7 +1119,7 @@ static void input_tab(int *lastWasTab) } } } -#endif /* BB_FEATURE_COMMAND_TAB_COMPLETION */ +#endif /* CONFIG_FEATURE_COMMAND_TAB_COMPLETION */ static void get_previous_history(struct history **hp, struct history *p) { @@ -1232,7 +1232,7 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ]) * if the len=0 and no chars to delete */ if (len == 0) { prepare_to_die: -#if !defined(BB_ASH) +#if !defined(CONFIG_ASH) printf("exit"); goto_new_line(); /* cmdedit_reset_term() called in atexit */ @@ -1259,7 +1259,7 @@ prepare_to_die: input_backspace(); break; case '\t': -#ifdef BB_FEATURE_COMMAND_TAB_COMPLETION +#ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION input_tab(&lastWasTab); #endif break; @@ -1299,7 +1299,7 @@ prepare_to_die: goto prepare_to_die; } switch (c) { -#ifdef BB_FEATURE_COMMAND_TAB_COMPLETION +#ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION case '\t': /* Alt-Tab */ input_tab(&lastWasTab); @@ -1367,7 +1367,7 @@ prepare_to_die: } default: /* If it's regular input, do the normal thing */ -#ifdef BB_FEATURE_NONPRINTABLE_INVERSE_PUT +#ifdef CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT /* Control-V -- Add non-printable symbol */ if (c == 22) { if (safe_read(0, &c, 1) < 1) @@ -1457,7 +1457,7 @@ prepare_to_die: history_counter++; } } -#if defined(BB_FEATURE_SH_FANCY_PROMPT) +#if defined(CONFIG_FEATURE_SH_FANCY_PROMPT) num_ok_lines++; #endif } @@ -1465,10 +1465,10 @@ prepare_to_die: command[len++] = '\n'; /* set '\n' */ command[len] = 0; } -#if defined(BB_FEATURE_CLEAN_UP) && defined(BB_FEATURE_COMMAND_TAB_COMPLETION) +#if defined(CONFIG_FEATURE_CLEAN_UP) && defined(CONFIG_FEATURE_COMMAND_TAB_COMPLETION) input_tab(0); /* strong free */ #endif -#if defined(BB_FEATURE_SH_FANCY_PROMPT) +#if defined(CONFIG_FEATURE_SH_FANCY_PROMPT) free(cmdedit_prompt); #endif cmdedit_reset_term(); @@ -1477,7 +1477,7 @@ prepare_to_die: -#endif /* BB_FEATURE_COMMAND_EDITING */ +#endif /* CONFIG_FEATURE_COMMAND_EDITING */ #ifdef TEST @@ -1485,7 +1485,7 @@ prepare_to_die: const char *applet_name = "debug stuff usage"; const char *memory_exhausted = "Memory exhausted"; -#ifdef BB_FEATURE_NONPRINTABLE_INVERSE_PUT +#ifdef CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT #include <locale.h> #endif @@ -1493,7 +1493,7 @@ int main(int argc, char **argv) { char buff[BUFSIZ]; char *prompt = -#if defined(BB_FEATURE_SH_FANCY_PROMPT) +#if defined(CONFIG_FEATURE_SH_FANCY_PROMPT) "\\[\\033[32;1m\\]\\u@\\[\\x1b[33;1m\\]\\h:\ \\[\\033[34;1m\\]\\w\\[\\033[35;1m\\] \ \\!\\[\\e[36;1m\\]\\$ \\[\\E[0m\\]"; @@ -1501,7 +1501,7 @@ int main(int argc, char **argv) "% "; #endif -#ifdef BB_FEATURE_NONPRINTABLE_INVERSE_PUT +#ifdef CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT setlocale(LC_ALL, ""); #endif while(1) { diff --git a/shell/config.in b/shell/config.in new file mode 100644 index 000000000..e33669a7b --- /dev/null +++ b/shell/config.in @@ -0,0 +1,51 @@ +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +mainmenu_option next_comment +comment 'Bourne Shell' + +choice 'Choose your default shell' \ + "ash CONFIG_FEATURE_SH_IS_ASH \ + hush CONFIG_FEATURE_SH_IS_HUSH \ + lash CONFIG_FEATURE_SH_IS_LASH \ + msh CONFIG_FEATURE_SH_IS_MSH \ + none CONFIG_FEATURE_SH_IS_NONE" + +if [ "$CONFIG_FEATURE_SH_IS_ASH" = "y" ] ; then + define_bool CONFIG_ASH y +else + bool 'ash' CONFIG_ASH +fi + +if [ "$CONFIG_FEATURE_SH_IS_HUSH" = "y" ] ; then + define_bool CONFIG_HUSH y +else + bool 'hush' CONFIG_HUSH +fi + +if [ "$CONFIG_FEATURE_SH_IS_LASH" = "y" ] ; then + define_bool CONFIG_LASH y +else + bool 'lash' CONFIG_LASH +fi + +if [ "$CONFIG_FEATURE_SH_IS_MSH" = "y" ] ; then + define_bool CONFIG_MSH y +else + bool 'msh' CONFIG_MSH +fi + + +comment 'Bourne Shell Options' +bool 'command line editing' CONFIG_FEATURE_COMMAND_EDITING +bool 'tab completion' CONFIG_FEATURE_COMMAND_TAB_COMPLETION +bool 'username completion' CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION +bool 'Standalone shell' CONFIG_FEATURE_SH_STANDALONE_SHELL +bool 'Standalone shell -- applets always win' CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN +bool 'Fancy shell prompts' CONFIG_FEATURE_SH_FANCY_PROMPT +bool 'Hide message on interactive shell startup' CONFIG_FEATURE_SH_EXTRA_QUIET + +endmenu + diff --git a/shell/hush.c b/shell/hush.c index cb0e6e980..d37842b79 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -113,7 +113,8 @@ #define applet_name "hush" #include "standalone.h" #define hush_main main -#undef BB_FEATURE_SH_FANCY_PROMPT +#undef CONFIG_FEATURE_SH_FANCY_PROMPT +#define BB_BANNER #endif typedef enum { @@ -836,7 +837,7 @@ static int static_peek(struct in_str *i) static inline void cmdedit_set_initial_prompt(void) { -#ifndef BB_FEATURE_SH_FANCY_PROMPT +#ifndef CONFIG_FEATURE_SH_FANCY_PROMPT PS1 = NULL; #else PS1 = getenv("PS1"); @@ -848,7 +849,7 @@ static inline void cmdedit_set_initial_prompt(void) static inline void setup_prompt_string(int promptmode, char **prompt_str) { debug_printf("setup_prompt_string %d ",promptmode); -#ifndef BB_FEATURE_SH_FANCY_PROMPT +#ifndef CONFIG_FEATURE_SH_FANCY_PROMPT /* Set up the prompt */ if (promptmode == 1) { if (PS1) @@ -871,7 +872,7 @@ static void get_user_input(struct in_str *i) static char the_command[BUFSIZ]; setup_prompt_string(i->promptmode, &prompt_str); -#ifdef BB_FEATURE_COMMAND_EDITING +#ifdef CONFIG_FEATURE_COMMAND_EDITING /* ** enable command line editing only while a command line ** is actually being read; otherwise, we'll end up bequeathing @@ -1085,18 +1086,18 @@ static void pseudo_exec(struct child_prog *child) * really dislike relying on /proc for things. We could exec ourself * from global_argv[0], but if we are in a chroot, we may not be able * to find ourself... */ -#ifdef BB_FEATURE_SH_STANDALONE_SHELL +#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL { int argc_l; char** argv_l=child->argv; char *name = child->argv[0]; -#ifdef BB_FEATURE_SH_APPLETS_ALWAYS_WIN +#ifdef CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN /* Following discussions from November 2000 on the busybox mailing * list, the default configuration, (without * get_last_path_component()) lets the user force use of an * external command by specifying the full (with slashes) filename. - * If you enable BB_FEATURE_SH_APPLETS_ALWAYS_WIN, then applets + * If you enable CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN, then applets * _aways_ override external commands, so if you want to run * /bin/cat, it will use BusyBox cat even if /bin/cat exists on the * filesystem and is _not_ busybox. Some systems may want this, @@ -2586,7 +2587,7 @@ int hush_main(int argc, char **argv) /* Initialize some more globals to non-zero values */ set_cwd(); -#ifdef BB_FEATURE_COMMAND_EDITING +#ifdef CONFIG_FEATURE_COMMAND_EDITING cmdedit_set_initial_prompt(); #else PS1 = NULL; @@ -2655,7 +2656,7 @@ int hush_main(int argc, char **argv) debug_printf("\ninteractive=%d\n", interactive); if (interactive) { /* Looks like they want an interactive shell */ -#ifndef BB_FEATURE_SH_EXTRA_QUIET +#ifndef CONFIG_FEATURE_SH_EXTRA_QUIET printf( "\n\n" BB_BANNER " hush - the humble shell v0.01 (testing)\n"); printf( "Enter 'help' for a list of built-in commands.\n\n"); #endif @@ -2673,7 +2674,7 @@ int hush_main(int argc, char **argv) input = xfopen(argv[optind], "r"); opt = parse_file_outer(input); -#ifdef BB_FEATURE_CLEAN_UP +#ifdef CONFIG_FEATURE_CLEAN_UP fclose(input); if (cwd && cwd != unknown) free((char*)cwd); diff --git a/shell/lash.c b/shell/lash.c index ffdec8781..004d9495a 100644 --- a/shell/lash.c +++ b/shell/lash.c @@ -2,8 +2,8 @@ /* * lash -- the BusyBox Lame-Ass SHell * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org> + * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen <andersee@debian.org> * * Based in part on ladsh.c by Michael K. Johnson and Erik W. Troan, which is * under the following liberal license: "We have placed this source code in the @@ -25,8 +25,10 @@ * */ -/* This shell's parsing engine is officially at a dead-end. - * Future work shell work should be done using hush.c +/* This shell's parsing engine is officially at a dead-end. Future + * work shell work should be done using hush, msh, or ash. This is + * still a very useful, small shell -- it just don't need any more + * features beyond what it already has... */ //For debugging/development on the shell only... @@ -48,7 +50,7 @@ #include "busybox.h" #include "cmdedit.h" -#ifdef BB_LOCALE_SUPPORT +#ifdef CONFIG_LOCALE_SUPPORT #include <locale.h> #endif @@ -390,12 +392,12 @@ static int builtin_export(struct child_prog *child) res = putenv(v); if (res) fprintf(stderr, "export: %m\n"); -#ifdef BB_FEATURE_SH_FANCY_PROMPT +#ifdef CONFIG_FEATURE_SH_FANCY_PROMPT if (strncmp(v, "PS1=", 4)==0) PS1 = getenv("PS1"); #endif -#ifdef BB_LOCALE_SUPPORT +#ifdef CONFIG_LOCALE_SUPPORT if(strncmp(v, "LC_ALL=", 7)==0) setlocale(LC_ALL, getenv("LC_ALL")); if(strncmp(v, "LC_CTYPE=", 9)==0) @@ -661,7 +663,7 @@ static void restore_redirects(int squirrel[]) static inline void cmdedit_set_initial_prompt(void) { -#ifndef BB_FEATURE_SH_FANCY_PROMPT +#ifndef CONFIG_FEATURE_SH_FANCY_PROMPT PS1 = NULL; #else PS1 = getenv("PS1"); @@ -672,7 +674,7 @@ static inline void cmdedit_set_initial_prompt(void) static inline void setup_prompt_string(char **prompt_str) { -#ifndef BB_FEATURE_SH_FANCY_PROMPT +#ifndef CONFIG_FEATURE_SH_FANCY_PROMPT /* Set up the prompt */ if (shell_context == 0) { if (PS1) @@ -706,7 +708,7 @@ static int get_command(FILE * source, char *command) if (source == stdin) { setup_prompt_string(&prompt_str); -#ifdef BB_FEATURE_COMMAND_EDITING +#ifdef CONFIG_FEATURE_COMMAND_EDITING /* ** enable command line editing only while a command line ** is actually being read; otherwise, we'll end up bequeathing @@ -1201,7 +1203,7 @@ static int parse_command(char **command_ptr, struct job *job, int *inbg) static int pseudo_exec(struct child_prog *child) { struct built_in_command *x; -#ifdef BB_FEATURE_SH_STANDALONE_SHELL +#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL char *name; #endif @@ -1223,7 +1225,7 @@ static int pseudo_exec(struct child_prog *child) exit (x->function(child)); } } -#ifdef BB_FEATURE_SH_STANDALONE_SHELL +#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL /* Check if the command matches any busybox internal * commands ("applets") here. Following discussions from * November 2000 on busybox@opensource.lineo.com, don't use @@ -1237,8 +1239,8 @@ static int pseudo_exec(struct child_prog *child) */ name = child->argv[0]; -#ifdef BB_FEATURE_SH_APPLETS_ALWAYS_WIN - /* If you enable BB_FEATURE_SH_APPLETS_ALWAYS_WIN, then +#ifdef CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN + /* If you enable CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN, then * if you run /bin/cat, it will use BusyBox cat even if * /bin/cat exists on the filesystem and is _not_ busybox. * Some systems want this, others do not. Choose wisely. :-) @@ -1504,7 +1506,7 @@ static int busy_loop(FILE * input) } -#ifdef BB_FEATURE_CLEAN_UP +#ifdef CONFIG_FEATURE_CLEAN_UP void free_memory(void) { if (cwd && cwd!=unknown) { @@ -1611,7 +1613,7 @@ int lash_main(int argc_l, char **argv_l) if (interactive==TRUE) { //printf( "optind=%d argv[optind]='%s'\n", optind, argv[optind]); /* Looks like they want an interactive shell */ -#ifndef BB_FEATURE_SH_EXTRA_QUIET +#ifndef CONFIG_FEATURE_SH_EXTRA_QUIET printf( "\n\n" BB_BANNER " Built-in shell (lash)\n"); printf( "Enter 'help' for a list of built-in commands.\n\n"); #endif @@ -1626,11 +1628,11 @@ int lash_main(int argc_l, char **argv_l) if (!cwd) cwd = unknown; -#ifdef BB_FEATURE_CLEAN_UP +#ifdef CONFIG_FEATURE_CLEAN_UP atexit(free_memory); #endif -#ifdef BB_FEATURE_COMMAND_EDITING +#ifdef CONFIG_FEATURE_COMMAND_EDITING cmdedit_set_initial_prompt(); #else PS1 = NULL; diff --git a/shell/msh.c b/shell/msh.c index 5c4ec1019..a2f98c837 100644 --- a/shell/msh.c +++ b/shell/msh.c @@ -681,7 +681,7 @@ static void * brktop; static void * brkaddr; -#ifdef BB_FEATURE_COMMAND_EDITING +#ifdef CONFIG_FEATURE_COMMAND_EDITING static char * current_prompt; #endif @@ -732,7 +732,7 @@ extern int msh_main(int argc, char **argv) setval(ifs, " \t\n"); prompt = lookup("PS1"); -#ifdef BB_FEATURE_SH_FANCY_PROMPT +#ifdef CONFIG_FEATURE_SH_FANCY_PROMPT if (prompt->value == null) #endif setval(prompt, "$ "); @@ -741,7 +741,7 @@ extern int msh_main(int argc, char **argv) prompt->status &= ~EXPORT; } cprompt = lookup("PS2"); -#ifdef BB_FEATURE_SH_FANCY_PROMPT +#ifdef CONFIG_FEATURE_SH_FANCY_PROMPT if (cprompt->value == null) #endif setval(cprompt, "> "); @@ -801,7 +801,7 @@ extern int msh_main(int argc, char **argv) PUSHIO(afile, 0, iof); if (isatty(0) && isatty(1) && !cflag) { interactive++; -#ifndef BB_FEATURE_SH_EXTRA_QUIET +#ifndef CONFIG_FEATURE_SH_EXTRA_QUIET printf( "\n\n" BB_BANNER " Built-in shell (msh)\n"); printf( "Enter 'help' for a list of built-in commands.\n\n"); #endif @@ -835,7 +835,7 @@ extern int msh_main(int argc, char **argv) for (;;) { if (interactive && e.iop <= iostack) { -#ifdef BB_FEATURE_COMMAND_EDITING +#ifdef CONFIG_FEATURE_COMMAND_EDITING current_prompt=prompt->value; #else prs(prompt->value); @@ -2171,7 +2171,7 @@ loop: startl = 1; if (multiline || cf & CONTIN) { if (interactive && e.iop <= iostack) { -#ifdef BB_FEATURE_COMMAND_EDITING +#ifdef CONFIG_FEATURE_COMMAND_EDITING current_prompt=cprompt->value; #else prs(cprompt->value); @@ -2224,7 +2224,7 @@ register int c, c1; return(YYERRCODE); } if (interactive && c == '\n' && e.iop <= iostack) { -#ifdef BB_FEATURE_COMMAND_EDITING +#ifdef CONFIG_FEATURE_COMMAND_EDITING current_prompt=cprompt->value; #else prs(cprompt->value); @@ -2838,9 +2838,9 @@ char *c, **v, **envp; register char *sp, *tp; int eacces = 0, asis = 0; -#ifdef BB_FEATURE_SH_STANDALONE_SHELL +#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL char *name = c; -#ifdef BB_FEATURE_SH_APPLETS_ALWAYS_WIN +#ifdef CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN name = get_last_path_component(name); #endif optind = 1; @@ -2960,7 +2960,7 @@ static int dohelp() col = 0; } } -#ifdef BB_FEATURE_SH_STANDALONE_SHELL +#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL { int i; const struct BB_applet *applet; @@ -4256,7 +4256,7 @@ readc() if (multiline) return e.iop->prev = 0; if (interactive && e.iop == iostack+1) { -#ifdef BB_FEATURE_COMMAND_EDITING +#ifdef CONFIG_FEATURE_COMMAND_EDITING current_prompt=prompt->value; #else prs(prompt->value); @@ -4462,7 +4462,7 @@ register struct ioarg *ap; return *bp->bufp++ & 0177; } -#ifdef BB_FEATURE_COMMAND_EDITING +#ifdef CONFIG_FEATURE_COMMAND_EDITING if (interactive) { static char mycommand[BUFSIZ]; static int position = 0, size = 0; @@ -4721,7 +4721,7 @@ int ec; e.iobase = e.iop; for (;;) { if (interactive && e.iop <= iostack) { -#ifdef BB_FEATURE_COMMAND_EDITING +#ifdef CONFIG_FEATURE_COMMAND_EDITING current_prompt=cprompt->value; #else prs(cprompt->value); diff --git a/sleep.c b/sleep.c deleted file mode 100644 index 3bcab88ee..000000000 --- a/sleep.c +++ /dev/null @@ -1,38 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini sleep implementation for busybox - * - * - * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <stdio.h> -#include <unistd.h> -#include <stdlib.h> -#include "busybox.h" - -extern int sleep_main(int argc, char **argv) -{ - if ((argc < 2) || (**(argv + 1) == '-')) { - show_usage(); - } - - if (sleep(atoi(*(++argv))) != 0) - perror_msg_and_die("sleep"); - return EXIT_SUCCESS; -} diff --git a/sort.c b/sort.c deleted file mode 100644 index 4f4979cc5..000000000 --- a/sort.c +++ /dev/null @@ -1,106 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini sort implementation for busybox - * - * - * Copyright (C) 2000 by Matt Kraai <kraai@alumni.carnegiemellon.edu> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <getopt.h> -#include <string.h> -#include <stdlib.h> -#include "busybox.h" - -static int compare_ascii(const void *x, const void *y) -{ - return strcmp(*(char **)x, *(char **)y); -} - -static int compare_numeric(const void *x, const void *y) -{ - int z = atoi(*(char **)x) - atoi(*(char **)y); - return z ? z : strcmp(*(char **)x, *(char **)y); -} - -int sort_main(int argc, char **argv) -{ - FILE *fp; - char *line, **lines = NULL; - int i, opt, nlines = 0; - int (*compare)(const void *, const void *) = compare_ascii; -#ifdef BB_FEATURE_SORT_REVERSE - int reverse = FALSE; -#endif -#ifdef BB_FEATURE_SORT_UNIQUE - int unique = FALSE; -#endif - - while ((opt = getopt(argc, argv, "nru")) != -1) { - switch (opt) { - case 'n': - compare = compare_numeric; - break; -#ifdef BB_FEATURE_SORT_REVERSE - case 'r': - reverse = TRUE; - break; -#endif -#ifdef BB_FEATURE_SORT_UNIQUE - case 'u': - unique = TRUE; - break; -#endif - default: - show_usage(); - } - } - - /* read the input */ - for (i = optind; i == optind || i < argc; i++) { - if (argv[i] == NULL) - fp = stdin; - else - fp = xfopen(argv[i], "r"); - - while ((line = get_line_from_file(fp)) != NULL) { - lines = xrealloc(lines, sizeof(char *) * (nlines + 1)); - chomp(line); - lines[nlines++] = line; - } - } - - /* sort it */ - qsort(lines, nlines, sizeof(char *), compare); - - /* print it */ -#ifdef BB_FEATURE_SORT_REVERSE - if (reverse) { - for (i = --nlines; 0 <= i; i--) -#ifdef BB_FEATURE_SORT_UNIQUE - if((!unique) || (i == nlines) || (strcmp(lines[i + 1], lines[i]))) -#endif - puts(lines[i]); - } else -#endif - for (i = 0; i < nlines; i++) -#ifdef BB_FEATURE_SORT_UNIQUE - if((!unique) || (!i) || (strcmp(lines[i - 1], lines[i]))) -#endif - puts(lines[i]); - return EXIT_SUCCESS; -} diff --git a/start_stop_daemon.c b/start_stop_daemon.c deleted file mode 100644 index 0152283ad..000000000 --- a/start_stop_daemon.c +++ /dev/null @@ -1,271 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini start-stop-daemon implementation(s) for busybox - * - * Written by Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl>, - * public domain. - * Adapted for busybox David Kimdon <dwhedon@gordian.com> - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <stdarg.h> -#include <signal.h> -#include <errno.h> -#include <sys/stat.h> -#include <dirent.h> -#include <unistd.h> -#include <pwd.h> - -#include "busybox.h" - -static int start = 0; -static int stop = 0; -static int signal_nr = 15; -static int user_id = -1; -static const char *userspec = NULL; -static const char *cmdname = NULL; -static char *execname = NULL; -static char *startas = NULL; -static const char *progname = ""; - -struct pid_list { - struct pid_list *next; - int pid; -}; - -static struct pid_list *found = NULL; -static struct pid_list *killed = NULL; - -static void -push(struct pid_list **list, int pid) -{ - struct pid_list *p; - - p = xmalloc(sizeof(*p)); - p->next = *list; - p->pid = pid; - *list = p; -} - - -static void -parse_options(int argc, char * const *argv) -{ - - int c; - - for (;;) { - c = getopt (argc, argv, "a:n:s:u:x:KS"); - if (c == EOF) - break; - switch (c) { - case 'K': - stop = 1; - break; - case 'S': - start = 1; - break; - case 'a': - startas = optarg; - break; - case 'n': - cmdname = optarg; - break; - case 's': - if (sscanf(optarg, "%d", &signal_nr) != 1) - error_msg_and_die ("-s takes a numeric argument"); - break; - case 'u': - userspec = optarg; - break; - case 'x': - execname = optarg; - break; - default: - show_usage(); - exit(1); - } - } - - if (start == stop) - error_msg_and_die ("need one of -S or -K"); - - if (!execname && !userspec) - error_msg_and_die ("need at least one of -x or -u"); - - if (!startas) - startas = execname; - - if (start && !startas) - error_msg_and_die ("-S needs -x or -a"); -} - - -static int -pid_is_exec(int pid, const char *exec) -{ - char buf[PATH_MAX]; - FILE *fp; - - sprintf(buf, "/proc/%d/cmdline", pid); - fp = fopen(buf, "r"); - if (fp && fgets (buf, sizeof (buf), fp) ) { - if (strncmp (buf, exec, strlen(exec)) == 0) - return 1; - } - return 0; -} - - -static int -pid_is_user(int pid, int uid) -{ - struct stat sb; - char buf[32]; - - sprintf(buf, "/proc/%d", pid); - if (stat(buf, &sb) != 0) - return 0; - return (sb.st_uid == uid); -} - - -static int -pid_is_cmd(int pid, const char *name) -{ - char buf[32]; - FILE *f; - int c; - - sprintf(buf, "/proc/%d/stat", pid); - f = fopen(buf, "r"); - if (!f) - return 0; - while ((c = getc(f)) != EOF && c != '(') - ; - if (c != '(') { - fclose(f); - return 0; - } - /* this hopefully handles command names containing ')' */ - while ((c = getc(f)) != EOF && c == *name) - name++; - fclose(f); - return (c == ')' && *name == '\0'); -} - - -static void -check(int pid) -{ - if (execname && !pid_is_exec(pid, execname)) { - return; - } - if (userspec && !pid_is_user(pid, user_id)) { - return; - } - if (cmdname && !pid_is_cmd(pid, cmdname)) { - return; - } - push(&found, pid); -} - - - -static void -do_procfs(void) -{ - DIR *procdir; - struct dirent *entry; - int foundany, pid; - - procdir = opendir("/proc"); - if (!procdir) - perror_msg_and_die ("opendir /proc"); - - foundany = 0; - while ((entry = readdir(procdir)) != NULL) { - if (sscanf(entry->d_name, "%d", &pid) != 1) - continue; - foundany++; - check(pid); - } - closedir(procdir); - if (!foundany) - error_msg_and_die ("nothing in /proc - not mounted?"); -} - - -static void -do_stop(void) -{ - char what[1024]; - struct pid_list *p; - - if (cmdname) - strcpy(what, cmdname); - else if (execname) - strcpy(what, execname); - else if (userspec) - sprintf(what, "process(es) owned by `%s'", userspec); - else - error_msg_and_die ("internal error, please report"); - - if (!found) { - printf("no %s found; none killed.\n", what); - exit(0); - } - for (p = found; p; p = p->next) { - if (kill(p->pid, signal_nr) == 0) - push(&killed, p->pid); - else - printf("%s: warning: failed to kill %d: %s\n", - progname, p->pid, strerror(errno)); - } - if (killed) { - printf("stopped %s (pid", what); - for (p = killed; p; p = p->next) - printf(" %d", p->pid); - printf(").\n"); - } -} - - -int -start_stop_daemon_main(int argc, char **argv) -{ - progname = argv[0]; - - parse_options(argc, argv); - argc -= optind; - argv += optind; - - if (userspec && sscanf(userspec, "%d", &user_id) != 1) { - struct passwd *pw; - - pw = getpwnam(userspec); - if (!pw) - error_msg_and_die ("user `%s' not found\n", userspec); - - user_id = pw->pw_uid; - } - - do_procfs(); - - if (stop) { - do_stop(); - exit(0); - } - - if (found) { - printf("%s already running.\n", execname); - printf("%d\n",found->pid); - exit(0); - } - *--argv = startas; - execv(startas, argv); - perror_msg_and_die ("unable to start %s", startas); -} - diff --git a/stty.c b/stty.c deleted file mode 100644 index 2e00a496d..000000000 --- a/stty.c +++ /dev/null @@ -1,1376 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* stty -- change and print terminal line settings - Copyright (C) 1990-1999 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -/* Usage: stty [-ag] [-F device] [setting...] - - Options: - -a Write all current settings to stdout in human-readable form. - -g Write all current settings to stdout in stty-readable form. - -F Open and use the specified device instead of stdin - - If no args are given, write to stdout the baud rate and settings that - have been changed from their defaults. Mode reading and changes - are done on the specified device, or stdin if none was specified. - - David MacKenzie <djm@gnu.ai.mit.edu> - - Special for busybox ported by Vladimir Oleynik <dzo@simtreas.ru> 2001 - - */ - -//#define TEST - -#include <termios.h> -#include <sys/ioctl.h> -#include <getopt.h> - -#include <sys/param.h> -#include <unistd.h> - -#ifndef STDIN_FILENO -# define STDIN_FILENO 0 -#endif - -#ifndef STDOUT_FILENO -# define STDOUT_FILENO 1 -#endif - -#include <stdlib.h> -#include <string.h> -#include <assert.h> -#include <ctype.h> -#include <errno.h> -#include <limits.h> -#include <memory.h> -#include <fcntl.h> -#include "busybox.h" - -#define STREQ(a, b) (strcmp ((a), (b)) == 0) - - -#ifndef _POSIX_VDISABLE -# define _POSIX_VDISABLE ((unsigned char) 0) -#endif - -#define Control(c) ((c) & 0x1f) -/* Canonical values for control characters. */ -#ifndef CINTR -# define CINTR Control ('c') -#endif -#ifndef CQUIT -# define CQUIT 28 -#endif -#ifndef CERASE -# define CERASE 127 -#endif -#ifndef CKILL -# define CKILL Control ('u') -#endif -#ifndef CEOF -# define CEOF Control ('d') -#endif -#ifndef CEOL -# define CEOL _POSIX_VDISABLE -#endif -#ifndef CSTART -# define CSTART Control ('q') -#endif -#ifndef CSTOP -# define CSTOP Control ('s') -#endif -#ifndef CSUSP -# define CSUSP Control ('z') -#endif -#if defined(VEOL2) && !defined(CEOL2) -# define CEOL2 _POSIX_VDISABLE -#endif -/* ISC renamed swtch to susp for termios, but we'll accept either name. */ -#if defined(VSUSP) && !defined(VSWTCH) -# define VSWTCH VSUSP -# define CSWTCH CSUSP -#endif -#if defined(VSWTCH) && !defined(CSWTCH) -# define CSWTCH _POSIX_VDISABLE -#endif - -/* SunOS 5.3 loses (^Z doesn't work) if `swtch' is the same as `susp'. - So the default is to disable `swtch.' */ -#if defined (__sparc__) && defined (__svr4__) -# undef CSWTCH -# define CSWTCH _POSIX_VDISABLE -#endif - -#if defined(VWERSE) && !defined (VWERASE) /* AIX-3.2.5 */ -# define VWERASE VWERSE -#endif -#if defined(VDSUSP) && !defined (CDSUSP) -# define CDSUSP Control ('y') -#endif -#if !defined(VREPRINT) && defined(VRPRNT) /* Irix 4.0.5 */ -# define VREPRINT VRPRNT -#endif -#if defined(VREPRINT) && !defined(CRPRNT) -# define CRPRNT Control ('r') -#endif -#if defined(VWERASE) && !defined(CWERASE) -# define CWERASE Control ('w') -#endif -#if defined(VLNEXT) && !defined(CLNEXT) -# define CLNEXT Control ('v') -#endif -#if defined(VDISCARD) && !defined(VFLUSHO) -# define VFLUSHO VDISCARD -#endif -#if defined(VFLUSH) && !defined(VFLUSHO) /* Ultrix 4.2 */ -# define VFLUSHO VFLUSH -#endif -#if defined(CTLECH) && !defined(ECHOCTL) /* Ultrix 4.3 */ -# define ECHOCTL CTLECH -#endif -#if defined(TCTLECH) && !defined(ECHOCTL) /* Ultrix 4.2 */ -# define ECHOCTL TCTLECH -#endif -#if defined(CRTKIL) && !defined(ECHOKE) /* Ultrix 4.2 and 4.3 */ -# define ECHOKE CRTKIL -#endif -#if defined(VFLUSHO) && !defined(CFLUSHO) -# define CFLUSHO Control ('o') -#endif -#if defined(VSTATUS) && !defined(CSTATUS) -# define CSTATUS Control ('t') -#endif - -/* Which speeds to set. */ -enum speed_setting { - input_speed, output_speed, both_speeds -}; - -/* What to output and how. */ -enum output_type { - changed, all, recoverable /* Default, -a, -g. */ -}; - -/* Which member(s) of `struct termios' a mode uses. */ -enum mode_type { - control, input, output, local, combination -}; - - -static const char evenp [] = "evenp"; -static const char raw [] = "raw"; -static const char stty_min [] = "min"; -static const char stty_time [] = "time"; -static const char stty_swtch[] = "swtch"; -static const char stty_eol [] = "eol"; -static const char stty_eof [] = "eof"; -static const char parity [] = "parity"; -static const char stty_oddp [] = "oddp"; -static const char stty_nl [] = "nl"; -static const char stty_ek [] = "ek"; -static const char stty_sane [] = "sane"; -static const char cbreak [] = "cbreak"; -static const char stty_pass8[] = "pass8"; -static const char litout [] = "litout"; -static const char cooked [] = "cooked"; -static const char decctlq [] = "decctlq"; -static const char stty_tabs [] = "tabs"; -static const char stty_lcase[] = "lcase"; -static const char stty_LCASE[] = "LCASE"; -static const char stty_crt [] = "crt"; -static const char stty_dec [] = "dec"; - - -/* Flags for `struct mode_info'. */ -#define SANE_SET 1 /* Set in `sane' mode. */ -#define SANE_UNSET 2 /* Unset in `sane' mode. */ -#define REV 4 /* Can be turned off by prepending `-'. */ -#define OMIT 8 /* Don't display value. */ - -/* Each mode. */ -struct mode_info { - const char *name; /* Name given on command line. */ - enum mode_type type; /* Which structure element to change. */ - char flags; /* Setting and display options. */ - unsigned long bits; /* Bits to set for this mode. */ - unsigned long mask; /* Other bits to turn off for this mode. */ -}; - -static const struct mode_info mode_info[] = { - {"parenb", control, REV, PARENB, 0 }, - {"parodd", control, REV, PARODD, 0 }, - {"cs5", control, 0, CS5, CSIZE}, - {"cs6", control, 0, CS6, CSIZE}, - {"cs7", control, 0, CS7, CSIZE}, - {"cs8", control, 0, CS8, CSIZE}, - {"hupcl", control, REV, HUPCL, 0 }, - {"hup", control, REV | OMIT, HUPCL, 0 }, - {"cstopb", control, REV, CSTOPB, 0 }, - {"cread", control, SANE_SET | REV, CREAD, 0 }, - {"clocal", control, REV, CLOCAL, 0 }, -#ifdef CRTSCTS - {"crtscts", control, REV, CRTSCTS, 0 }, -#endif - {"ignbrk", input, SANE_UNSET | REV, IGNBRK, 0 }, - {"brkint", input, SANE_SET | REV, BRKINT, 0 }, - {"ignpar", input, REV, IGNPAR, 0 }, - {"parmrk", input, REV, PARMRK, 0 }, - {"inpck", input, REV, INPCK, 0 }, - {"istrip", input, REV, ISTRIP, 0 }, - {"inlcr", input, SANE_UNSET | REV, INLCR, 0 }, - {"igncr", input, SANE_UNSET | REV, IGNCR, 0 }, - {"icrnl", input, SANE_SET | REV, ICRNL, 0 }, - {"ixon", input, REV, IXON, 0 }, - {"ixoff", input, SANE_UNSET | REV, IXOFF, 0 }, - {"tandem", input, REV | OMIT, IXOFF, 0 }, -#ifdef IUCLC - {"iuclc", input, SANE_UNSET | REV, IUCLC, 0 }, -#endif -#ifdef IXANY - {"ixany", input, SANE_UNSET | REV, IXANY, 0 }, -#endif -#ifdef IMAXBEL - {"imaxbel", input, SANE_SET | REV, IMAXBEL, 0 }, -#endif - {"opost", output, SANE_SET | REV, OPOST, 0 }, -#ifdef OLCUC - {"olcuc", output, SANE_UNSET | REV, OLCUC, 0 }, -#endif -#ifdef OCRNL - {"ocrnl", output, SANE_UNSET | REV, OCRNL, 0 }, -#endif -#ifdef ONLCR - {"onlcr", output, SANE_SET | REV, ONLCR, 0 }, -#endif -#ifdef ONOCR - {"onocr", output, SANE_UNSET | REV, ONOCR, 0 }, -#endif -#ifdef ONLRET - {"onlret", output, SANE_UNSET | REV, ONLRET, 0 }, -#endif -#ifdef OFILL - {"ofill", output, SANE_UNSET | REV, OFILL, 0 }, -#endif -#ifdef OFDEL - {"ofdel", output, SANE_UNSET | REV, OFDEL, 0 }, -#endif -#ifdef NLDLY - {"nl1", output, SANE_UNSET, NL1, NLDLY}, - {"nl0", output, SANE_SET, NL0, NLDLY}, -#endif -#ifdef CRDLY - {"cr3", output, SANE_UNSET, CR3, CRDLY}, - {"cr2", output, SANE_UNSET, CR2, CRDLY}, - {"cr1", output, SANE_UNSET, CR1, CRDLY}, - {"cr0", output, SANE_SET, CR0, CRDLY}, -#endif - -#ifdef TABDLY - {"tab3", output, SANE_UNSET, TAB3, TABDLY}, - {"tab2", output, SANE_UNSET, TAB2, TABDLY}, - {"tab1", output, SANE_UNSET, TAB1, TABDLY}, - {"tab0", output, SANE_SET, TAB0, TABDLY}, -#else -# ifdef OXTABS - {"tab3", output, SANE_UNSET, OXTABS, 0 }, -# endif -#endif - -#ifdef BSDLY - {"bs1", output, SANE_UNSET, BS1, BSDLY}, - {"bs0", output, SANE_SET, BS0, BSDLY}, -#endif -#ifdef VTDLY - {"vt1", output, SANE_UNSET, VT1, VTDLY}, - {"vt0", output, SANE_SET, VT0, VTDLY}, -#endif -#ifdef FFDLY - {"ff1", output, SANE_UNSET, FF1, FFDLY}, - {"ff0", output, SANE_SET, FF0, FFDLY}, -#endif - {"isig", local, SANE_SET | REV, ISIG, 0 }, - {"icanon", local, SANE_SET | REV, ICANON, 0 }, -#ifdef IEXTEN - {"iexten", local, SANE_SET | REV, IEXTEN, 0 }, -#endif - {"echo", local, SANE_SET | REV, ECHO, 0 }, - {"echoe", local, SANE_SET | REV, ECHOE, 0 }, - {"crterase", local, REV | OMIT, ECHOE, 0 }, - {"echok", local, SANE_SET | REV, ECHOK, 0 }, - {"echonl", local, SANE_UNSET | REV, ECHONL, 0 }, - {"noflsh", local, SANE_UNSET | REV, NOFLSH, 0 }, -#ifdef XCASE - {"xcase", local, SANE_UNSET | REV, XCASE, 0 }, -#endif -#ifdef TOSTOP - {"tostop", local, SANE_UNSET | REV, TOSTOP, 0 }, -#endif -#ifdef ECHOPRT - {"echoprt", local, SANE_UNSET | REV, ECHOPRT, 0 }, - {"prterase", local, REV | OMIT, ECHOPRT, 0 }, -#endif -#ifdef ECHOCTL - {"echoctl", local, SANE_SET | REV, ECHOCTL, 0 }, - {"ctlecho", local, REV | OMIT, ECHOCTL, 0 }, -#endif -#ifdef ECHOKE - {"echoke", local, SANE_SET | REV, ECHOKE, 0 }, - {"crtkill", local, REV | OMIT, ECHOKE, 0 }, -#endif - {evenp, combination, REV | OMIT, 0, 0 }, - {parity, combination, REV | OMIT, 0, 0 }, - {stty_oddp, combination, REV | OMIT, 0, 0 }, - {stty_nl, combination, REV | OMIT, 0, 0 }, - {stty_ek, combination, OMIT, 0, 0 }, - {stty_sane, combination, OMIT, 0, 0 }, - {cooked, combination, REV | OMIT, 0, 0 }, - {raw, combination, REV | OMIT, 0, 0 }, - {stty_pass8, combination, REV | OMIT, 0, 0 }, - {litout, combination, REV | OMIT, 0, 0 }, - {cbreak, combination, REV | OMIT, 0, 0 }, -#ifdef IXANY - {decctlq, combination, REV | OMIT, 0, 0 }, -#endif -#if defined (TABDLY) || defined (OXTABS) - {stty_tabs, combination, REV | OMIT, 0, 0 }, -#endif -#if defined(XCASE) && defined(IUCLC) && defined(OLCUC) - {stty_lcase, combination, REV | OMIT, 0, 0 }, - {stty_LCASE, combination, REV | OMIT, 0, 0 }, -#endif - {stty_crt, combination, OMIT, 0, 0 }, - {stty_dec, combination, OMIT, 0, 0 }, -}; - -static const int NUM_mode_info = - - (sizeof(mode_info) / sizeof(struct mode_info)); - -/* Control character settings. */ -struct control_info { - const char *name; /* Name given on command line. */ - unsigned char saneval; /* Value to set for `stty sane'. */ - int offset; /* Offset in c_cc. */ -}; - -/* Control characters. */ - -static const struct control_info control_info[] = { - {"intr", CINTR, VINTR}, - {"quit", CQUIT, VQUIT}, - {"erase", CERASE, VERASE}, - {"kill", CKILL, VKILL}, - {stty_eof, CEOF, VEOF}, - {stty_eol, CEOL, VEOL}, -#ifdef VEOL2 - {"eol2", CEOL2, VEOL2}, -#endif -#ifdef VSWTCH - {stty_swtch, CSWTCH, VSWTCH}, -#endif - {"start", CSTART, VSTART}, - {"stop", CSTOP, VSTOP}, - {"susp", CSUSP, VSUSP}, -#ifdef VDSUSP - {"dsusp", CDSUSP, VDSUSP}, -#endif -#ifdef VREPRINT - {"rprnt", CRPRNT, VREPRINT}, -#endif -#ifdef VWERASE - {"werase", CWERASE, VWERASE}, -#endif -#ifdef VLNEXT - {"lnext", CLNEXT, VLNEXT}, -#endif -#ifdef VFLUSHO - {"flush", CFLUSHO, VFLUSHO}, -#endif -#ifdef VSTATUS - {"status", CSTATUS, VSTATUS}, -#endif - /* These must be last because of the display routines. */ - {stty_min, 1, VMIN}, - {stty_time, 0, VTIME}, -}; - -static const int NUM_control_info = - (sizeof(control_info) / sizeof(struct control_info)); - - -static const char * visible(unsigned int ch); -static unsigned long baud_to_value(speed_t speed); -static int recover_mode(char *arg, struct termios *mode); -static int screen_columns(void); -static int set_mode(const struct mode_info *info, - int reversed, struct termios *mode); -static speed_t string_to_baud(const char *arg); -static tcflag_t* mode_type_flag(enum mode_type type, struct termios *mode); -static void display_all(struct termios *mode, int fd, - const char *device_name); -static void display_changed(struct termios *mode); -static void display_recoverable(struct termios *mode); -static void display_settings(enum output_type output_type, - struct termios *mode, int fd, - const char *device_name); -static void display_speed(struct termios *mode, int fancy); -static void display_window_size(int fancy, int fd, - const char *device_name); -static void sane_mode(struct termios *mode); -static void set_control_char(const struct control_info *info, - const char *arg, struct termios *mode); -static void set_speed(enum speed_setting type, - const char *arg, struct termios *mode); -static void set_window_size(int rows, int cols, int fd, - const char *device_name); - -/* The width of the screen, for output wrapping. */ -static int max_col; - -/* Current position, to know when to wrap. */ -static int current_col; - -/* Print format string MESSAGE and optional args. - Wrap to next line first if it won't fit. - Print a space first unless MESSAGE will start a new line. */ - -static void wrapf(const char *message, ...) -{ - va_list args; - char buf[1024]; /* Plenty long for our needs. */ - int buflen; - - va_start(args, message); - vsprintf(buf, message, args); - va_end(args); - buflen = strlen(buf); - if (current_col + (current_col > 0) + buflen >= max_col) { - putchar('\n'); - current_col = 0; - } - if (current_col > 0) { - putchar(' '); - current_col++; - } - fputs(buf, stdout); - current_col += buflen; -} - -static const struct suffix_mult stty_suffixes[] = { - {"b", 512 }, - {"k", 1024}, - {"B", 1024}, - {NULL, 0 } -}; - -#ifndef TEST -extern int stty_main(int argc, char **argv) -#else -extern int main(int argc, char **argv) -#endif -{ - struct termios mode; - enum output_type output_type; - int optc; - int require_set_attr; - int speed_was_set; - int verbose_output; - int recoverable_output; - int k; - int noargs = 1; - char * file_name = NULL; - int fd; - const char *device_name; - - output_type = changed; - verbose_output = 0; - recoverable_output = 0; - - /* Don't print error messages for unrecognized options. */ - opterr = 0; - - while ((optc = getopt(argc, argv, "agF:")) != -1) { - switch (optc) { - case 'a': - verbose_output = 1; - output_type = all; - break; - - case 'g': - recoverable_output = 1; - output_type = recoverable; - break; - - case 'F': - if (file_name) - error_msg_and_die("only one device may be specified"); - file_name = optarg; - break; - - default: /* unrecognized option */ - noargs = 0; - break; - } - - if (noargs == 0) - break; - } - - if (optind < argc) - noargs = 0; - - /* Specifying both -a and -g gets an error. */ - if (verbose_output && recoverable_output) - error_msg_and_die ("verbose and stty-readable output styles are mutually exclusive"); - - /* Specifying any other arguments with -a or -g gets an error. */ - if (!noargs && (verbose_output || recoverable_output)) - error_msg_and_die ("modes may not be set when specifying an output style"); - - /* FIXME: it'd be better not to open the file until we've verified - that all arguments are valid. Otherwise, we could end up doing - only some of the requested operations and then failing, probably - leaving things in an undesirable state. */ - - if (file_name) { - int fdflags; - - device_name = file_name; - fd = open(device_name, O_RDONLY | O_NONBLOCK); - if (fd < 0) - perror_msg_and_die("%s", device_name); - if ((fdflags = fcntl(fd, F_GETFL)) == -1 - || fcntl(fd, F_SETFL, fdflags & ~O_NONBLOCK) < 0) - perror_msg_and_die("%s: couldn't reset non-blocking mode", - device_name); - } else { - fd = 0; - device_name = "standard input"; - } - - /* Initialize to all zeroes so there is no risk memcmp will report a - spurious difference in an uninitialized portion of the structure. */ - memset(&mode, 0, sizeof(mode)); - if (tcgetattr(fd, &mode)) - perror_msg_and_die("%s", device_name); - - if (verbose_output || recoverable_output || noargs) { - max_col = screen_columns(); - current_col = 0; - display_settings(output_type, &mode, fd, device_name); - return EXIT_SUCCESS; - } - - speed_was_set = 0; - require_set_attr = 0; - k = optind; - while (k < argc) { - int match_found = 0; - int reversed = 0; - int i; - - if (argv[k][0] == '-') { - ++argv[k]; - reversed = 1; - } - for (i = 0; i < NUM_mode_info; ++i) - if (STREQ(argv[k], mode_info[i].name)) { - match_found = set_mode(&mode_info[i], reversed, &mode); - require_set_attr = 1; - break; - } - - if (match_found == 0 && reversed) - error_msg_and_die("invalid argument `%s'", --argv[k]); - - if (match_found == 0) - for (i = 0; i < NUM_control_info; ++i) - if (STREQ(argv[k], control_info[i].name)) { - if (k == argc - 1) - error_msg_and_die("missing argument to `%s'", argv[k]); - match_found = 1; - ++k; - set_control_char(&control_info[i], argv[k], &mode); - require_set_attr = 1; - break; - } - - if (match_found == 0) { - if (STREQ(argv[k], "ispeed")) { - if (k == argc - 1) - error_msg_and_die("missing argument to `%s'", argv[k]); - ++k; - set_speed(input_speed, argv[k], &mode); - speed_was_set = 1; - require_set_attr = 1; - } else if (STREQ(argv[k], "ospeed")) { - if (k == argc - 1) - error_msg_and_die("missing argument to `%s'", argv[k]); - ++k; - set_speed(output_speed, argv[k], &mode); - speed_was_set = 1; - require_set_attr = 1; - } -#ifdef TIOCGWINSZ - else if (STREQ(argv[k], "rows")) { - if (k == argc - 1) - error_msg_and_die("missing argument to `%s'", argv[k]); - ++k; - set_window_size((int) parse_number(argv[k], stty_suffixes), - -1, fd, device_name); - } else if (STREQ(argv[k], "cols") || STREQ(argv[k], "columns")) { - if (k == argc - 1) - error_msg_and_die("missing argument to `%s'", argv[k]); - ++k; - set_window_size(-1, - (int) parse_number(argv[k], stty_suffixes), - fd, device_name); - } else if (STREQ(argv[k], "size")) { - max_col = screen_columns(); - current_col = 0; - display_window_size(0, fd, device_name); - } -#endif -#ifdef HAVE_C_LINE - else if (STREQ(argv[k], "line")) { - if (k == argc - 1) - error_msg_and_die("missing argument to `%s'", argv[k]); - ++k; - mode.c_line = parse_number(argv[k], stty_suffixes); - require_set_attr = 1; - } -#endif - else if (STREQ(argv[k], "speed")) { - max_col = screen_columns(); - display_speed(&mode, 0); - } else if (recover_mode(argv[k], &mode) == 1) - require_set_attr = 1; - else if (string_to_baud(argv[k]) != (speed_t) - 1) { - set_speed(both_speeds, argv[k], &mode); - speed_was_set = 1; - require_set_attr = 1; - } else - error_msg_and_die("invalid argument `%s'", argv[k]); - } - k++; - } - - if (require_set_attr) { - struct termios new_mode; - - if (tcsetattr(fd, TCSADRAIN, &mode)) - perror_msg_and_die("%s", device_name); - - /* POSIX (according to Zlotnick's book) tcsetattr returns zero if - it performs *any* of the requested operations. This means it - can report `success' when it has actually failed to perform - some proper subset of the requested operations. To detect - this partial failure, get the current terminal attributes and - compare them to the requested ones. */ - - /* Initialize to all zeroes so there is no risk memcmp will report a - spurious difference in an uninitialized portion of the structure. */ - memset(&new_mode, 0, sizeof(new_mode)); - if (tcgetattr(fd, &new_mode)) - perror_msg_and_die("%s", device_name); - - /* Normally, one shouldn't use memcmp to compare structures that - may have `holes' containing uninitialized data, but we have been - careful to initialize the storage of these two variables to all - zeroes. One might think it more efficient simply to compare the - modified fields, but that would require enumerating those fields -- - and not all systems have the same fields in this structure. */ - - if (memcmp(&mode, &new_mode, sizeof(mode)) != 0) { -#ifdef CIBAUD - /* SunOS 4.1.3 (at least) has the problem that after this sequence, - tcgetattr (&m1); tcsetattr (&m1); tcgetattr (&m2); - sometimes (m1 != m2). The only difference is in the four bits - of the c_cflag field corresponding to the baud rate. To save - Sun users a little confusion, don't report an error if this - happens. But suppress the error only if we haven't tried to - set the baud rate explicitly -- otherwise we'd never give an - error for a true failure to set the baud rate. */ - - new_mode.c_cflag &= (~CIBAUD); - if (speed_was_set || memcmp(&mode, &new_mode, sizeof(mode)) != 0) -#endif - error_msg_and_die ("%s: unable to perform all requested operations", - device_name); - } - } - - return EXIT_SUCCESS; -} - -/* Return 0 if not applied because not reversible; otherwise return 1. */ - -static int -set_mode(const struct mode_info *info, int reversed, struct termios *mode) -{ - tcflag_t *bitsp; - - if (reversed && (info->flags & REV) == 0) - return 0; - - bitsp = mode_type_flag(info->type, mode); - - if (bitsp == NULL) { - /* Combination mode. */ - if (info->name == evenp || info->name == parity) { - if (reversed) - mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8; - else - mode->c_cflag = - (mode->c_cflag & ~PARODD & ~CSIZE) | PARENB | CS7; - } else if (info->name == stty_oddp) { - if (reversed) - mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8; - else - mode->c_cflag = - (mode->c_cflag & ~CSIZE) | CS7 | PARODD | PARENB; - } else if (info->name == stty_nl) { - if (reversed) { - mode->c_iflag = (mode->c_iflag | ICRNL) & ~INLCR & ~IGNCR; - mode->c_oflag = (mode->c_oflag -#ifdef ONLCR - | ONLCR -#endif - ) -#ifdef OCRNL - & ~OCRNL -#endif -#ifdef ONLRET - & ~ONLRET -#endif - ; - } else { - mode->c_iflag = mode->c_iflag & ~ICRNL; -#ifdef ONLCR - mode->c_oflag = mode->c_oflag & ~ONLCR; -#endif - } - } else if (info->name == stty_ek) { - mode->c_cc[VERASE] = CERASE; - mode->c_cc[VKILL] = CKILL; - } else if (info->name == stty_sane) - sane_mode(mode); - else if (info->name == cbreak) { - if (reversed) - mode->c_lflag |= ICANON; - else - mode->c_lflag &= ~ICANON; - } else if (info->name == stty_pass8) { - if (reversed) { - mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARENB; - mode->c_iflag |= ISTRIP; - } else { - mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8; - mode->c_iflag &= ~ISTRIP; - } - } else if (info->name == litout) { - if (reversed) { - mode->c_cflag = (mode->c_cflag & ~CSIZE) | CS7 | PARENB; - mode->c_iflag |= ISTRIP; - mode->c_oflag |= OPOST; - } else { - mode->c_cflag = (mode->c_cflag & ~PARENB & ~CSIZE) | CS8; - mode->c_iflag &= ~ISTRIP; - mode->c_oflag &= ~OPOST; - } - } else if (info->name == raw || info->name == cooked) { - if ((info->name[0] == 'r' && reversed) - || (info->name[0] == 'c' && !reversed)) { - /* Cooked mode. */ - mode->c_iflag |= BRKINT | IGNPAR | ISTRIP | ICRNL | IXON; - mode->c_oflag |= OPOST; - mode->c_lflag |= ISIG | ICANON; -#if VMIN == VEOF - mode->c_cc[VEOF] = CEOF; -#endif -#if VTIME == VEOL - mode->c_cc[VEOL] = CEOL; -#endif - } else { - /* Raw mode. */ - mode->c_iflag = 0; - mode->c_oflag &= ~OPOST; - mode->c_lflag &= ~(ISIG | ICANON -#ifdef XCASE - | XCASE -#endif - ); - mode->c_cc[VMIN] = 1; - mode->c_cc[VTIME] = 0; - } - } -#ifdef IXANY - else if (info->name == decctlq) { - if (reversed) - mode->c_iflag |= IXANY; - else - mode->c_iflag &= ~IXANY; - } -#endif -#ifdef TABDLY - else if (info->name == stty_tabs) { - if (reversed) - mode->c_oflag = (mode->c_oflag & ~TABDLY) | TAB3; - else - mode->c_oflag = (mode->c_oflag & ~TABDLY) | TAB0; - } -#else -# ifdef OXTABS - else if (info->name == stty_tabs) { - if (reversed) - mode->c_oflag = mode->c_oflag | OXTABS; - else - mode->c_oflag = mode->c_oflag & ~OXTABS; - } -# endif -#endif -#if defined(XCASE) && defined(IUCLC) && defined(OLCUC) - else if (info->name == stty_lcase || info->name == stty_LCASE) { - if (reversed) { - mode->c_lflag &= ~XCASE; - mode->c_iflag &= ~IUCLC; - mode->c_oflag &= ~OLCUC; - } else { - mode->c_lflag |= XCASE; - mode->c_iflag |= IUCLC; - mode->c_oflag |= OLCUC; - } - } -#endif - else if (info->name == stty_crt) - mode->c_lflag |= ECHOE -#ifdef ECHOCTL - | ECHOCTL -#endif -#ifdef ECHOKE - | ECHOKE -#endif - ; - else if (info->name == stty_dec) { - mode->c_cc[VINTR] = 3; /* ^C */ - mode->c_cc[VERASE] = 127; /* DEL */ - mode->c_cc[VKILL] = 21; /* ^U */ - mode->c_lflag |= ECHOE -#ifdef ECHOCTL - | ECHOCTL -#endif -#ifdef ECHOKE - | ECHOKE -#endif - ; -#ifdef IXANY - mode->c_iflag &= ~IXANY; -#endif - } - } else if (reversed) - *bitsp = *bitsp & ~info->mask & ~info->bits; - else - *bitsp = (*bitsp & ~info->mask) | info->bits; - - return 1; -} - -static void -set_control_char(const struct control_info *info, const char *arg, - struct termios *mode) -{ - unsigned char value; - - if (info->name == stty_min || info->name == stty_time) - value = parse_number(arg, stty_suffixes); - else if (arg[0] == '\0' || arg[1] == '\0') - value = arg[0]; - else if (STREQ(arg, "^-") || STREQ(arg, "undef")) - value = _POSIX_VDISABLE; - else if (arg[0] == '^' && arg[1] != '\0') { /* Ignore any trailing junk. */ - if (arg[1] == '?') - value = 127; - else - value = arg[1] & ~0140; /* Non-letters get weird results. */ - } else - value = parse_number(arg, stty_suffixes); - mode->c_cc[info->offset] = value; -} - -static void -set_speed(enum speed_setting type, const char *arg, struct termios *mode) -{ - speed_t baud; - - baud = string_to_baud(arg); - if (type == input_speed || type == both_speeds) - cfsetispeed(mode, baud); - if (type == output_speed || type == both_speeds) - cfsetospeed(mode, baud); -} - -#ifdef TIOCGWINSZ - -static int get_win_size(int fd, struct winsize *win) -{ - int err = ioctl(fd, TIOCGWINSZ, (char *) win); - - return err; -} - -static void -set_window_size(int rows, int cols, int fd, const char *device_name) -{ - struct winsize win; - - if (get_win_size(fd, &win)) { - if (errno != EINVAL) - perror_msg_and_die("%s", device_name); - memset(&win, 0, sizeof(win)); - } - - if (rows >= 0) - win.ws_row = rows; - if (cols >= 0) - win.ws_col = cols; - -# ifdef TIOCSSIZE - /* Alexander Dupuy <dupuy@cs.columbia.edu> wrote: - The following code deals with a bug in the SunOS 4.x (and 3.x?) kernel. - This comment from sys/ttold.h describes Sun's twisted logic - a better - test would have been (ts_lines > 64k || ts_cols > 64k || ts_cols == 0). - At any rate, the problem is gone in Solaris 2.x. */ - - if (win.ws_row == 0 || win.ws_col == 0) { - struct ttysize ttysz; - - ttysz.ts_lines = win.ws_row; - ttysz.ts_cols = win.ws_col; - - win.ws_row = 1; - win.ws_col = 1; - - if (ioctl(fd, TIOCSWINSZ, (char *) &win)) - perror_msg_and_die("%s", device_name); - - if (ioctl(fd, TIOCSSIZE, (char *) &ttysz)) - perror_msg_and_die("%s", device_name); - return; - } -# endif - - if (ioctl(fd, TIOCSWINSZ, (char *) &win)) - perror_msg_and_die("%s", device_name); -} - -static void display_window_size(int fancy, int fd, const char *device_name) -{ - struct winsize win; - - if (get_win_size(fd, &win)) { - if (errno != EINVAL) - perror_msg_and_die("%s", device_name); - if (!fancy) - perror_msg_and_die("%s: no size information for this device", - device_name); - } else { - wrapf(fancy ? "rows %d; columns %d;" : "%d %d\n", - win.ws_row, win.ws_col); - if (!fancy) - current_col = 0; - } -} -#endif - -static int screen_columns(void) -{ -#ifdef TIOCGWINSZ - struct winsize win; - - /* With Solaris 2.[123], this ioctl fails and errno is set to - EINVAL for telnet (but not rlogin) sessions. - On ISC 3.0, it fails for the console and the serial port - (but it works for ptys). - It can also fail on any system when stdout isn't a tty. - In case of any failure, just use the default. */ - if (get_win_size(STDOUT_FILENO, &win) == 0 && win.ws_col > 0) - return win.ws_col; -#endif - - if (getenv("COLUMNS")) - return atoi(getenv("COLUMNS")); - return 80; -} - -static tcflag_t *mode_type_flag(enum mode_type type, struct termios *mode) -{ - switch (type) { - case control: - return &mode->c_cflag; - - case input: - return &mode->c_iflag; - - case output: - return &mode->c_oflag; - - case local: - return &mode->c_lflag; - - default: /* combination: */ - return NULL; - } -} - -static void -display_settings(enum output_type output_type, struct termios *mode, - int fd, const char *device_name) -{ - switch (output_type) { - case changed: - display_changed(mode); - break; - - case all: - display_all(mode, fd, device_name); - break; - - case recoverable: - display_recoverable(mode); - break; - } -} - -static void display_changed(struct termios *mode) -{ - int i; - int empty_line; - tcflag_t *bitsp; - unsigned long mask; - enum mode_type prev_type = control; - - display_speed(mode, 1); -#ifdef HAVE_C_LINE - wrapf("line = %d;", mode->c_line); -#endif - putchar('\n'); - current_col = 0; - - empty_line = 1; - for (i = 0; control_info[i].name != stty_min; ++i) { - if (mode->c_cc[control_info[i].offset] == control_info[i].saneval) - continue; - /* If swtch is the same as susp, don't print both. */ -#if VSWTCH == VSUSP - if (control_info[i].name == stty_swtch) - continue; -#endif - /* If eof uses the same slot as min, only print whichever applies. */ -#if VEOF == VMIN - if ((mode->c_lflag & ICANON) == 0 - && (control_info[i].name == stty_eof - || control_info[i].name == stty_eol)) continue; -#endif - - empty_line = 0; - wrapf("%s = %s;", control_info[i].name, - visible(mode->c_cc[control_info[i].offset])); - } - if ((mode->c_lflag & ICANON) == 0) { - wrapf("min = %d; time = %d;\n", (int) mode->c_cc[VMIN], - (int) mode->c_cc[VTIME]); - } else if (empty_line == 0) - putchar('\n'); - current_col = 0; - - empty_line = 1; - for (i = 0; i < NUM_mode_info; ++i) { - if (mode_info[i].flags & OMIT) - continue; - if (mode_info[i].type != prev_type) { - if (empty_line == 0) { - putchar('\n'); - current_col = 0; - empty_line = 1; - } - prev_type = mode_info[i].type; - } - - bitsp = mode_type_flag(mode_info[i].type, mode); - mask = mode_info[i].mask ? mode_info[i].mask : mode_info[i].bits; - if ((*bitsp & mask) == mode_info[i].bits) { - if (mode_info[i].flags & SANE_UNSET) { - wrapf("%s", mode_info[i].name); - empty_line = 0; - } - } - else if ((mode_info[i].flags & (SANE_SET | REV)) == - (SANE_SET | REV)) { - wrapf("-%s", mode_info[i].name); - empty_line = 0; - } - } - if (empty_line == 0) - putchar('\n'); - current_col = 0; -} - -static void -display_all(struct termios *mode, int fd, const char *device_name) -{ - int i; - tcflag_t *bitsp; - unsigned long mask; - enum mode_type prev_type = control; - - display_speed(mode, 1); -#ifdef TIOCGWINSZ - display_window_size(1, fd, device_name); -#endif -#ifdef HAVE_C_LINE - wrapf("line = %d;", mode->c_line); -#endif - putchar('\n'); - current_col = 0; - - for (i = 0; control_info[i].name != stty_min; ++i) { - /* If swtch is the same as susp, don't print both. */ -#if VSWTCH == VSUSP - if (control_info[i].name == stty_swtch) - continue; -#endif - /* If eof uses the same slot as min, only print whichever applies. */ -#if VEOF == VMIN - if ((mode->c_lflag & ICANON) == 0 - && (control_info[i].name == stty_eof - || control_info[i].name == stty_eol)) continue; -#endif - wrapf("%s = %s;", control_info[i].name, - visible(mode->c_cc[control_info[i].offset])); - } -#if VEOF == VMIN - if ((mode->c_lflag & ICANON) == 0) -#endif - wrapf("min = %d; time = %d;", mode->c_cc[VMIN], mode->c_cc[VTIME]); - if (current_col != 0) - putchar('\n'); - current_col = 0; - - for (i = 0; i < NUM_mode_info; ++i) { - if (mode_info[i].flags & OMIT) - continue; - if (mode_info[i].type != prev_type) { - putchar('\n'); - current_col = 0; - prev_type = mode_info[i].type; - } - - bitsp = mode_type_flag(mode_info[i].type, mode); - mask = mode_info[i].mask ? mode_info[i].mask : mode_info[i].bits; - if ((*bitsp & mask) == mode_info[i].bits) - wrapf("%s", mode_info[i].name); - else if (mode_info[i].flags & REV) - wrapf("-%s", mode_info[i].name); - } - putchar('\n'); - current_col = 0; -} - -static void display_speed(struct termios *mode, int fancy) -{ - if (cfgetispeed(mode) == 0 || cfgetispeed(mode) == cfgetospeed(mode)) - wrapf(fancy ? "speed %lu baud;" : "%lu\n", - baud_to_value(cfgetospeed(mode))); - else - wrapf(fancy ? "ispeed %lu baud; ospeed %lu baud;" : "%lu %lu\n", - baud_to_value(cfgetispeed(mode)), - baud_to_value(cfgetospeed(mode))); - if (!fancy) - current_col = 0; -} - -static void display_recoverable(struct termios *mode) -{ - int i; - - printf("%lx:%lx:%lx:%lx", - (unsigned long) mode->c_iflag, (unsigned long) mode->c_oflag, - (unsigned long) mode->c_cflag, (unsigned long) mode->c_lflag); - for (i = 0; i < NCCS; ++i) - printf(":%x", (unsigned int) mode->c_cc[i]); - putchar('\n'); -} - -static int recover_mode(char *arg, struct termios *mode) -{ - int i, n; - unsigned int chr; - unsigned long iflag, oflag, cflag, lflag; - - /* Scan into temporaries since it is too much trouble to figure out - the right format for `tcflag_t'. */ - if (sscanf(arg, "%lx:%lx:%lx:%lx%n", - &iflag, &oflag, &cflag, &lflag, &n) != 4) - return 0; - mode->c_iflag = iflag; - mode->c_oflag = oflag; - mode->c_cflag = cflag; - mode->c_lflag = lflag; - arg += n; - for (i = 0; i < NCCS; ++i) { - if (sscanf(arg, ":%x%n", &chr, &n) != 1) - return 0; - mode->c_cc[i] = chr; - arg += n; - } - - /* Fail if there are too many fields. */ - if (*arg != '\0') - return 0; - - return 1; -} - -struct speed_map { - speed_t speed; /* Internal form. */ - unsigned long value; /* Numeric value. */ -}; - -static const struct speed_map speeds[] = { - {B0, 0}, - {B50, 50}, - {B75, 75}, - {B110, 110}, - {B134, 134}, - {B150, 150}, - {B200, 200}, - {B300, 300}, - {B600, 600}, - {B1200, 1200}, - {B1800, 1800}, - {B2400, 2400}, - {B4800, 4800}, - {B9600, 9600}, - {B19200, 19200}, - {B38400, 38400}, -#ifdef B57600 - {B57600, 57600}, -#endif -#ifdef B115200 - {B115200, 115200}, -#endif -#ifdef B230400 - {B230400, 230400}, -#endif -#ifdef B460800 - {B460800, 460800}, -#endif -}; - -static const int NUM_SPEEDS = (sizeof(speeds) / sizeof(struct speed_map)); - -static speed_t string_to_baud(const char *arg) -{ - int i; - - for (i = 0; i < NUM_SPEEDS; ++i) - if (parse_number(arg, 0) == speeds[i].value) - return speeds[i].speed; - return (speed_t) - 1; -} - -static unsigned long baud_to_value(speed_t speed) -{ - int i; - - for (i = 0; i < NUM_SPEEDS; ++i) - if (speed == speeds[i].speed) - return speeds[i].value; - return 0; -} - -static void sane_mode(struct termios *mode) -{ - int i; - tcflag_t *bitsp; - - for (i = 0; i < NUM_control_info; ++i) { -#if VMIN == VEOF - if (control_info[i].name == stty_min) - break; -#endif - mode->c_cc[control_info[i].offset] = control_info[i].saneval; - } - - for (i = 0; i < NUM_mode_info; ++i) { - if (mode_info[i].flags & SANE_SET) { - bitsp = mode_type_flag(mode_info[i].type, mode); - *bitsp = (*bitsp & ~mode_info[i].mask) | mode_info[i].bits; - } else if (mode_info[i].flags & SANE_UNSET) { - bitsp = mode_type_flag(mode_info[i].type, mode); - *bitsp = *bitsp & ~mode_info[i].mask & ~mode_info[i].bits; - } - } -} - -/* Return a string that is the printable representation of character CH. */ -/* Adapted from `cat' by Torbjorn Granlund. */ - -static const char *visible(unsigned int ch) -{ - static char buf[10]; - char *bpout = buf; - - if (ch == _POSIX_VDISABLE) - return "<undef>"; - - if (ch >= 32) { - if (ch < 127) - *bpout++ = ch; - else if (ch == 127) { - *bpout++ = '^'; - *bpout++ = '?'; - } else { - *bpout++ = 'M', *bpout++ = '-'; - if (ch >= 128 + 32) { - if (ch < 128 + 127) - *bpout++ = ch - 128; - else { - *bpout++ = '^'; - *bpout++ = '?'; - } - } else { - *bpout++ = '^'; - *bpout++ = ch - 128 + 64; - } - } - } else { - *bpout++ = '^'; - *bpout++ = ch + 64; - } - *bpout = '\0'; - return (const char *) buf; -} - -#ifdef TEST - -const char *applet_name = "stty"; - -#endif - -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ diff --git a/swaponoff.c b/swaponoff.c deleted file mode 100644 index d9eb5baae..000000000 --- a/swaponoff.c +++ /dev/null @@ -1,115 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini swapon/swapoff implementation for busybox - * - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <stdio.h> -#include <mntent.h> -#include <dirent.h> -#include <errno.h> -#include <string.h> -#include <stdlib.h> -#include <sys/mount.h> - -#if __GNU_LIBRARY__ < 5 -/* libc5 doesn't have sys/swap.h, define these here. */ -extern int swapon (__const char *__path, int __flags); -extern int swapoff (__const char *__path); -#else -#include <sys/swap.h> -#endif - -#include "busybox.h" - -static int whichApp; - -static const int SWAPON_APP = 1; -static const int SWAPOFF_APP = 2; - - -static void swap_enable_disable(char *device) -{ - int status; - - if (whichApp == SWAPON_APP) - status = swapon(device, 0); - else - status = swapoff(device); - - if (status != 0) - perror_msg_and_die(applet_name); -} - -static void do_em_all(void) -{ - struct mntent *m; - FILE *f = setmntent("/etc/fstab", "r"); - - if (f == NULL) - perror_msg_and_die("/etc/fstab"); - while ((m = getmntent(f)) != NULL) { - if (strcmp(m->mnt_type, MNTTYPE_SWAP)==0) { - swap_enable_disable(m->mnt_fsname); - } - } - endmntent(f); - exit(EXIT_SUCCESS); -} - - -extern int swap_on_off_main(int argc, char **argv) -{ - if (strcmp(applet_name, "swapon") == 0) { - whichApp = SWAPON_APP; - } else { - whichApp = SWAPOFF_APP; - } - - if (argc != 2) { - goto usage_and_exit; - } - argc--; - argv++; - - /* Parse any options */ - while (**argv == '-') { - while (*++(*argv)) - switch (**argv) { - case 'a': - { - struct stat statBuf; - - if (stat("/etc/fstab", &statBuf) < 0) - error_msg_and_die("/etc/fstab file missing"); - } - do_em_all(); - break; - default: - goto usage_and_exit; - } - } - swap_enable_disable(*argv); - return EXIT_SUCCESS; - - usage_and_exit: - show_usage(); -} diff --git a/sync.c b/sync.c deleted file mode 100644 index ee22ae109..000000000 --- a/sync.c +++ /dev/null @@ -1,35 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini sync implementation for busybox - * - * - * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include "busybox.h" - -extern int sync_main(int argc, char **argv) -{ - if (argc > 1 && **(argv + 1) == '-') - show_usage(); - sync(); - return(EXIT_SUCCESS); -} diff --git a/sysdeps/linux/config.in b/sysdeps/linux/config.in new file mode 100644 index 000000000..c4191d65f --- /dev/null +++ b/sysdeps/linux/config.in @@ -0,0 +1,23 @@ +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# +mainmenu_name "BusyBox Configuration" + + +source archival/config.in +source console-tools/config.in +source editors/config.in +source fileutils/config.in +source findutils/config.in +source init/config.in +source miscutils/config.in +source modutils/config.in +source networking/config.in +source procps/config.in +source shell/config.in +source shellutils/config.in +source sysklogd/config.in +source textutils/config.in +source util-linux/config.in + diff --git a/sysdeps/linux/defconfig b/sysdeps/linux/defconfig new file mode 100644 index 000000000..e69de29bb diff --git a/sysklogd/Makefile b/sysklogd/Makefile new file mode 100644 index 000000000..3bfe90324 --- /dev/null +++ b/sysklogd/Makefile @@ -0,0 +1,38 @@ +# Makefile for busybox +# +# Copyright (C) 1999,2000,2001 by Erik Andersen <andersee@debian.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +TOPDIR :=.. +L_TARGET := sysklogd.a + +obj-y := +obj-n := +obj- := + + +obj-$(CONFIG_KLOGD) += klogd.o +obj-$(CONFIG_LOGGER) += logger.o +obj-$(CONFIG_LOGREAD) += logread.o +obj-$(CONFIG_SYSLOGD) += syslogd.o + +# Hand off to toplevel Rules.mak +include $(TOPDIR)/Rules.mak + +clean: + rm -f $(L_TARGET) *.o core + diff --git a/sysklogd/config.in b/sysklogd/config.in new file mode 100644 index 000000000..8a8e42086 --- /dev/null +++ b/sysklogd/config.in @@ -0,0 +1,16 @@ +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +mainmenu_option next_comment +comment 'System Logging Utilities' + +bool 'klogd' CONFIG_KLOGD +bool 'logger' CONFIG_LOGGER +bool 'logread' CONFIG_LOGREAD +bool 'syslogd' CONFIG_SYSLOGD + + +endmenu + diff --git a/sysklogd/klogd.c b/sysklogd/klogd.c index d7b54e9c8..33bc783fe 100644 --- a/sysklogd/klogd.c +++ b/sysklogd/klogd.c @@ -6,8 +6,8 @@ * Changes: Made this a standalone busybox module which uses standalone * syslog() client interface. * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org> + * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen <andersee@debian.org> * * Copyright (C) 2000 by Karl M. Hegbloom <karlheg@debian.org> * diff --git a/sysklogd/logger.c b/sysklogd/logger.c index 9f730915f..380bde5ca 100644 --- a/sysklogd/logger.c +++ b/sysklogd/logger.c @@ -2,8 +2,8 @@ /* * Mini logger implementation for busybox * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org> + * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen <andersee@debian.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,7 +30,7 @@ #include <stdlib.h> #include "busybox.h" -#if !defined BB_SYSLOGD +#if !defined CONFIG_SYSLOGD #define SYSLOG_NAMES #include <sys/syslog.h> diff --git a/sysklogd/logread.c b/sysklogd/logread.c index d3349625c..13ff1aeb9 100644 --- a/sysklogd/logread.c +++ b/sysklogd/logread.c @@ -38,7 +38,7 @@ #if __GNU_LIBRARY__ < 5 #error Sorry. Looks like you are using libc5. #error libc5 shm support isnt good enough. -#error Please disable BB_FEATURE_IPC_SYSLOG +#error Please disable CONFIG_FEATURE_IPC_SYSLOG #endif diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c index 25bc68f20..db6401c52 100644 --- a/sysklogd/syslogd.c +++ b/sysklogd/syslogd.c @@ -2,8 +2,8 @@ /* * Mini syslogd implementation for busybox * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org> + * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen <andersee@debian.org> * * Copyright (C) 2000 by Karl M. Hegbloom <karlheg@debian.org> * @@ -65,7 +65,7 @@ static int MarkInterval = 20 * 60; /* localhost's name */ static char LocalHostName[32]; -#ifdef BB_FEATURE_REMOTE_LOG +#ifdef CONFIG_FEATURE_REMOTE_LOG #include <netinet/in.h> /* udp socket for logging to remote host */ static int remotefd = -1; @@ -79,7 +79,7 @@ static int local_logging = FALSE; #endif /* circular buffer variables/structures */ -#ifdef BB_FEATURE_IPC_SYSLOG +#ifdef CONFIG_FEATURE_IPC_SYSLOG #include <sys/ipc.h> #include <sys/sem.h> @@ -269,7 +269,7 @@ static void message (char *fmt, ...) fl.l_start = 0; fl.l_len = 1; -#ifdef BB_FEATURE_IPC_SYSLOG +#ifdef CONFIG_FEATURE_IPC_SYSLOG if ((circular_logging == TRUE) && (buf != NULL)){ char b[1024]; va_start (arguments, fmt); @@ -339,7 +339,7 @@ static void logMessage (int pri, char *msg) /* todo: supress duplicates */ -#ifdef BB_FEATURE_REMOTE_LOG +#ifdef CONFIG_FEATURE_REMOTE_LOG /* send message to remote logger */ if ( -1 != remotefd){ static const int IOV_COUNT = 2; @@ -372,7 +372,7 @@ static void quit_signal(int sig) { logMessage(LOG_SYSLOG | LOG_INFO, "System log daemon exiting."); unlink(lfile); -#ifdef BB_FEATURE_IPC_SYSLOG +#ifdef CONFIG_FEATURE_IPC_SYSLOG ipcsyslog_cleanup(); #endif @@ -392,7 +392,7 @@ static void domark(int sig) #define BUFSIZE 1023 static int serveConnection (int conn) { - RESERVE_BB_BUFFER(tmpbuf, BUFSIZE + 1); + RESERVE_CONFIG_BUFFER(tmpbuf, BUFSIZE + 1); int n_read; char *p = tmpbuf; @@ -433,12 +433,12 @@ static int serveConnection (int conn) /* Now log it */ logMessage (pri, line); } - RELEASE_BB_BUFFER (tmpbuf); + RELEASE_CONFIG_BUFFER (tmpbuf); return n_read; } -#ifdef BB_FEATURE_REMOTE_LOG +#ifdef CONFIG_FEATURE_REMOTE_LOG static void init_RemoteLog (void){ struct sockaddr_in remoteaddr; @@ -512,13 +512,13 @@ static void doSyslogd (void) FD_ZERO (&fds); FD_SET (sock_fd, &fds); -#ifdef BB_FEATURE_IPC_SYSLOG +#ifdef CONFIG_FEATURE_IPC_SYSLOG if (circular_logging == TRUE ){ ipcsyslog_init(); } #endif - #ifdef BB_FEATURE_REMOTE_LOG + #ifdef CONFIG_FEATURE_REMOTE_LOG if (doRemoteLog == TRUE){ init_RemoteLog(); } @@ -585,7 +585,7 @@ extern int syslogd_main(int argc, char **argv) case 'O': logFilePath = strdup(optarg); break; -#ifdef BB_FEATURE_REMOTE_LOG +#ifdef CONFIG_FEATURE_REMOTE_LOG case 'R': RemoteHost = strdup(optarg); if ( (p = strchr(RemoteHost, ':'))){ @@ -598,7 +598,7 @@ extern int syslogd_main(int argc, char **argv) local_logging = TRUE; break; #endif -#ifdef BB_FEATURE_IPC_SYSLOG +#ifdef CONFIG_FEATURE_IPC_SYSLOG case 'C': circular_logging = TRUE; break; @@ -608,7 +608,7 @@ extern int syslogd_main(int argc, char **argv) } } -#ifdef BB_FEATURE_REMOTE_LOG +#ifdef CONFIG_FEATURE_REMOTE_LOG /* If they have not specified remote logging, then log locally */ if (doRemoteLog == FALSE) local_logging = TRUE; diff --git a/syslogd.c b/syslogd.c deleted file mode 100644 index 25bc68f20..000000000 --- a/syslogd.c +++ /dev/null @@ -1,641 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini syslogd implementation for busybox - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org> - * - * Copyright (C) 2000 by Karl M. Hegbloom <karlheg@debian.org> - * - * "circular buffer" Copyright (C) 2001 by Gennady Feldman <gfeldman@cachier.com> - * - * Maintainer: Gennady Feldman <gena01@cachier.com> as of Mar 12, 2001 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <stdio.h> -#include <stdlib.h> -#include <ctype.h> -#include <errno.h> -#include <fcntl.h> -#include <netdb.h> -#include <paths.h> -#include <signal.h> -#include <stdarg.h> -#include <time.h> -#include <string.h> -#include <unistd.h> -#include <sys/socket.h> -#include <sys/types.h> -#include <sys/un.h> -#include <sys/param.h> - -#include "busybox.h" - -/* SYSLOG_NAMES defined to pull some extra junk from syslog.h */ -#define SYSLOG_NAMES -#include <sys/syslog.h> -#include <sys/uio.h> - -/* Path for the file where all log messages are written */ -#define __LOG_FILE "/var/log/messages" - -/* Path to the unix socket */ -static char lfile[BUFSIZ]; - -static char *logFilePath = __LOG_FILE; - -/* interval between marks in seconds */ -static int MarkInterval = 20 * 60; - -/* localhost's name */ -static char LocalHostName[32]; - -#ifdef BB_FEATURE_REMOTE_LOG -#include <netinet/in.h> -/* udp socket for logging to remote host */ -static int remotefd = -1; -/* where do we log? */ -static char *RemoteHost; -/* what port to log to? */ -static int RemotePort = 514; -/* To remote log or not to remote log, that is the question. */ -static int doRemoteLog = FALSE; -static int local_logging = FALSE; -#endif - -/* circular buffer variables/structures */ -#ifdef BB_FEATURE_IPC_SYSLOG - -#include <sys/ipc.h> -#include <sys/sem.h> -#include <sys/shm.h> - -/* our shared key */ -static const long KEY_ID = 0x414e4547; /*"GENA"*/ - -// Semaphore operation structures -static struct shbuf_ds { - int size; // size of data written - int head; // start of message list - int tail; // end of message list - char data[1]; // data/messages -} *buf = NULL; // shared memory pointer - -static struct sembuf SMwup[1] = {{1, -1, IPC_NOWAIT}}; // set SMwup -static struct sembuf SMwdn[3] = {{0, 0}, {1, 0}, {1, +1}}; // set SMwdn - -static int shmid = -1; // ipc shared memory id -static int s_semid = -1; // ipc semaphore id -int data_size = 16000; // data size -int shm_size = 16000 + sizeof(*buf); // our buffer size -static int circular_logging = FALSE; - -/* - * sem_up - up()'s a semaphore. - */ -static inline void sem_up(int semid) -{ - if ( semop(semid, SMwup, 1) == -1 ) - perror_msg_and_die("semop[SMwup]"); -} - -/* - * sem_down - down()'s a semaphore - */ -static inline void sem_down(int semid) -{ - if ( semop(semid, SMwdn, 3) == -1 ) - perror_msg_and_die("semop[SMwdn]"); -} - - -void ipcsyslog_cleanup(void){ - printf("Exiting Syslogd!\n"); - if (shmid != -1) - shmdt(buf); - - if (shmid != -1) - shmctl(shmid, IPC_RMID, NULL); - if (s_semid != -1) - semctl(s_semid, 0, IPC_RMID, 0); -} - -void ipcsyslog_init(void){ - if (buf == NULL){ - if ((shmid = shmget(KEY_ID, shm_size, IPC_CREAT | 1023)) == -1) - perror_msg_and_die("shmget"); - - - if ((buf = shmat(shmid, NULL, 0)) == NULL) - perror_msg_and_die("shmat"); - - - buf->size=data_size; - buf->head=buf->tail=0; - - // we'll trust the OS to set initial semval to 0 (let's hope) - if ((s_semid = semget(KEY_ID, 2, IPC_CREAT | IPC_EXCL | 1023)) == -1){ - if (errno == EEXIST){ - if ((s_semid = semget(KEY_ID, 2, 0)) == -1) - perror_msg_and_die("semget"); - }else - perror_msg_and_die("semget"); - } - }else{ - printf("Buffer already allocated just grab the semaphore?"); - } -} - -/* write message to buffer */ -void circ_message(const char *msg){ - int l=strlen(msg)+1; /* count the whole message w/ '\0' included */ - - sem_down(s_semid); - - /* - * Circular Buffer Algorithm: - * -------------------------- - * - * Start-off w/ empty buffer of specific size SHM_SIZ - * Start filling it up w/ messages. I use '\0' as separator to break up messages. - * This is also very handy since we can do printf on message. - * - * Once the buffer is full we need to get rid of the first message in buffer and - * insert the new message. (Note: if the message being added is >1 message then - * we will need to "remove" >1 old message from the buffer). The way this is done - * is the following: - * When we reach the end of the buffer we set a mark and start from the beginning. - * Now what about the beginning and end of the buffer? Well we have the "head" - * index/pointer which is the starting point for the messages and we have "tail" - * index/pointer which is the ending point for the messages. When we "display" the - * messages we start from the beginning and continue until we reach "tail". If we - * reach end of buffer, then we just start from the beginning (offset 0). "head" and - * "tail" are actually offsets from the beginning of the buffer. - * - * Note: This algorithm uses Linux IPC mechanism w/ shared memory and semaphores to provide - * a threasafe way of handling shared memory operations. - */ - if ( (buf->tail + l) < buf->size ){ - /* before we append the message we need to check the HEAD so that we won't - overwrite any of the message that we still need and adjust HEAD to point - to the next message! */ - if ( buf->tail < buf->head){ - if ( (buf->tail + l) >= buf->head ){ - /* we need to move the HEAD to point to the next message - * Theoretically we have enough room to add the whole message to the - * buffer, because of the first outer IF statement, so we don't have - * to worry about overflows here! - */ - int k= buf->tail + l - buf->head; /* we need to know how many bytes - we are overwriting to make - enough room */ - char *c=memchr(buf->data+buf->head + k,'\0',buf->size - (buf->head + k)); - if (c != NULL) {/* do a sanity check just in case! */ - buf->head = c - buf->data + 1; /* we need to convert pointer to - offset + skip the '\0' since - we need to point to the beginning - of the next message */ - /* Note: HEAD is only used to "retrieve" messages, it's not used - when writing messages into our buffer */ - }else{ /* show an error message to know we messed up? */ - printf("Weird! Can't find the terminator token??? \n"); - buf->head=0; - } - } - } /* in other cases no overflows have been done yet, so we don't care! */ - - /* we should be ok to append the message now */ - strncpy(buf->data + buf->tail,msg,l); /* append our message */ - buf->tail+=l; /* count full message w/ '\0' terminating char */ - }else{ - /* we need to break up the message and "circle" it around */ - char *c; - int k=buf->tail + l - buf->size; /* count # of bytes we don't fit */ - - /* We need to move HEAD! This is always the case since we are going - * to "circle" the message. - */ - c=memchr(buf->data + k ,'\0', buf->size - k); - - if (c != NULL) /* if we don't have '\0'??? weird!!! */{ - /* move head pointer*/ - buf->head=c-buf->data+1; - - /* now write the first part of the message */ - strncpy(buf->data + buf->tail, msg, l - k - 1); - - /* ALWAYS terminate end of buffer w/ '\0' */ - buf->data[buf->size-1]='\0'; - - /* now write out the rest of the string to the beginning of the buffer */ - strcpy(buf->data, &msg[l-k-1]); - - /* we need to place the TAIL at the end of the message */ - buf->tail = k + 1; - }else{ - printf("Weird! Can't find the terminator token from the beginning??? \n"); - buf->head = buf->tail = 0; /* reset buffer, since it's probably corrupted */ - } - - } - sem_up(s_semid); -} -#endif -/* Note: There is also a function called "message()" in init.c */ -/* Print a message to the log file. */ -static void message (char *fmt, ...) __attribute__ ((format (printf, 1, 2))); -static void message (char *fmt, ...) -{ - int fd; - struct flock fl; - va_list arguments; - - fl.l_whence = SEEK_SET; - fl.l_start = 0; - fl.l_len = 1; - -#ifdef BB_FEATURE_IPC_SYSLOG - if ((circular_logging == TRUE) && (buf != NULL)){ - char b[1024]; - va_start (arguments, fmt); - vsprintf (b, fmt, arguments); - va_end (arguments); - circ_message(b); - - }else -#endif - if ((fd = device_open (logFilePath, - O_WRONLY | O_CREAT | O_NOCTTY | O_APPEND | - O_NONBLOCK)) >= 0) { - fl.l_type = F_WRLCK; - fcntl (fd, F_SETLKW, &fl); - va_start (arguments, fmt); - vdprintf (fd, fmt, arguments); - va_end (arguments); - fl.l_type = F_UNLCK; - fcntl (fd, F_SETLKW, &fl); - close (fd); - } else { - /* Always send console messages to /dev/console so people will see them. */ - if ((fd = device_open (_PATH_CONSOLE, - O_WRONLY | O_NOCTTY | O_NONBLOCK)) >= 0) { - va_start (arguments, fmt); - vdprintf (fd, fmt, arguments); - va_end (arguments); - close (fd); - } else { - fprintf (stderr, "Bummer, can't print: "); - va_start (arguments, fmt); - vfprintf (stderr, fmt, arguments); - fflush (stderr); - va_end (arguments); - } - } -} - -static void logMessage (int pri, char *msg) -{ - time_t now; - char *timestamp; - static char res[20] = ""; - CODE *c_pri, *c_fac; - - if (pri != 0) { - for (c_fac = facilitynames; - c_fac->c_name && !(c_fac->c_val == LOG_FAC(pri) << 3); c_fac++); - for (c_pri = prioritynames; - c_pri->c_name && !(c_pri->c_val == LOG_PRI(pri)); c_pri++); - if (c_fac->c_name == NULL || c_pri->c_name == NULL) - snprintf(res, sizeof(res), "<%d>", pri); - else - snprintf(res, sizeof(res), "%s.%s", c_fac->c_name, c_pri->c_name); - } - - if (strlen(msg) < 16 || msg[3] != ' ' || msg[6] != ' ' || - msg[9] != ':' || msg[12] != ':' || msg[15] != ' ') { - time(&now); - timestamp = ctime(&now) + 4; - timestamp[15] = '\0'; - } else { - timestamp = msg; - timestamp[15] = '\0'; - msg += 16; - } - - /* todo: supress duplicates */ - -#ifdef BB_FEATURE_REMOTE_LOG - /* send message to remote logger */ - if ( -1 != remotefd){ -static const int IOV_COUNT = 2; - struct iovec iov[IOV_COUNT]; - struct iovec *v = iov; - - memset(&res, 0, sizeof(res)); - snprintf(res, sizeof(res), "<%d>", pri); - v->iov_base = res ; - v->iov_len = strlen(res); - v++; - - v->iov_base = msg; - v->iov_len = strlen(msg); - - if ( -1 == writev(remotefd,iov, IOV_COUNT)){ - error_msg_and_die("syslogd: cannot write to remote file handle on" - "%s:%d",RemoteHost,RemotePort); - } - } - if (local_logging == TRUE) -#endif - /* now spew out the message to wherever it is supposed to go */ - message("%s %s %s %s\n", timestamp, LocalHostName, res, msg); - - -} - -static void quit_signal(int sig) -{ - logMessage(LOG_SYSLOG | LOG_INFO, "System log daemon exiting."); - unlink(lfile); -#ifdef BB_FEATURE_IPC_SYSLOG - ipcsyslog_cleanup(); -#endif - - exit(TRUE); -} - -static void domark(int sig) -{ - if (MarkInterval > 0) { - logMessage(LOG_SYSLOG | LOG_INFO, "-- MARK --"); - alarm(MarkInterval); - } -} - -/* This must be a #define, since when DODEBUG and BUFFERS_GO_IN_BSS are - * enabled, we otherwise get a "storage size isn't constant error. */ -#define BUFSIZE 1023 -static int serveConnection (int conn) -{ - RESERVE_BB_BUFFER(tmpbuf, BUFSIZE + 1); - int n_read; - char *p = tmpbuf; - - n_read = read (conn, tmpbuf, BUFSIZE ); - - while (p < tmpbuf + n_read) { - - int pri = (LOG_USER | LOG_NOTICE); - char line[ BUFSIZE + 1 ]; - unsigned char c; - - char *q = line; - - tmpbuf[ n_read - 1 ] = '\0'; - - while (p && (c = *p) && q < &line[ sizeof (line) - 1 ]) { - if (c == '<') { - /* Parse the magic priority number. */ - pri = 0; - while (isdigit (*(++p))) { - pri = 10 * pri + (*p - '0'); - } - if (pri & ~(LOG_FACMASK | LOG_PRIMASK)){ - pri = (LOG_USER | LOG_NOTICE); - } - } else if (c == '\n') { - *q++ = ' '; - } else if (iscntrl (c) && (c < 0177)) { - *q++ = '^'; - *q++ = c ^ 0100; - } else { - *q++ = c; - } - p++; - } - *q = '\0'; - p++; - /* Now log it */ - logMessage (pri, line); - } - RELEASE_BB_BUFFER (tmpbuf); - return n_read; -} - - -#ifdef BB_FEATURE_REMOTE_LOG -static void init_RemoteLog (void){ - - struct sockaddr_in remoteaddr; - struct hostent *hostinfo; - int len = sizeof(remoteaddr); - - memset(&remoteaddr, 0, len); - - remotefd = socket(AF_INET, SOCK_DGRAM, 0); - - if (remotefd < 0) { - error_msg_and_die("syslogd: cannot create socket"); - } - - hostinfo = xgethostbyname(RemoteHost); - - remoteaddr.sin_family = AF_INET; - remoteaddr.sin_addr = *(struct in_addr *) *hostinfo->h_addr_list; - remoteaddr.sin_port = htons(RemotePort); - - /* - Since we are using UDP sockets, connect just sets the default host and port - for future operations - */ - if ( 0 != (connect(remotefd, (struct sockaddr *) &remoteaddr, len))){ - error_msg_and_die("syslogd: cannot connect to remote host %s:%d", RemoteHost, RemotePort); - } - -} -#endif - -static void doSyslogd (void) __attribute__ ((noreturn)); -static void doSyslogd (void) -{ - struct sockaddr_un sunx; - socklen_t addrLength; - - - int sock_fd; - fd_set fds; - - /* Set up signal handlers. */ - signal (SIGINT, quit_signal); - signal (SIGTERM, quit_signal); - signal (SIGQUIT, quit_signal); - signal (SIGHUP, SIG_IGN); - signal (SIGCHLD, SIG_IGN); -#ifdef SIGCLD - signal (SIGCLD, SIG_IGN); -#endif - signal (SIGALRM, domark); - alarm (MarkInterval); - - /* Create the syslog file so realpath() can work. */ - if (realpath (_PATH_LOG, lfile) != NULL) - unlink (lfile); - - memset (&sunx, 0, sizeof (sunx)); - sunx.sun_family = AF_UNIX; - strncpy (sunx.sun_path, lfile, sizeof (sunx.sun_path)); - if ((sock_fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0) - perror_msg_and_die ("Couldn't get file descriptor for socket " _PATH_LOG); - - addrLength = sizeof (sunx.sun_family) + strlen (sunx.sun_path); - if ((bind (sock_fd, (struct sockaddr *) &sunx, addrLength)) || (listen (sock_fd, 5))) - perror_msg_and_die ("Could not connect to socket " _PATH_LOG); - - if (chmod (lfile, 0666) < 0) - perror_msg_and_die ("Could not set permission on " _PATH_LOG); - - FD_ZERO (&fds); - FD_SET (sock_fd, &fds); - -#ifdef BB_FEATURE_IPC_SYSLOG - if (circular_logging == TRUE ){ - ipcsyslog_init(); - } -#endif - - #ifdef BB_FEATURE_REMOTE_LOG - if (doRemoteLog == TRUE){ - init_RemoteLog(); - } - #endif - - logMessage (LOG_SYSLOG | LOG_INFO, "syslogd started: " BB_BANNER); - - for (;;) { - - fd_set readfds; - int n_ready; - int fd; - - memcpy (&readfds, &fds, sizeof (fds)); - - if ((n_ready = select (FD_SETSIZE, &readfds, NULL, NULL, NULL)) < 0) { - if (errno == EINTR) continue; /* alarm may have happened. */ - perror_msg_and_die ("select error"); - } - - for (fd = 0; (n_ready > 0) && (fd < FD_SETSIZE); fd++) { - if (FD_ISSET (fd, &readfds)) { - - --n_ready; - - if (fd == sock_fd) { - int conn; - - //printf("New Connection request.\n"); - if ((conn = accept (sock_fd, (struct sockaddr *) &sunx, &addrLength)) < 0) { - perror_msg_and_die ("accept error"); - } - - FD_SET(conn, &fds); - //printf("conn: %i, set_size: %i\n",conn,FD_SETSIZE); - } else { - //printf("Serving connection: %i\n",fd); - if ( serveConnection(fd) <= 0 ) { - close (fd); - FD_CLR(fd, &fds); - } - } /* fd == sock_fd */ - }/* FD_ISSET() */ - }/* for */ - } /* for main loop */ -} - -extern int syslogd_main(int argc, char **argv) -{ - int opt; - int doFork = TRUE; - - char *p; - - /* do normal option parsing */ - while ((opt = getopt(argc, argv, "m:nO:R:LC")) > 0) { - switch (opt) { - case 'm': - MarkInterval = atoi(optarg) * 60; - break; - case 'n': - doFork = FALSE; - break; - case 'O': - logFilePath = strdup(optarg); - break; -#ifdef BB_FEATURE_REMOTE_LOG - case 'R': - RemoteHost = strdup(optarg); - if ( (p = strchr(RemoteHost, ':'))){ - RemotePort = atoi(p+1); - *p = '\0'; - } - doRemoteLog = TRUE; - break; - case 'L': - local_logging = TRUE; - break; -#endif -#ifdef BB_FEATURE_IPC_SYSLOG - case 'C': - circular_logging = TRUE; - break; -#endif - default: - show_usage(); - } - } - -#ifdef BB_FEATURE_REMOTE_LOG - /* If they have not specified remote logging, then log locally */ - if (doRemoteLog == FALSE) - local_logging = TRUE; -#endif - - - /* Store away localhost's name before the fork */ - gethostname(LocalHostName, sizeof(LocalHostName)); - if ((p = strchr(LocalHostName, '.'))) { - *p++ = '\0'; - } - - umask(0); - - if (doFork == TRUE) { - if (daemon(0, 1) < 0) - perror_msg_and_die("daemon"); - } - doSyslogd(); - - return EXIT_SUCCESS; -} - -/* -Local Variables -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ diff --git a/tail.c b/tail.c deleted file mode 100644 index 5e5fbc14f..000000000 --- a/tail.c +++ /dev/null @@ -1,251 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini tail implementation for busybox - * - * - * Copyright (C) 2001 by Matt Kraai <kraai@alumni.carnegiemellon.edu> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - - -#include <fcntl.h> -#include <getopt.h> -#include <string.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/types.h> -#include "busybox.h" - -static const struct suffix_mult tail_suffixes[] = { - { "b", 512 }, - { "k", 1024 }, - { "m", 1048576 }, - { NULL, 0 } -}; - -static const int BYTES = 0; -static const int LINES = 1; - -static char *tailbuf; -static int taillen; -static int newline; - -static void tailbuf_append(char *buf, int len) -{ - tailbuf = xrealloc(tailbuf, taillen + len); - memcpy(tailbuf + taillen, buf, len); - taillen += len; -} - -static void tailbuf_trunc(void) -{ - char *s; - s = memchr(tailbuf, '\n', taillen); - memmove(tailbuf, s + 1, taillen - ((s + 1) - tailbuf)); - taillen -= (s + 1) - tailbuf; - newline = 0; -} - -int tail_main(int argc, char **argv) -{ - int from_top = 0, units = LINES, count = 10, sleep_period = 1; - int show_headers = 0, hide_headers = 0, follow = 0; - int *fds, nfiles = 0, status = EXIT_SUCCESS, nread, nwrite, seen = 0; - char *s, *start, *end, buf[BUFSIZ]; - int i, opt; - - while ((opt = getopt(argc, argv, "c:fhn:q:s:v")) > 0) { - switch (opt) { - case 'f': - follow = 1; - break; -#ifdef BB_FEATURE_FANCY_TAIL - case 'c': - units = BYTES; - /* FALLS THROUGH */ -#endif - case 'n': - count = parse_number(optarg, tail_suffixes); - if (count < 0) - count = -count; - if (optarg[0] == '+') - from_top = 1; - break; -#ifdef BB_FEATURE_FANCY_TAIL - case 'q': - hide_headers = 1; - break; - case 's': - sleep_period = parse_number(optarg, 0); - break; - case 'v': - show_headers = 1; - break; -#endif - default: - show_usage(); - } - } - - /* open all the files */ - fds = (int *)xmalloc(sizeof(int) * (argc - optind + 1)); - if (argc == optind) { - fds[nfiles++] = STDIN_FILENO; - argv[optind] = "standard input"; - } else { - for (i = optind; i < argc; i++) { - if (strcmp(argv[i], "-") == 0) { - fds[nfiles++] = STDIN_FILENO; - argv[i] = "standard input"; - } else if ((fds[nfiles++] = open(argv[i], O_RDONLY)) < 0) { - perror_msg("%s", argv[i]); - status = EXIT_FAILURE; - } - } - } - -#ifdef BB_FEATURE_FANCY_TAIL - /* tail the files */ - if (!from_top && units == BYTES) - tailbuf = xmalloc(count); -#endif - - for (i = 0; i < nfiles; i++) { - if (fds[i] == -1) - continue; - if (!count) { - lseek(fds[i], 0, SEEK_END); - continue; - } - seen = 0; - if (show_headers || (!hide_headers && nfiles > 1)) - printf("%s==> %s <==\n", i == 0 ? "" : "\n", argv[optind + i]); - while ((nread = safe_read(fds[i], buf, sizeof(buf))) > 0) { - if (from_top) { -#ifdef BB_FEATURE_FANCY_TAIL - if (units == BYTES) { - if (count - 1 <= seen) - nwrite = nread; - else if (count - 1 <= seen + nread) - nwrite = nread + seen - (count - 1); - else - nwrite = 0; - seen += nread; - } else { -#else - { -#endif - if (count - 1 <= seen) - nwrite = nread; - else { - nwrite = 0; - for (s = memchr(buf, '\n', nread); s != NULL; - s = memchr(s+1, '\n', nread - (s + 1 - buf))) { - if (count - 1 <= ++seen) { - nwrite = nread - (s + 1 - buf); - break; - } - } - } - } - if (full_write(STDOUT_FILENO, buf + nread - nwrite, - nwrite) < 0) { - perror_msg("write"); - status = EXIT_FAILURE; - break; - } - } else { -#ifdef BB_FEATURE_FANCY_TAIL - if (units == BYTES) { - if (nread < count) { - memmove(tailbuf, tailbuf + nread, count - nread); - memcpy(tailbuf + count - nread, buf, nread); - } else { - memcpy(tailbuf, buf + nread - count, count); - } - seen += nread; - } else { -#else - { -#endif - for (start = buf, end = memchr(buf, '\n', nread); - end != NULL; start = end+1, - end = memchr(start, '\n', nread - (start - buf))) { - if (newline && count <= seen) - tailbuf_trunc(); - tailbuf_append(start, end - start + 1); - seen++; - newline = 1; - } - if (newline && count <= seen && nread - (start - buf) > 0) - tailbuf_trunc(); - tailbuf_append(start, nread - (start - buf)); - } - } - } - - if (nread < 0) { - perror_msg("read"); - status = EXIT_FAILURE; - } - -#ifdef BB_FEATURE_FANCY_TAIL - if (!from_top && units == BYTES) { - if (count < seen) - seen = count; - if (full_write(STDOUT_FILENO, tailbuf + count - seen, seen) < 0) { - perror_msg("write"); - status = EXIT_FAILURE; - } - } -#endif - - if (!from_top && units == LINES) { - if (full_write(STDOUT_FILENO, tailbuf, taillen) < 0) { - perror_msg("write"); - status = EXIT_FAILURE; - } - } - - taillen = 0; - } - - while (follow) { - sleep(sleep_period); - - for (i = 0; i < nfiles; i++) { - if (fds[i] == -1) - continue; - - if ((nread = safe_read(fds[i], buf, sizeof(buf))) > 0) { - if (show_headers || (!hide_headers && nfiles > 1)) - printf("\n==> %s <==\n", argv[optind + i]); - - do { - full_write(STDOUT_FILENO, buf, nread); - } while ((nread = safe_read(fds[i], buf, sizeof(buf))) > 0); - } - - if (nread < 0) { - perror_msg("read"); - status = EXIT_FAILURE; - } - } - } - - return status; -} diff --git a/tar.c b/tar.c deleted file mode 100644 index f7a3da66f..000000000 --- a/tar.c +++ /dev/null @@ -1,745 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini tar implementation for busybox - * - * Modifed to use common extraction code used by ar, cpio, dpkg-deb, dpkg - * Glenn McGrath <bug1@optushome.com.au> - * - * Note, that as of BusyBox-0.43, tar has been completely rewritten from the - * ground up. It still has remnents of the old code lying about, but it is - * very different now (i.e., cleaner, less global variables, etc.) - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org> - * - * Based in part in the tar implementation in sash - * Copyright (c) 1999 by David I. Bell - * Permission is granted to use, distribute, or modify this source, - * provided that this copyright notice remains intact. - * Permission to distribute sash derived code under the GPL has been granted. - * - * Based in part on the tar implementation from busybox-0.28 - * Copyright (C) 1995 Bruce Perens - * This is free software under the GNU General Public License. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <fcntl.h> -#include <getopt.h> -#include <search.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <fnmatch.h> -#include <string.h> -#include <errno.h> -#include "busybox.h" - -#ifdef BB_FEATURE_TAR_CREATE - -/* Tar file constants */ -# define TAR_MAGIC "ustar" /* ustar and a null */ -# define TAR_VERSION " " /* Be compatable with GNU tar format */ - -# ifndef MAJOR -# define MAJOR(dev) (((dev)>>8)&0xff) -# define MINOR(dev) ((dev)&0xff) -# endif - -static const int TAR_BLOCK_SIZE = 512; -static const int TAR_MAGIC_LEN = 6; -static const int TAR_VERSION_LEN = 2; - -/* POSIX tar Header Block, from POSIX 1003.1-1990 */ -enum { NAME_SIZE = 100 }; /* because gcc won't let me use 'static const int' */ -struct TarHeader -{ /* byte offset */ - char name[NAME_SIZE]; /* 0-99 */ - char mode[8]; /* 100-107 */ - char uid[8]; /* 108-115 */ - char gid[8]; /* 116-123 */ - char size[12]; /* 124-135 */ - char mtime[12]; /* 136-147 */ - char chksum[8]; /* 148-155 */ - char typeflag; /* 156-156 */ - char linkname[NAME_SIZE]; /* 157-256 */ - char magic[6]; /* 257-262 */ - char version[2]; /* 263-264 */ - char uname[32]; /* 265-296 */ - char gname[32]; /* 297-328 */ - char devmajor[8]; /* 329-336 */ - char devminor[8]; /* 337-344 */ - char prefix[155]; /* 345-499 */ - char padding[12]; /* 500-512 (pad to exactly the TAR_BLOCK_SIZE) */ -}; -typedef struct TarHeader TarHeader; - -/* -** writeTarFile(), writeFileToTarball(), and writeTarHeader() are -** the only functions that deal with the HardLinkInfo structure. -** Even these functions use the xxxHardLinkInfo() functions. -*/ -typedef struct HardLinkInfo HardLinkInfo; -struct HardLinkInfo -{ - HardLinkInfo *next; /* Next entry in list */ - dev_t dev; /* Device number */ - ino_t ino; /* Inode number */ - short linkCount; /* (Hard) Link Count */ - char name[1]; /* Start of filename (must be last) */ -}; - -/* Some info to be carried along when creating a new tarball */ -struct TarBallInfo -{ - char* fileName; /* File name of the tarball */ - int tarFd; /* Open-for-write file descriptor - for the tarball */ - struct stat statBuf; /* Stat info for the tarball, letting - us know the inode and device that the - tarball lives, so we can avoid trying - to include the tarball into itself */ - int verboseFlag; /* Whether to print extra stuff or not */ - char** excludeList; /* List of files to not include */ - HardLinkInfo *hlInfoHead; /* Hard Link Tracking Information */ - HardLinkInfo *hlInfo; /* Hard Link Info for the current file */ -}; -typedef struct TarBallInfo TarBallInfo; - -/* A nice enum with all the possible tar file content types */ -enum TarFileType -{ - REGTYPE = '0', /* regular file */ - REGTYPE0 = '\0', /* regular file (ancient bug compat)*/ - LNKTYPE = '1', /* hard link */ - SYMTYPE = '2', /* symbolic link */ - CHRTYPE = '3', /* character special */ - BLKTYPE = '4', /* block special */ - DIRTYPE = '5', /* directory */ - FIFOTYPE = '6', /* FIFO special */ - CONTTYPE = '7', /* reserved */ - GNULONGLINK = 'K', /* GNU long (>100 chars) link name */ - GNULONGNAME = 'L', /* GNU long (>100 chars) file name */ -}; -typedef enum TarFileType TarFileType; - -/* Might be faster (and bigger) if the dev/ino were stored in numeric order;) */ -static void -addHardLinkInfo (HardLinkInfo **hlInfoHeadPtr, dev_t dev, ino_t ino, - short linkCount, const char *name) -{ - /* Note: hlInfoHeadPtr can never be NULL! */ - HardLinkInfo *hlInfo; - - hlInfo = (HardLinkInfo *)xmalloc(sizeof(HardLinkInfo)+strlen(name)+1); - if (hlInfo) { - hlInfo->next = *hlInfoHeadPtr; - *hlInfoHeadPtr = hlInfo; - hlInfo->dev = dev; - hlInfo->ino = ino; - hlInfo->linkCount = linkCount; - strcpy(hlInfo->name, name); - } - return; -} - -static void -freeHardLinkInfo (HardLinkInfo **hlInfoHeadPtr) -{ - HardLinkInfo *hlInfo = NULL; - HardLinkInfo *hlInfoNext = NULL; - - if (hlInfoHeadPtr) { - hlInfo = *hlInfoHeadPtr; - while (hlInfo) { - hlInfoNext = hlInfo->next; - free(hlInfo); - hlInfo = hlInfoNext; - } - *hlInfoHeadPtr = NULL; - } - return; -} - -/* Might be faster (and bigger) if the dev/ino were stored in numeric order;) */ -static HardLinkInfo * -findHardLinkInfo (HardLinkInfo *hlInfo, dev_t dev, ino_t ino) -{ - while(hlInfo) { - if ((ino == hlInfo->ino) && (dev == hlInfo->dev)) - break; - hlInfo = hlInfo->next; - } - return(hlInfo); -} - -/* Put an octal string into the specified buffer. - * The number is zero and space padded and possibly null padded. - * Returns TRUE if successful. */ -static int putOctal (char *cp, int len, long value) -{ - int tempLength; - char tempBuffer[32]; - char *tempString = tempBuffer; - - /* Create a string of the specified length with an initial space, - * leading zeroes and the octal number, and a trailing null. */ - sprintf (tempString, "%0*lo", len - 1, value); - - /* If the string is too large, suppress the leading space. */ - tempLength = strlen (tempString) + 1; - if (tempLength > len) { - tempLength--; - tempString++; - } - - /* If the string is still too large, suppress the trailing null. */ - if (tempLength > len) - tempLength--; - - /* If the string is still too large, fail. */ - if (tempLength > len) - return FALSE; - - /* Copy the string to the field. */ - memcpy (cp, tempString, len); - - return TRUE; -} - -/* Write out a tar header for the specified file/directory/whatever */ -static int -writeTarHeader(struct TarBallInfo *tbInfo, const char *header_name, - const char *real_name, struct stat *statbuf) -{ - long chksum=0; - struct TarHeader header; - const unsigned char *cp = (const unsigned char *) &header; - ssize_t size = sizeof(struct TarHeader); - - memset( &header, 0, size); - - strncpy(header.name, header_name, sizeof(header.name)); - - putOctal(header.mode, sizeof(header.mode), statbuf->st_mode); - putOctal(header.uid, sizeof(header.uid), statbuf->st_uid); - putOctal(header.gid, sizeof(header.gid), statbuf->st_gid); - putOctal(header.size, sizeof(header.size), 0); /* Regular file size is handled later */ - putOctal(header.mtime, sizeof(header.mtime), statbuf->st_mtime); - strncpy(header.magic, TAR_MAGIC TAR_VERSION, - TAR_MAGIC_LEN + TAR_VERSION_LEN ); - - /* Enter the user and group names (default to root if it fails) */ - my_getpwuid(header.uname, statbuf->st_uid); - if (! *header.uname) - strcpy(header.uname, "root"); - my_getgrgid(header.gname, statbuf->st_gid); - if (! *header.uname) - strcpy(header.uname, "root"); - - if (tbInfo->hlInfo) { - /* This is a hard link */ - header.typeflag = LNKTYPE; - strncpy(header.linkname, tbInfo->hlInfo->name, sizeof(header.linkname)); - } else if (S_ISLNK(statbuf->st_mode)) { - char *lpath = xreadlink(real_name); - if (!lpath) /* Already printed err msg inside xreadlink() */ - return ( FALSE); - header.typeflag = SYMTYPE; - strncpy(header.linkname, lpath, sizeof(header.linkname)); - free(lpath); - } else if (S_ISDIR(statbuf->st_mode)) { - header.typeflag = DIRTYPE; - strncat(header.name, "/", sizeof(header.name)); - } else if (S_ISCHR(statbuf->st_mode)) { - header.typeflag = CHRTYPE; - putOctal(header.devmajor, sizeof(header.devmajor), MAJOR(statbuf->st_rdev)); - putOctal(header.devminor, sizeof(header.devminor), MINOR(statbuf->st_rdev)); - } else if (S_ISBLK(statbuf->st_mode)) { - header.typeflag = BLKTYPE; - putOctal(header.devmajor, sizeof(header.devmajor), MAJOR(statbuf->st_rdev)); - putOctal(header.devminor, sizeof(header.devminor), MINOR(statbuf->st_rdev)); - } else if (S_ISFIFO(statbuf->st_mode)) { - header.typeflag = FIFOTYPE; - } else if (S_ISREG(statbuf->st_mode)) { - header.typeflag = REGTYPE; - putOctal(header.size, sizeof(header.size), statbuf->st_size); - } else { - error_msg("%s: Unknown file type", real_name); - return ( FALSE); - } - - /* Calculate and store the checksum (i.e., the sum of all of the bytes of - * the header). The checksum field must be filled with blanks for the - * calculation. The checksum field is formatted differently from the - * other fields: it has [6] digits, a null, then a space -- rather than - * digits, followed by a null like the other fields... */ - memset(header.chksum, ' ', sizeof(header.chksum)); - cp = (const unsigned char *) &header; - while (size-- > 0) - chksum += *cp++; - putOctal(header.chksum, 7, chksum); - - /* Now write the header out to disk */ - if ((size=full_write(tbInfo->tarFd, (char*)&header, sizeof(struct TarHeader))) < 0) { - error_msg(io_error, real_name, strerror(errno)); - return ( FALSE); - } - /* Pad the header up to the tar block size */ - for (; size<TAR_BLOCK_SIZE; size++) { - write(tbInfo->tarFd, "\0", 1); - } - /* Now do the verbose thing (or not) */ - if (tbInfo->verboseFlag==TRUE) { - FILE *vbFd = stdout; - if (tbInfo->tarFd == fileno(stdout)) // If the archive goes to stdout, verbose to stderr - vbFd = stderr; - fprintf(vbFd, "%s\n", header.name); - } - - return ( TRUE); -} - -static int exclude_file(char **excluded_files, const char *file) -{ - int i; - - if (excluded_files == NULL) - return 0; - - for (i = 0; excluded_files[i] != NULL; i++) { - if (excluded_files[i][0] == '/') { - if (fnmatch(excluded_files[i], file, - FNM_PATHNAME | FNM_LEADING_DIR) == 0) - return 1; - } else { - const char *p; - - for (p = file; p[0] != '\0'; p++) { - if ((p == file || p[-1] == '/') && p[0] != '/' && - fnmatch(excluded_files[i], p, - FNM_PATHNAME | FNM_LEADING_DIR) == 0) - return 1; - } - } - } - - return 0; -} - -static int writeFileToTarball(const char *fileName, struct stat *statbuf, void* userData) -{ - struct TarBallInfo *tbInfo = (struct TarBallInfo *)userData; - const char *header_name; - - /* - ** Check to see if we are dealing with a hard link. - ** If so - - ** Treat the first occurance of a given dev/inode as a file while - ** treating any additional occurances as hard links. This is done - ** by adding the file information to the HardLinkInfo linked list. - */ - tbInfo->hlInfo = NULL; - if (statbuf->st_nlink > 1) { - tbInfo->hlInfo = findHardLinkInfo(tbInfo->hlInfoHead, statbuf->st_dev, - statbuf->st_ino); - if (tbInfo->hlInfo == NULL) - addHardLinkInfo (&tbInfo->hlInfoHead, statbuf->st_dev, - statbuf->st_ino, statbuf->st_nlink, fileName); - } - - /* It is against the rules to archive a socket */ - if (S_ISSOCK(statbuf->st_mode)) { - error_msg("%s: socket ignored", fileName); - return( TRUE); - } - - /* It is a bad idea to store the archive we are in the process of creating, - * so check the device and inode to be sure that this particular file isn't - * the new tarball */ - if (tbInfo->statBuf.st_dev == statbuf->st_dev && - tbInfo->statBuf.st_ino == statbuf->st_ino) { - error_msg("%s: file is the archive; skipping", fileName); - return( TRUE); - } - - header_name = fileName; - while (header_name[0] == '/') { - static int alreadyWarned=FALSE; - if (alreadyWarned==FALSE) { - error_msg("Removing leading '/' from member names"); - alreadyWarned=TRUE; - } - header_name++; - } - - if (strlen(fileName) >= NAME_SIZE) { - error_msg(name_longer_than_foo, NAME_SIZE); - return ( TRUE); - } - - if (header_name[0] == '\0') - return TRUE; - -# if defined BB_FEATURE_TAR_EXCLUDE - if (exclude_file(tbInfo->excludeList, header_name)) { - return SKIP; - } -# endif //BB_FEATURE_TAR_EXCLUDE - - if (writeTarHeader(tbInfo, header_name, fileName, statbuf)==FALSE) { - return( FALSE); - } - - /* Now, if the file is a regular file, copy it out to the tarball */ - if ((tbInfo->hlInfo == NULL) - && (S_ISREG(statbuf->st_mode))) { - int inputFileFd; - char buffer[BUFSIZ]; - ssize_t size=0, readSize=0; - - /* open the file we want to archive, and make sure all is well */ - if ((inputFileFd = open(fileName, O_RDONLY)) < 0) { - error_msg("%s: Cannot open: %s", fileName, strerror(errno)); - return( FALSE); - } - - /* write the file to the archive */ - while ( (size = full_read(inputFileFd, buffer, sizeof(buffer))) > 0 ) { - if (full_write(tbInfo->tarFd, buffer, size) != size ) { - /* Output file seems to have a problem */ - error_msg(io_error, fileName, strerror(errno)); - return( FALSE); - } - readSize+=size; - } - if (size == -1) { - error_msg(io_error, fileName, strerror(errno)); - return( FALSE); - } - /* Pad the file up to the tar block size */ - for (; (readSize%TAR_BLOCK_SIZE) != 0; readSize++) { - write(tbInfo->tarFd, "\0", 1); - } - close( inputFileFd); - } - - return( TRUE); -} - -static int writeTarFile(const char* tarName, int verboseFlag, char **argv, - char** excludeList) -{ - int tarFd=-1; - int errorFlag=FALSE; - ssize_t size; - struct TarBallInfo tbInfo; - tbInfo.verboseFlag = verboseFlag; - tbInfo.hlInfoHead = NULL; - - /* Make sure there is at least one file to tar up. */ - if (*argv == NULL) - error_msg_and_die("Cowardly refusing to create an empty archive"); - - /* Open the tar file for writing. */ - if (!strcmp(tarName, "-")) - tbInfo.tarFd = fileno(stdout); - else - tbInfo.tarFd = open (tarName, O_WRONLY | O_CREAT | O_TRUNC, 0644); - if (tbInfo.tarFd < 0) { - perror_msg( "Error opening '%s'", tarName); - freeHardLinkInfo(&tbInfo.hlInfoHead); - return ( FALSE); - } - tbInfo.excludeList=excludeList; - /* Store the stat info for the tarball's file, so - * can avoid including the tarball into itself.... */ - if (fstat(tbInfo.tarFd, &tbInfo.statBuf) < 0) - error_msg_and_die(io_error, tarName, strerror(errno)); - - /* Read the directory/files and iterate over them one at a time */ - while (*argv != NULL) { - if (recursive_action(*argv++, TRUE, FALSE, FALSE, - writeFileToTarball, writeFileToTarball, - (void*) &tbInfo) == FALSE) { - errorFlag = TRUE; - } - } - /* Write two empty blocks to the end of the archive */ - for (size=0; size<(2*TAR_BLOCK_SIZE); size++) { - write(tbInfo.tarFd, "\0", 1); - } - - /* To be pedantically correct, we would check if the tarball - * is smaller than 20 tar blocks, and pad it if it was smaller, - * but that isn't necessary for GNU tar interoperability, and - * so is considered a waste of space */ - - /* Hang up the tools, close up shop, head home */ - close(tarFd); - if (errorFlag == TRUE) { - error_msg("Error exit delayed from previous errors"); - freeHardLinkInfo(&tbInfo.hlInfoHead); - return(FALSE); - } - freeHardLinkInfo(&tbInfo.hlInfoHead); - return( TRUE); -} -#endif //tar_create - -void append_file_to_list(const char *new_name, char ***list, int *list_count) -{ - *list = realloc(*list, sizeof(char *) * (*list_count + 2)); - (*list)[*list_count] = xstrdup(new_name); - (*list_count)++; - (*list)[*list_count] = NULL; -} - -void append_file_list_to_list(char *filename, char ***name_list, int *num_of_entries) -{ - FILE *src_stream; - char *line; - char *line_ptr; - - src_stream = xfopen(filename, "r"); - while ((line = get_line_from_file(src_stream)) != NULL) { - line_ptr = last_char_is(line, '\n'); - if (line_ptr) { - *line_ptr = '\0'; - } - append_file_to_list(line, name_list, num_of_entries); - free(line); - } - fclose(src_stream); -} - -#ifdef BB_FEATURE_TAR_EXCLUDE -/* - * Create a list of names that are in the include list AND NOT in the exclude lists - */ -char **list_and_not_list(char **include_list, char **exclude_list) -{ - char **new_include_list = NULL; - int new_include_count = 0; - int include_count = 0; - int exclude_count; - - if (include_list == NULL) { - return(NULL); - } - - while (include_list[include_count] != NULL) { - int found = FALSE; - exclude_count = 0; - while (exclude_list[exclude_count] != NULL) { - if (strcmp(include_list[include_count], exclude_list[exclude_count]) == 0) { - found = TRUE; - break; - } - exclude_count++; - } - - if (found == FALSE) { - new_include_list = realloc(new_include_list, sizeof(char *) * (include_count + 2)); - new_include_list[new_include_count] = include_list[include_count]; - new_include_count++; - } else { - free(include_list[include_count]); - } - include_count++; - } - new_include_list[new_include_count] = NULL; - return(new_include_list); -} -#endif - -int tar_main(int argc, char **argv) -{ - enum untar_funct_e { - /* These are optional */ - untar_from_file = 1, - untar_from_stdin = 2, - untar_unzip = 4, - /* Require one and only one of these */ - untar_list = 8, - untar_create = 16, - untar_extract = 32 - }; - - FILE *src_stream = NULL; - FILE *uncompressed_stream = NULL; - char **include_list = NULL; - char **exclude_list = NULL; - char *src_filename = NULL; - char *dst_prefix = NULL; - char *file_list_name = NULL; - int opt; - unsigned short untar_funct = 0; - unsigned short untar_funct_required = 0; - unsigned short extract_function = 0; - int include_list_count = 0; - int exclude_list_count = 0; - int gunzip_pid; - int gz_fd = 0; - - if (argc < 2) { - show_usage(); - } - - /* Prepend '-' to the first argument if required */ - if (argv[1][0] != '-') { - char *tmp = xmalloc(strlen(argv[1]) + 2); - tmp[0] = '-'; - strcpy(tmp + 1, argv[1]); - argv[1] = tmp; - } - - while ((opt = getopt(argc, argv, "ctxT:X:C:f:Opvz")) != -1) { - switch (opt) { - - /* One and only one of these is required */ - case 'c': - untar_funct_required |= untar_create; - break; - case 't': - untar_funct_required |= untar_list; - extract_function |= extract_list |extract_unconditional; - break; - case 'x': - untar_funct_required |= untar_extract; - extract_function |= (extract_all_to_fs | extract_unconditional | extract_create_leading_dirs); - break; - - /* These are optional */ - /* Exclude or Include files listed in <filename>*/ -#ifdef BB_FEATURE_TAR_EXCLUDE - case 'X': - append_file_list_to_list(optarg, &exclude_list, &exclude_list_count); - break; -#endif - case 'T': - // by default a list is an include list - append_file_list_to_list(optarg, &include_list, &include_list_count); - break; - - case 'C': // Change to dir <optarg> - /* Make sure dst_prefix ends in a '/' */ - dst_prefix = concat_path_file(optarg, "/"); - break; - case 'f': // archive filename - if (strcmp(optarg, "-") == 0) { - // Untar from stdin to stdout - untar_funct |= untar_from_stdin; - } else { - untar_funct |= untar_from_file; - src_filename = xstrdup(optarg); - } - break; - case 'O': - extract_function |= extract_to_stdout; - break; - case 'p': - break; - case 'v': - if (extract_function & extract_list) { - extract_function |= extract_verbose_list; - } - extract_function |= extract_list; - break; -#ifdef BB_FEATURE_TAR_GZIP - case 'z': - untar_funct |= untar_unzip; - break; -#endif - default: - show_usage(); - } - } - - /* Make sure the valid arguments were passed */ - if (untar_funct_required == 0) { - error_msg_and_die("You must specify one of the `-ctx' options"); - } - if ((untar_funct_required != untar_create) && - (untar_funct_required != untar_extract) && - (untar_funct_required != untar_list)) { - error_msg_and_die("You may not specify more than one `ctx' option."); - } - untar_funct |= untar_funct_required; - - /* Setup an array of filenames to work with */ - while (optind < argc) { - append_file_to_list(argv[optind], &include_list, &include_list_count); - optind++; - } - - if (extract_function & (extract_list | extract_all_to_fs)) { - if (dst_prefix == NULL) { - dst_prefix = xstrdup("./"); - } - - /* Setup the source of the tar data */ - if (untar_funct & untar_from_file) { - src_stream = xfopen(src_filename, "r"); - } else { - src_stream = stdin; - } -#ifdef BB_FEATURE_TAR_GZIP - /* Get a binary tree of all the tar file headers */ - if (untar_funct & untar_unzip) { - uncompressed_stream = gz_open(src_stream, &gunzip_pid); - } else -#endif // BB_FEATURE_TAR_GZIP - uncompressed_stream = src_stream; - - /* extract or list archive */ - unarchive(uncompressed_stream, stdout, &get_header_tar, extract_function, dst_prefix, include_list, exclude_list); - fclose(uncompressed_stream); - } -#ifdef BB_FEATURE_TAR_CREATE - /* create an archive */ - else if (untar_funct & untar_create) { - int verboseFlag = FALSE; - -#ifdef BB_FEATURE_TAR_GZIP - if (untar_funct && untar_unzip) { - error_msg_and_die("Creation of compressed tarfile not internally support by tar, pipe to busybox gunzip"); - } -#endif // BB_FEATURE_TAR_GZIP - if (extract_function & extract_verbose_list) { - verboseFlag = TRUE; - } - writeTarFile(src_filename, verboseFlag, &argv[argc - 1], include_list); - } -#endif // BB_FEATURE_TAR_CREATE - - /* Cleanups */ -#ifdef BB_FEATURE_TAR_GZIP - if (untar_funct & untar_unzip) { - fclose(src_stream); - close(gz_fd); - gz_close(gunzip_pid); - } -#endif // BB_FEATURE_TAR_GZIP - if (src_filename) { - free(src_filename); - } - if (file_list_name) { - free(file_list_name); - } - return(EXIT_SUCCESS); -} diff --git a/tee.c b/tee.c deleted file mode 100644 index 64a0922b7..000000000 --- a/tee.c +++ /dev/null @@ -1,67 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini tee implementation for busybox - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Matt Kraai <kraai@alumni.carnegiemellon.edu> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include "busybox.h" -#include <getopt.h> -#include <stdio.h> - -int -tee_main(int argc, char **argv) -{ - char *mode = "w"; - int c, i, status = 0, nfiles = 0; - FILE **files; - - while ((c = getopt(argc, argv, "a")) != EOF) { - switch (c) { - case 'a': - mode = "a"; - break; - default: - show_usage(); - } - } - - files = (FILE **)xmalloc(sizeof(FILE *) * (argc - optind + 1)); - files[nfiles++] = stdout; - while (optind < argc) { - if ((files[nfiles++] = wfopen(argv[optind++], mode)) == NULL) { - nfiles--; - status = 1; - } - } - - while ((c = getchar()) != EOF) - for (i = 0; i < nfiles; i++) - putc(c, files[i]); - - return status; -} - -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ diff --git a/telnet.c b/telnet.c deleted file mode 100644 index ce82a0ee8..000000000 --- a/telnet.c +++ /dev/null @@ -1,711 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * telnet implementation for busybox - * - * Author: Tomi Ollila <too@iki.fi> - * Copyright (C) 1994-2000 by Tomi Ollila - * - * Created: Thu Apr 7 13:29:41 1994 too - * Last modified: Fri Jun 9 14:34:24 2000 too - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * HISTORY - * Revision 3.1 1994/04/17 11:31:54 too - * initial revision - * Modified 2000/06/13 for inclusion into BusyBox by Erik Andersen - * <andersen@lineo.com> - * Modified 2001/05/07 to add ability to pass TTYPE to remote host by Jim McQuillan - * <jam@ltsp.org> - * - */ - -#include <termios.h> -#include <unistd.h> -#include <errno.h> -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <signal.h> -#include <arpa/telnet.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <netdb.h> -#include "busybox.h" - -#if 0 -static const int DOTRACE = 1; -#endif - -#ifdef DOTRACE -#include <arpa/inet.h> /* for inet_ntoa()... */ -#define TRACE(x, y) do { if (x) printf y; } while (0) -#else -#define TRACE(x, y) -#endif - -#if 0 -#define USE_POLL -#include <sys/poll.h> -#else -#include <sys/time.h> -#endif - -#define DATABUFSIZE 128 -#define IACBUFSIZE 128 - -static const int CHM_TRY = 0; -static const int CHM_ON = 1; -static const int CHM_OFF = 2; - -static const int UF_ECHO = 0x01; -static const int UF_SGA = 0x02; - -enum { - TS_0 = 1, - TS_IAC = 2, - TS_OPT = 3, - TS_SUB1 = 4, - TS_SUB2 = 5, -}; - -#define WriteCS(fd, str) write(fd, str, sizeof str -1) - -typedef unsigned char byte; - -/* use globals to reduce size ??? */ /* test this hypothesis later */ -static struct Globalvars { - int netfd; /* console fd:s are 0 and 1 (and 2) */ - /* same buffer used both for network and console read/write */ - char buf[DATABUFSIZE]; /* allocating so static size is smaller */ - byte telstate; /* telnet negotiation state from network input */ - byte telwish; /* DO, DONT, WILL, WONT */ - byte charmode; - byte telflags; - byte gotsig; - /* buffer to handle telnet negotiations */ - char iacbuf[IACBUFSIZE]; - short iaclen; /* could even use byte */ - struct termios termios_def; - struct termios termios_raw; -} G; - -#define xUSE_GLOBALVAR_PTR /* xUSE... -> don't use :D (makes smaller code) */ - -#ifdef USE_GLOBALVAR_PTR -struct Globalvars * Gptr; -#define G (*Gptr) -#else -static struct Globalvars G; -#endif - -static inline void iacflush() -{ - write(G.netfd, G.iacbuf, G.iaclen); - G.iaclen = 0; -} - -/* Function prototypes */ -static int getport(char * p); -static struct in_addr getserver(char * p); -static int create_socket(); -static void setup_sockaddr_in(struct sockaddr_in * addr, int port); -static int remote_connect(struct in_addr addr, int port); -static void rawmode(); -static void cookmode(); -static void do_linemode(); -static void will_charmode(); -static void telopt(byte c); -static int subneg(byte c); -#if 0 -static int local_bind(int port); -#endif - -/* Some globals */ -static int one = 1; - -#ifdef BB_FEATURE_TELNET_TTYPE -static char *ttype; -#endif - -static void doexit(int ev) -{ - cookmode(); - exit(ev); -} - -static void conescape() -{ - char b; - - if (G.gotsig) /* came from line mode... go raw */ - rawmode(); - - WriteCS(1, "\r\nConsole escape. Commands are:\r\n\n" - " l go to line mode\r\n" - " c go to character mode\r\n" - " z suspend telnet\r\n" - " e exit telnet\r\n"); - - if (read(0, &b, 1) <= 0) - doexit(1); - - switch (b) - { - case 'l': - if (!G.gotsig) - { - do_linemode(); - goto rrturn; - } - break; - case 'c': - if (G.gotsig) - { - will_charmode(); - goto rrturn; - } - break; - case 'z': - cookmode(); - kill(0, SIGTSTP); - rawmode(); - break; - case 'e': - doexit(0); - } - - WriteCS(1, "continuing...\r\n"); - - if (G.gotsig) - cookmode(); - - rrturn: - G.gotsig = 0; - -} -static void handlenetoutput(int len) -{ - /* here we could do smart tricks how to handle 0xFF:s in output - * stream like writing twice every sequence of FF:s (thus doing - * many write()s. But I think interactive telnet application does - * not need to be 100% 8-bit clean, so changing every 0xff:s to - * 0x7f:s */ - - int i; - byte * p = G.buf; - - for (i = len; i > 0; i--, p++) - { - if (*p == 0x1d) - { - conescape(); - return; - } - if (*p == 0xff) - *p = 0x7f; - } - write(G.netfd, G.buf, len); -} - - -static void handlenetinput(int len) -{ - int i; - int cstart = 0; - - for (i = 0; i < len; i++) - { - byte c = G.buf[i]; - - if (G.telstate == 0) /* most of the time state == 0 */ - { - if (c == IAC) - { - cstart = i; - G.telstate = TS_IAC; - } - } - else - switch (G.telstate) - { - case TS_0: - if (c == IAC) - G.telstate = TS_IAC; - else - G.buf[cstart++] = c; - break; - - case TS_IAC: - if (c == IAC) /* IAC IAC -> 0xFF */ - { - G.buf[cstart++] = c; - G.telstate = TS_0; - break; - } - /* else */ - switch (c) - { - case SB: - G.telstate = TS_SUB1; - break; - case DO: - case DONT: - case WILL: - case WONT: - G.telwish = c; - G.telstate = TS_OPT; - break; - default: - G.telstate = TS_0; /* DATA MARK must be added later */ - } - break; - case TS_OPT: /* WILL, WONT, DO, DONT */ - telopt(c); - G.telstate = TS_0; - break; - case TS_SUB1: /* Subnegotiation */ - case TS_SUB2: /* Subnegotiation */ - if (subneg(c) == TRUE) - G.telstate = TS_0; - break; - } - } - if (G.telstate) - { - if (G.iaclen) iacflush(); - if (G.telstate == TS_0) G.telstate = 0; - - len = cstart; - } - - if (len) - write(1, G.buf, len); -} - - -/* ******************************* */ - -static inline void putiac(int c) -{ - G.iacbuf[G.iaclen++] = c; -} - - -static void putiac2(byte wwdd, byte c) -{ - if (G.iaclen + 3 > IACBUFSIZE) - iacflush(); - - putiac(IAC); - putiac(wwdd); - putiac(c); -} - -#if 0 -static void putiac1(byte c) -{ - if (G.iaclen + 2 > IACBUFSIZE) - iacflush(); - - putiac(IAC); - putiac(c); -} -#endif - -#ifdef BB_FEATURE_TELNET_TTYPE -static void putiac_subopt(byte c, char *str) -{ - int len = strlen(str) + 6; // ( 2 + 1 + 1 + strlen + 2 ) - - if (G.iaclen + len > IACBUFSIZE) - iacflush(); - - putiac(IAC); - putiac(SB); - putiac(c); - putiac(0); - - while(*str) - putiac(*str++); - - putiac(IAC); - putiac(SE); -} -#endif - -/* void putiacstring (subneg strings) */ - -/* ******************************* */ - -static char const escapecharis[] = "\r\nEscape character is "; - -static void setConMode() -{ - if (G.telflags & UF_ECHO) - { - if (G.charmode == CHM_TRY) { - G.charmode = CHM_ON; - printf("\r\nEntering character mode%s'^]'.\r\n", escapecharis); - rawmode(); - } - } - else - { - if (G.charmode != CHM_OFF) { - G.charmode = CHM_OFF; - printf("\r\nEntering line mode%s'^C'.\r\n", escapecharis); - cookmode(); - } - } -} - -/* ******************************* */ - -static void will_charmode() -{ - G.charmode = CHM_TRY; - G.telflags |= (UF_ECHO | UF_SGA); - setConMode(); - - putiac2(DO, TELOPT_ECHO); - putiac2(DO, TELOPT_SGA); - iacflush(); -} - -static void do_linemode() -{ - G.charmode = CHM_TRY; - G.telflags &= ~(UF_ECHO | UF_SGA); - setConMode(); - - putiac2(DONT, TELOPT_ECHO); - putiac2(DONT, TELOPT_SGA); - iacflush(); -} - -/* ******************************* */ - -static inline void to_notsup(char c) -{ - if (G.telwish == WILL) putiac2(DONT, c); - else if (G.telwish == DO) putiac2(WONT, c); -} - -static inline void to_echo() -{ - /* if server requests ECHO, don't agree */ - if (G.telwish == DO) { putiac2(WONT, TELOPT_ECHO); return; } - else if (G.telwish == DONT) return; - - if (G.telflags & UF_ECHO) - { - if (G.telwish == WILL) - return; - } - else - if (G.telwish == WONT) - return; - - if (G.charmode != CHM_OFF) - G.telflags ^= UF_ECHO; - - if (G.telflags & UF_ECHO) - putiac2(DO, TELOPT_ECHO); - else - putiac2(DONT, TELOPT_ECHO); - - setConMode(); - WriteCS(1, "\r\n"); /* sudden modec */ -} - -static inline void to_sga() -{ - /* daemon always sends will/wont, client do/dont */ - - if (G.telflags & UF_SGA) - { - if (G.telwish == WILL) - return; - } - else - if (G.telwish == WONT) - return; - - if ((G.telflags ^= UF_SGA) & UF_SGA) /* toggle */ - putiac2(DO, TELOPT_SGA); - else - putiac2(DONT, TELOPT_SGA); - - return; -} - -#ifdef BB_FEATURE_TELNET_TTYPE -static inline void to_ttype() -{ - /* Tell server we will (or won't) do TTYPE */ - - if(ttype) - putiac2(WILL, TELOPT_TTYPE); - else - putiac2(WONT, TELOPT_TTYPE); - - return; -} -#endif - -static void telopt(byte c) -{ - switch (c) - { - case TELOPT_ECHO: to_echo(c); break; - case TELOPT_SGA: to_sga(c); break; -#ifdef BB_FEATURE_TELNET_TTYPE - case TELOPT_TTYPE: to_ttype(c); break; -#endif - default: to_notsup(c); break; - } -} - - -/* ******************************* */ - -/* subnegotiation -- ignore all (except TTYPE) */ - -static int subneg(byte c) -{ - switch (G.telstate) - { - case TS_SUB1: - if (c == IAC) - G.telstate = TS_SUB2; -#ifdef BB_FEATURE_TELNET_TTYPE - else - if (c == TELOPT_TTYPE) - putiac_subopt(TELOPT_TTYPE,ttype); -#endif - break; - case TS_SUB2: - if (c == SE) - return TRUE; - G.telstate = TS_SUB1; - /* break; */ - } - return FALSE; -} - -/* ******************************* */ - -static void fgotsig(int sig) -{ - G.gotsig = sig; -} - - -static void rawmode() -{ - tcsetattr(0, TCSADRAIN, &G.termios_raw); -} - -static void cookmode() -{ - tcsetattr(0, TCSADRAIN, &G.termios_def); -} - -extern int telnet_main(int argc, char** argv) -{ - struct in_addr host; - int port; - int len; -#ifdef USE_POLL - struct pollfd ufds[2]; -#else - fd_set readfds; - int maxfd; -#endif - -#ifdef BB_FEATURE_TELNET_TTYPE - ttype = getenv("TERM"); -#endif - - memset(&G, 0, sizeof G); - - if (tcgetattr(0, &G.termios_def) < 0) - exit(1); - - G.termios_raw = G.termios_def; - cfmakeraw(&G.termios_raw); - - if (argc < 2) show_usage(); - port = (argc > 2)? getport(argv[2]): 23; - - host = getserver(argv[1]); - - G.netfd = remote_connect(host, port); - - signal(SIGINT, fgotsig); - -#ifdef USE_POLL - ufds[0].fd = 0; ufds[1].fd = G.netfd; - ufds[0].events = ufds[1].events = POLLIN; -#else - FD_ZERO(&readfds); - FD_SET(0, &readfds); - FD_SET(G.netfd, &readfds); - maxfd = G.netfd + 1; -#endif - - while (1) - { -#ifndef USE_POLL - fd_set rfds = readfds; - - switch (select(maxfd, &rfds, NULL, NULL, NULL)) -#else - switch (poll(ufds, 2, -1)) -#endif - { - case 0: - /* timeout */ - case -1: - /* error, ignore and/or log something, bay go to loop */ - if (G.gotsig) - conescape(); - else - sleep(1); - break; - default: - -#ifdef USE_POLL - if (ufds[0].revents) /* well, should check POLLIN, but ... */ -#else - if (FD_ISSET(0, &rfds)) -#endif - { - len = read(0, G.buf, DATABUFSIZE); - - if (len <= 0) - doexit(0); - - TRACE(0, ("Read con: %d\n", len)); - - handlenetoutput(len); - } - -#ifdef USE_POLL - if (ufds[1].revents) /* well, should check POLLIN, but ... */ -#else - if (FD_ISSET(G.netfd, &rfds)) -#endif - { - len = read(G.netfd, G.buf, DATABUFSIZE); - - if (len <= 0) - { - WriteCS(1, "Connection closed by foreign host.\r\n"); - doexit(1); - } - TRACE(0, ("Read netfd (%d): %d\n", G.netfd, len)); - - handlenetinput(len); - } - } - } -} - -static int getport(char * p) -{ - unsigned int port = atoi(p); - - if ((unsigned)(port - 1 ) > 65534) - { - error_msg_and_die("%s: bad port number", p); - } - return port; -} - -static struct in_addr getserver(char * host) -{ - struct in_addr addr; - - struct hostent * he; - he = xgethostbyname(host); - memcpy(&addr, he->h_addr, sizeof addr); - - TRACE(1, ("addr: %s\n", inet_ntoa(addr))); - - return addr; -} - -static int create_socket() -{ - return socket(AF_INET, SOCK_STREAM, 0); -} - -static void setup_sockaddr_in(struct sockaddr_in * addr, int port) -{ - memset(addr, 0, sizeof(struct sockaddr_in)); - addr->sin_family = AF_INET; - addr->sin_port = htons(port); -} - -#if 0 -static int local_bind(int port) -{ - struct sockaddr_in s_addr; - int s = create_socket(); - - setup_sockaddr_in(&s_addr, port); - - setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one); - - if (bind(s, &s_addr, sizeof s_addr) < 0) - { - char * e = sys_errlist[errno]; - syserrorexit("bind"); - exit(1); - } - listen(s, 1); - - return s; -} -#endif - -static int remote_connect(struct in_addr addr, int port) -{ - struct sockaddr_in s_addr; - int s = create_socket(); - - setup_sockaddr_in(&s_addr, port); - s_addr.sin_addr = addr; - - setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof one); - - if (connect(s, (struct sockaddr *)&s_addr, sizeof s_addr) < 0) - { - perror_msg_and_die("Unable to connect to remote host"); - } - return s; -} - -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ - diff --git a/test.c b/test.c deleted file mode 100644 index 3404b02b4..000000000 --- a/test.c +++ /dev/null @@ -1,579 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * test implementation for busybox - * - * Copyright (c) by a whole pile of folks: - * - * test(1); version 7-like -- author Erik Baalbergen - * modified by Eric Gisin to be used as built-in. - * modified by Arnold Robbins to add SVR3 compatibility - * (-x -c -b -p -u -g -k) plus Korn's -L -nt -ot -ef and new -S (socket). - * modified by J.T. Conklin for NetBSD. - * modified by Herbert Xu to be used as built-in in ash. - * modified by Erik Andersen <andersee@debian.org> to be used - * in busybox. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Original copyright notice states: - * "This program is in the Public Domain." - */ - -#include <sys/types.h> -#include <unistd.h> -#include <ctype.h> -#include <errno.h> -#include <stdlib.h> -#include <string.h> -#include "busybox.h" - -/* test(1) accepts the following grammar: - oexpr ::= aexpr | aexpr "-o" oexpr ; - aexpr ::= nexpr | nexpr "-a" aexpr ; - nexpr ::= primary | "!" primary - primary ::= unary-operator operand - | operand binary-operator operand - | operand - | "(" oexpr ")" - ; - unary-operator ::= "-r"|"-w"|"-x"|"-f"|"-d"|"-c"|"-b"|"-p"| - "-u"|"-g"|"-k"|"-s"|"-t"|"-z"|"-n"|"-o"|"-O"|"-G"|"-L"|"-S"; - - binary-operator ::= "="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt"| - "-nt"|"-ot"|"-ef"; - operand ::= <any legal UNIX file name> -*/ - -enum token { - EOI, - FILRD, - FILWR, - FILEX, - FILEXIST, - FILREG, - FILDIR, - FILCDEV, - FILBDEV, - FILFIFO, - FILSOCK, - FILSYM, - FILGZ, - FILTT, - FILSUID, - FILSGID, - FILSTCK, - FILNT, - FILOT, - FILEQ, - FILUID, - FILGID, - STREZ, - STRNZ, - STREQ, - STRNE, - STRLT, - STRGT, - INTEQ, - INTNE, - INTGE, - INTGT, - INTLE, - INTLT, - UNOT, - BAND, - BOR, - LPAREN, - RPAREN, - OPERAND -}; - -enum token_types { - UNOP, - BINOP, - BUNOP, - BBINOP, - PAREN -}; - -static const struct t_op { - const char *op_text; - short op_num, op_type; -} ops [] = { - {"-r", FILRD, UNOP}, - {"-w", FILWR, UNOP}, - {"-x", FILEX, UNOP}, - {"-e", FILEXIST,UNOP}, - {"-f", FILREG, UNOP}, - {"-d", FILDIR, UNOP}, - {"-c", FILCDEV,UNOP}, - {"-b", FILBDEV,UNOP}, - {"-p", FILFIFO,UNOP}, - {"-u", FILSUID,UNOP}, - {"-g", FILSGID,UNOP}, - {"-k", FILSTCK,UNOP}, - {"-s", FILGZ, UNOP}, - {"-t", FILTT, UNOP}, - {"-z", STREZ, UNOP}, - {"-n", STRNZ, UNOP}, - {"-h", FILSYM, UNOP}, /* for backwards compat */ - {"-O", FILUID, UNOP}, - {"-G", FILGID, UNOP}, - {"-L", FILSYM, UNOP}, - {"-S", FILSOCK,UNOP}, - {"=", STREQ, BINOP}, - {"!=", STRNE, BINOP}, - {"<", STRLT, BINOP}, - {">", STRGT, BINOP}, - {"-eq", INTEQ, BINOP}, - {"-ne", INTNE, BINOP}, - {"-ge", INTGE, BINOP}, - {"-gt", INTGT, BINOP}, - {"-le", INTLE, BINOP}, - {"-lt", INTLT, BINOP}, - {"-nt", FILNT, BINOP}, - {"-ot", FILOT, BINOP}, - {"-ef", FILEQ, BINOP}, - {"!", UNOT, BUNOP}, - {"-a", BAND, BBINOP}, - {"-o", BOR, BBINOP}, - {"(", LPAREN, PAREN}, - {")", RPAREN, PAREN}, - {0, 0, 0} -}; - -static char **t_wp; -static struct t_op const *t_wp_op; -static gid_t *group_array = NULL; -static int ngroups; - -static enum token t_lex(char* s); -static int oexpr(enum token n); -static int aexpr(enum token n); -static int nexpr(enum token n); -static int binop(void); -static int primary(enum token n); -static int filstat(char *nm, enum token mode); -static int getn(const char *s); -static int newerf(const char *f1, const char *f2); -static int olderf(const char *f1, const char *f2); -static int equalf(const char *f1, const char *f2); -static void syntax(const char *op, const char *msg); -static int test_eaccess(char *path, int mode); -static int is_a_group_member(gid_t gid); -static void initialize_group_array(void); - -extern int -test_main(int argc, char** argv) -{ - int res; - - if (strcmp(applet_name, "[") == 0) { - if (strcmp(argv[--argc], "]")) - error_msg_and_die("missing ]"); - argv[argc] = NULL; - } - /* Implement special cases from POSIX.2, section 4.62.4 */ - switch (argc) { - case 1: - exit( 1); - case 2: - exit (*argv[1] == '\0'); - case 3: - if (argv[1][0] == '!' && argv[1][1] == '\0') { - exit (!(*argv[2] == '\0')); - } - break; - case 4: - if (argv[1][0] != '!' || argv[1][1] != '\0') { - if (t_lex(argv[2]), - t_wp_op && t_wp_op->op_type == BINOP) { - t_wp = &argv[1]; - exit (binop() == 0); - } - } - break; - case 5: - if (argv[1][0] == '!' && argv[1][1] == '\0') { - if (t_lex(argv[3]), - t_wp_op && t_wp_op->op_type == BINOP) { - t_wp = &argv[2]; - exit (!(binop() == 0)); - } - } - break; - } - - t_wp = &argv[1]; - res = !oexpr(t_lex(*t_wp)); - - if (*t_wp != NULL && *++t_wp != NULL) - syntax(*t_wp, "unknown operand"); - - return( res); -} - -static void -syntax(op, msg) - const char *op; - const char *msg; -{ - if (op && *op) - error_msg_and_die("%s: %s", op, msg); - else - error_msg_and_die("%s", msg); -} - -static int -oexpr(n) - enum token n; -{ - int res; - - res = aexpr(n); - if (t_lex(*++t_wp) == BOR) - return oexpr(t_lex(*++t_wp)) || res; - t_wp--; - return res; -} - -static int -aexpr(n) - enum token n; -{ - int res; - - res = nexpr(n); - if (t_lex(*++t_wp) == BAND) - return aexpr(t_lex(*++t_wp)) && res; - t_wp--; - return res; -} - -static int -nexpr(n) - enum token n; /* token */ -{ - if (n == UNOT) - return !nexpr(t_lex(*++t_wp)); - return primary(n); -} - -static int -primary(n) - enum token n; -{ - int res; - - if (n == EOI) - syntax(NULL, "argument expected"); - if (n == LPAREN) { - res = oexpr(t_lex(*++t_wp)); - if (t_lex(*++t_wp) != RPAREN) - syntax(NULL, "closing paren expected"); - return res; - } - if (t_wp_op && t_wp_op->op_type == UNOP) { - /* unary expression */ - if (*++t_wp == NULL) - syntax(t_wp_op->op_text, "argument expected"); - switch (n) { - case STREZ: - return strlen(*t_wp) == 0; - case STRNZ: - return strlen(*t_wp) != 0; - case FILTT: - return isatty(getn(*t_wp)); - default: - return filstat(*t_wp, n); - } - } - - if (t_lex(t_wp[1]), t_wp_op && t_wp_op->op_type == BINOP) { - return binop(); - } - - return strlen(*t_wp) > 0; -} - -static int -binop() -{ - const char *opnd1, *opnd2; - struct t_op const *op; - - opnd1 = *t_wp; - (void) t_lex(*++t_wp); - op = t_wp_op; - - if ((opnd2 = *++t_wp) == (char *)0) - syntax(op->op_text, "argument expected"); - - switch (op->op_num) { - case STREQ: - return strcmp(opnd1, opnd2) == 0; - case STRNE: - return strcmp(opnd1, opnd2) != 0; - case STRLT: - return strcmp(opnd1, opnd2) < 0; - case STRGT: - return strcmp(opnd1, opnd2) > 0; - case INTEQ: - return getn(opnd1) == getn(opnd2); - case INTNE: - return getn(opnd1) != getn(opnd2); - case INTGE: - return getn(opnd1) >= getn(opnd2); - case INTGT: - return getn(opnd1) > getn(opnd2); - case INTLE: - return getn(opnd1) <= getn(opnd2); - case INTLT: - return getn(opnd1) < getn(opnd2); - case FILNT: - return newerf (opnd1, opnd2); - case FILOT: - return olderf (opnd1, opnd2); - case FILEQ: - return equalf (opnd1, opnd2); - } - /* NOTREACHED */ - return 1; -} - -static int -filstat(nm, mode) - char *nm; - enum token mode; -{ - struct stat s; - unsigned int i; - - if (mode == FILSYM) { -#ifdef S_IFLNK - if (lstat(nm, &s) == 0) { - i = S_IFLNK; - goto filetype; - } -#endif - return 0; - } - - if (stat(nm, &s) != 0) - return 0; - - switch (mode) { - case FILRD: - return test_eaccess(nm, R_OK) == 0; - case FILWR: - return test_eaccess(nm, W_OK) == 0; - case FILEX: - return test_eaccess(nm, X_OK) == 0; - case FILEXIST: - return 1; - case FILREG: - i = S_IFREG; - goto filetype; - case FILDIR: - i = S_IFDIR; - goto filetype; - case FILCDEV: - i = S_IFCHR; - goto filetype; - case FILBDEV: - i = S_IFBLK; - goto filetype; - case FILFIFO: -#ifdef S_IFIFO - i = S_IFIFO; - goto filetype; -#else - return 0; -#endif - case FILSOCK: -#ifdef S_IFSOCK - i = S_IFSOCK; - goto filetype; -#else - return 0; -#endif - case FILSUID: - i = S_ISUID; - goto filebit; - case FILSGID: - i = S_ISGID; - goto filebit; - case FILSTCK: - i = S_ISVTX; - goto filebit; - case FILGZ: - return s.st_size > 0L; - case FILUID: - return s.st_uid == geteuid(); - case FILGID: - return s.st_gid == getegid(); - default: - return 1; - } - -filetype: - return ((s.st_mode & S_IFMT) == i); - -filebit: - return ((s.st_mode & i) != 0); -} - -static enum token -t_lex(s) - char *s; -{ - struct t_op const *op = ops; - - if (s == 0) { - t_wp_op = (struct t_op *)0; - return EOI; - } - while (op->op_text) { - if (strcmp(s, op->op_text) == 0) { - t_wp_op = op; - return op->op_num; - } - op++; - } - t_wp_op = (struct t_op *)0; - return OPERAND; -} - -/* atoi with error detection */ -static int -getn(s) - const char *s; -{ - char *p; - long r; - - errno = 0; - r = strtol(s, &p, 10); - - if (errno != 0) - error_msg_and_die("%s: out of range", s); - - while (isspace(*p)) - p++; - - if (*p) - error_msg_and_die("%s: bad number", s); - - return (int) r; -} - -static int -newerf (f1, f2) -const char *f1, *f2; -{ - struct stat b1, b2; - - return (stat (f1, &b1) == 0 && - stat (f2, &b2) == 0 && - b1.st_mtime > b2.st_mtime); -} - -static int -olderf (f1, f2) -const char *f1, *f2; -{ - struct stat b1, b2; - - return (stat (f1, &b1) == 0 && - stat (f2, &b2) == 0 && - b1.st_mtime < b2.st_mtime); -} - -static int -equalf (f1, f2) -const char *f1, *f2; -{ - struct stat b1, b2; - - return (stat (f1, &b1) == 0 && - stat (f2, &b2) == 0 && - b1.st_dev == b2.st_dev && - b1.st_ino == b2.st_ino); -} - -/* Do the same thing access(2) does, but use the effective uid and gid, - and don't make the mistake of telling root that any file is - executable. */ -static int -test_eaccess (path, mode) -char *path; -int mode; -{ - struct stat st; - unsigned int euid = geteuid(); - - if (stat (path, &st) < 0) - return (-1); - - if (euid == 0) { - /* Root can read or write any file. */ - if (mode != X_OK) - return (0); - - /* Root can execute any file that has any one of the execute - bits set. */ - if (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) - return (0); - } - - if (st.st_uid == euid) /* owner */ - mode <<= 6; - else if (is_a_group_member (st.st_gid)) - mode <<= 3; - - if (st.st_mode & mode) - return (0); - - return (-1); -} - -static void -initialize_group_array () -{ - ngroups = getgroups(0, NULL); - group_array = xrealloc(group_array, ngroups * sizeof(gid_t)); - getgroups(ngroups, group_array); -} - -/* Return non-zero if GID is one that we have in our groups list. */ -static int -is_a_group_member (gid) -gid_t gid; -{ - register int i; - - /* Short-circuit if possible, maybe saving a call to getgroups(). */ - if (gid == getgid() || gid == getegid()) - return (1); - - if (ngroups == 0) - initialize_group_array (); - - /* Search through the list looking for GID. */ - for (i = 0; i < ngroups; i++) - if (gid == group_array[i]) - return (1); - - return (0); -} diff --git a/tests/multibuild.pl b/tests/multibuild.pl index 94930bd95..a3e49a625 100755 --- a/tests/multibuild.pl +++ b/tests/multibuild.pl @@ -12,13 +12,13 @@ $logfile = "multibuild.log"; -# How to handle all the BB_FEATURE_FOO lines +# How to handle all the CONFIG_FEATURE_FOO lines if ($ARGV[0] eq "-all" ) { shift(@ARGV); $choice="all"; } if ($ARGV[0] eq "-none") { shift(@ARGV); $choice="none"; } # neither means, leave that part of Config.h alone # Support building from pristine source -$make_opt = "-f $ARGV[0]/Makefile BB_SRC_DIR=$ARGV[0]" if ($ARGV[0] ne ""); +$make_opt = "-f $ARGV[0]/Makefile CONFIG_SRC_DIR=$ARGV[0]" if ($ARGV[0] ne ""); # Move the config file to a safe place -e "Config.h.orig" || 0==system("mv -f Config.h Config.h.orig") || die; @@ -38,7 +38,7 @@ while (<C>) { $trailer .= $_; } else { $in_trailer=1 if /End of Applications List/; - if (/^\/*#define BB_([A-Z0-9_]*)/) { + if (/^\/*#define CONFIG_([A-Z0-9_]*)/) { push @apps, $1; } } @@ -50,7 +50,7 @@ $failed_tests=0; for $a (@apps) { # print "Testing build of applet $a ...\n"; open (O, ">Config.h") || die; - print O "#define BB_$a\n", $trailer; + print O "#define CONFIG_$a\n", $trailer; close O; system("echo -e '\n***\n$a\n***' >>$logfile"); # With a fast computer and 1-second resolution on file timestamps, this diff --git a/tests/multifeat.pl b/tests/multifeat.pl index adcb30bbd..875b4a277 100755 --- a/tests/multifeat.pl +++ b/tests/multifeat.pl @@ -11,14 +11,14 @@ $logfile = "multifeat.log"; -# How to handle all the BB_APPLET lines +# How to handle all the CONFIG_APPLET lines # (most thorough testing occurs when you call it with the -all switch) if ($ARGV[0] eq "-all" ) { shift(@ARGV); $choice="all"; } if ($ARGV[0] eq "-none") { shift(@ARGV); $choice="none"; } # neither means, leave that part of Config.h alone # Support building from pristine source -$make_opt = "-f $ARGV[0]/Makefile BB_SRC_DIR=$ARGV[0]" if ($ARGV[0] ne ""); +$make_opt = "-f $ARGV[0]/Makefile CONFIG_SRC_DIR=$ARGV[0]" if ($ARGV[0] ne ""); # Move the config file to a safe place -e "Config.h.orig" || 0==system("mv -f Config.h Config.h.orig") || die; @@ -42,7 +42,7 @@ while (<C>) { } } elsif ($in_features) { - if (/^\/*#define BB_FEATURE_([A-Z0-9_]*)/) { + if (/^\/*#define CONFIG_FEATURE_([A-Z0-9_]*)/) { push @features, $1; } if (/End of Features List/) { @@ -60,7 +60,7 @@ $failed_tests=0; for $f (@features) { # print "Testing build with feature $f ...\n"; open (O, ">Config.h") || die; - print O $header, "#define BB_FEATURE_$f\n", $trailer; + print O $header, "#define CONFIG_FEATURE_$f\n", $trailer; close O; system("echo -e '\n***\n$f\n***' >>$logfile"); # With a fast computer and 1-second resolution on file timestamps, this diff --git a/tests/testcases b/tests/testcases index 2aad9b651..2c28bf389 100644 --- a/tests/testcases +++ b/tests/testcases @@ -199,7 +199,7 @@ id -un # ifconfig -# requires BB_FEATURE_IFCONFIG_STATUS +# requires CONFIG_FEATURE_IFCONFIG_STATUS ifconfig #ifconfig -a #ifconfig eth0 diff --git a/tests/tester.sh b/tests/tester.sh index a767c6c7f..09ba750ec 100755 --- a/tests/tester.sh +++ b/tests/tester.sh @@ -10,7 +10,7 @@ BUSYBOX=../busybox TESTCASES=testcases LOGFILE=tester.log -BB_OUT=bb.out +CONFIG_OUT=bb.out GNU_OUT=gnu.out SETUP="" CLEANUP="" @@ -25,7 +25,7 @@ do p) BUSYBOX=$OPTARG; ;; t) TESTCASES=$OPTARG; ;; l) LOGFILE=$OPTARG; ;; -# b) BB_OUT=$OPTARG; ;; +# b) CONFIG_OUT=$OPTARG; ;; # g) GNU_OUT=$OPTARG; ;; s) SETUP=$OPTARG; ;; c) CLEANUP=$OPTARG; ;; @@ -59,7 +59,7 @@ then echo "BUSYBOX=$BUSYBOX" echo "TESTCASES=$TESTCASES" echo "LOGFILE=$LOGFILE" - echo "BB_OUT=$BB_OUT" + echo "CONFIG_OUT=$CONFIG_OUT" echo "GNU_OUT=$GNU_OUT" echo "SETUP=$SETUP" echo "CLEANUP=$CLEANUP" @@ -129,14 +129,14 @@ do # execute line using busybox programs [ $DEBUG -ge 2 ] && echo "testing: $line" | tee -a $LOGFILE - sh -c "$line" > $BB_OUT + sh -c "$line" > $CONFIG_OUT # see if they match - diff -q $BB_OUT $GNU_OUT > /dev/null + diff -q $CONFIG_OUT $GNU_OUT > /dev/null if [ $? -eq 1 ] then [ $DEBUG -ge 1 ] && echo "FAILED: $line" | tee -a $LOGFILE - diff -u $BB_OUT $GNU_OUT >> $LOGFILE + diff -u $CONFIG_OUT $GNU_OUT >> $LOGFILE fi fi fi @@ -147,7 +147,7 @@ done # do normal cleanup -[ "$KEEPTMPFILES" = "no" ] && rm -f $BB_OUT $GNU_OUT +[ "$KEEPTMPFILES" = "no" ] && rm -f $CONFIG_OUT $GNU_OUT # do extra cleanup (if any) diff --git a/tftp.c b/tftp.c deleted file mode 100644 index 530b3d134..000000000 --- a/tftp.c +++ /dev/null @@ -1,574 +0,0 @@ -/* ------------------------------------------------------------------------- */ -/* tftp.c */ -/* */ -/* A simple tftp client for busybox. */ -/* Tries to follow RFC1350. */ -/* Only "octet" mode supported. */ -/* Optional blocksize negotiation (RFC2347 + RFC2348) */ -/* */ -/* Copyright (C) 2001 Magnus Damm <damm@opensource.se> */ -/* */ -/* Parts of the code based on: */ -/* */ -/* atftp: Copyright (C) 2000 Jean-Pierre Lefebvre <helix@step.polymtl.ca> */ -/* and Remi Lefebvre <remi@debian.org> */ -/* */ -/* utftp: Copyright (C) 1999 Uwe Ohse <uwe@ohse.de> */ -/* */ -/* This program is free software; you can redistribute it and/or modify */ -/* it under the terms of the GNU General Public License as published by */ -/* the Free Software Foundation; either version 2 of the License, or */ -/* (at your option) any later version. */ -/* */ -/* This program is distributed in the hope that it will be useful, */ -/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ -/* General Public License for more details. */ -/* */ -/* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* */ -/* ------------------------------------------------------------------------- */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/time.h> -#include <sys/stat.h> -#include <netdb.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <unistd.h> -#include <fcntl.h> - -#include "busybox.h" - -//#define BB_FEATURE_TFTP_DEBUG - -#define TFTP_BLOCKSIZE_DEFAULT 512 /* according to RFC 1350, don't change */ -#define TFTP_TIMEOUT 5 /* seconds */ - -/* opcodes we support */ - -#define TFTP_RRQ 1 -#define TFTP_WRQ 2 -#define TFTP_DATA 3 -#define TFTP_ACK 4 -#define TFTP_ERROR 5 -#define TFTP_OACK 6 - -static const char *tftp_error_msg[] = { - "Undefined error", - "File not found", - "Access violation", - "Disk full or allocation error", - "Illegal TFTP operation", - "Unknown transfer ID", - "File already exists", - "No such user" -}; - -const int tftp_cmd_get = 1; -const int tftp_cmd_put = 2; - -#ifdef BB_FEATURE_TFTP_BLOCKSIZE - -static int tftp_blocksize_check(int blocksize, int bufsize) -{ - /* Check if the blocksize is valid: - * RFC2348 says between 8 and 65464, - * but our implementation makes it impossible - * to use blocksizes smaller than 22 octets. - */ - - if ((bufsize && (blocksize > bufsize)) || - (blocksize < 8) || (blocksize > 65464)) { - error_msg("bad blocksize"); - return 0; - } - - return blocksize; -} - -static char *tftp_option_get(char *buf, int len, char *option) -{ - int opt_val = 0; - int opt_found = 0; - int k; - - while (len > 0) { - - /* Make sure the options are terminated correctly */ - - for (k = 0; k < len; k++) { - if (buf[k] == '\0') { - break; - } - } - - if (k >= len) { - break; - } - - if (opt_val == 0) { - if (strcasecmp(buf, option) == 0) { - opt_found = 1; - } - } - else { - if (opt_found) { - return buf; - } - } - - k++; - - buf += k; - len -= k; - - opt_val ^= 1; - } - - return NULL; -} - -#endif - -static inline int tftp(const int cmd, const struct hostent *host, - const char *remotefile, int localfd, const int port, int tftp_bufsize) -{ - const int cmd_get = cmd & tftp_cmd_get; - const int cmd_put = cmd & tftp_cmd_put; - const int bb_tftp_num_retries = 5; - - struct sockaddr_in sa; - struct sockaddr_in from; - struct timeval tv; - socklen_t fromlen; - fd_set rfds; - char *cp; - unsigned short tmp; - int socketfd; - int len; - int opcode = 0; - int finished = 0; - int timeout = bb_tftp_num_retries; - int block_nr = 1; - -#ifdef BB_FEATURE_TFTP_BLOCKSIZE - int want_option_ack = 0; -#endif - - RESERVE_BB_BUFFER(buf, tftp_bufsize + 4); /* Opcode + Block # + Data */ - - tftp_bufsize += 4; - - if ((socketfd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { - perror_msg("socket"); - return EXIT_FAILURE; - } - - len = sizeof(sa); - - memset(&sa, 0, len); - bind(socketfd, (struct sockaddr *)&sa, len); - - sa.sin_family = host->h_addrtype; - sa.sin_port = htons(port); - memcpy(&sa.sin_addr, (struct in_addr *) host->h_addr, - sizeof(sa.sin_addr)); - - /* build opcode */ - - if (cmd_get) { - opcode = TFTP_RRQ; - } - - if (cmd_put) { - opcode = TFTP_WRQ; - } - - while (1) { - - cp = buf; - - /* first create the opcode part */ - - *((unsigned short *) cp) = htons(opcode); - - cp += 2; - - /* add filename and mode */ - - if ((cmd_get && (opcode == TFTP_RRQ)) || - (cmd_put && (opcode == TFTP_WRQ))) { - int too_long = 0; - - /* see if the filename fits into buf */ - /* and fill in packet */ - - len = strlen(remotefile) + 1; - - if ((cp + len) >= &buf[tftp_bufsize - 1]) { - too_long = 1; - } - else { - safe_strncpy(cp, remotefile, len); - cp += len; - } - - if (too_long || ((&buf[tftp_bufsize - 1] - cp) < 6)) { - error_msg("too long remote-filename"); - break; - } - - /* add "mode" part of the package */ - - memcpy(cp, "octet", 6); - cp += 6; - -#ifdef BB_FEATURE_TFTP_BLOCKSIZE - - len = tftp_bufsize - 4; /* data block size */ - - if (len != TFTP_BLOCKSIZE_DEFAULT) { - - if ((&buf[tftp_bufsize - 1] - cp) < 15) { - error_msg("too long remote-filename"); - break; - } - - /* add "blksize" + number of blocks */ - - memcpy(cp, "blksize", 8); - cp += 8; - - cp += snprintf(cp, 6, "%d", len) + 1; - - want_option_ack = 1; - } -#endif - } - - /* add ack and data */ - - if ((cmd_get && (opcode == TFTP_ACK)) || - (cmd_put && (opcode == TFTP_DATA))) { - - *((unsigned short *) cp) = htons(block_nr); - - cp += 2; - - block_nr++; - - if (cmd_put && (opcode == TFTP_DATA)) { - len = read(localfd, cp, tftp_bufsize - 4); - - if (len < 0) { - perror_msg("read"); - break; - } - - if (len != (tftp_bufsize - 4)) { - finished++; - } - - cp += len; - } else if (finished) { - break; - } - } - - - /* send packet */ - - - do { - - len = cp - buf; - -#ifdef BB_FEATURE_TFTP_DEBUG - printf("sending %u bytes\n", len); - for (cp = buf; cp < &buf[len]; cp++) - printf("%02x ", *cp); - printf("\n"); -#endif - if (sendto(socketfd, buf, len, 0, - (struct sockaddr *) &sa, sizeof(sa)) < 0) { - perror_msg("send"); - len = -1; - break; - } - - - /* receive packet */ - - - memset(&from, 0, sizeof(from)); - fromlen = sizeof(from); - - tv.tv_sec = TFTP_TIMEOUT; - tv.tv_usec = 0; - - FD_ZERO(&rfds); - FD_SET(socketfd, &rfds); - - switch (select(FD_SETSIZE, &rfds, NULL, NULL, &tv)) { - case 1: - len = recvfrom(socketfd, buf, tftp_bufsize, 0, - (struct sockaddr *) &from, &fromlen); - - if (len < 0) { - perror_msg("recvfrom"); - break; - } - - timeout = 0; - - if (sa.sin_port == htons(port)) { - sa.sin_port = from.sin_port; - } - if (sa.sin_port == from.sin_port) { - break; - } - - /* fall-through for bad packets! */ - /* discard the packet - treat as timeout */ - timeout = bb_tftp_num_retries; - - case 0: - error_msg("timeout"); - - if (timeout == 0) { - len = -1; - error_msg("last timeout"); - } else { - timeout--; - } - break; - - default: - perror_msg("select"); - len = -1; - } - - } while (timeout && (len >= 0)); - - if (len < 0) { - break; - } - - /* process received packet */ - - - opcode = ntohs(*((unsigned short *) buf)); - tmp = ntohs(*((unsigned short *) &buf[2])); - -#ifdef BB_FEATURE_TFTP_DEBUG - printf("received %d bytes: %04x %04x\n", len, opcode, tmp); -#endif - - if (opcode == TFTP_ERROR) { - char *msg = NULL; - - if (buf[4] != '\0') { - msg = &buf[4]; - buf[tftp_bufsize - 1] = '\0'; - } else if (tmp < (sizeof(tftp_error_msg) - / sizeof(char *))) { - - msg = (char *) tftp_error_msg[tmp]; - } - - if (msg) { - error_msg("server says: %s", msg); - } - - break; - } - -#ifdef BB_FEATURE_TFTP_BLOCKSIZE - if (want_option_ack) { - - want_option_ack = 0; - - if (opcode == TFTP_OACK) { - - /* server seems to support options */ - - char *res; - - res = tftp_option_get(&buf[2], len-2, - "blksize"); - - if (res) { - int foo = atoi(res); - - if (tftp_blocksize_check(foo, - tftp_bufsize - 4)) { - - if (cmd_put) { - opcode = TFTP_DATA; - } - else { - opcode = TFTP_ACK; - } -#ifdef BB_FEATURE_TFTP_DEBUG - printf("using blksize %u\n"); -#endif - tftp_bufsize = foo + 4; - block_nr = 0; - continue; - } - } - /* FIXME: - * we should send ERROR 8 */ - error_msg("bad server option"); - break; - } - - error_msg("warning: blksize not supported by server" - " - reverting to 512"); - - tftp_bufsize = TFTP_BLOCKSIZE_DEFAULT + 4; - } -#endif - - if (cmd_get && (opcode == TFTP_DATA)) { - - if (tmp == block_nr) { - - len = write(localfd, &buf[4], len - 4); - - if (len < 0) { - perror_msg("write"); - break; - } - - if (len != (tftp_bufsize - 4)) { - finished++; - } - - opcode = TFTP_ACK; - continue; - } - } - - if (cmd_put && (opcode == TFTP_ACK)) { - - if (tmp == (block_nr - 1)) { - if (finished) { - break; - } - - opcode = TFTP_DATA; - continue; - } - } - } - -#ifdef BB_FEATURE_CLEAN_UP - close(socketfd); - - RELEASE_BB_BUFFER(buf); -#endif - - return finished ? EXIT_SUCCESS : EXIT_FAILURE; -} - -int tftp_main(int argc, char **argv) -{ - struct hostent *host = NULL; - char *localfile = NULL; - char *remotefile = NULL; - int port = 69; - int cmd = 0; - int fd = -1; - int flags = 0; - int opt; - int result; - int blocksize = TFTP_BLOCKSIZE_DEFAULT; - - /* figure out what to pass to getopt */ - -#ifdef BB_FEATURE_TFTP_BLOCKSIZE -#define BS "b:" -#else -#define BS -#endif - -#ifdef BB_FEATURE_TFTP_GET -#define GET "g" -#else -#define GET -#endif - -#ifdef BB_FEATURE_TFTP_PUT -#define PUT "p" -#else -#define PUT -#endif - - while ((opt = getopt(argc, argv, BS GET PUT "l:r:")) != -1) { - switch (opt) { -#ifdef BB_FEATURE_TFTP_BLOCKSIZE - case 'b': - blocksize = atoi(optarg); - if (!tftp_blocksize_check(blocksize, 0)) { - return EXIT_FAILURE; - } - break; -#endif -#ifdef BB_FEATURE_TFTP_GET - case 'g': - cmd = tftp_cmd_get; - flags = O_WRONLY | O_CREAT; - break; -#endif -#ifdef BB_FEATURE_TFTP_PUT - case 'p': - cmd = tftp_cmd_put; - flags = O_RDONLY; - break; -#endif - case 'l': - localfile = xstrdup(optarg); - break; - case 'r': - remotefile = xstrdup(optarg); - break; - } - } - - if ((cmd == 0) || (optind == argc)) { - show_usage(); - } - - fd = open(localfile, flags, 0644); - if (fd < 0) { - perror_msg_and_die("local file"); - } - - host = xgethostbyname(argv[optind]); - - if (optind + 2 == argc) { - port = atoi(argv[optind + 1]); - } - -#ifdef BB_FEATURE_TFTP_DEBUG - printf("using server \"%s\", remotefile \"%s\", " - "localfile \"%s\".\n", - inet_ntoa(*((struct in_addr *) host->h_addr)), - remotefile, localfile); -#endif - - result = tftp(cmd, host, remotefile, fd, port, blocksize); - -#ifdef BB_FEATURE_CLEAN_UP - close(fd); -#endif - return(result); -} diff --git a/touch.c b/touch.c deleted file mode 100644 index 1718da71e..000000000 --- a/touch.c +++ /dev/null @@ -1,75 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini touch implementation for busybox - * - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <stdio.h> -#include <sys/types.h> -#include <fcntl.h> -#include <utime.h> -#include <errno.h> -#include <unistd.h> -#include <stdlib.h> -#include "busybox.h" - -extern int touch_main(int argc, char **argv) -{ - int fd; - int create = TRUE; - - /* Parse options */ - while (--argc > 0 && **(++argv) == '-') { - while (*(++(*argv))) { - switch (**argv) { - case 'c': - create = FALSE; - break; - default: - show_usage(); - } - } - } - - if (argc < 1) { - show_usage(); - } - - while (argc > 0) { - fd = open(*argv, (create == FALSE) ? O_RDWR : O_RDWR | O_CREAT, - S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); - if (fd < 0) { - if (create == FALSE && errno == ENOENT) - return EXIT_SUCCESS; - else { - perror_msg_and_die("%s", *argv); - } - } - close(fd); - if (utime(*argv, NULL)) { - perror_msg_and_die("%s", *argv); - } - argc--; - argv++; - } - - return EXIT_SUCCESS; -} diff --git a/tr.c b/tr.c deleted file mode 100644 index 5b7b8d091..000000000 --- a/tr.c +++ /dev/null @@ -1,248 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini tr implementation for busybox - * - * Copyright (c) Michiel Huisjes - * - * This version of tr is adapted from Minix tr and was modified - * by Erik Andersen <andersee@debian.org> to be used in busybox. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Original copyright notice is retained at the end of this file. - */ - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/types.h> -#include "busybox.h" - -/* This must be a #define, since when DODEBUG and BUFFERS_GO_IN_BSS are - * enabled, we otherwise get a "storage size isn't constant error. */ -#define ASCII 0377 - -/* some "globals" shared across this file */ -static char com_fl, del_fl, sq_fl; -static short in_index, out_index; -/* these last are pointers to static buffers declared in tr_main */ -static unsigned char *poutput, *pinput; -static unsigned char *pvector; -static char *pinvec, *poutvec; - - -static void convert() -{ - short read_chars = 0; - short c, coded; - short last = -1; - - for (;;) { - if (in_index == read_chars) { - if ((read_chars = read(0, (char *) pinput, BUFSIZ)) <= 0) { - if (write(1, (char *) poutput, out_index) != out_index) - error_msg("%s", write_error); - exit(0); - } - in_index = 0; - } - c = pinput[in_index++]; - coded = pvector[c]; - if (del_fl && pinvec[c]) - continue; - if (sq_fl && last == coded && (pinvec[c] || poutvec[coded])) - continue; - poutput[out_index++] = last = coded; - if (out_index == BUFSIZ) { - if (write(1, (char *) poutput, out_index) != out_index) - error_msg_and_die("%s", write_error); - out_index = 0; - } - } - - /* NOTREACHED */ -} - -static void map(register unsigned char *string1, unsigned int string1_len, - register unsigned char *string2, unsigned int string2_len) -{ - unsigned char last = '0'; - unsigned int i, j; - - for (j = 0, i = 0; i < string1_len; i++) { - if (string2_len <= j) - pvector[string1[i]] = last; - else - pvector[string1[i]] = last = string2[j++]; - } -} - -/* supported constructs: - * Ranges, e.g., [0-9] ==> 0123456789 - * Escapes, e.g., \a ==> Control-G - */ -static unsigned int expand(const char *arg, register unsigned char *buffer) -{ - unsigned char *buffer_start = buffer; - int i, ac; - - while (*arg) { - if (*arg == '\\') { - arg++; - *buffer++ = process_escape_sequence(&arg); - } else if (*(arg+1) == '-') { - ac = *(arg+2); - if(ac == 0) { - *buffer++ = *arg++; - continue; - } - i = *arg; - while (i <= ac) - *buffer++ = i++; - arg += 3; /* Skip the assumed a-z */ - } else if (*arg == '[') { - arg++; - i = *arg++; - if (*arg++ != '-') { - *buffer++ = '['; - arg -= 2; - continue; - } - ac = *arg++; - while (i <= ac) - *buffer++ = i++; - arg++; /* Skip the assumed ']' */ - } else - *buffer++ = *arg++; - } - - return (buffer - buffer_start); -} - -static int complement(unsigned char *buffer, int buffer_len) -{ - register short i, j, ix; - char conv[ASCII + 2]; - - ix = 0; - for (i = 0; i <= ASCII; i++) { - for (j = 0; j < buffer_len; j++) - if (buffer[j] == i) - break; - if (j == buffer_len) - conv[ix++] = i & ASCII; - } - memcpy(buffer, conv, ix); - return ix; -} - -extern int tr_main(int argc, char **argv) -{ - register unsigned char *ptr; - int output_length=0, input_length; - int idx = 1; - int i; - RESERVE_BB_BUFFER(output, BUFSIZ); - RESERVE_BB_BUFFER(input, BUFSIZ); - RESERVE_BB_UBUFFER(vector, ASCII+1); - RESERVE_BB_BUFFER(invec, ASCII+1); - RESERVE_BB_BUFFER(outvec, ASCII+1); - - /* ... but make them available globally */ - poutput = output; - pinput = input; - pvector = vector; - pinvec = invec; - poutvec = outvec; - - if (argc > 1 && argv[idx][0] == '-') { - for (ptr = (unsigned char *) &argv[idx][1]; *ptr; ptr++) { - switch (*ptr) { - case 'c': - com_fl = TRUE; - break; - case 'd': - del_fl = TRUE; - break; - case 's': - sq_fl = TRUE; - break; - default: - show_usage(); - } - } - idx++; - } - for (i = 0; i <= ASCII; i++) { - vector[i] = i; - invec[i] = outvec[i] = FALSE; - } - - if (argv[idx] != NULL) { - input_length = expand(argv[idx++], input); - if (com_fl) - input_length = complement(input, input_length); - if (argv[idx] != NULL) { - if (*argv[idx] == '\0') - error_msg_and_die("STRING2 cannot be empty"); - output_length = expand(argv[idx], output); - map(input, input_length, output, output_length); - } - for (i = 0; i < input_length; i++) - invec[(int)input[i]] = TRUE; - for (i = 0; i < output_length; i++) - outvec[(int)output[i]] = TRUE; - } - convert(); - return (0); -} - -/* - * Copyright (c) 1987,1997, Prentice Hall - * All rights reserved. - * - * Redistribution and use of the MINIX operating system in source and - * binary forms, with or without modification, are permitted provided - * that the following conditions are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * Neither the name of Prentice Hall nor the names of the software - * authors or contributors may be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND - * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL PRENTICE HALL OR ANY AUTHORS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - diff --git a/traceroute.c b/traceroute.c deleted file mode 100644 index a3abd0a00..000000000 --- a/traceroute.c +++ /dev/null @@ -1,652 +0,0 @@ -/*- - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Van Jacobson. - * - * Special for busybox ported by Vladimir Oleynik <dzo@simtreas.ru> 2001 - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * traceroute host - trace the route ip packets follow going to "host". - * Notes - * ----- - * This program must be run by root or be setuid. (I suggest that - * you *don't* make it setuid -- casual use could result in a lot - * of unnecessary traffic on our poor, congested nets.) - * - * I stole the idea for this program from Steve Deering. Since - * the first release, I've learned that had I attended the right - * IETF working group meetings, I also could have stolen it from Guy - * Almes or Matt Mathis. I don't know (or care) who came up with - * the idea first. I envy the originators' perspicacity and I'm - * glad they didn't keep the idea a secret. - * - * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or - * enhancements to the original distribution. - * - * I've hacked up a round-trip-route version of this that works by - * sending a loose-source-routed udp datagram through the destination - * back to yourself. Unfortunately, SO many gateways botch source - * routing, the thing is almost worthless. Maybe one day... - * - * -- Van Jacobson (van@helios.ee.lbl.gov) - * Tue Dec 20 03:50:13 PST 1988 - */ - -#undef BB_FEATURE_TRACEROUTE_VERBOSE -//#define BB_FEATURE_TRACEROUTE_VERBOSE -#undef BB_FEATURE_TRACEROUTE_SO_DEBUG /* not in documentation man */ - -#include <stdio.h> -#include <errno.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <sys/time.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <netdb.h> -#include <endian.h> -#include <arpa/inet.h> -#include <netinet/udp.h> -#include <netinet/ip.h> -#include <netinet/ip_icmp.h> - - - /* It turns out that libc5 doesn't have proper icmp support - * built into it header files, so we have to supplement it */ -#if __GNU_LIBRARY__ < 5 -static const int ICMP_MINLEN = 8; /* abs minimum */ - -struct icmp_ra_addr -{ - u_int32_t ira_addr; - u_int32_t ira_preference; -}; - - -struct icmp -{ - u_int8_t icmp_type; /* type of message, see below */ - u_int8_t icmp_code; /* type sub code */ - u_int16_t icmp_cksum; /* ones complement checksum of struct */ - union - { - u_char ih_pptr; /* ICMP_PARAMPROB */ - struct in_addr ih_gwaddr; /* gateway address */ - struct ih_idseq /* echo datagram */ - { - u_int16_t icd_id; - u_int16_t icd_seq; - } ih_idseq; - u_int32_t ih_void; - - /* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */ - struct ih_pmtu - { - u_int16_t ipm_void; - u_int16_t ipm_nextmtu; - } ih_pmtu; - - struct ih_rtradv - { - u_int8_t irt_num_addrs; - u_int8_t irt_wpa; - u_int16_t irt_lifetime; - } ih_rtradv; - } icmp_hun; -#define icmp_pptr icmp_hun.ih_pptr -#define icmp_gwaddr icmp_hun.ih_gwaddr -#define icmp_id icmp_hun.ih_idseq.icd_id -#define icmp_seq icmp_hun.ih_idseq.icd_seq -#define icmp_void icmp_hun.ih_void -#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void -#define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu -#define icmp_num_addrs icmp_hun.ih_rtradv.irt_num_addrs -#define icmp_wpa icmp_hun.ih_rtradv.irt_wpa -#define icmp_lifetime icmp_hun.ih_rtradv.irt_lifetime - union - { - struct - { - u_int32_t its_otime; - u_int32_t its_rtime; - u_int32_t its_ttime; - } id_ts; - struct - { - struct ip idi_ip; - /* options and then 64 bits of data */ - } id_ip; - struct icmp_ra_addr id_radv; - u_int32_t id_mask; - u_int8_t id_data[1]; - } icmp_dun; -#define icmp_otime icmp_dun.id_ts.its_otime -#define icmp_rtime icmp_dun.id_ts.its_rtime -#define icmp_ttime icmp_dun.id_ts.its_ttime -#define icmp_ip icmp_dun.id_ip.idi_ip -#define icmp_radv icmp_dun.id_radv -#define icmp_mask icmp_dun.id_mask -#define icmp_data icmp_dun.id_data -}; - -#define ICMP_MINLEN 8 /* abs minimum */ -#define ICMP_UNREACH 3 /* dest unreachable, codes: */ -#define ICMP_TIMXCEED 11 /* time exceeded, code: */ -#define ICMP_TIMXCEED_INTRANS 0 /* ttl==0 in transit */ -#define ICMP_UNREACH_NET 0 /* bad net */ -#define ICMP_UNREACH_HOST 1 /* bad host */ -#define ICMP_UNREACH_PROTOCOL 2 /* bad protocol */ -#define ICMP_UNREACH_PORT 3 /* bad port */ -#define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */ -#define ICMP_UNREACH_SRCFAIL 5 /* src route failed */ -#endif - - -#define MAXPACKET 65535 /* max ip packet size */ -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 64 -#endif - -/* - * format of a (udp) probe packet. - */ -struct opacket { - struct ip ip; - struct udphdr udp; - u_char seq; /* sequence number of this packet */ - u_char ttl; /* ttl packet left with */ - struct timeval tv; /* time packet left */ -}; - -/* - * Definitions for internet protocol version 4. - * Per RFC 791, September 1981. - */ -#define IPVERSION 4 - - -#include "busybox.h" - -static u_char packet[512]; /* last inbound (icmp) packet */ -static struct opacket *outpacket; /* last output (udp) packet */ - -static int s; /* receive (icmp) socket file descriptor */ -static int sndsock; /* send (udp) socket file descriptor */ - -static struct sockaddr whereto; /* Who to try to reach */ -static int datalen; /* How much data */ - -static char *hostname; - -static int max_ttl = 30; -static u_short ident; -static u_short port = 32768+666; /* start udp dest port # for probe packets */ - -#ifdef BB_FEATURE_TRACEROUTE_VERBOSE -static int verbose; -#endif -static int waittime = 5; /* time to wait for response (in seconds) */ -static int nflag; /* print addresses numerically */ - -/* - * Construct an Internet address representation. - * If the nflag has been supplied, give - * numeric value, otherwise try for symbolic name. - */ -static inline void -inetname(struct sockaddr_in *from) -{ - char *cp; - struct hostent *hp; - static char domain[MAXHOSTNAMELEN + 1]; - static int first = 1; - const char *ina; - - if (first && !nflag) { - first = 0; - if (gethostname(domain, MAXHOSTNAMELEN) == 0 && - (cp = strchr(domain, '.'))) - (void) strcpy(domain, cp + 1); - else - domain[0] = 0; - } - cp = 0; - if (!nflag && from->sin_addr.s_addr != INADDR_ANY) { - hp = gethostbyaddr((char *)&(from->sin_addr), sizeof (from->sin_addr), AF_INET); - if (hp) { - if ((cp = strchr(hp->h_name, '.')) && - !strcmp(cp + 1, domain)) - *cp = 0; - cp = (char *)hp->h_name; - } - } - ina = inet_ntoa(from->sin_addr); - if (nflag) - printf(" %s", ina); - else - printf(" %s (%s)", (cp ? cp : ina), ina); -} - -static inline void -print(u_char *buf, int cc, struct sockaddr_in *from) -{ - struct ip *ip; - int hlen; - - ip = (struct ip *) buf; - hlen = ip->ip_hl << 2; - cc -= hlen; - - inetname(from); -#ifdef BB_FEATURE_TRACEROUTE_VERBOSE - if (verbose) - printf (" %d bytes to %s", cc, inet_ntoa (ip->ip_dst)); -#endif -} - -static inline double -deltaT(struct timeval *t1p, struct timeval *t2p) -{ - double dt; - - dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 + - (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0; - return (dt); -} - -static inline int -wait_for_reply(int sock, struct sockaddr_in *from, int reset_timer) -{ - fd_set fds; - static struct timeval wait; - int cc = 0; - int fromlen = sizeof (*from); - - FD_ZERO(&fds); - FD_SET(sock, &fds); - if (reset_timer) { - /* - * traceroute could hang if someone else has a ping - * running and our ICMP reply gets dropped but we don't - * realize it because we keep waking up to handle those - * other ICMP packets that keep coming in. To fix this, - * "reset_timer" will only be true if the last packet that - * came in was for us or if this is the first time we're - * waiting for a reply since sending out a probe. Note - * that this takes advantage of the select() feature on - * Linux where the remaining timeout is written to the - * struct timeval area. - */ - wait.tv_sec = waittime; - wait.tv_usec = 0; - } - - if (select(sock+1, &fds, (fd_set *)0, (fd_set *)0, &wait) > 0) - cc=recvfrom(s, (char *)packet, sizeof(packet), 0, - (struct sockaddr *)from, &fromlen); - - return(cc); -} - -#ifdef BB_FEATURE_TRACEROUTE_VERBOSE -/* - * Convert an ICMP "type" field to a printable string. - */ -static inline const char * -pr_type(t) - u_char t; -{ - static const char * const ttab[] = { - "Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable", - "Source Quench", "Redirect", "ICMP 6", "ICMP 7", - "Echo", "ICMP 9", "ICMP 10", "Time Exceeded", - "Param Problem", "Timestamp", "Timestamp Reply", "Info Request", - "Info Reply" - }; - - if(t > 16) - return("OUT-OF-RANGE"); - - return(ttab[t]); -} -#endif - -static inline int -packet_ok(u_char *buf, int cc, struct sockaddr_in *from, int seq) -{ - struct icmp *icp; - u_char type, code; - int hlen; - struct ip *ip; - - ip = (struct ip *) buf; - hlen = ip->ip_hl << 2; - if (cc < hlen + ICMP_MINLEN) { -#ifdef BB_FEATURE_TRACEROUTE_VERBOSE - if (verbose) - printf("packet too short (%d bytes) from %s\n", cc, - inet_ntoa(from->sin_addr)); -#endif - return (0); - } - cc -= hlen; - icp = (struct icmp *)(buf + hlen); - type = icp->icmp_type; code = icp->icmp_code; - if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) || - type == ICMP_UNREACH) { - struct ip *hip; - struct udphdr *up; - - hip = &icp->icmp_ip; - hlen = hip->ip_hl << 2; - up = (struct udphdr *)((u_char *)hip + hlen); - if (hlen + 12 <= cc && hip->ip_p == IPPROTO_UDP && - up->source == htons(ident) && - up->dest == htons(port+seq)) - return (type == ICMP_TIMXCEED? -1 : code+1); - } -#ifdef BB_FEATURE_TRACEROUTE_VERBOSE - if (verbose) { - int i; - u_long *lp = (u_long *)&icp->icmp_ip; - - printf("\n%d bytes from %s to %s: icmp type %d (%s) code %d\n", - cc, inet_ntoa(from->sin_addr), inet_ntoa(ip->ip_dst), - type, pr_type(type), icp->icmp_code); - for (i = 4; i < cc ; i += sizeof(long)) - printf("%2d: x%8.8lx\n", i, *lp++); - } -#endif - return(0); -} - -static void /* not inline */ -send_probe(int seq, int ttl) -{ - struct opacket *op = outpacket; - struct ip *ip = &op->ip; - struct udphdr *up = &op->udp; - int i; - struct timezone tz; - - ip->ip_off = 0; - ip->ip_hl = sizeof(*ip) >> 2; - ip->ip_p = IPPROTO_UDP; - ip->ip_len = datalen; - ip->ip_ttl = ttl; - ip->ip_v = IPVERSION; - ip->ip_id = htons(ident+seq); - - up->source = htons(ident); - up->dest = htons(port+seq); - up->len = htons((u_short)(datalen - sizeof(struct ip))); - up->check = 0; - - op->seq = seq; - op->ttl = ttl; - (void) gettimeofday(&op->tv, &tz); - - i = sendto(sndsock, (char *)outpacket, datalen, 0, &whereto, - sizeof(struct sockaddr)); - if (i < 0 || i != datalen) { - if (i<0) - perror("sendto"); - printf("traceroute: wrote %s %d chars, ret=%d\n", hostname, - datalen, i); - (void) fflush(stdout); - } -} - - -int -#ifndef BB_TRACEROUTE -main(argc, argv) -#else -traceroute_main(argc, argv) -#endif - int argc; - char *argv[]; -{ - extern char *optarg; - extern int optind; - struct hostent *hp; - struct sockaddr_in from, *to; - int ch, i, on, probe, seq, tos, ttl; - - int options = 0; /* socket options */ - char *source = 0; - int nprobes = 3; - - on = 1; - seq = tos = 0; - to = (struct sockaddr_in *)&whereto; - while ((ch = getopt(argc, argv, "dm:np:q:rs:t:w:v")) != EOF) - switch(ch) { - case 'd': -#ifdef BB_FEATURE_TRACEROUTE_SO_DEBUG - options |= SO_DEBUG; -#endif - break; - case 'm': - max_ttl = atoi(optarg); - if (max_ttl <= 1) - error_msg_and_die("max ttl must be >1."); - break; - case 'n': - nflag++; - break; - case 'p': - port = atoi(optarg); - if (port < 1) - error_msg_and_die("port must be >0."); - break; - case 'q': - nprobes = atoi(optarg); - if (nprobes < 1) - error_msg_and_die("nprobes must be >0."); - break; - case 'r': - options |= SO_DONTROUTE; - break; - case 's': - /* - * set the ip source address of the outbound - * probe (e.g., on a multi-homed host). - */ - source = optarg; - break; - case 't': - tos = atoi(optarg); - if (tos < 0 || tos > 255) - error_msg_and_die("tos must be 0 to 255."); - break; - case 'v': -#ifdef BB_FEATURE_TRACEROUTE_VERBOSE - verbose++; -#endif - break; - case 'w': - waittime = atoi(optarg); - if (waittime <= 1) - error_msg_and_die("wait must be >1 sec."); - break; - default: - show_usage(); - } - argc -= optind; - argv += optind; - - if (argc < 1) - show_usage(); - - setlinebuf (stdout); - - memset(&whereto, 0, sizeof(struct sockaddr)); - hp = xgethostbyname(*argv); - to->sin_family = hp->h_addrtype; - memcpy(&to->sin_addr, hp->h_addr, hp->h_length); - hostname = (char *)hp->h_name; - if (*++argv) - datalen = atoi(*argv); - if (datalen < 0 || datalen >= MAXPACKET - sizeof(struct opacket)) - error_msg_and_die("packet size must be 0 <= s < %d.", - MAXPACKET - sizeof(struct opacket)); - datalen += sizeof(struct opacket); - outpacket = (struct opacket *)xmalloc((unsigned)datalen); - memset(outpacket, 0, datalen); - outpacket->ip.ip_dst = to->sin_addr; - outpacket->ip.ip_tos = tos; - outpacket->ip.ip_v = IPVERSION; - outpacket->ip.ip_id = 0; - - ident = (getpid() & 0xffff) | 0x8000; - - if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) - perror_msg_and_die(can_not_create_raw_socket); - - s = create_icmp_socket(); - -#ifdef BB_FEATURE_TRACEROUTE_SO_DEBUG - if (options & SO_DEBUG) - (void) setsockopt(s, SOL_SOCKET, SO_DEBUG, - (char *)&on, sizeof(on)); -#endif - if (options & SO_DONTROUTE) - (void) setsockopt(s, SOL_SOCKET, SO_DONTROUTE, - (char *)&on, sizeof(on)); -#ifdef SO_SNDBUF - if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&datalen, - sizeof(datalen)) < 0) - perror_msg_and_die("SO_SNDBUF"); -#endif SO_SNDBUF -#ifdef IP_HDRINCL - if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on, - sizeof(on)) < 0) - perror_msg_and_die("IP_HDRINCL"); -#endif IP_HDRINCL -#ifdef BB_FEATURE_TRACEROUTE_SO_DEBUG - if (options & SO_DEBUG) - (void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, - (char *)&on, sizeof(on)); -#endif - if (options & SO_DONTROUTE) - (void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, - (char *)&on, sizeof(on)); - - if (source) { - memset(&from, 0, sizeof(struct sockaddr)); - from.sin_family = AF_INET; - from.sin_addr.s_addr = inet_addr(source); - if (from.sin_addr.s_addr == -1) - error_msg_and_die("unknown host %s", source); - outpacket->ip.ip_src = from.sin_addr; -#ifndef IP_HDRINCL - if (bind(sndsock, (struct sockaddr *)&from, sizeof(from)) < 0) - perror_msg_and_die("bind"); -#endif IP_HDRINCL - } - - fprintf(stderr, "traceroute to %s (%s)", hostname, - inet_ntoa(to->sin_addr)); - if (source) - fprintf(stderr, " from %s", source); - fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, datalen); - - for (ttl = 1; ttl <= max_ttl; ++ttl) { - u_long lastaddr = 0; - int got_there = 0; - int unreachable = 0; - - printf("%2d ", ttl); - for (probe = 0; probe < nprobes; ++probe) { - int cc, reset_timer; - struct timeval t1, t2; - struct timezone tz; - struct ip *ip; - - (void) gettimeofday(&t1, &tz); - send_probe(++seq, ttl); - reset_timer = 1; - while ((cc = wait_for_reply(s, &from, reset_timer)) != 0) { - (void) gettimeofday(&t2, &tz); - if ((i = packet_ok(packet, cc, &from, seq))) { - reset_timer = 1; - if (from.sin_addr.s_addr != lastaddr) { - print(packet, cc, &from); - lastaddr = from.sin_addr.s_addr; - } - printf(" %g ms", deltaT(&t1, &t2)); - switch(i - 1) { - case ICMP_UNREACH_PORT: - ip = (struct ip *)packet; - if (ip->ip_ttl <= 1) - printf(" !"); - ++got_there; - break; - case ICMP_UNREACH_NET: - ++unreachable; - printf(" !N"); - break; - case ICMP_UNREACH_HOST: - ++unreachable; - printf(" !H"); - break; - case ICMP_UNREACH_PROTOCOL: - ++got_there; - printf(" !P"); - break; - case ICMP_UNREACH_NEEDFRAG: - ++unreachable; - printf(" !F"); - break; - case ICMP_UNREACH_SRCFAIL: - ++unreachable; - printf(" !S"); - break; - } - break; - } else - reset_timer = 0; - } - if (cc == 0) - printf(" *"); - (void) fflush(stdout); - } - putchar('\n'); - if (got_there || unreachable >= nprobes-1) - exit(0); - } - - return 0; -} diff --git a/true_false.c b/true_false.c deleted file mode 100644 index 76183431c..000000000 --- a/true_false.c +++ /dev/null @@ -1,39 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini true/false implementation for busybox - * - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* getopt not needed */ - -#include <stdlib.h> -#include "busybox.h" - - -extern int true_main(int argc, char **argv) -{ - return EXIT_SUCCESS; -} - -extern int false_main(int argc, char **argv) -{ - return EXIT_FAILURE; -} diff --git a/tty.c b/tty.c deleted file mode 100644 index 4510c2996..000000000 --- a/tty.c +++ /dev/null @@ -1,44 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini tty implementation for busybox - * - * Copyright (C) 2000 Edward Betts <edward@debian.org>. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/types.h> -#include "busybox.h" - -extern int tty_main(int argc, char **argv) -{ - char *tty; - - if (argc > 1) { - if (argv[1][0] != '-' || argv[1][1] != 's') - show_usage(); - } else { - tty = ttyname(0); - if (tty) - puts(tty); - else - puts("not a tty"); - } - return(isatty(0) ? EXIT_SUCCESS : EXIT_FAILURE); -} diff --git a/umount.c b/umount.c deleted file mode 100644 index 74638d21c..000000000 --- a/umount.c +++ /dev/null @@ -1,298 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini umount implementation for busybox - * - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <limits.h> -#include <stdio.h> -#include <mntent.h> -#include <errno.h> -#include <string.h> -#include <stdlib.h> -#include "busybox.h" - -/* Teach libc5 about realpath -- it includes it but the - * prototype is missing... */ -#if (__GLIBC__ <= 2) && (__GLIBC_MINOR__ < 1) -extern char *realpath(const char *path, char *resolved_path); -#endif - -static const int MNT_FORCE = 1; -static const int MS_MGC_VAL = 0xc0ed0000; /* Magic number indicatng "new" flags */ -static const int MS_REMOUNT = 32; /* Alter flags of a mounted FS. */ -static const int MS_RDONLY = 1; /* Mount read-only. */ - -extern int mount (__const char *__special_file, __const char *__dir, - __const char *__fstype, unsigned long int __rwflag, - __const void *__data); -extern int umount (__const char *__special_file); -extern int umount2 (__const char *__special_file, int __flags); - -struct _mtab_entry_t { - char *device; - char *mountpt; - struct _mtab_entry_t *next; -}; - -static struct _mtab_entry_t *mtab_cache = NULL; - - - -#if defined BB_FEATURE_MOUNT_FORCE -static int doForce = FALSE; -#endif -#if defined BB_FEATURE_MOUNT_LOOP -static int freeLoop = TRUE; -#endif -#if defined BB_FEATURE_MTAB_SUPPORT -static int useMtab = TRUE; -#endif -static int umountAll = FALSE; -static int doRemount = FALSE; -extern const char mtab_file[]; /* Defined in utility.c */ - - - -/* These functions are here because the getmntent functions do not appear - * to be re-entrant, which leads to all sorts of problems when we try to - * use them recursively - randolph - * - * TODO: Perhaps switch to using Glibc's getmntent_r - * -Erik - */ -static void mtab_read(void) -{ - struct _mtab_entry_t *entry = NULL; - struct mntent *e; - FILE *fp; - - if (mtab_cache != NULL) - return; - - if ((fp = setmntent(mtab_file, "r")) == NULL) { - error_msg("Cannot open %s", mtab_file); - return; - } - while ((e = getmntent(fp))) { - entry = xmalloc(sizeof(struct _mtab_entry_t)); - entry->device = strdup(e->mnt_fsname); - entry->mountpt = strdup(e->mnt_dir); - entry->next = mtab_cache; - mtab_cache = entry; - } - endmntent(fp); -} - -static char *mtab_getinfo(const char *match, const char which) -{ - struct _mtab_entry_t *cur = mtab_cache; - - while (cur) { - if (strcmp(cur->mountpt, match) == 0 || - strcmp(cur->device, match) == 0) { - if (which == MTAB_GETMOUNTPT) { - return cur->mountpt; - } else { -#if !defined BB_FEATURE_MTAB_SUPPORT - if (strcmp(cur->device, "/dev/root") == 0) { - /* Adjusts device to be the real root device, - * or leaves device alone if it can't find it */ - cur->device = find_real_root_device_name(cur->device); - } -#endif - return cur->device; - } - } - cur = cur->next; - } - return NULL; -} - -static char *mtab_next(void **iter) -{ - char *mp; - - if (iter == NULL || *iter == NULL) - return NULL; - mp = ((struct _mtab_entry_t *) (*iter))->mountpt; - *iter = (void *) ((struct _mtab_entry_t *) (*iter))->next; - return mp; -} - -static char *mtab_first(void **iter) -{ - struct _mtab_entry_t *mtab_iter; - - if (!iter) - return NULL; - mtab_iter = mtab_cache; - *iter = (void *) mtab_iter; - return mtab_next(iter); -} - -/* Don't bother to clean up, since exit() does that - * automagically, so we can save a few bytes */ -#ifdef BB_FEATURE_CLEAN_UP -static void mtab_free(void) -{ - struct _mtab_entry_t *this, *next; - - this = mtab_cache; - while (this) { - next = this->next; - if (this->device) - free(this->device); - if (this->mountpt) - free(this->mountpt); - free(this); - this = next; - } -} -#endif - -static int do_umount(const char *name) -{ - int status; - char *blockDevice = mtab_getinfo(name, MTAB_GETDEVICE); - - if (blockDevice && strcmp(blockDevice, name) == 0) - name = mtab_getinfo(blockDevice, MTAB_GETMOUNTPT); - - status = umount(name); - -#if defined BB_FEATURE_MOUNT_LOOP - if (freeLoop == TRUE && blockDevice != NULL && !strncmp("/dev/loop", blockDevice, 9)) - /* this was a loop device, delete it */ - del_loop(blockDevice); -#endif -#if defined BB_FEATURE_MOUNT_FORCE - if (status != 0 && doForce == TRUE) { - status = umount2(blockDevice, MNT_FORCE); - if (status != 0) { - error_msg_and_die("forced umount of %s failed!", blockDevice); - } - } -#endif - if (status != 0 && doRemount == TRUE && errno == EBUSY) { - status = mount(blockDevice, name, NULL, - MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL); - if (status == 0) { - error_msg("%s busy - remounted read-only", blockDevice); - } else { - error_msg("Cannot remount %s read-only", blockDevice); - } - } - if (status == 0) { -#if defined BB_FEATURE_MTAB_SUPPORT - if (useMtab == TRUE) - erase_mtab(name); -#endif - return (TRUE); - } - return (FALSE); -} - -static int umount_all(void) -{ - int status = TRUE; - char *mountpt; - void *iter; - - for (mountpt = mtab_first(&iter); mountpt; mountpt = mtab_next(&iter)) { - /* Never umount /proc on a umount -a */ - if (strstr(mountpt, "proc")!= NULL) - continue; - if (!do_umount(mountpt)) { - /* Don't bother retrying the umount on busy devices */ - if (errno == EBUSY) { - perror_msg("%s", mountpt); - status = FALSE; - continue; - } - if (!do_umount(mountpt)) { - printf("Couldn't umount %s on %s: %s\n", - mountpt, mtab_getinfo(mountpt, MTAB_GETDEVICE), - strerror(errno)); - status = FALSE; - } - } - } - return (status); -} - -extern int umount_main(int argc, char **argv) -{ - char path[PATH_MAX]; - - if (argc < 2) { - show_usage(); - } -#ifdef BB_FEATURE_CLEAN_UP - atexit(mtab_free); -#endif - - /* Parse any options */ - while (--argc > 0 && **(++argv) == '-') { - while (*++(*argv)) - switch (**argv) { - case 'a': - umountAll = TRUE; - break; -#if defined BB_FEATURE_MOUNT_LOOP - case 'l': - freeLoop = FALSE; - break; -#endif -#ifdef BB_FEATURE_MTAB_SUPPORT - case 'n': - useMtab = FALSE; - break; -#endif -#ifdef BB_FEATURE_MOUNT_FORCE - case 'f': - doForce = TRUE; - break; -#endif - case 'r': - doRemount = TRUE; - break; - case 'v': - break; /* ignore -v */ - default: - show_usage(); - } - } - - mtab_read(); - if (umountAll == TRUE) { - if (umount_all() == TRUE) - return EXIT_SUCCESS; - else - return EXIT_FAILURE; - } - if (realpath(*argv, path) == NULL) - perror_msg_and_die("%s", path); - if (do_umount(path) == TRUE) - return EXIT_SUCCESS; - perror_msg_and_die("%s", *argv); -} - diff --git a/uname.c b/uname.c deleted file mode 100644 index f7e2291a8..000000000 --- a/uname.c +++ /dev/null @@ -1,156 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* uname -- print system information - Copyright (C) 1989-1999 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -/* Option Example - - -s, --sysname SunOS - -n, --nodename rocky8 - -r, --release 4.0 - -v, --version - -m, --machine sun - -a, --all SunOS rocky8 4.0 sun - - The default behavior is equivalent to `-s'. - - David MacKenzie <djm@gnu.ai.mit.edu> */ - -/* Busyboxed by Erik Andersen */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <sys/utsname.h> - -#if defined (HAVE_SYSINFO) && defined (HAVE_SYS_SYSTEMINFO_H) -# include <sys/systeminfo.h> -#endif -#include "busybox.h" - -static void print_element(unsigned int mask, char *element); - -/* Values that are bitwise or'd into `toprint'. */ -/* Operating system name. */ -static const int PRINT_SYSNAME = 1; - -/* Node name on a communications network. */ -static const int PRINT_NODENAME = 2; - -/* Operating system release. */ -static const int PRINT_RELEASE = 4; - -/* Operating system version. */ -static const int PRINT_VERSION = 8; - -/* Machine hardware name. */ -static const int PRINT_MACHINE = 16; - - /* Host processor type. */ -static const int PRINT_PROCESSOR = 32; - -/* Mask indicating which elements of the name to print. */ -static unsigned char toprint; - - -int uname_main(int argc, char **argv) -{ - struct utsname name; - char processor[256]; - -#if defined(__sparc__) && defined(__linux__) - char *fake_sparc = getenv("FAKE_SPARC"); -#endif - - toprint = 0; - - /* Parse any options */ - //fprintf(stderr, "argc=%d, argv=%s\n", argc, *argv); - while (--argc > 0 && **(++argv) == '-') { - while (*(++(*argv))) { - switch (**argv) { - case 's': - toprint |= PRINT_SYSNAME; - break; - case 'n': - toprint |= PRINT_NODENAME; - break; - case 'r': - toprint |= PRINT_RELEASE; - break; - case 'v': - toprint |= PRINT_VERSION; - break; - case 'm': - toprint |= PRINT_MACHINE; - break; - case 'p': - toprint |= PRINT_PROCESSOR; - break; - case 'a': - toprint = (PRINT_SYSNAME | PRINT_NODENAME | PRINT_RELEASE | - PRINT_PROCESSOR | PRINT_VERSION | - PRINT_MACHINE); - break; - default: - show_usage(); - } - } - } - - if (toprint == 0) - toprint = PRINT_SYSNAME; - - if (uname(&name) == -1) - perror_msg("cannot get system name"); - -#if defined (HAVE_SYSINFO) && defined (SI_ARCHITECTURE) - if (sysinfo(SI_ARCHITECTURE, processor, sizeof(processor)) == -1) - perror_msg("cannot get processor type"); -} - -#else - strcpy(processor, "unknown"); -#endif - -#if defined(__sparc__) && defined(__linux__) - if (fake_sparc != NULL - && (fake_sparc[0] == 'y' - || fake_sparc[0] == 'Y')) strcpy(name.machine, "sparc"); -#endif - - print_element(PRINT_SYSNAME, name.sysname); - print_element(PRINT_NODENAME, name.nodename); - print_element(PRINT_RELEASE, name.release); - print_element(PRINT_VERSION, name.version); - print_element(PRINT_MACHINE, name.machine); - print_element(PRINT_PROCESSOR, processor); - - return EXIT_SUCCESS; -} - -/* If the name element set in MASK is selected for printing in `toprint', - print ELEMENT; then print a space unless it is the last element to - be printed, in which case print a newline. */ - -static void print_element(unsigned int mask, char *element) -{ - if (toprint & mask) { - toprint &= ~mask; - printf("%s%c", element, toprint ? ' ' : '\n'); - } -} diff --git a/uniq.c b/uniq.c deleted file mode 100644 index 53e3c64f2..000000000 --- a/uniq.c +++ /dev/null @@ -1,89 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini uniq implementation for busybox - * - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by John Beppu <beppu@lineo.com> - * Rewritten by Matt Kraai <kraai@alumni.carnegiemellon.edu> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <stdio.h> -#include <string.h> -#include <getopt.h> -#include <errno.h> -#include <stdlib.h> -#include "busybox.h" - -static int print_count; -static int print_uniq = 1; -static int print_duplicates = 1; - -static void print_line(char *line, int count, FILE *fp) -{ - if ((print_duplicates && count > 1) || (print_uniq && count == 1)) { - if (print_count) - fprintf(fp, "%7d\t%s", count, line); - else - fputs(line, fp); - } -} - -int uniq_main(int argc, char **argv) -{ - FILE *in = stdin, *out = stdout; - char *lastline = NULL, *input; - int opt, count = 0; - - /* parse argv[] */ - while ((opt = getopt(argc, argv, "cdu")) > 0) { - switch (opt) { - case 'c': - print_count = 1; - break; - case 'd': - print_duplicates = 1; - print_uniq = 0; - break; - case 'u': - print_duplicates = 0; - print_uniq = 1; - break; - } - } - - if (argv[optind] != NULL) { - in = xfopen(argv[optind], "r"); - if (argv[optind+1] != NULL) - out = xfopen(argv[optind+1], "w"); - } - - while ((input = get_line_from_file(in)) != NULL) { - if (lastline == NULL || strcmp(input, lastline) != 0) { - print_line(lastline, count, out); - free(lastline); - lastline = input; - count = 0; - } - count++; - } - print_line(lastline, count, out); - free(lastline); - - return EXIT_SUCCESS; -} diff --git a/update.c b/update.c deleted file mode 100644 index 27a04ddee..000000000 --- a/update.c +++ /dev/null @@ -1,112 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini update implementation for busybox; much pasted from update-2.11 - * - * - * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>. - * Copyright (c) 1996, 1997, 1999 Torsten Poulin. - * Copyright (c) 2000 by Karl M. Hegbloom <karlheg@debian.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* - * Note: This program is only necessary if you are running a 2.0.x (or - * earlier) kernel. 2.2.x and higher flush filesystem buffers automatically. - */ - -#include <sys/param.h> -#include <sys/syslog.h> -#include <unistd.h> /* for getopt() */ -#include <stdlib.h> - -#if __GNU_LIBRARY__ > 5 - #include <sys/kdaemon.h> -#else - extern int bdflush (int func, long int data); -#endif - -#include "busybox.h" - -static unsigned int sync_duration = 30; -static unsigned int flush_duration = 5; -static int use_sync = 0; - -extern int update_main(int argc, char **argv) -{ - int pid; - int opt; - - while ((opt = getopt(argc, argv, "Ss:f:")) > 0) { - switch (opt) { - case 'S': - use_sync = 1; - break; - case 's': - sync_duration = atoi(optarg); - break; - case 'f': - flush_duration = atoi(optarg); - break; - default: - show_usage(); - } - } - - if (daemon(0, 1) < 0) - perror_msg_and_die("daemon"); - -#ifdef OPEN_MAX - for (pid = 0; pid < OPEN_MAX; pid++) close(pid); -#else - /* glibc 2.1.92 requires using sysconf(_SC_OPEN_MAX) */ - for (pid = 0; pid < sysconf(_SC_OPEN_MAX); pid++) close(pid); -#endif - - /* This is no longer necessary since 1.3.5x, but it will harmlessly - * exit if that is the case. - */ - - /* set the program name that will show up in a 'ps' listing */ - argv[0] = "bdflush (update)"; - argv[1] = NULL; - argv[2] = NULL; - for (;;) { - if (use_sync) { - sleep(sync_duration); - sync(); - } else { - sleep(flush_duration); - if (bdflush(1, 0) < 0) { - openlog("update", LOG_CONS, LOG_DAEMON); - syslog(LOG_INFO, - "This kernel does not need update(8). Exiting."); - closelog(); - return EXIT_SUCCESS; - } - } - } - - return EXIT_SUCCESS; -} - -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ diff --git a/uptime.c b/uptime.c deleted file mode 100644 index 6758d959e..000000000 --- a/uptime.c +++ /dev/null @@ -1,77 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini uptime implementation for busybox - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* 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 BB_FEATURE_UTMP_SUPPORT #define - */ - -/* getopt not needed */ - - -#include <stdio.h> -#include <time.h> -#include <errno.h> -#include <stdlib.h> -#include "busybox.h" - -static const int FSHIFT = 16; /* nr of bits of precision */ -#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) - - -extern 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(" %2d:%02d%s up ", - current_time->tm_hour%12 ? current_time->tm_hour%12 : 12, - current_time->tm_min, current_time->tm_hour > 11 ? "pm" : "am"); - 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; -} diff --git a/usage.c b/usage.c deleted file mode 100644 index dfea1f96b..000000000 --- a/usage.c +++ /dev/null @@ -1,10 +0,0 @@ -#include "busybox.h" - -const char usage_messages[] = - -#define MAKE_USAGE -#include "usage.h" - -#include "applets.h" - -; diff --git a/usage.h b/usage.h deleted file mode 100644 index 5e514274a..000000000 --- a/usage.h +++ /dev/null @@ -1,1894 +0,0 @@ -#define addgroup_trivial_usage \ - "[OPTIONS] <group_name>" -#define addgroup_full_usage \ - "Adds a group to the system" \ - "Options:\n" \ - "\t-g\t\tspecify gid\n" - -#define adduser_trivial_usage \ - "[OPTIONS] <user_name>" -#define adduser_full_usage \ - "Adds a user to the system" \ - "Options:\n" \ - "\t-h\t\thome directory\n" \ - "\t-s\t\tshell\n" \ - "\t-g\t\tGECOS string\n" - -#define adjtimex_trivial_usage \ - "[-q] [-o offset] [-f frequency] [-p timeconstant] [-t tick]" -#define adjtimex_full_usage \ - "Reads and optionally sets system timebase parameters.\n" \ - "See adjtimex(2).\n\n" \ - "Options:\n" \ - "\t-q\t\tquiet mode - do not print\n" \ - "\t-o offset\ttime offset, microseconds\n" \ - "\t-f frequency\tfrequency adjust, integer kernel units (65536 is 1ppm)\n" \ - "\t\t\t(positive values make the system clock run fast)\n" \ - "\t-t tick\t\tmicroseconds per tick, usually 10000\n" \ - "\t-p timeconstant\n" - -#define ar_trivial_usage \ - "-[ov][ptx] ARCHIVE FILES" -#define ar_full_usage \ - "Extract or list FILES from an ar archive.\n\n" \ - "Options:\n" \ - "\t-o\t\tpreserve original dates\n" \ - "\t-p\t\textract to stdout\n" \ - "\t-t\t\tlist\n" \ - "\t-x\t\textract\n" \ - "\t-v\t\tverbosely list files processed\n" - -#define basename_trivial_usage \ - "FILE [SUFFIX]" -#define basename_full_usage \ - "Strips directory path and suffixes from FILE.\n" \ - "If specified, also removes any trailing SUFFIX." -#define basename_example_usage \ - "$ basename /usr/local/bin/foo\n" \ - "foo\n" \ - "$ basename /usr/local/bin/\n" \ - "bin\n" \ - "$ basename /foo/bar.txt .txt\n" \ - "bar" - -#define bunzip2_trivial_usage \ - "FILE" -#define bunzip2_full_usage \ - "Uncompress FILE to current directory, stripping its .bz2 extension.\n"\ - " -k is assumed" - -#define cat_trivial_usage \ - "[FILE]..." -#define cat_full_usage \ - "Concatenates FILE(s) and prints them to stdout." -#define cat_example_usage \ - "$ cat /proc/uptime\n" \ - "110716.72 17.67" - -#define chgrp_trivial_usage \ - "[OPTION]... GROUP FILE..." -#define chgrp_full_usage \ - "Change the group membership of each FILE to GROUP.\n" \ - "\nOptions:\n" \ - "\t-R\tChanges files and directories recursively." -#define chgrp_example_usage \ - "$ ls -l /tmp/foo\n" \ - "-r--r--r-- 1 andersen andersen 0 Apr 12 18:25 /tmp/foo\n" \ - "$ chgrp root /tmp/foo\n" \ - "$ ls -l /tmp/foo\n" \ - "-r--r--r-- 1 andersen root 0 Apr 12 18:25 /tmp/foo\n" - -#define chmod_trivial_usage \ - "[-R] MODE[,MODE]... FILE..." -#define chmod_full_usage \ - "Each MODE is one or more of the letters ugoa, one of the\n" \ - "symbols +-= and one or more of the letters rwxst.\n\n" \ - "Options:\n" \ - "\t-R\tChanges files and directories recursively." -#define chmod_example_usage \ - "$ ls -l /tmp/foo\n" \ - "-rw-rw-r-- 1 root root 0 Apr 12 18:25 /tmp/foo\n" \ - "$ chmod u+x /tmp/foo\n" \ - "$ ls -l /tmp/foo\n" \ - "-rwxrw-r-- 1 root root 0 Apr 12 18:25 /tmp/foo*\n" \ - "$ chmod 444 /tmp/foo\n" \ - "$ ls -l /tmp/foo\n" \ - "-r--r--r-- 1 root root 0 Apr 12 18:25 /tmp/foo\n" - -#define chown_trivial_usage \ - "[ -Rh ]... OWNER[<.|:>[GROUP]] FILE..." -#define chown_full_usage \ - "Change the owner and/or group of each FILE to OWNER and/or GROUP.\n" \ - "\nOptions:\n" \ - "\t-R\tChanges files and directories recursively.\n" \ - "\t-h\tDo not dereference symbolic links." -#define chown_example_usage \ - "$ ls -l /tmp/foo\n" \ - "-r--r--r-- 1 andersen andersen 0 Apr 12 18:25 /tmp/foo\n" \ - "$ chown root /tmp/foo\n" \ - "$ ls -l /tmp/foo\n" \ - "-r--r--r-- 1 root andersen 0 Apr 12 18:25 /tmp/foo\n" \ - "$ chown root.root /tmp/foo\n" \ - "ls -l /tmp/foo\n" \ - "-r--r--r-- 1 root root 0 Apr 12 18:25 /tmp/foo\n" - -#define chroot_trivial_usage \ - "NEWROOT [COMMAND...]" -#define chroot_full_usage \ - "Run COMMAND with root directory set to NEWROOT." -#define chroot_example_usage \ - "$ ls -l /bin/ls\n" \ - "lrwxrwxrwx 1 root root 12 Apr 13 00:46 /bin/ls -> /BusyBox\n" \ - "$ mount /dev/hdc1 /mnt -t minix\n" \ - "$ chroot /mnt\n" \ - "$ ls -l /bin/ls\n" \ - "-rwxr-xr-x 1 root root 40816 Feb 5 07:45 /bin/ls*\n" - -#define chvt_trivial_usage \ - "N" -#define chvt_full_usage \ - "Changes the foreground virtual terminal to /dev/ttyN" - -#define clear_trivial_usage \ - "" -#define clear_full_usage \ - "Clear screen." - -#define cmp_trivial_usage \ - "FILE1 [FILE2]" -#define cmp_full_usage \ - "\t-s\tquiet mode - do not print\n" \ - "Compare files." - -#define cp_trivial_usage \ - "[OPTION]... SOURCE DEST" -#define cp_full_usage \ - "Copies SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.\n" \ - "\n" \ - "\t-a\tSame as -dpR\n" \ - "\t-d\tPreserves links\n" \ - "\t-p\tPreserves file attributes if possible\n" \ - "\t-f\tforce (implied; ignored) - always set\n" \ - "\t-R\tCopies directories recursively" - -#define cpio_trivial_usage \ - "-[dimtuv][F cpiofile]" -#define cpio_full_usage \ - "Extract or list files from a cpio archive\n" \ - "Main operation mode:\n" \ - "\td\t\tmake leading directories\n" \ - "\ti\t\textract\n" \ - "\tm\t\tpreserve mtime\n" \ - "\tt\t\tlist\n" \ - "\tu\t\tunconditional overwrite\t" \ - "\tF\t\tinput from file\t" - -#define cut_trivial_usage \ - "[OPTION]... [FILE]..." -#define cut_full_usage \ - "Prints selected fields from each input FILE to standard output.\n\n" \ - "Options:\n" \ - "\t-b LIST\t\tOutput only bytes from LIST\n" \ - "\t-c LIST\t\tOutput only characters from LIST\n" \ - "\t-d CHAR\t\tUse CHAR instead of tab as the field delimiter\n" \ - "\t-s\t\tOutput only the lines containing delimiter\n" \ - "\t-f N\t\tPrint only these fields\n" \ - "\t-n\t\tIgnored" -#define cut_example_usage \ - "$ echo "Hello world" | cut -f 1 -d ' '\n" \ - "Hello\n" \ - "$ echo "Hello world" | cut -f 2 -d ' '\n" \ - "world\n" - -#define date_trivial_usage \ - "[OPTION]... [+FORMAT]" -#define date_full_usage \ - "Displays the current time in the given FORMAT, or sets the system date.\n" \ - "\nOptions:\n" \ - "\t-R\t\tOutputs RFC-822 compliant date string\n" \ - "\t-d STRING\tdisplay time described by STRING, not `now'\n" \ - "\t-s\t\tSets time described by STRING\n" \ - "\t-u\t\tPrints or sets Coordinated Universal Time" -#define date_example_usage \ - "$ date\n" \ - "Wed Apr 12 18:52:41 MDT 2000\n" - -#define dc_trivial_usage \ - "expression ..." -#define dc_full_usage \ - "This is a Tiny RPN calculator that understands the\n" \ - "following operations: +, -, /, *, and, or, not, eor.\n" \ - "i.e., 'dc 2 2 add' -> 4, and 'dc 8 8 \\* 2 2 + /' -> 16" -#define dc_example_usage \ - "$ dc 2 2 +\n" \ - "4\n" \ - "$ dc 8 8 \* 2 2 + /\n" \ - "16\n" \ - "$ dc 0 1 and\n" \ - "0\n" \ - "$ dc 0 1 or\n" \ - "1\n" \ - "$ echo 72 9 div 8 mul | dc\n" \ - "64\n" - -#define dd_trivial_usage \ - "[if=FILE] [of=FILE] [bs=N] [count=N] [skip=N]\n" \ - "\t [seek=N] [conv=notrunc|sync]" -#define dd_full_usage \ - "Copy a file, converting and formatting according to options\n\n" \ - "\tif=FILE\t\tread from FILE instead of stdin\n" \ - "\tof=FILE\t\twrite to FILE instead of stdout\n" \ - "\tbs=N\t\tread and write N bytes at a time\n" \ - "\tcount=N\t\tcopy only N input blocks\n" \ - "\tskip=N\t\tskip N input blocks\n" \ - "\tseek=N\t\tskip N output blocks\n" \ - "\tconv=notrunc\tdon't truncate output file\n" \ - "\tconv=sync\tpad blocks with zeros\n" \ - "\n" \ - "Numbers may be suffixed by c (x1), w (x2), b (x512), kD (x1000), k (x1024),\n" \ - "MD (x1000000), M (x1048576), GD (x1000000000) or G (x1073741824)." -#define dd_example_usage \ - "$ dd if=/dev/zero of=/dev/ram1 bs=1M count=4\n" \ - "4+0 records in\n" \ - "4+0 records out\n" - -#define deallocvt_trivial_usage \ - "N" -#define deallocvt_full_usage \ - "Deallocate unused virtual terminal /dev/ttyN" - -#define delgroup_trivial_usage \ - "GROUP" -#define delgroup_full_usage \ - "Deletes group GROUP from the system" - -#define deluser_trivial_usage \ - "USER" -#define deluser_full_usage \ - "Deletes user USER from the system" - -#ifdef BB_FEATURE_HUMAN_READABLE - #define USAGE_HUMAN_READABLE(a) a - #define USAGE_NOT_HUMAN_READABLE(a) -#else - #define USAGE_HUMAN_READABLE(a) - #define USAGE_NOT_HUMAN_READABLE(a) a -#endif -#define df_trivial_usage \ - "[-" USAGE_HUMAN_READABLE("hm") USAGE_NOT_HUMAN_READABLE("") "k] [FILESYSTEM ...]" -#define df_full_usage \ - "Print the filesystem space used and space available.\n\n" \ - "Options:\n" \ - USAGE_HUMAN_READABLE( \ - "\n\t-h\tprint sizes in human readable format (e.g., 1K 243M 2G )\n" \ - "\t-m\tprint sizes in megabytes\n" \ - "\t-k\tprint sizes in kilobytes(default)") USAGE_NOT_HUMAN_READABLE( \ - "\n\t-k\tprint sizes in kilobytes(compatibility)") -#define df_example_usage \ - "$ df\n" \ - "Filesystem 1k-blocks Used Available Use% Mounted on\n" \ - "/dev/sda3 8690864 8553540 137324 98% /\n" \ - "/dev/sda1 64216 36364 27852 57% /boot\n" \ - "$ df /dev/sda3\n" \ - "Filesystem 1k-blocks Used Available Use% Mounted on\n" \ - "/dev/sda3 8690864 8553540 137324 98% /\n" - -#define dirname_trivial_usage \ - "[FILENAME ...]" -#define dirname_full_usage \ - "Strips non-directory suffix from FILENAME" -#define dirname_example_usage \ - "$ dirname /tmp/foo\n" \ - "/tmp\n" \ - "$ dirname /tmp/foo/\n" \ - "/tmp\n" - -#define dmesg_trivial_usage \ - "[-c] [-n LEVEL] [-s SIZE]" -#define dmesg_full_usage \ - "Prints or controls the kernel ring buffer\n\n" \ - "Options:\n" \ - "\t-c\t\tClears the ring buffer's contents after printing\n" \ - "\t-n LEVEL\tSets console logging level\n" \ - "\t-s SIZE\t\tUse a buffer of size SIZE" - -#define dos2unix_trivial_usage \ - "[option] [FILE]" -#define dos2unix_full_usage \ - "Converts FILE from dos format to unix format. When no option\n" \ - "is given, the input is converted to the opposite output format.\n" \ - "When no file is given, uses stdin for input and stdout for output.\n\n" \ - "Options:\n" \ - "\t-u\toutput will be in UNIX format\n" \ - "\t-d\toutput will be in DOS format" - -#define dpkg_trivial_usage \ - "-i package_file\n" - "[-CPru] package_name" -#define dpkg_full_usage \ - "\t-i\tInstall the package\n" \ - "\t-C\tConfigure an unpackaged package\n" \ - "\t-P\tPurge all files of a package\n" \ - "\t-r\tRemove all but the configuration files for a package\n" \ - "\t-u\tUnpack a package, but dont configure it\n" - -#define dpkg_deb_trivial_usage \ - "[-cefItxX] FILE [argument]" -#define dpkg_deb_full_usage \ - "Perform actions on debian packages (.debs)\n\n" \ - "Options:\n" \ - "\t-c\tList contents of filesystem tree\n" \ - "\t-e\tExtract control files to [argument] directory\n" \ - "\t-f\tDisplay control field name starting with [argument]\n" \ - "\t-I\tDisplay the control filenamed [argument]\n" \ - "\t-t\tExtract filesystem tree to stdout in tar format\n" \ - "\t-x\tExtract packages filesystem tree to directory\n" \ - "\t-X\tVerbose extract" -#define dpkg_deb_example_usage \ - "$ dpkg-deb -X ./busybox_0.48-1_i386.deb /tmp\n" - -#define du_trivial_usage \ - "[-ls" USAGE_HUMAN_READABLE("hm") USAGE_NOT_HUMAN_READABLE("") "k] [FILE]..." -#define du_full_usage \ - "Summarizes disk space used for each FILE and/or directory.\n" \ - "Disk space is printed in units of 1024 bytes.\n\n" \ - "Options:\n" \ - "\t-l\tcount sizes many times if hard linked\n" \ - "\t-s\tdisplay only a total for each argument" \ - USAGE_HUMAN_READABLE( \ - "\n\t-h\tprint sizes in human readable format (e.g., 1K 243M 2G )\n" \ - "\t-m\tprint sizes in megabytes\n" \ - "\t-k\tprint sizes in kilobytes(default)") USAGE_NOT_HUMAN_READABLE( \ - "\n\t-k\tprint sizes in kilobytes(compatibility)") -#define du_example_usage \ - "$ du\n" \ - "16 ./CVS\n" \ - "12 ./kernel-patches/CVS\n" \ - "80 ./kernel-patches\n" \ - "12 ./tests/CVS\n" \ - "36 ./tests\n" \ - "12 ./scripts/CVS\n" \ - "16 ./scripts\n" \ - "12 ./docs/CVS\n" \ - "104 ./docs\n" \ - "2417 .\n" - -#define dumpkmap_trivial_usage \ - "> keymap" -#define dumpkmap_full_usage \ - "Prints out a binary keyboard translation table to standard output." -#define dumpkmap_example_usage \ - "$ dumpkmap > keymap\n" - -#define dutmp_trivial_usage \ - "[FILE]" -#define dutmp_full_usage \ - "Dump utmp file format (pipe delimited) from FILE\n" \ - "or stdin to stdout. (i.e., 'dutmp /var/run/utmp')" -#define dutmp_example_usage \ - "$ dutmp /var/run/utmp\n" \ - "8|7||si|||0|0|0|955637625|760097|0\n" \ - "2|0|~|~~|reboot||0|0|0|955637625|782235|0\n" \ - "1|20020|~|~~|runlevel||0|0|0|955637625|800089|0\n" \ - "8|125||l4|||0|0|0|955637629|998367|0\n" \ - "6|245|tty1|1|LOGIN||0|0|0|955637630|998974|0\n" \ - "6|246|tty2|2|LOGIN||0|0|0|955637630|999498|0\n" \ - "7|336|pts/0|vt00andersen|andersen|:0.0|0|0|0|955637763|0|0\n" - -#define echo_trivial_usage \ - "[-neE] [ARG ...]" -#define echo_full_usage \ - "Prints the specified ARGs to stdout\n\n" \ - "Options:\n" \ - "\t-n\tsuppress trailing newline\n" \ - "\t-e\tinterpret backslash-escaped characters (i.e., \\t=tab)\n" \ - "\t-E\tdisable interpretation of backslash-escaped characters" -#define echo_example_usage \ - "$ echo "Erik is cool"\n" \ - "Erik is cool\n" \ - "$ echo -e "Erik\\nis\\ncool"\n" \ - "Erik\n" \ - "is\n" \ - "cool\n" \ - "$ echo "Erik\\nis\\ncool"\n" \ - "Erik\\nis\\ncool\n" - -#define env_trivial_usage \ - "[-iu] [-] [name=value]... [command]" -#define env_full_usage \ - "Prints the current environment or runs a program after setting\n" \ - "up the specified environment.\n\n" \ - "Options:\n" \ - "\t-, -i\tstart with an empty environment\n" \ - "\t-u\tremove variable from the environment\n" - -#define expr_trivial_usage \ - "EXPRESSION" -#define expr_full_usage \ - "Prints the value of EXPRESSION to standard output.\n\n" \ - "EXPRESSION may be:\n" \ - "\tARG1 | ARG2 ARG1 if it is neither null nor 0, otherwise ARG2\n" \ - "\tARG1 & ARG2 ARG1 if neither argument is null or 0, otherwise 0\n" \ - "\tARG1 < ARG2 ARG1 is less than ARG2\n" \ - "\tARG1 <= ARG2 ARG1 is less than or equal to ARG2\n" \ - "\tARG1 = ARG2 ARG1 is equal to ARG2\n" \ - "\tARG1 != ARG2 ARG1 is unequal to ARG2\n" \ - "\tARG1 >= ARG2 ARG1 is greater than or equal to ARG2\n" \ - "\tARG1 > ARG2 ARG1 is greater than ARG2\n" \ - "\tARG1 + ARG2 arithmetic sum of ARG1 and ARG2\n" \ - "\tARG1 - ARG2 arithmetic difference of ARG1 and ARG2\n" \ - "\tARG1 * ARG2 arithmetic product of ARG1 and ARG2\n" \ - "\tARG1 / ARG2 arithmetic quotient of ARG1 divided by ARG2\n" \ - "\tARG1 % ARG2 arithmetic remainder of ARG1 divided by ARG2\n" \ - "\tSTRING : REGEXP anchored pattern match of REGEXP in STRING\n" \ - "\tmatch STRING REGEXP same as STRING : REGEXP\n" \ - "\tsubstr STRING POS LENGTH substring of STRING, POS counted from 1\n" \ - "\tindex STRING CHARS index in STRING where any CHARS is found,\n" \ - "\t or 0\n" \ - "\tlength STRING length of STRING\n" \ - "\tquote TOKEN interpret TOKEN as a string, even if\n" \ - "\t it is a keyword like `match' or an\n" \ - "\t operator like `/'\n" \ - "\t( EXPRESSION ) value of EXPRESSION\n\n" \ - "Beware that many operators need to be escaped or quoted for shells.\n" \ - "Comparisons are arithmetic if both ARGs are numbers, else\n" \ - "lexicographical. Pattern matches return the string matched between \n" \ - "\\( and \\) or null; if \\( and \\) are not used, they return the number \n" \ - "of characters matched or 0." - -#define false_trivial_usage \ - "" -#define false_full_usage \ - "Return an exit code of FALSE (1)." -#define false_example_usage \ - "$ false\n" \ - "$ echo $?\n" \ - "1\n" - -#define fbset_trivial_usage \ - "[options] [mode]" -#define fbset_full_usage \ - "Show and modify frame buffer settings" -#define fbset_example_usage \ - "$ fbset\n" \ - "mode "1024x768-76"\n" \ - "\t# D: 78.653 MHz, H: 59.949 kHz, V: 75.694 Hz\n" \ - "\tgeometry 1024 768 1024 768 16\n" \ - "\ttimings 12714 128 32 16 4 128 4\n" \ - "\taccel false\n" \ - "\trgba 5/11,6/5,5/0,0/0\n" \ - "endmode\n" - -#define fdflush_trivial_usage \ - "DEVICE" -#define fdflush_full_usage \ - "Forces floppy disk drive to detect disk change" - -#ifdef BB_FEATURE_FIND_TYPE - #define USAGE_FIND_TYPE(a) a -#else - #define USAGE_FIND_TYPE(a) -#endif -#ifdef BB_FEATURE_FIND_PERM - #define USAGE_FIND_PERM(a) a -#else - #define USAGE_FIND_PERM(a) -#endif -#ifdef BB_FEATURE_FIND_MTIME - #define USAGE_FIND_MTIME(a) a -#else - #define USAGE_FIND_MTIME(a) -#endif - -#define find_trivial_usage \ - "[PATH...] [EXPRESSION]" -#define find_full_usage \ - "Search for files in a directory hierarchy. The default PATH is\n" \ - "the current directory; default EXPRESSION is '-print'\n" \ - "\nEXPRESSION may consist of:\n" \ - "\t-follow\t\tDereference symbolic links.\n" \ - "\t-name PATTERN\tFile name (leading directories removed) matches PATTERN.\n" \ - "\t-print\t\tPrint (default and assumed).\n" \ - USAGE_FIND_TYPE( \ - "\n\t-type X\t\tFiletype matches X (where X is one of: f,d,l,b,c,...)" \ -) USAGE_FIND_PERM( \ - "\n\t-perm PERMS\tPermissions match any of (+NNN); all of (-NNN);\n\t\t\tor exactly (NNN)" \ -) USAGE_FIND_MTIME( \ - "\n\t-mtime TIME\tModified time is greater than (+N); less than (-N);\n\t\t\tor exactly (N) days") -#define find_example_usage \ - "$ find / -name /etc/passwd\n" \ - "/etc/passwd\n" - -#define free_trivial_usage \ - "" -#define free_full_usage \ - "Displays the amount of free and used system memory" -#define free_example_usage \ - "$ free\n" \ - " total used free shared buffers\n" \ - " Mem: 257628 248724 8904 59644 93124\n" \ - " Swap: 128516 8404 120112\n" \ - "Total: 386144 257128 129016\n" \ - -#define freeramdisk_trivial_usage \ - "DEVICE" -#define freeramdisk_full_usage \ - "Frees all memory used by the specified ramdisk." -#define freeramdisk_example_usage \ - "$ freeramdisk /dev/ram2\n" - -#define fsck_minix_trivial_usage \ - "[-larvsmf] /dev/name" -#define fsck_minix_full_usage \ - "Performs a consistency check for MINIX filesystems.\n\n" \ - "Options:\n" \ - "\t-l\tLists all filenames\n" \ - "\t-r\tPerform interactive repairs\n" \ - "\t-a\tPerform automatic repairs\n" \ - "\t-v\tverbose\n" \ - "\t-s\tOutputs super-block information\n" \ - "\t-m\tActivates MINIX-like \"mode not cleared\" warnings\n" \ - "\t-f\tForce file system check." - -#define getopt_trivial_usage \ - "[OPTIONS]..." -#define getopt_full_usage \ - "Parse command options\n" \ - "\t-a, --alternative Allow long options starting with single -\n" \ - "\t-l, --longoptions=longopts Long options to be recognized\n" \ - "\t-n, --name=progname The name under which errors are reported\n" \ - "\t-o, --options=optstring Short options to be recognized\n" \ - "\t-q, --quiet Disable error reporting by getopt(3)\n" \ - "\t-Q, --quiet-output No normal output\n" \ - "\t-s, --shell=shell Set shell quoting conventions\n" \ - "\t-T, --test Test for getopt(1) version\n" \ - "\t-u, --unqote Do not quote the output" -#define getopt_example_usage \ - "$ cat getopt.test\n" \ - "#!/bin/sh\n" \ - "GETOPT=`getopt -o ab:c:: --long a-long,b-long:,c-long:: \\\n" \ - " -n 'example.busybox' -- "$@"`\n" \ - "if [ $? != 0 ] ; then exit 1 ; fi\n" \ - "eval set -- "$GETOPT"\n" \ - "while true ; do\n" \ - " case $1 in\n" \ - " -a|--a-long) echo \"Option a\" ; shift ;;\n" \ - " -b|--b-long) echo \"Option b, argument \`$2'\" ; shift 2 ;;\n" \ - " -c|--c-long)\n" \ - " case "$2" in\n" \ - " \"\") echo \"Option c, no argument\"; shift 2 ;;\n" \ - " *) echo \"Option c, argument \`$2'\" ; shift 2 ;;\n" \ - " esac ;;\n" \ - " --) shift ; break ;;\n" \ - " *) echo \"Internal error!\" ; exit 1 ;;\n" \ - " esac\n" \ - "done\n" - -#define getty_trivial_usage \ - "getty [OPTIONS]... baud_rate,... line [termtype]" -#define getty_full_usage \ - "\nOpens a tty, prompts for a login name, then invokes /bin/login\n\n" \ - "Options:\n" \ - "\t-h\t\tEnable hardware (RTS/CTS) flow control.\n" \ - "\t-i\t\tDo not display /etc/issue before running login.\n" \ - "\t-L\t\tLocal line, so do not do carrier detect.\n" \ - "\t-m\t\tGet baud rate from modem's CONNECT status message.\n" \ - "\t-w\t\tWait for a CR or LF before sending /etc/issue.\n" \ - "\t-l login_app\tInvoke login_app instead of /bin/login.\n" \ - "\t-t timeout\tTerminate after timeout if no username is read.\n" \ - "\t-I initstring\tSets the init string to send before anything else.\n" \ - "\t-H login_host\tLog login_host into the utmp file as the hostname." - - -#define grep_trivial_usage \ - "[-ihHnqvs] PATTERN [FILEs...]" -#define grep_full_usage \ - "Search for PATTERN in each FILE or standard input.\n\n" \ - "Options:\n" \ - "\t-H\tprefix output lines with filename where match was found\n" \ - "\t-h\tsuppress the prefixing filename on output\n" \ - "\t-i\tignore case distinctions\n" \ - "\t-l\tlist names of files that match\n" \ - "\t-n\tprint line number with output lines\n" \ - "\t-q\tbe quiet. Returns 0 if result was found, 1 otherwise\n" \ - "\t-v\tselect non-matching lines\n" \ - "\t-s\tsuppress file open/read error messages" -#define grep_example_usage \ - "$ grep root /etc/passwd\n" \ - "root:x:0:0:root:/root:/bin/bash\n" \ - "$ grep ^[rR]oo. /etc/passwd\n" \ - "root:x:0:0:root:/root:/bin/bash\n" - -#define gunzip_trivial_usage \ - "[OPTION]... FILE" -#define gunzip_full_usage \ - "Uncompress FILE (or standard input if FILE is '-').\n\n" \ - "Options:\n" \ - "\t-c\tWrite output to standard output\n" \ - "\t-t\tTest compressed file integrity" -#define gunzip_example_usage \ - "$ ls -la /tmp/BusyBox*\n" \ - "-rw-rw-r-- 1 andersen andersen 557009 Apr 11 10:55 /tmp/BusyBox-0.43.tar.gz\n" \ - "$ gunzip /tmp/BusyBox-0.43.tar.gz\n" \ - "$ ls -la /tmp/BusyBox*\n" \ - "-rw-rw-r-- 1 andersen andersen 1761280 Apr 14 17:47 /tmp/BusyBox-0.43.tar\n" - -#define gzip_trivial_usage \ - "[OPTION]... FILE" -#define gzip_full_usage \ - "Compress FILE with maximum compression.\n" \ - "When FILE is '-', reads standard input. Implies -c.\n\n" \ - "Options:\n" \ - "\t-c\tWrite output to standard output instead of FILE.gz\n" \ - "\t-d\tdecompress" -#define gzip_example_usage \ - "$ ls -la /tmp/busybox*\n" \ - "-rw-rw-r-- 1 andersen andersen 1761280 Apr 14 17:47 /tmp/busybox.tar\n" \ - "$ gzip /tmp/busybox.tar\n" \ - "$ ls -la /tmp/busybox*\n" \ - "-rw-rw-r-- 1 andersen andersen 554058 Apr 14 17:49 /tmp/busybox.tar.gz\n" - -#define halt_trivial_usage \ - "" -#define halt_full_usage \ - "Halt the system." - -#define head_trivial_usage \ - "[OPTION] [FILE]..." -#define head_full_usage \ - "Print first 10 lines of each FILE to standard output.\n" \ - "With more than one FILE, precede each with a header giving the\n" \ - "file name. With no FILE, or when FILE is -, read standard input.\n\n" \ - "Options:\n" \ - "\t-n NUM\t\tPrint first NUM lines instead of first 10" -#define head_example_usage \ - "$ head -n 2 /etc/passwd\n" \ - "root:x:0:0:root:/root:/bin/bash\n" \ - "daemon:x:1:1:daemon:/usr/sbin:/bin/sh\n" - -#define hostid_trivial_usage \ - "" -#define hostid_full_usage \ - "Print out a unique 32-bit identifier for the machine." - -#define hostname_trivial_usage \ - "[OPTION] {hostname | -F FILE}" -#define hostname_full_usage \ - "Get or set the hostname or DNS domain name. If a hostname is given\n" \ - "(or FILE with the -F parameter), the host name will be set.\n\n" \ - "Options:\n" \ - "\t-s\t\tShort\n" \ - "\t-i\t\tAddresses for the hostname\n" \ - "\t-d\t\tDNS domain name\n" \ - "\t-F, --file FILE\tUse the contents of FILE to specify the hostname" -#define hostname_example_usage \ - "$ hostname\n" \ - "sage \n" - -#define id_trivial_usage \ - "[OPTIONS]... [USERNAME]" -#define id_full_usage \ - "Print information for USERNAME or the current user\n\n" \ - "Options:\n" \ - "\t-g\tprints only the group ID\n" \ - "\t-u\tprints only the user ID\n" \ - "\t-n\tprint a name instead of a number (with for -ug)\n" \ - "\t-r\tprints the real user ID instead of the effective ID (with -ug)" -#define id_example_usage \ - "$ id\n" \ - "uid=1000(andersen) gid=1000(andersen)\n" - -#ifdef BB_FEATURE_IFCONFIG_SLIP - #define USAGE_SIOCSKEEPALIVE(a) a -#else - #define USAGE_SIOCSKEEPALIVE(a) -#endif -#ifdef BB_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ - #define USAGE_IFCONFIG_MII(a) a -#else - #define USAGE_IFCONFIG_MII(a) -#endif -#ifdef BB_FEATURE_IFCONFIG_HW - #define USAGE_IFCONFIG_HW(a) a -#else - #define USAGE_IFCONFIG_HW(a) -#endif -#ifdef BB_FEATURE_IFCONFIG_STATUS - #define USAGE_IFCONFIG_OPT_A(a) a -#else - #define USAGE_IFCONFIG_OPT_A(a) -#endif - -#define ifconfig_trivial_usage \ - USAGE_IFCONFIG_OPT_A("[-a]") " <interface> [<address>]" -#define ifconfig_full_usage \ - "configure a network interface\n\n" \ - "Options:\n" \ - "\t[[-]broadcast [<address>]] [[-]pointopoint [<address>]]\n" \ - "\t[netmask <address>] [dstaddr <address>]\n" \ - USAGE_SIOCSKEEPALIVE("\t[outfill <NN>] [keepalive <NN>]\n") \ - "\t" USAGE_IFCONFIG_HW("[hw ether <address>] ") \ - "[metric <NN>] [mtu <NN>]\n" \ - "\t[[-]trailers] [[-]arp] [[-]allmulti]\n" \ - "\t[multicast] [[-]promisc] [txqueuelen <NN>] [[-]dynamic]\n" \ - USAGE_IFCONFIG_MII("\t[mem_start <NN>] [io_addr <NN>] [irq <NN>]\n") \ - "\t[up|down] ..." - -#define init_trivial_usage \ - "" -#define init_full_usage \ - "Init is the parent of all processes." -#define init_notes_usage \ -"This version of init is designed to be run only by the kernel.\n" \ -"\n" \ -"BusyBox init doesn't support multiple runlevels. The runlevels field of\n" \ -"the /etc/inittab file is completely ignored by BusyBox init. If you want \n" \ -"runlevels, use sysvinit.\n" \ -"\n" \ -"BusyBox init works just fine without an inittab. If no inittab is found, \n" \ -"it has the following default behavior:\n" \ -"\n" \ -" ::sysinit:/etc/init.d/rcS\n" \ -" ::askfirst:/bin/sh\n" \ -" ::ctrlaltdel:/sbin/reboot\n" \ -" ::shutdown:/sbin/swapoff -a\n" \ -" ::shutdown:/bin/umount -a -r\n" \ -"\n" \ -"if it detects that /dev/console is _not_ a serial console, it will also run:\n" \ -"\n" \ -" tty2::askfirst:/bin/sh\n" \ -" tty3::askfirst:/bin/sh\n" \ -" tty4::askfirst:/bin/sh\n" \ -"\n" \ -"If you choose to use an /etc/inittab file, the inittab entry format is as follows:\n" \ -"\n" \ -" <id>:<runlevels>:<action>:<process>\n" \ -"\n" \ -" <id>: \n" \ -"\n" \ -" WARNING: This field has a non-traditional meaning for BusyBox init!\n" \ -" The id field is used by BusyBox init to specify the controlling tty for\n" \ -" the specified process to run on. The contents of this field are\n" \ -" appended to "/dev/" and used as-is. There is no need for this field to\n" \ -" be unique, although if it isn't you may have strange results. If this\n" \ -" field is left blank, the controlling tty is set to the console. Also\n" \ -" note that if BusyBox detects that a serial console is in use, then only\n" \ -" entries whose controlling tty is either the serial console or /dev/null\n" \ -" will be run. BusyBox init does nothing with utmp. We don't need no\n" \ -" stinkin' utmp.\n" \ -"\n" \ -" <runlevels>: \n" \ -"\n" \ -" The runlevels field is completely ignored.\n" \ -"\n" \ -" <action>: \n" \ -"\n" \ -" Valid actions include: sysinit, respawn, askfirst, wait, \n" \ -" once, ctrlaltdel, and shutdown.\n" \ -"\n" \ -" The available actions can be classified into two groups: actions\n" \ -" that are run only once, and actions that are re-run when the specified\n" \ -" process exits.\n" \ -"\n" \ -" Run only-once actions:\n" \ -"\n" \ -" 'sysinit' is the first item run on boot. init waits until all\n" \ -" sysinit actions are completed before continuing. Following the\n" \ -" completion of all sysinit actions, all 'wait' actions are run.\n" \ -" 'wait' actions, like 'sysinit' actions, cause init to wait until\n" \ -" the specified task completes. 'once' actions are asynchronous,\n" \ -" therefore, init does not wait for them to complete. 'ctrlaltdel'\n" \ -" actions are run when the system detects that someone on the system\n" \ -" console has pressed the CTRL-ALT-DEL key combination. Typically one\n" \ -" wants to run 'reboot' at this point to cause the system to reboot.\n" \ -" Finally the 'shutdown' action specifies the actions to taken when\n" \ -" init is told to reboot. Unmounting filesystems and disabling swap\n" \ -" is a very good here\n" \ -"\n" \ -" Run repeatedly actions:\n" \ -"\n" \ -" 'respawn' actions are run after the 'once' actions. When a process\n" \ -" started with a 'respawn' action exits, init automatically restarts\n" \ -" it. Unlike sysvinit, BusyBox init does not stop processes from\n" \ -" respawning out of control. The 'askfirst' actions acts just like\n" \ -" respawn, except that before running the specified process it\n" \ -" displays the line "Please press Enter to activate this console."\n" \ -" and then waits for the user to press enter before starting the\n" \ -" specified process. \n" \ -"\n" \ -" Unrecognized actions (like initdefault) will cause init to emit an\n" \ -" error message, and then go along with its business. All actions are\n" \ -" run in the reverse order from how they appear in /etc/inittab.\n" \ -"\n" \ -" <process>: \n" \ -"\n" \ -" Specifies the process to be executed and it's command line.\n" \ -"\n" \ -"Example /etc/inittab file:\n" \ -"\n" \ -" # This is run first except when booting in single-user mode.\n" \ -" #\n" \ -" ::sysinit:/etc/init.d/rcS\n" \ -" \n" \ -" # /bin/sh invocations on selected ttys\n" \ -" #\n" \ -" # Start an "askfirst" shell on the console (whatever that may be)\n" \ -" ::askfirst:-/bin/sh\n" \ -" # Start an "askfirst" shell on /dev/tty2-4\n" \ -" tty2::askfirst:-/bin/sh\n" \ -" tty3::askfirst:-/bin/sh\n" \ -" tty4::askfirst:-/bin/sh\n" \ -" \n" \ -" # /sbin/getty invocations for selected ttys\n" \ -" #\n" \ -" tty4::respawn:/sbin/getty 38400 tty5\n" \ -" tty5::respawn:/sbin/getty 38400 tty6\n" \ -" \n" \ -" \n" \ -" # Example of how to put a getty on a serial line (for a terminal)\n" \ -" #\n" \ -" #::respawn:/sbin/getty -L ttyS0 9600 vt100\n" \ -" #::respawn:/sbin/getty -L ttyS1 9600 vt100\n" \ -" #\n" \ -" # Example how to put a getty on a modem line.\n" \ -" #::respawn:/sbin/getty 57600 ttyS2\n" \ -" \n" \ -" # Stuff to do before rebooting\n" \ -" ::ctrlaltdel:/sbin/reboot\n" \ -" ::shutdown:/bin/umount -a -r\n" \ -" ::shutdown:/sbin/swapoff -a\n" - -#define insmod_trivial_usage \ - "[OPTION]... MODULE [symbol=value]..." -#define insmod_full_usage \ - "Loads the specified kernel modules into the kernel.\n\n" \ - "Options:\n" \ - "\t-f\tForce module to load into the wrong kernel version.\n" \ - "\t-k\tMake module autoclean-able.\n" \ - "\t-v\tverbose output\n" \ - "\t-L\tLock to prevent simultaneous loads of a module\n" \ - "\t-x\tdo not export externs" - -#define kill_trivial_usage \ - "[-signal] process-id [process-id ...]" -#define kill_full_usage \ - "Send a signal (default is SIGTERM) to the specified process(es).\n\n"\ - "Options:\n" \ - "\t-l\tList all signal names and numbers." -#define kill_example_usage \ - "$ ps | grep apache\n" \ - "252 root root S [apache]\n" \ - "263 www-data www-data S [apache]\n" \ - "264 www-data www-data S [apache]\n" \ - "265 www-data www-data S [apache]\n" \ - "266 www-data www-data S [apache]\n" \ - "267 www-data www-data S [apache]\n" \ - "$ kill 252\n" - -#define killall_trivial_usage \ - "[-signal] process-name [process-name ...]" -#define killall_full_usage \ - "Send a signal (default is SIGTERM) to the specified process(es).\n\n"\ - "Options:\n" \ - "\t-l\tList all signal names and numbers." -#define killall_example_usage \ - "$ killall apache\n" - -#define klogd_trivial_usage \ - "-n" -#define klogd_full_usage \ - "Kernel logger.\n"\ - "Options:\n"\ - "\t-n\tRun as a foreground process." - -#define length_trivial_usage \ - "STRING" -#define length_full_usage \ - "Prints out the length of the specified STRING." -#define length_example_usage \ - "$ length Hello\n" \ - "5\n" - -#define ln_trivial_usage \ - "[OPTION] TARGET... LINK_NAME|DIRECTORY" -#define ln_full_usage \ - "Create a link named LINK_NAME or DIRECTORY to the specified TARGET\n"\ - "\nYou may use '--' to indicate that all following arguments are non-options.\n\n" \ - "Options:\n" \ - "\t-s\tmake symbolic links instead of hard links\n" \ - "\t-f\tremove existing destination files\n" \ - "\t-n\tno dereference symlinks - treat like normal file" -#define ln_example_usage \ - "$ ln -s BusyBox /tmp/ls\n" \ - "$ ls -l /tmp/ls\n" \ - "lrwxrwxrwx 1 root root 7 Apr 12 18:39 ls -> BusyBox*\n" - -#define loadacm_trivial_usage \ - "< mapfile" -#define loadacm_full_usage \ - "Loads an acm from standard input." -#define loadacm_example_usage \ - "$ loadacm < /etc/i18n/acmname\n" - -#define loadfont_trivial_usage \ - "< font" -#define loadfont_full_usage \ - "Loads a console font from standard input." -#define loadfont_example_usage \ - "$ loadfont < /etc/i18n/fontname\n" - -#define loadkmap_trivial_usage \ - "< keymap" -#define loadkmap_full_usage \ - "Loads a binary keyboard translation table from standard input." -#define loadkmap_example_usage \ - "$ loadkmap < /etc/i18n/lang-keymap\n" - -#define logger_trivial_usage \ - "[OPTION]... [MESSAGE]" -#define logger_full_usage \ - "Write MESSAGE to the system log. If MESSAGE is omitted, log stdin.\n\n" \ - "Options:\n" \ - "\t-s\tLog to stderr as well as the system log.\n" \ - "\t-t\tLog using the specified tag (defaults to user name).\n" \ - "\t-p\tEnter the message with the specified priority.\n" \ - "\t\tThis may be numerical or a ``facility.level'' pair." -#define logger_example_usage \ - "$ logger "hello"\n" - -#define logname_trivial_usage \ - "" -#define logname_full_usage \ - "Print the name of the current user." -#define logname_example_usage \ - "$ logname\n" \ - "root\n" - -#define logread_trivial_usage \ - "" - -#define logread_full_usage \ - "Shows the messages from syslogd (using circular buffer)." - -#ifdef BB_FEATURE_LS_TIMESTAMPS - #define USAGE_LS_TIMESTAMPS(a) a -#else - #define USAGE_LS_TIMESTAMPS(a) -#endif -#ifdef BB_FEATURE_LS_FILETYPES - #define USAGE_LS_FILETYPES(a) a -#else - #define USAGE_LS_FILETYPES(a) -#endif -#ifdef BB_FEATURE_LS_FOLLOWLINKS - #define USAGE_LS_FOLLOWLINKS(a) a -#else - #define USAGE_LS_FOLLOWLINKS(a) -#endif -#ifdef BB_FEATURE_LS_RECURSIVE - #define USAGE_LS_RECURSIVE(a) a -#else - #define USAGE_LS_RECURSIVE(a) -#endif -#ifdef BB_FEATURE_LS_SORTFILES - #define USAGE_LS_SORTFILES(a) a -#else - #define USAGE_LS_SORTFILES(a) -#endif -#ifdef BB_FEATURE_AUTOWIDTH - #define USAGE_AUTOWIDTH(a) a -#else - #define USAGE_AUTOWIDTH(a) -#endif -#define ls_trivial_usage \ - "[-1Aa" USAGE_LS_TIMESTAMPS("c") "Cd" USAGE_LS_TIMESTAMPS("e") USAGE_LS_FILETYPES("F") "iln" USAGE_LS_FILETYPES("p") USAGE_LS_FOLLOWLINKS("L") USAGE_LS_RECURSIVE("R") USAGE_LS_SORTFILES("rS") "s" USAGE_AUTOWIDTH("T") USAGE_LS_TIMESTAMPS("tu") USAGE_LS_SORTFILES("v") USAGE_AUTOWIDTH("w") "x" USAGE_LS_SORTFILES("X") USAGE_HUMAN_READABLE("h") USAGE_NOT_HUMAN_READABLE("") "k] [filenames...]" -#define ls_full_usage \ - "List directory contents\n\n" \ - "Options:\n" \ - "\t-1\tlist files in a single column\n" \ - "\t-A\tdo not list implied . and ..\n" \ - "\t-a\tdo not hide entries starting with .\n" \ - "\t-C\tlist entries by columns\n" \ - USAGE_LS_TIMESTAMPS("\t-c\twith -l: show ctime\n") \ - "\t-d\tlist directory entries instead of contents\n" \ - USAGE_LS_TIMESTAMPS("\t-e\tlist both full date and full time\n") \ - USAGE_LS_FILETYPES("\t-F\tappend indicator (one of */=@|) to entries\n") \ - "\t-i\tlist the i-node for each file\n" \ - "\t-l\tuse a long listing format\n" \ - "\t-n\tlist numeric UIDs and GIDs instead of names\n" \ - USAGE_LS_FILETYPES("\t-p\tappend indicator (one of /=@|) to entries\n") \ - USAGE_LS_FOLLOWLINKS("\t-L\tlist entries pointed to by symbolic links\n") \ - USAGE_LS_RECURSIVE("\t-R\tlist subdirectories recursively\n") \ - USAGE_LS_SORTFILES("\t-r\tsort the listing in reverse order\n") \ - USAGE_LS_SORTFILES("\t-S\tsort the listing by file size\n") \ - "\t-s\tlist the size of each file, in blocks\n" \ - USAGE_AUTOWIDTH("\t-T NUM\tassume Tabstop every NUM columns\n") \ - USAGE_LS_TIMESTAMPS("\t-t\twith -l: show modification time\n") \ - USAGE_LS_TIMESTAMPS("\t-u\twith -l: show access time\n") \ - USAGE_LS_SORTFILES("\t-v\tsort the listing by version\n") \ - USAGE_AUTOWIDTH("\t-w NUM\tassume the terminal is NUM columns wide\n") \ - "\t-x\tlist entries by lines instead of by columns\n" \ - USAGE_LS_SORTFILES("\t-X\tsort the listing by extension\n") \ - USAGE_HUMAN_READABLE( \ - "\t-h\tprint sizes in human readable format (e.g., 1K 243M 2G )\n" \ - "\t-k\tprint sizes in kilobytes(default)") USAGE_NOT_HUMAN_READABLE( \ - "\t-k\tprint sizes in kilobytes(compatibility)") - -#define lsmod_trivial_usage \ - "" -#define lsmod_full_usage \ - "List the currently loaded kernel modules." - -#define makedevs_trivial_usage \ - "NAME TYPE MAJOR MINOR FIRST LAST [s]" -#define makedevs_full_usage \ - "Creates a range of block or character special files\n\n" \ - "TYPEs include:\n" \ - "\tb:\tMake a block (buffered) device.\n" \ - "\tc or u:\tMake a character (un-buffered) device.\n" \ - "\tp:\tMake a named pipe. MAJOR and MINOR are ignored for named pipes.\n\n" \ - "FIRST specifies the number appended to NAME to create the first device.\n" \ - "LAST specifies the number of the last item that should be created.\n" \ - "If 's' is the last argument, the base device is created as well.\n\n" \ - "For example:\n" \ - "\tmakedevs /dev/ttyS c 4 66 2 63 -> ttyS2-ttyS63\n" \ - "\tmakedevs /dev/hda b 3 0 0 8 s -> hda,hda1-hda8" -#define makedevs_example_usage \ - "$ makedevs /dev/ttyS c 4 66 2 63\n" \ - "[creates ttyS2-ttyS63]\n" \ - "$ makedevs /dev/hda b 3 0 0 8 s\n" \ - "[creates hda,hda1-hda8]\n" - -#define md5sum_trivial_usage \ - "[OPTION] [FILE]...\n" \ - "or: md5sum [OPTION] -c [FILE]" -#define md5sum_full_usage \ - "Print or check MD5 checksums.\n\n" \ - "Options:\n" \ - "With no FILE, or when FILE is -, read standard input.\n\n" \ - "\t-b\tread files in binary mode\n" \ - "\t-c\tcheck MD5 sums against given list\n" \ - "\t-t\tread files in text mode (default)\n" \ - "\t-g\tread a string\n" \ - "\nThe following two options are useful only when verifying checksums:\n" \ - "\t-s\tdon't output anything, status code shows success\n" \ - "\t-w\twarn about improperly formated MD5 checksum lines" -#define md5sum_example_usage \ - "$ md5sum < busybox\n" \ - "6fd11e98b98a58f64ff3398d7b324003\n" \ - "$ md5sum busybox\n" \ - "6fd11e98b98a58f64ff3398d7b324003 busybox\n" \ - "$ md5sum -c -\n" \ - "6fd11e98b98a58f64ff3398d7b324003 busybox\n" \ - "busybox: OK\n" \ - "^D\n" - -#define mkdir_trivial_usage \ - "[OPTION] DIRECTORY..." -#define mkdir_full_usage \ - "Create the DIRECTORY(ies) if they do not already exist\n\n" \ - "Options:\n" \ - "\t-m\tset permission mode (as in chmod), not rwxrwxrwx - umask\n" \ - "\t-p\tno error if existing, make parent directories as needed" -#define mkdir_example_usage \ - "$ mkdir /tmp/foo\n" \ - "$ mkdir /tmp/foo\n" \ - "/tmp/foo: File exists\n" \ - "$ mkdir /tmp/foo/bar/baz\n" \ - "/tmp/foo/bar/baz: No such file or directory\n" \ - "$ mkdir -p /tmp/foo/bar/baz\n" - -#define mkfifo_trivial_usage \ - "[OPTIONS] name" -#define mkfifo_full_usage \ - "Creates a named pipe (identical to 'mknod name p')\n\n" \ - "Options:\n" \ - "\t-m\tcreate the pipe using the specified mode (default a=rw)" - -#define mkfs_minix_trivial_usage \ - "[-c | -l filename] [-nXX] [-iXX] /dev/name [blocks]" -#define mkfs_minix_full_usage \ - "Make a MINIX filesystem.\n\n" \ - "Options:\n" \ - "\t-c\t\tCheck the device for bad blocks\n" \ - "\t-n [14|30]\tSpecify the maximum length of filenames\n" \ - "\t-i INODES\tSpecify the number of inodes for the filesystem\n" \ - "\t-l FILENAME\tRead the bad blocks list from FILENAME\n" \ - "\t-v\t\tMake a Minix version 2 filesystem" - -#define mknod_trivial_usage \ - "[OPTIONS] NAME TYPE MAJOR MINOR" -#define mknod_full_usage \ - "Create a special file (block, character, or pipe).\n\n" \ - "Options:\n" \ - "\t-m\tcreate the special file using the specified mode (default a=rw)\n\n" \ - "TYPEs include:\n" \ - "\tb:\tMake a block (buffered) device.\n" \ - "\tc or u:\tMake a character (un-buffered) device.\n" \ - "\tp:\tMake a named pipe. MAJOR and MINOR are ignored for named pipes." -#define mknod_example_usage \ - "$ mknod /dev/fd0 b 2 0 \n" \ - "$ mknod -m 644 /tmp/pipe p\n" - -#define mkswap_trivial_usage \ - "[-c] [-v0|-v1] device [block-count]" -#define mkswap_full_usage \ - "Prepare a disk partition to be used as a swap partition.\n\n" \ - "Options:\n" \ - "\t-c\t\tCheck for read-ability.\n" \ - "\t-v0\t\tMake version 0 swap [max 128 Megs].\n" \ - "\t-v1\t\tMake version 1 swap [big!] (default for kernels >\n\t\t\t2.1.117).\n" \ - "\tblock-count\tNumber of block to use (default is entire partition)." - -#define mktemp_trivial_usage \ - "[-q] TEMPLATE" -#define mktemp_full_usage \ - "Creates a temporary file with its name based on TEMPLATE.\n" \ - "TEMPLATE is any name with six `Xs' (i.e., /tmp/temp.XXXXXX)." -#define mktemp_example_usage \ - "$ mktemp /tmp/temp.XXXXXX\n" \ - "/tmp/temp.mWiLjM\n" \ - "$ ls -la /tmp/temp.mWiLjM\n" \ - "-rw------- 1 andersen andersen 0 Apr 25 17:10 /tmp/temp.mWiLjM\n" - -#define modprobe_trivial_usage \ - "[FILE ...]" -#define modprobe_full_usage \ - "Used for hight level module loading and unloading." -#define modprobe_example_usage \ - "$ modprobe cdrom\n" - -#define more_trivial_usage \ - "[FILE ...]" -#define more_full_usage \ - "More is a filter for viewing FILE one screenful at a time." -#define more_example_usage \ - "$ dmesg | more\n" - -#ifdef BB_FEATURE_MOUNT_LOOP - #define USAGE_MOUNT_LOOP(a) a -#else - #define USAGE_MOUNT_LOOP(a) -#endif -#ifdef BB_FEATURE_MTAB_SUPPORT - #define USAGE_MTAB(a) a -#else - #define USAGE_MTAB(a) -#endif -#define mount_trivial_usage \ - "[flags] DEVICE NODE [-o options,more-options]" -#define mount_full_usage \ - "Mount a filesystem\n\n" \ - "Flags:\n" \ - "\t-a:\t\tMount all filesystems in fstab.\n" \ - USAGE_MTAB( \ - "\t-f:\t\t\"Fake\" Add entry to mount table but don't mount it.\n" \ - "\t-n:\t\tDon't write a mount table entry.\n" \ - ) \ - "\t-o option:\tOne of many filesystem options, listed below.\n" \ - "\t-r:\t\tMount the filesystem read-only.\n" \ - "\t-t fs-type:\tSpecify the filesystem type.\n" \ - "\t-w:\t\tMount for reading and writing (default).\n" \ - "\n" \ - "Options for use with the \"-o\" flag:\n" \ - "\tasync/sync:\tWrites are asynchronous / synchronous.\n" \ - "\tatime/noatime:\tEnable / disable updates to inode access times.\n" \ - "\tdev/nodev:\tAllow use of special device files / disallow them.\n" \ - "\texec/noexec:\tAllow use of executable files / disallow them.\n" \ - USAGE_MOUNT_LOOP( \ - "\tloop:\t\tMounts a file via loop device.\n" \ - ) \ - "\tsuid/nosuid:\tAllow set-user-id-root programs / disallow them.\n" \ - "\tremount:\tRe-mount a mounted filesystem, changing its flags.\n" \ - "\tro/rw:\t\tMount for read-only / read-write.\n" \ - "\tbind:\t\tUse the linux 2.4.x \"bind\" feature.\n" \ - "\nThere are EVEN MORE flags that are specific to each filesystem.\n" \ - "You'll have to see the written documentation for those filesystems." -#define mount_example_usage \ - "$ mount\n" \ - "/dev/hda3 on / type minix (rw)\n" \ - "proc on /proc type proc (rw)\n" \ - "devpts on /dev/pts type devpts (rw)\n" \ - "$ mount /dev/fd0 /mnt -t msdos -o ro\n" \ - "$ mount /tmp/diskimage /opt -t ext2 -o loop\n" - -#define mt_trivial_usage \ - "[-f device] opcode value" -#define mt_full_usage \ - "Control magnetic tape drive operation\n" \ - "\nAvailable Opcodes:\n\n" \ - "bsf bsfm bsr bss datacompression drvbuffer eof eom erase\n" \ - "fsf fsfm fsr fss load lock mkpart nop offline ras1 ras2\n" \ - "ras3 reset retension rew rewoffline seek setblk setdensity\n" \ - "setpart tell unload unlock weof wset" - -#define mv_trivial_usage \ - "SOURCE DEST\n" \ - "or: mv SOURCE... DIRECTORY" -#define mv_full_usage \ - "Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY." -#define mv_example_usage \ - "$ mv /tmp/foo /bin/bar\n" - -#define nc_trivial_usage \ - "[IP] [port]" -#define nc_full_usage \ - "Netcat opens a pipe to IP:port" -#define nc_example_usage \ - "$ nc foobar.somedomain.com 25\n" \ - "220 foobar ESMTP Exim 3.12 #1 Sat, 15 Apr 2000 00:03:02 -0600\n" \ - "help\n" \ - "214-Commands supported:\n" \ - "214- HELO EHLO MAIL RCPT DATA AUTH\n" \ - "214 NOOP QUIT RSET HELP\n" \ - "quit\n" \ - "221 foobar closing connection\n" - -#define nslookup_trivial_usage \ - "[HOST] [SERVER]" -#define nslookup_full_usage \ - "Queries the nameserver for the IP address of the given HOST\n" \ - "optionally using a specified DNS server" -#define nslookup_example_usage \ - "$ nslookup localhost\n" \ - "Server: default\n" \ - "Address: default\n" \ - "\n" \ - "Name: debian\n" \ - "Address: 127.0.0.1\n" - -#define pidof_trivial_usage \ - "process-name [process-name ...]" -#define pidof_full_usage \ - "Lists the PIDs of all processes with names that match the names on the command line" -#define pidof_example_usage \ - "$ pidof init\n" \ - "1\n" - -#ifndef BB_FEATURE_FANCY_PING -#define ping_trivial_usage "host" -#define ping_full_usage "Send ICMP ECHO_REQUEST packets to network hosts" -#else -#define ping_trivial_usage \ - "[OPTION]... host" -#define ping_full_usage \ - "Send ICMP ECHO_REQUEST packets to network hosts.\n\n" \ - "Options:\n" \ - "\t-c COUNT\tSend only COUNT pings.\n" \ - "\t-s SIZE\t\tSend SIZE data bytes in packets (default=56).\n" \ - "\t-q\t\tQuiet mode, only displays output at start\n" \ - "\t\t\tand when finished." -#endif -#define ping_example_usage \ - "$ ping localhost\n" \ - "PING slag (127.0.0.1): 56 data bytes\n" \ - "64 bytes from 127.0.0.1: icmp_seq=0 ttl=255 time=20.1 ms\n" \ - "\n" \ - "--- debian ping statistics ---\n" \ - "1 packets transmitted, 1 packets received, 0% packet loss\n" \ - "round-trip min/avg/max = 20.1/20.1/20.1 ms\n" - -#define pivot_root_trivial_usage \ - "NEW_ROOT PUT_OLD" -#define pivot_root_full_usage \ - "Move the current root file system to PUT_OLD and make NEW_ROOT\n" \ - "the new root file system." - -#define poweroff_trivial_usage \ - "" -#define poweroff_full_usage \ - "Halt the system and request that the kernel shut off the power." - -#define printf_trivial_usage \ - "FORMAT [ARGUMENT...]" -#define printf_full_usage \ - "Formats and prints ARGUMENT(s) according to FORMAT,\n" \ - "Where FORMAT controls the output exactly as in C printf." -#define printf_example_usage \ - "$ printf "Val=%d\\n" 5\n" \ - "Val=5\n" - -#define ps_trivial_usage \ - "" -#define ps_full_usage \ - "Report process status\n" \ - "\nThis version of ps accepts no options." -#define ps_example_usage \ - "$ ps\n" \ - " PID Uid Gid State Command\n" \ - " 1 root root S init\n" \ - " 2 root root S [kflushd]\n" \ - " 3 root root S [kupdate]\n" \ - " 4 root root S [kpiod]\n" \ - " 5 root root S [kswapd]\n" \ - " 742 andersen andersen S [bash]\n" \ - " 743 andersen andersen S -bash\n" \ - " 745 root root S [getty]\n" \ - " 2990 andersen andersen R ps\n" - -#define pwd_trivial_usage \ - "" -#define pwd_full_usage \ - "Print the full filename of the current working directory." -#define pwd_example_usage \ - "$ pwd\n" \ - "/root\n" - -#define rdate_trivial_usage \ - "[OPTION] HOST" -#define rdate_full_usage \ - "Get and possibly set the system date and time from a remote HOST.\n\n" \ - "Options:\n" \ - "\t-s\tSet the system date and time (default).\n" \ - "\t-p\tPrint the date and time." - -#define readlink_trivial_usage \ - "" -#define readlink_full_usage \ - "Read a symbolic link." - -#define reboot_trivial_usage \ - "" -#define reboot_full_usage \ - "Reboot the system." - -#define renice_trivial_usage \ - "priority pid [pid ...]" -#define renice_full_usage \ - "Changes priority of running processes. Allowed priorities range\n" \ - "from 20 (the process runs only when nothing else is running) to 0\n" \ - "(default priority) to -20 (almost nothing else ever gets to run)." - -#define reset_trivial_usage \ - "" -#define reset_full_usage \ - "Resets the screen." - -#define rm_trivial_usage \ - "[OPTION]... FILE..." -#define rm_full_usage \ - "Remove (unlink) the FILE(s). You may use '--' to\n" \ - "indicate that all following arguments are non-options.\n\n" \ - "Options:\n" \ - "\t-i\t\talways prompt before removing each destination" \ - "\t-f\t\tremove existing destinations, never prompt\n" \ - "\t-r or -R\tremove the contents of directories recursively" -#define rm_example_usage \ - "$ rm -rf /tmp/foo\n" - -#define rmdir_trivial_usage \ - "[OPTION]... DIRECTORY..." -#define rmdir_full_usage \ - "Remove the DIRECTORY(ies), if they are empty." -#define rmdir_example_usage \ - "# rmdir /tmp/foo\n" - -#define rmmod_trivial_usage \ - "[OPTION]... [MODULE]..." -#define rmmod_full_usage \ - "Unloads the specified kernel modules from the kernel.\n\n" \ - "Options:\n" \ - "\t-a\tTry to remove all unused kernel modules." -#define rmmod_example_usage \ - "$ rmmod tulip\n" - -#define route_trivial_usage \ - "[{add|del|flush}]" -#define route_full_usage \ - "Edit the kernel's routing tables" - -#define rpm2cpio_trivial_usage \ - "package.rpm" -#define rpm2cpio_full_usage \ - "Outputs a cpio archive of the rpm file." - -#define sed_trivial_usage \ - "[-nef] pattern [files...]" -#define sed_full_usage \ - "Options:\n" \ - "\t-n\t\tsuppress automatic printing of pattern space\n" \ - "\t-e script\tadd the script to the commands to be executed\n" \ - "\t-f scriptfile\tadd the contents of script-file to the commands to be executed\n" \ - "\n" \ - "If no -e or -f is given, the first non-option argument is taken as the\n" \ - "sed script to interpret. All remaining arguments are names of input\n" \ - "files; if no input files are specified, then the standard input is read." -#define sed_example_usage \ - "$ echo "foo" | sed -e 's/f[a-zA-Z]o/bar/g'\n" \ - "bar\n" - -#define setkeycodes_trivial_usage \ - "SCANCODE KEYCODE ..." -#define setkeycodes_full_usage \ - "Set entries into the kernel's scancode-to-keycode map,\n" \ - "allowing unusual keyboards to generate usable keycodes.\n\n" \ - "SCANCODE may be either xx or e0xx (hexadecimal),\n" \ - "and KEYCODE is given in decimal" -#define setkeycodes_example_usage \ - "$ setkeycodes e030 127\n" - -#define lash_trivial_usage \ - "[FILE]...\n" \ - "or: sh -c command [args]..." -#define lash_full_usage \ - "lash: The BusyBox LAme SHell (command interpreter)" -#define lash_notes_usage \ -"This command does not yet have proper documentation.\n" \ -"\n" \ -"Use lash just as you would use any other shell. It properly handles pipes,\n" \ -"redirects, job control, can be used as the shell for scripts, and has a\n" \ -"sufficient set of builtins to do what is needed. It does not (yet) support\n" \ -"Bourne Shell syntax. If you need things like "if-then-else", "while", and such\n" \ -"use ash or bash. If you just need a very simple and extremely small shell,\n" \ -"this will do the job." - -#define sleep_trivial_usage \ - "N" -#define sleep_full_usage \ - "Pause for N seconds." -#define sleep_example_usage \ - "$ sleep 2\n" \ - "[2 second delay results]\n" - - -#ifdef BB_FEATURE_SORT_UNIQUE - #define USAGE_SORT_UNIQUE(a) a -#else - #define USAGE_SORT_UNIQUE(a) -#endif -#ifdef BB_FEATURE_SORT_REVERSE - #define USAGE_SORT_REVERSE(a) a -#else - #define USAGE_SORT_REVERSE(a) -#endif -#define sort_trivial_usage \ - "[-n" USAGE_SORT_REVERSE("r") USAGE_SORT_UNIQUE("u") "] [FILE]..." -#define sort_full_usage \ - "Sorts lines of text in the specified files\n\n"\ - "Options:\n" \ - USAGE_SORT_UNIQUE("\t-u\tsuppress duplicate lines\n") \ - USAGE_SORT_REVERSE("\t-r\tsort in reverse order\n") \ - "\t-n\tsort numerics" -#define sort_example_usage \ - "$ echo -e \"e\\nf\\nb\\nd\\nc\\na\" | sort\n" \ - "a\n" \ - "b\n" \ - "c\n" \ - "d\n" \ - "e\n" \ - "f\n" - -#define start_stop_daemon_trivial_usage \ - "[OPTIONS]" -#define start_stop_daemon_full_usage \ - "Program to start and stop services.\n"\ - "Options:\n" \ - "-S\t\t\tstart\n"\ - "-K\t\t\tstop\n"\ - "-x <executable>\t\tprogram to start/check if it is running\n"\ - "-p <pid-file>\t\tpid file to check\n"\ - "-u <username>|<uid>\tstop this user's processes\n"\ - "-n <process-name>\tstop processes with this name\n"\ - "-s <signal>\t\tsignal to send (default 15)\n"\ - "-a <pathname>\t\tprogram to start (default <executable>)\n" - -#define stty_trivial_usage \ - "[-a|g] [-F DEVICE] [SETTING]..." -#define stty_full_usage \ - "Without arguments, prints baud rate, line discipline," \ - "\nand deviations from stty sane." \ - "\n\nOptions:" \ - "\n\t-F DEVICE\topen device instead of stdin" \ - "\n\t-a\t\tprint all current settings in human-readable form" \ - "\n\t-g\t\tprint in stty-readable form" \ - "\n\t[SETTING]\tsee manpage" - -#define swapoff_trivial_usage \ - "[OPTION] [DEVICE]" -#define swapoff_full_usage \ - "Stop swapping virtual memory pages on DEVICE.\n\n" \ - "Options:\n" \ - "\t-a\tStop swapping on all swap devices" - -#define swapon_trivial_usage \ - "[OPTION] [DEVICE]" -#define swapon_full_usage \ - "Start swapping virtual memory pages on DEVICE.\n\n" \ - "Options:\n" \ - "\t-a\tStart swapping on all swap devices" - -#define sync_trivial_usage \ - "" -#define sync_full_usage \ - "Write all buffered filesystem blocks to disk." - - -#ifdef BB_FEATURE_REMOTE_LOG - #define USAGE_REMOTE_LOG(a) a -#else - #define USAGE_REMOTE_LOG(a) -#endif -#define syslogd_trivial_usage \ - "[OPTION]..." -#define syslogd_full_usage \ - "Linux system and kernel logging utility.\n" \ - "Note that this version of syslogd ignores /etc/syslog.conf.\n\n" \ - "Options:\n" \ - "\t-m NUM\t\tInterval between MARK lines (default=20min, 0=off)\n" \ - "\t-n\t\tRun as a foreground process\n" \ - "\t-O FILE\t\tUse an alternate log file (default=/var/log/messages)" \ - USAGE_REMOTE_LOG( \ - "\n\t-R HOST[:PORT]\tLog to IP or hostname on PORT (default PORT=514/UDP)\n" \ - "\t-L\t\tLog locally and via network logging (default is network only)") -#define syslogd_example_usage \ - "$ syslogd -R masterlog:514\n" \ - "$ syslogd -R 192.168.1.1:601\n" - - -#ifndef BB_FEATURE_FANCY_TAIL - #define USAGE_UNSIMPLE_TAIL(a) -#else - #define USAGE_UNSIMPLE_TAIL(a) a -#endif -#define tail_trivial_usage \ - "[OPTION]... [FILE]..." -#define tail_full_usage \ - "Print last 10 lines of each FILE to standard output.\n" \ - "With more than one FILE, precede each with a header giving the\n" \ - "file name. With no FILE, or when FILE is -, read standard input.\n\n" \ - "Options:\n" \ - USAGE_UNSIMPLE_TAIL("\t-c N[kbm]\toutput the last N bytes\n") \ - "\t-n N[kbm]\tprint last N lines instead of last 10\n" \ - "\t-f\t\toutput data as the file grows" \ - USAGE_UNSIMPLE_TAIL( "\n\t-q\t\tnever output headers giving file names\n" \ - "\t-s SEC\t\twait SEC seconds between reads with -f\n" \ - "\t-v\t\talways output headers giving file names\n\n" \ - "If the first character of N (bytes or lines) is a '+', output begins with \n" \ - "the Nth item from the start of each file, otherwise, print the last N items\n" \ - "in the file. N bytes may be suffixed by k (x1024), b (x512), or m (1024^2)." ) -#define tail_example_usage \ - "$ tail -n 1 /etc/resolv.conf\n" \ - "nameserver 10.0.0.1\n" - -#ifdef BB_FEATURE_TAR_CREATE - #define USAGE_TAR_CREATE(a) a -#else - #define USAGE_TAR_CREATE(a) -#endif -#ifdef BB_FEATURE_TAR_EXCLUDE - #define USAGE_TAR_EXCLUDE(a) a -#else - #define USAGE_TAR_EXCLUDE(a) -#endif -#define tar_trivial_usage \ - "-[" USAGE_TAR_CREATE("c") "xtvO] " \ - USAGE_TAR_EXCLUDE("[--exclude FILE] [-X FILE]") \ - "[-f TARFILE] [-C DIR] [FILE(s)] ..." -#define tar_full_usage \ - "Create, extract, or list files from a tar file.\n\n" \ - "Options:\n" \ - USAGE_TAR_CREATE("\tc\t\tcreate\n") \ - "\tx\t\textract\n" \ - "\tt\t\tlist\n" \ - "\nFile selection:\n" \ - "\tf\t\tname of TARFILE or \"-\" for stdin\n" \ - "\tO\t\textract to stdout\n" \ - USAGE_TAR_EXCLUDE( \ - "\texclude\t\tfile to exclude\n" \ - "\tX\t\tfile with names to exclude\n" \ - ) \ - "\tC\t\tchange to directory DIR before operation\n" \ - "\tv\t\tverbosely list files processed" -#define tar_example_usage \ - "$ zcat /tmp/tarball.tar.gz | tar -xf -\n" \ - "$ tar -cf /tmp/tarball.tar /usr/local\n" - -#define tee_trivial_usage \ - "[OPTION]... [FILE]..." -#define tee_full_usage \ - "Copy standard input to each FILE, and also to standard output.\n\n" \ - "Options:\n" \ - "\t-a\tappend to the given FILEs, do not overwrite" -#define tee_example_usage \ - "$ echo "Hello" | tee /tmp/foo\n" \ - "$ cat /tmp/foo\n" \ - "Hello\n" - -#define telnet_trivial_usage \ - "HOST [PORT]" -#define telnet_full_usage \ - "Telnet is used to establish interactive communication with another\n"\ - "computer over a network using the TELNET protocol." - -#define test_trivial_usage \ - "EXPRESSION\n or [ EXPRESSION ]" -#define test_full_usage \ - "Checks file types and compares values returning an exit\n" \ - "code determined by the value of EXPRESSION." -#define test_example_usage \ - "$ test 1 -eq 2\n" \ - "$ echo $?\n" \ - "1\n" \ - "$ test 1 -eq 1\n" \ - "$ echo $? \n" \ - "0\n" \ - "$ [ -d /etc ]\n" \ - "$ echo $?\n" \ - "0\n" \ - "$ [ -d /junk ]\n" \ - "$ echo $?\n" \ - "1\n" - -#ifdef BB_FEATURE_TFTP_GET - #define USAGE_TFTP_GET(a) a -#else - #define USAGE_TFTP_GET(a) -#endif -#ifdef BB_FEATURE_TFTP_PUT - #define USAGE_TFTP_PUT(a) a -#else - #define USAGE_TFTP_PUT(a) -#endif -#ifdef BB_FEATURE_TFTP_BLOCKSIZE - #define USAGE_TFTP_BS(a) a -#else - #define USAGE_TFTP_BS(a) -#endif - -#define tftp_trivial_usage \ - "[OPTION]... HOST [PORT]" -#define tftp_full_usage \ - "Transfers a file from/to a tftp server using \"octet\" mode.\n\n" \ - "Options:\n" \ - "\t-l FILE\tLocal FILE.\n" \ - "\t-r FILE\tRemote FILE.\n" \ - USAGE_TFTP_GET( \ - "\t-g\tGet file.\n" \ - ) \ - USAGE_TFTP_PUT( \ - "\t-p\tPut file.\n" \ - ) \ - USAGE_TFTP_BS( \ - "\t-b SIZE\tTransfer blocks of SIZE octets.\n" \ - ) - -#define touch_trivial_usage \ - "[-c] FILE [FILE ...]" -#define touch_full_usage \ - "Update the last-modified date on the given FILE[s].\n\n" \ - "Options:\n" \ - "\t-c\tDo not create any files" -#define touch_example_usage \ - "$ ls -l /tmp/foo\n" \ - "/bin/ls: /tmp/foo: No such file or directory\n" \ - "$ touch /tmp/foo\n" \ - "$ ls -l /tmp/foo\n" \ - "-rw-rw-r-- 1 andersen andersen 0 Apr 15 01:11 /tmp/foo\n" - -#define tr_trivial_usage \ - "[-cds] STRING1 [STRING2]" -#define tr_full_usage \ - "Translate, squeeze, and/or delete characters from\n" \ - "standard input, writing to standard output.\n\n" \ - "Options:\n" \ - "\t-c\ttake complement of STRING1\n" \ - "\t-d\tdelete input characters coded STRING1\n" \ - "\t-s\tsqueeze multiple output characters of STRING2 into one character" -#define tr_example_usage \ - "$ echo "gdkkn vnqkc" | tr [a-y] [b-z]\n" \ - "hello world\n" - -#define traceroute_trivial_usage \ - "[-dnrv] [-m max_ttl] [-p port#] [-q nqueries]\n\ - [-s src_addr] [-t tos] [-w wait] host [data size]" -#define traceroute_full_usage \ - "trace the route ip packets follow going to \"host\"\n" \ - "Options:\n" \ - "\t-d\tset SO_DEBUG options to socket\n" \ - "\t-n\tPrint hop addresses numerically rather than symbolically\n" \ - "\t-r\tBypass the normal routing tables and send directly to a host\n" \ - "\t-v\tVerbose output\n" \ - "\t-m max_ttl\tSet the max time-to-live (max number of hops)\n" \ - "\t-p port#\tSet the base UDP port number used in probes\n" \ - "\t\t(default is 33434)\n" \ - "\t-q nqueries\tSet the number of probes per ``ttl'' to nqueries\n" \ - "\t\t(default is 3)\n" \ - "\t-s src_addr\tUse the following IP address as the source address\n" \ - "\t-t tos\tSet the type-of-service in probe packets to the following value\n" \ - "\t\t(default 0)\n" \ - "\t-w wait\tSet the time (in seconds) to wait for a response to a probe\n" \ - "\t\t(default 3 sec.)." - - -#define true_trivial_usage \ - "" -#define true_full_usage \ - "Return an exit code of TRUE (0)." -#define true_example_usage \ - "$ true\n" \ - "$ echo $?\n" \ - "0\n" - -#define tty_trivial_usage \ - "" -#define tty_full_usage \ - "Print the file name of the terminal connected to standard input.\n\n"\ - "Options:\n" \ - "\t-s\tprint nothing, only return an exit status" -#define tty_example_usage \ - "$ tty\n" \ - "/dev/tty2\n" - -#ifdef BB_FEATURE_MOUNT_FORCE - #define USAGE_MOUNT_FORCE(a) a -#else - #define USAGE_MOUNT_FORCE(a) -#endif -#define umount_trivial_usage \ - "[flags] FILESYSTEM|DIRECTORY" -#define umount_full_usage \ - "Unmount file systems\n" \ - "\nFlags:\n" "\t-a\tUnmount all file systems" \ - USAGE_MTAB(" in /etc/mtab\n\t-n\tDon't erase /etc/mtab entries") \ - "\n\t-r\tTry to remount devices as read-only if mount is busy" \ - USAGE_MOUNT_FORCE("\n\t-f\tForce umount (i.e., unreachable NFS server)") \ - USAGE_MOUNT_LOOP("\n\t-l\tDo not free loop device (if a loop device has been used)") -#define umount_example_usage \ - "$ umount /dev/hdc1 \n" - -#define uname_trivial_usage \ - "[OPTION]..." -#define uname_full_usage \ - "Print certain system information. With no OPTION, same as -s.\n\n" \ - "Options:\n" \ - "\t-a\tprint all information\n" \ - "\t-m\tthe machine (hardware) type\n" \ - "\t-n\tprint the machine's network node hostname\n" \ - "\t-r\tprint the operating system release\n" \ - "\t-s\tprint the operating system name\n" \ - "\t-p\tprint the host processor type\n" \ - "\t-v\tprint the operating system version" -#define uname_example_usage \ - "$ uname -a\n" \ - "Linux debian 2.2.15pre13 #5 Tue Mar 14 16:03:50 MST 2000 i686 unknown\n" - -#define uniq_trivial_usage \ - "[OPTION]... [INPUT [OUTPUT]]" -#define uniq_full_usage \ - "Discard all but one of successive identical lines from INPUT\n" \ - "(or standard input), writing to OUTPUT (or standard output).\n\n" \ - "Options:\n" \ - "\t-c\tprefix lines by the number of occurrences\n" \ - "\t-d\tonly print duplicate lines\n" \ - "\t-u\tonly print unique lines" -#define uniq_example_usage \ - "$ echo -e \"a\\na\\nb\\nc\\nc\\na\" | sort | uniq\n" \ - "a\n" \ - "b\n" \ - "c\n" - -#define unix2dos_trivial_usage \ - "[option] [FILE]" -#define unix2dos_full_usage \ - "Converts FILE from unix format to dos format. When no option\n" \ - "is given, the input is converted to the opposite output format.\n" \ - "When no file is given, uses stdin for input and stdout for output.\n" \ - "Options:\n" \ - "\t-u\toutput will be in UNIX format\n" \ - "\t-d\toutput will be in DOS format" - -#define update_trivial_usage \ - "[options]" -#define update_full_usage \ - "Periodically flushes filesystem buffers.\n\n" \ - "Options:\n" \ - "\t-S\tforce use of sync(2) instead of flushing\n" \ - "\t-s SECS\tcall sync this often (default 30)\n" \ - "\t-f SECS\tflush some buffers this often (default 5)" - -#define uptime_trivial_usage \ - "" -#define uptime_full_usage \ - "Display the time since the last boot." -#define uptime_example_usage \ - "$ uptime\n" \ - " 1:55pm up 2:30, load average: 0.09, 0.04, 0.00\n" - -#define usleep_trivial_usage \ - "N" -#define usleep_full_usage \ - "Pause for N microseconds." -#define usleep_example_usage \ - "$ usleep 1000000\n" \ - "[pauses for 1 second]\n" - -#define uudecode_trivial_usage \ - "[FILE]..." -#define uudecode_full_usage \ - "Uudecode a file that is uuencoded.\n\n" \ - "Options:\n" \ - "\t-o FILE\tdirect output to FILE" -#define uudecode_example_usage \ - "$ uudecode -o busybox busybox.uu\n" \ - "$ ls -l busybox\n" \ - "-rwxr-xr-x 1 ams ams 245264 Jun 7 21:35 busybox\n" - -#define uuencode_trivial_usage \ - "[OPTION] [INFILE] REMOTEFILE" -#define uuencode_full_usage \ - "Uuencode a file.\n\n" \ - "Options:\n" \ - "\t-m\tuse base64 encoding per RFC1521" -#define uuencode_example_usage \ - "$ uuencode busybox busybox\n" \ - "begin 755 busybox\n" \ - "<encoded file snipped>\n" \ - "$ uudecode busybox busybox > busybox.uu\n" \ - "$\n" - -#define vi_trivial_usage \ - "[OPTION] [FILE]..." -#define vi_full_usage \ - "edit FILE.\n\n" \ - "Options:\n" \ - "\t-R\tRead-only- do not write to the file." - -#define watchdog_trivial_usage \ - "DEV" -#define watchdog_full_usage \ - "Periodically write to watchdog device DEV" - -#define wc_trivial_usage \ - "[OPTION]... [FILE]..." -#define wc_full_usage \ - "Print line, word, and byte counts for each FILE, and a total line if\n" \ - "more than one FILE is specified. With no FILE, read standard input.\n\n" \ - "Options:\n" \ - "\t-c\tprint the byte counts\n" \ - "\t-l\tprint the newline counts\n" \ - "\t-L\tprint the length of the longest line\n" \ - "\t-w\tprint the word counts" -#define wc_example_usage \ - "$ wc /etc/passwd\n" \ - " 31 46 1365 /etc/passwd\n" - -#define wget_trivial_usage \ - "[-c|--continue] [-q|--quiet] [-O|--output-document file]\n\t[--header 'header: value'] [-P DIR] url" -#define wget_full_usage \ - "wget retrieves files via HTTP or FTP\n\n" \ - "Options:\n" \ - "\t-c\tcontinue retrieval of aborted transfers\n" \ - "\t-q\tquiet mode - do not print\n" \ - "\t-P\tSet directory prefix to DIR\n" \ - "\t-O\tsave to filename ('-' for stdout)" - -#define which_trivial_usage \ - "[COMMAND ...]" -#define which_full_usage \ - "Locates a COMMAND." -#define which_example_usage \ - "$ which login\n" \ - "/bin/login\n" - -#define whoami_trivial_usage \ - "" -#define whoami_full_usage \ - "Prints the user name associated with the current effective user id." - -#define xargs_trivial_usage \ - "[COMMAND] [ARGS...]" -#define xargs_full_usage \ - "Executes COMMAND on every item given by standard input." -#define xargs_example_usage \ - "$ ls | xargs gzip\n" \ - "$ find . -name '*.c' -print | xargs rm\n" - -#define yes_trivial_usage \ - "[OPTION]... [STRING]..." -#define yes_full_usage \ - "Repeatedly outputs a line with all specified STRING(s), or 'y'." - -#define zcat_trivial_usage \ - "FILE" -#define zcat_full_usage \ - "Uncompress to stdout." diff --git a/usleep.c b/usleep.c deleted file mode 100644 index 6023bf430..000000000 --- a/usleep.c +++ /dev/null @@ -1,38 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini usleep implementation for busybox - * - * - * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* getopt not needed */ - -#include <stdlib.h> -#include <unistd.h> -#include "busybox.h" - -extern int usleep_main(int argc, char **argv) -{ - if ((argc < 2) || (**(argv + 1) == '-')) { - show_usage(); - } - - usleep(atoi(*(++argv))); /* return void */ - return EXIT_SUCCESS; -} diff --git a/util-linux/Makefile b/util-linux/Makefile new file mode 100644 index 000000000..ddecf50d3 --- /dev/null +++ b/util-linux/Makefile @@ -0,0 +1,48 @@ +# Makefile for busybox +# +# Copyright (C) 1999,2000,2001 by Erik Andersen <andersee@debian.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +TOPDIR :=.. +L_TARGET := util-linux.a + +obj-y := +obj-n := +obj- := + +obj-$(CONFIG_DMESG) += dmesg.o +obj-$(CONFIG_FBSET) += fbset.o +obj-$(CONFIG_FDFLUSH) += fdflush.o +obj-$(CONFIG_FREERAMDISK) += freeramdisk.o +obj-$(CONFIG_FSCK_MINIX) += fsck_minix.o +obj-$(CONFIG_GETOPT) += getopt.o +obj-$(CONFIG_MKFS_MINIX) += mkfs_minix.o +obj-$(CONFIG_MKSWAP) += mkswap.o +obj-$(CONFIG_MORE) += more.o +obj-$(CONFIG_MOUNT) += mount.o +obj-$(CONFIG_NFSMOUNT) += nfsmount.o +obj-$(CONFIG_PIVOT_ROOT) += pivot_root.o +obj-$(CONFIG_RDATE) += rdate.o +obj-$(CONFIG_SWAPONOFF) += swaponoff.o +obj-$(CONFIG_UMOUNT) += umount.o + +# Hand off to toplevel Rules.mak +include $(TOPDIR)/Rules.mak + +clean: + rm -f $(L_TARGET) *.o core + diff --git a/util-linux/config.in b/util-linux/config.in new file mode 100644 index 000000000..3eb8ee0b5 --- /dev/null +++ b/util-linux/config.in @@ -0,0 +1,27 @@ +# +# For a description of the syntax of this configuration file, +# see scripts/kbuild/config-language.txt. +# + +mainmenu_option next_comment +comment 'Linux System Utilities' + + +bool 'dmesg' CONFIG_DMESG +bool 'fbset' CONFIG_FBSET +bool 'fdflush' CONFIG_FDFLUSH +bool 'freeramdisk' CONFIG_FREERAMDISK +bool 'fsck_minix' CONFIG_FSCK_MINIX +bool 'getopt' CONFIG_GETOPT +bool 'mkfs_minix' CONFIG_MKFS_MINIX +bool 'mkswap' CONFIG_MKSWAP +bool 'more' CONFIG_MORE +bool 'mount' CONFIG_MOUNT +bool 'nfsmount' CONFIG_NFSMOUNT +bool 'pivot_root' CONFIG_PIVOT_ROOT +bool 'rdate' CONFIG_RDATE +bool 'swaponoff' CONFIG_SWAPONOFF +bool 'umount' CONFIG_UMOUNT + +endmenu + diff --git a/util-linux/fbset.c b/util-linux/fbset.c index 5ccd80e79..2a959c21c 100644 --- a/util-linux/fbset.c +++ b/util-linux/fbset.c @@ -56,7 +56,7 @@ enum { CMD_INFO = 12, CMD_CHANGE = 13, -#ifdef BB_FEATURE_FBSET_FANCY +#ifdef CONFIG_FEATURE_FBSET_FANCY CMD_XRES = 100, CMD_YRES = 101, CMD_VXRES = 102, @@ -149,7 +149,7 @@ static struct cmdoptions_t { "-laced", 1, CMD_LACED}, { "-double", 1, CMD_DOUBLE}, { "-n", 0, CMD_CHANGE}, { -#ifdef BB_FEATURE_FBSET_FANCY +#ifdef CONFIG_FEATURE_FBSET_FANCY "-all", 0, CMD_ALL}, { "-xres", 1, CMD_XRES}, { "-yres", 1, CMD_YRES}, { @@ -177,7 +177,7 @@ static struct cmdoptions_t { 0, 0, 0} }; -#ifdef BB_FEATURE_FBSET_READMODE +#ifdef CONFIG_FEATURE_FBSET_READMODE /* taken from linux/fb.h */ static const int FB_VMODE_INTERLACED = 1; /* interlaced */ static const int FB_VMODE_DOUBLE = 2; /* double scan */ @@ -189,7 +189,7 @@ static const int FB_SYNC_COMP_HIGH_ACT = 8; /* composite sync high active */ static int readmode(struct fb_var_screeninfo *base, const char *fn, const char *mode) { -#ifdef BB_FEATURE_FBSET_READMODE +#ifdef CONFIG_FEATURE_FBSET_READMODE FILE *f; char buf[256]; char *p = buf; @@ -313,7 +313,7 @@ static void showmode(struct fb_var_screeninfo *v) v->vsync_len); } printf("\nmode \"%ux%u-%u\"\n", v->xres, v->yres, (int) (vrate + 0.5)); -#ifdef BB_FEATURE_FBSET_FANCY +#ifdef CONFIG_FEATURE_FBSET_FANCY printf("\t# D: %.3f MHz, H: %.3f kHz, V: %.3f Hz\n", drate / 1e6, hrate / 1e3, vrate); #endif @@ -377,7 +377,7 @@ extern int fbset_main(int argc, char **argv) case CMD_CHANGE: g_options |= OPT_CHANGE; break; -#ifdef BB_FEATURE_FBSET_FANCY +#ifdef CONFIG_FEATURE_FBSET_FANCY case CMD_XRES: varset.xres = strtoul(argv[1], 0, 0); break; diff --git a/util-linux/fsck_minix.c b/util-linux/fsck_minix.c index 952968d85..dbe4f74b3 100644 --- a/util-linux/fsck_minix.c +++ b/util-linux/fsck_minix.c @@ -191,7 +191,7 @@ static const int ROOT_INO = 1; #define UPPER(size,n) ((size+((n)-1))/(n)) #define INODE_SIZE (sizeof(struct minix_inode)) -#ifdef BB_FEATURE_MINIX2 +#ifdef CONFIG_FEATURE_MINIX2 #define INODE_SIZE2 (sizeof(struct minix2_inode)) #define INODE_BLOCKS UPPER(INODES, (version2 ? MINIX2_INODES_PER_BLOCK \ : MINIX_INODES_PER_BLOCK)) @@ -232,7 +232,7 @@ static char super_block_buffer[BLOCK_SIZE]; #define Super (*(struct minix_super_block *)super_block_buffer) #define INODES ((unsigned long)Super.s_ninodes) -#ifdef BB_FEATURE_MINIX2 +#ifdef CONFIG_FEATURE_MINIX2 #define ZONES ((unsigned long)(version2 ? Super.s_zones : Super.s_nzones)) #else #define ZONES ((unsigned long)(Super.s_nzones)) @@ -252,7 +252,7 @@ static unsigned char *inode_count = NULL; static unsigned char *zone_count = NULL; static void recursive_check(unsigned int ino); -#ifdef BB_FEATURE_MINIX2 +#ifdef CONFIG_FEATURE_MINIX2 static void recursive_check2(unsigned int ino); #endif @@ -408,7 +408,7 @@ static int check_zone_nr(unsigned short *nr, int *corrected) return 0; } -#ifdef BB_FEATURE_MINIX2 +#ifdef CONFIG_FEATURE_MINIX2 static int check_zone_nr2(unsigned int *nr, int *corrected) { if (!*nr) @@ -515,7 +515,7 @@ static int map_block(struct minix_inode *inode, unsigned int blknr) return result; } -#ifdef BB_FEATURE_MINIX2 +#ifdef CONFIG_FEATURE_MINIX2 static int map_block2(struct minix2_inode *inode, unsigned int blknr) { unsigned int ind[BLOCK_SIZE >> 2]; @@ -613,7 +613,7 @@ static void get_dirsize(void) char blk[BLOCK_SIZE]; int size; -#ifdef BB_FEATURE_MINIX2 +#ifdef CONFIG_FEATURE_MINIX2 if (version2) block = Inode2[ROOT_INO].i_zone[0]; else @@ -644,7 +644,7 @@ static void read_superblock(void) namelen = 30; dirsize = 32; version2 = 0; -#ifdef BB_FEATURE_MINIX2 +#ifdef CONFIG_FEATURE_MINIX2 } else if (MAGIC == MINIX2_SUPER_MAGIC) { namelen = 14; dirsize = 16; @@ -742,7 +742,7 @@ static struct minix_inode *get_inode(unsigned int nr) return inode; } -#ifdef BB_FEATURE_MINIX2 +#ifdef CONFIG_FEATURE_MINIX2 static struct minix2_inode *get_inode2(unsigned int nr) { struct minix2_inode *inode; @@ -798,7 +798,7 @@ static void check_root(void) die("root inode isn't a directory"); } -#ifdef BB_FEATURE_MINIX2 +#ifdef CONFIG_FEATURE_MINIX2 static void check_root2(void) { struct minix2_inode *inode = Inode2 + ROOT_INO; @@ -841,7 +841,7 @@ static int add_zone(unsigned short *znr, int *corrected) return block; } -#ifdef BB_FEATURE_MINIX2 +#ifdef CONFIG_FEATURE_MINIX2 static int add_zone2(unsigned int *znr, int *corrected) { int result; @@ -892,7 +892,7 @@ static void add_zone_ind(unsigned short *znr, int *corrected) write_block(block, blk); } -#ifdef BB_FEATURE_MINIX2 +#ifdef CONFIG_FEATURE_MINIX2 static void add_zone_ind2(unsigned int *znr, int *corrected) { static char blk[BLOCK_SIZE]; @@ -926,7 +926,7 @@ static void add_zone_dind(unsigned short *znr, int *corrected) write_block(block, blk); } -#ifdef BB_FEATURE_MINIX2 +#ifdef CONFIG_FEATURE_MINIX2 static void add_zone_dind2(unsigned int *znr, int *corrected) { static char blk[BLOCK_SIZE]; @@ -977,7 +977,7 @@ static void check_zones(unsigned int i) add_zone_dind(8 + inode->i_zone, &changed); } -#ifdef BB_FEATURE_MINIX2 +#ifdef CONFIG_FEATURE_MINIX2 static void check_zones2(unsigned int i) { struct minix2_inode *inode; @@ -1062,7 +1062,7 @@ static void check_file(struct minix_inode *dir, unsigned int offset) return; } -#ifdef BB_FEATURE_MINIX2 +#ifdef CONFIG_FEATURE_MINIX2 static void check_file2(struct minix2_inode *dir, unsigned int offset) { static char blk[BLOCK_SIZE]; @@ -1143,7 +1143,7 @@ static void recursive_check(unsigned int ino) check_file(dir, offset); } -#ifdef BB_FEATURE_MINIX2 +#ifdef CONFIG_FEATURE_MINIX2 static void recursive_check2(unsigned int ino) { struct minix2_inode *dir; @@ -1221,7 +1221,7 @@ static void check_counts(void) } } -#ifdef BB_FEATURE_MINIX2 +#ifdef CONFIG_FEATURE_MINIX2 static void check_counts2(void) { int i; @@ -1283,7 +1283,7 @@ static void check(void) check_counts(); } -#ifdef BB_FEATURE_MINIX2 +#ifdef CONFIG_FEATURE_MINIX2 static void check2(void) { memset(inode_count, 0, (INODES + 1) * sizeof(*inode_count)); @@ -1305,7 +1305,7 @@ static void alloc_name_list(void) name_list[i] = xmalloc(sizeof(char) * BUFSIZ + 1); } -#ifdef BB_FEATURE_CLEAN_UP +#ifdef CONFIG_FEATURE_CLEAN_UP /* execute this atexit() to deallocate name_list[] */ /* piptigger was here */ static void free_name_list(void) @@ -1330,7 +1330,7 @@ extern int fsck_minix_main(int argc, char **argv) int retcode = 0; alloc_name_list(); -#ifdef BB_FEATURE_CLEAN_UP +#ifdef CONFIG_FEATURE_CLEAN_UP /* Don't bother to free memory. Exit does * that automagically, so we can save a few bytes */ atexit(free_name_list); @@ -1338,7 +1338,7 @@ extern int fsck_minix_main(int argc, char **argv) if (INODE_SIZE * MINIX_INODES_PER_BLOCK != BLOCK_SIZE) die("bad inode size"); -#ifdef BB_FEATURE_MINIX2 +#ifdef CONFIG_FEATURE_MINIX2 if (INODE_SIZE2 * MINIX2_INODES_PER_BLOCK != BLOCK_SIZE) die("bad v2 inode size"); #endif @@ -1422,7 +1422,7 @@ extern int fsck_minix_main(int argc, char **argv) tcsetattr(0, TCSANOW, &tmp); termios_set = 1; } -#ifdef BB_FEATURE_MINIX2 +#ifdef CONFIG_FEATURE_MINIX2 if (version2) { check_root2(); check2(); diff --git a/util-linux/mkfs_minix.c b/util-linux/mkfs_minix.c index ccc0e85d7..a388d0ab0 100644 --- a/util-linux/mkfs_minix.c +++ b/util-linux/mkfs_minix.c @@ -180,7 +180,7 @@ struct minix_dir_entry { #define UPPER(size,n) (((size)+((n)-1))/(n)) #define INODE_SIZE (sizeof(struct minix_inode)) -#ifdef BB_FEATURE_MINIX2 +#ifdef CONFIG_FEATURE_MINIX2 #define INODE_SIZE2 (sizeof(struct minix2_inode)) #define INODE_BLOCKS UPPER(INODES, (version2 ? MINIX2_INODES_PER_BLOCK \ : MINIX_INODES_PER_BLOCK)) @@ -208,7 +208,7 @@ static char root_block[BLOCK_SIZE] = "\0"; static char *inode_buffer = NULL; #define Inode (((struct minix_inode *) inode_buffer)-1) -#ifdef BB_FEATURE_MINIX2 +#ifdef CONFIG_FEATURE_MINIX2 #define Inode2 (((struct minix2_inode *) inode_buffer)-1) #endif static char super_block_buffer[BLOCK_SIZE]; @@ -216,7 +216,7 @@ static char boot_block_buffer[512]; #define Super (*(struct minix_super_block *)super_block_buffer) #define INODES ((unsigned long)Super.s_ninodes) -#ifdef BB_FEATURE_MINIX2 +#ifdef CONFIG_FEATURE_MINIX2 #define ZONES ((unsigned long)(version2 ? Super.s_zones : Super.s_nzones)) #else #define ZONES ((unsigned long)(Super.s_nzones)) @@ -436,7 +436,7 @@ static void make_bad_inode(void) write_block(dind, (char *) dind_block); } -#ifdef BB_FEATURE_MINIX2 +#ifdef CONFIG_FEATURE_MINIX2 static void make_bad_inode2(void) { struct minix2_inode *inode = &Inode2[MINIX_BAD_INO]; @@ -509,7 +509,7 @@ static void make_root_inode(void) write_block(inode->i_zone[0], root_block); } -#ifdef BB_FEATURE_MINIX2 +#ifdef CONFIG_FEATURE_MINIX2 static void make_root_inode2(void) { struct minix2_inode *inode = &Inode2[MINIX_ROOT_INO]; @@ -550,7 +550,7 @@ static void setup_tables(void) else inodes = req_nr_inodes; /* Round up inode count to fill block size */ -#ifdef BB_FEATURE_MINIX2 +#ifdef CONFIG_FEATURE_MINIX2 if (version2) inodes = ((inodes + MINIX2_INODES_PER_BLOCK - 1) & ~(MINIX2_INODES_PER_BLOCK - 1)); @@ -699,7 +699,7 @@ extern int mkfs_minix_main(int argc, char **argv) if (INODE_SIZE * MINIX_INODES_PER_BLOCK != BLOCK_SIZE) error_msg_and_die("bad inode size"); -#ifdef BB_FEATURE_MINIX2 +#ifdef CONFIG_FEATURE_MINIX2 if (INODE_SIZE2 * MINIX2_INODES_PER_BLOCK != BLOCK_SIZE) error_msg_and_die("bad inode size"); #endif @@ -764,7 +764,7 @@ extern int mkfs_minix_main(int argc, char **argv) break; } case 'v': -#ifdef BB_FEATURE_MINIX2 +#ifdef CONFIG_FEATURE_MINIX2 version2 = 1; #else error_msg("%s: not compiled with minix v2 support", @@ -796,7 +796,7 @@ goodbye: if (!device_name || BLOCKS < 10) { show_usage(); } -#ifdef BB_FEATURE_MINIX2 +#ifdef CONFIG_FEATURE_MINIX2 if (version2) { if (namelen == 14) magic = MINIX2_SUPER_MAGIC; @@ -830,7 +830,7 @@ goodbye: check_blocks(); else if (listfile) get_list_blocks(listfile); -#ifdef BB_FEATURE_MINIX2 +#ifdef CONFIG_FEATURE_MINIX2 if (version2) { make_root_inode2(); make_bad_inode2(); diff --git a/util-linux/more.c b/util-linux/more.c index 780cddf66..5fe1da423 100644 --- a/util-linux/more.c +++ b/util-linux/more.c @@ -37,7 +37,7 @@ static FILE *cin; -#ifdef BB_FEATURE_USE_TERMIOS +#ifdef CONFIG_FEATURE_USE_TERMIOS #include <termios.h> #define setTermSettings(fd,argp) tcsetattr(fd,TCSANOW,argp) #define getTermSettings(fd,argp) tcgetattr(fd, argp); @@ -54,7 +54,7 @@ static void gotsig(int sig) putchar('\n'); exit(EXIT_FAILURE); } -#endif /* BB_FEATURE_USE_TERMIOS */ +#endif /* CONFIG_FEATURE_USE_TERMIOS */ static int terminal_width = 79; /* not 80 in case terminal has linefold bug */ @@ -69,7 +69,7 @@ extern int more_main(int argc, char **argv) FILE *file; int len, page_height; -#if defined BB_FEATURE_AUTOWIDTH && defined BB_FEATURE_USE_TERMIOS +#if defined CONFIG_FEATURE_AUTOWIDTH && defined CONFIG_FEATURE_USE_TERMIOS struct winsize win = { 0, 0, 0, 0 }; #endif @@ -83,7 +83,7 @@ extern int more_main(int argc, char **argv) if (!cin) cin = xfopen(CONSOLE_DEV, "r"); please_display_more_prompt = 0; -#ifdef BB_FEATURE_USE_TERMIOS +#ifdef CONFIG_FEATURE_USE_TERMIOS getTermSettings(fileno(cin), &initial_settings); new_settings = initial_settings; new_settings.c_lflag &= ~ICANON; @@ -114,7 +114,7 @@ extern int more_main(int argc, char **argv) if(please_display_more_prompt>0) please_display_more_prompt = 0; -#if defined BB_FEATURE_AUTOWIDTH && defined BB_FEATURE_USE_TERMIOS +#if defined CONFIG_FEATURE_AUTOWIDTH && defined CONFIG_FEATURE_USE_TERMIOS ioctl(fileno(stdout), TIOCGWINSZ, &win); if (win.ws_row > 4) terminal_height = win.ws_row - 2; @@ -147,7 +147,7 @@ extern int more_main(int argc, char **argv) * to get input from the user. */ input = getc(cin); -#ifndef BB_FEATURE_USE_TERMIOS +#ifndef CONFIG_FEATURE_USE_TERMIOS printf("\033[A"); /* up cursor */ #endif /* Erase the "More" message */ diff --git a/util-linux/mount.c b/util-linux/mount.c index af57a7623..bfa9a3040 100644 --- a/util-linux/mount.c +++ b/util-linux/mount.c @@ -52,7 +52,7 @@ #include <mntent.h> #include <ctype.h> #include "busybox.h" -#if defined BB_FEATURE_USE_DEVPS_PATCH +#if defined CONFIG_FEATURE_USE_DEVPS_PATCH # include <linux/devmtab.h> /* For Erik's nifty devmtab device driver */ #endif @@ -74,7 +74,7 @@ enum { }; -#if defined BB_FEATURE_MOUNT_LOOP +#if defined CONFIG_FEATURE_MOUNT_LOOP #include <fcntl.h> #include <sys/ioctl.h> static int use_loop = FALSE; @@ -123,13 +123,13 @@ do_mount(char *specialfile, char *dir, char *filesystemtype, char *mtab_opts, int mount_all) { int status = 0; -#if defined BB_FEATURE_MOUNT_LOOP +#if defined CONFIG_FEATURE_MOUNT_LOOP char *lofile = NULL; #endif if (fakeIt == FALSE) { -#if defined BB_FEATURE_MOUNT_LOOP +#if defined CONFIG_FEATURE_MOUNT_LOOP if (use_loop==TRUE) { int loro = flags & MS_RDONLY; @@ -162,7 +162,7 @@ do_mount(char *specialfile, char *dir, char *filesystemtype, /* If the mount was sucessful, do anything needed, then return TRUE */ if (status == 0 || fakeIt==TRUE) { -#if defined BB_FEATURE_MTAB_SUPPORT +#if defined CONFIG_FEATURE_MTAB_SUPPORT if (useMtab == TRUE) { erase_mtab(specialfile); // Clean any stale entries write_mtab(specialfile, dir, filesystemtype, flags, mtab_opts); @@ -172,7 +172,7 @@ do_mount(char *specialfile, char *dir, char *filesystemtype, } /* Bummer. mount failed. Clean up */ -#if defined BB_FEATURE_MOUNT_LOOP +#if defined CONFIG_FEATURE_MOUNT_LOOP if (lofile != NULL) { del_loop(specialfile); } @@ -209,7 +209,7 @@ parse_mount_options(char *options, int *flags, char *strflags) } f++; } -#if defined BB_FEATURE_MOUNT_LOOP +#if defined CONFIG_FEATURE_MOUNT_LOOP if (gotone == FALSE && !strcasecmp("loop", options)) { /* loop device support */ use_loop = TRUE; gotone = TRUE; @@ -240,7 +240,7 @@ mount_one(char *blockDevice, char *directory, char *filesystemType, { int status = 0; -#if defined BB_FEATURE_USE_DEVPS_PATCH +#if defined CONFIG_FEATURE_USE_DEVPS_PATCH if (strcmp(filesystemType, "auto") == 0) { static const char *noauto_array[] = { "tmpfs", "shm", "proc", "ramfs", "devpts", "devfs", "usbdevfs", 0 }; const char **noauto_fstype; @@ -310,7 +310,7 @@ mount_one(char *blockDevice, char *directory, char *filesystemType, void show_mounts(void) { -#if defined BB_FEATURE_USE_DEVPS_PATCH +#if defined CONFIG_FEATURE_USE_DEVPS_PATCH int fd, i, numfilesystems; char device[] = "/dev/mtab"; struct k_mntent *mntentlist; @@ -337,7 +337,7 @@ void show_mounts(void) mntentlist[i].mnt_opts, mntentlist[i].mnt_freq, mntentlist[i].mnt_passno); } -#ifdef BB_FEATURE_CLEAN_UP +#ifdef CONFIG_FEATURE_CLEAN_UP /* Don't bother to close files or free memory. Exit * does that automagically, so we can save a few bytes */ free( mntentlist); @@ -357,7 +357,7 @@ void show_mounts(void) } printf("%s on %s type %s (%s)\n", blockDevice, m->mnt_dir, m->mnt_type, m->mnt_opts); -#ifdef BB_FEATURE_CLEAN_UP +#ifdef CONFIG_FEATURE_CLEAN_UP if(blockDevice != m->mnt_fsname) free(blockDevice); #endif @@ -408,7 +408,7 @@ extern int mount_main(int argc, char **argv) case 'f': fakeIt = TRUE; break; -#ifdef BB_FEATURE_MTAB_SUPPORT +#ifdef CONFIG_FEATURE_MTAB_SUPPORT case 'n': useMtab = FALSE; break; @@ -467,7 +467,7 @@ extern int mount_main(int argc, char **argv) singlemount: string_flags = strdup(string_flags); rc = EXIT_SUCCESS; -#ifdef BB_NFSMOUNT +#ifdef CONFIG_NFSMOUNT if (strchr(device, ':') != NULL) filesystemType = "nfs"; if (strcmp(filesystemType, "nfs") == 0) { diff --git a/util-linux/swaponoff.c b/util-linux/swaponoff.c index d9eb5baae..6cc736ab1 100644 --- a/util-linux/swaponoff.c +++ b/util-linux/swaponoff.c @@ -2,9 +2,8 @@ /* * Mini swapon/swapoff implementation for busybox * - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org> + * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen <andersee@debian.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/util-linux/umount.c b/util-linux/umount.c index 74638d21c..99db3084c 100644 --- a/util-linux/umount.c +++ b/util-linux/umount.c @@ -2,9 +2,8 @@ /* * Mini umount implementation for busybox * - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org> + * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen + * Copyright (C) 1999,2000,2001 by Erik Andersen <andersee@debian.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -57,13 +56,13 @@ static struct _mtab_entry_t *mtab_cache = NULL; -#if defined BB_FEATURE_MOUNT_FORCE +#if defined CONFIG_FEATURE_MOUNT_FORCE static int doForce = FALSE; #endif -#if defined BB_FEATURE_MOUNT_LOOP +#if defined CONFIG_FEATURE_MOUNT_LOOP static int freeLoop = TRUE; #endif -#if defined BB_FEATURE_MTAB_SUPPORT +#if defined CONFIG_FEATURE_MTAB_SUPPORT static int useMtab = TRUE; #endif static int umountAll = FALSE; @@ -112,7 +111,7 @@ static char *mtab_getinfo(const char *match, const char which) if (which == MTAB_GETMOUNTPT) { return cur->mountpt; } else { -#if !defined BB_FEATURE_MTAB_SUPPORT +#if !defined CONFIG_FEATURE_MTAB_SUPPORT if (strcmp(cur->device, "/dev/root") == 0) { /* Adjusts device to be the real root device, * or leaves device alone if it can't find it */ @@ -151,7 +150,7 @@ static char *mtab_first(void **iter) /* Don't bother to clean up, since exit() does that * automagically, so we can save a few bytes */ -#ifdef BB_FEATURE_CLEAN_UP +#ifdef CONFIG_FEATURE_CLEAN_UP static void mtab_free(void) { struct _mtab_entry_t *this, *next; @@ -179,12 +178,12 @@ static int do_umount(const char *name) status = umount(name); -#if defined BB_FEATURE_MOUNT_LOOP +#if defined CONFIG_FEATURE_MOUNT_LOOP if (freeLoop == TRUE && blockDevice != NULL && !strncmp("/dev/loop", blockDevice, 9)) /* this was a loop device, delete it */ del_loop(blockDevice); #endif -#if defined BB_FEATURE_MOUNT_FORCE +#if defined CONFIG_FEATURE_MOUNT_FORCE if (status != 0 && doForce == TRUE) { status = umount2(blockDevice, MNT_FORCE); if (status != 0) { @@ -202,7 +201,7 @@ static int do_umount(const char *name) } } if (status == 0) { -#if defined BB_FEATURE_MTAB_SUPPORT +#if defined CONFIG_FEATURE_MTAB_SUPPORT if (useMtab == TRUE) erase_mtab(name); #endif @@ -246,7 +245,7 @@ extern int umount_main(int argc, char **argv) if (argc < 2) { show_usage(); } -#ifdef BB_FEATURE_CLEAN_UP +#ifdef CONFIG_FEATURE_CLEAN_UP atexit(mtab_free); #endif @@ -257,17 +256,17 @@ extern int umount_main(int argc, char **argv) case 'a': umountAll = TRUE; break; -#if defined BB_FEATURE_MOUNT_LOOP +#if defined CONFIG_FEATURE_MOUNT_LOOP case 'l': freeLoop = FALSE; break; #endif -#ifdef BB_FEATURE_MTAB_SUPPORT +#ifdef CONFIG_FEATURE_MTAB_SUPPORT case 'n': useMtab = FALSE; break; #endif -#ifdef BB_FEATURE_MOUNT_FORCE +#ifdef CONFIG_FEATURE_MOUNT_FORCE case 'f': doForce = TRUE; break; diff --git a/uudecode.c b/uudecode.c deleted file mode 100644 index a4059ddfe..000000000 --- a/uudecode.c +++ /dev/null @@ -1,353 +0,0 @@ -/* uudecode.c -- uudecode utility. - * Copyright (C) 1994, 1995 Free Software Foundation, Inc. - * - * This product is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This product is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this product; see the file COPYING. If not, write to - * the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Reworked to GNU style by Ian Lance Taylor, ian@airs.com, August 93. - * - * Original copyright notice is retained at the end of this file. - */ - - - -#include <stdio.h> -#include <errno.h> -#include <getopt.h> -#include <string.h> -#include <stdlib.h> -#include "busybox.h" -#include "pwd_grp/pwd.h" -#include "pwd_grp/grp.h" - -/*struct passwd *getpwnam();*/ - -/* Single character decode. */ -#define DEC(Char) (((Char) - ' ') & 077) - -static int read_stduu (const char *inname) -{ - char buf[2 * BUFSIZ]; - - while (1) { - int n; - char *p; - - if (fgets (buf, sizeof(buf), stdin) == NULL) { - error_msg("%s: Short file", inname); - return FALSE; - } - p = buf; - - /* N is used to avoid writing out all the characters at the end of - the file. */ - n = DEC (*p); - if (n <= 0) - break; - for (++p; n > 0; p += 4, n -= 3) { - char ch; - - if (n >= 3) { - ch = DEC (p[0]) << 2 | DEC (p[1]) >> 4; - putchar (ch); - ch = DEC (p[1]) << 4 | DEC (p[2]) >> 2; - putchar (ch); - ch = DEC (p[2]) << 6 | DEC (p[3]); - putchar (ch); - } else { - if (n >= 1) { - ch = DEC (p[0]) << 2 | DEC (p[1]) >> 4; - putchar (ch); - } - if (n >= 2) { - ch = DEC (p[1]) << 4 | DEC (p[2]) >> 2; - putchar (ch); - } - } - } - } - - if (fgets (buf, sizeof(buf), stdin) == NULL - || strcmp (buf, "end\n")) { - error_msg("%s: No `end' line", inname); - return FALSE; - } - - return TRUE; -} - -static int read_base64 (const char *inname) -{ - static const char b64_tab[256] = { - '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*000-007*/ - '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*010-017*/ - '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*020-027*/ - '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*030-037*/ - '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*040-047*/ - '\177', '\177', '\177', '\76', '\177', '\177', '\177', '\77', /*050-057*/ - '\64', '\65', '\66', '\67', '\70', '\71', '\72', '\73', /*060-067*/ - '\74', '\75', '\177', '\177', '\177', '\100', '\177', '\177', /*070-077*/ - '\177', '\0', '\1', '\2', '\3', '\4', '\5', '\6', /*100-107*/ - '\7', '\10', '\11', '\12', '\13', '\14', '\15', '\16', /*110-117*/ - '\17', '\20', '\21', '\22', '\23', '\24', '\25', '\26', /*120-127*/ - '\27', '\30', '\31', '\177', '\177', '\177', '\177', '\177', /*130-137*/ - '\177', '\32', '\33', '\34', '\35', '\36', '\37', '\40', /*140-147*/ - '\41', '\42', '\43', '\44', '\45', '\46', '\47', '\50', /*150-157*/ - '\51', '\52', '\53', '\54', '\55', '\56', '\57', '\60', /*160-167*/ - '\61', '\62', '\63', '\177', '\177', '\177', '\177', '\177', /*170-177*/ - '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*200-207*/ - '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*210-217*/ - '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*220-227*/ - '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*230-237*/ - '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*240-247*/ - '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*250-257*/ - '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*260-267*/ - '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*270-277*/ - '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*300-307*/ - '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*310-317*/ - '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*320-327*/ - '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*330-337*/ - '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*340-347*/ - '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*350-357*/ - '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*360-367*/ - '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /*370-377*/ - }; - unsigned char buf[2 * BUFSIZ]; - - while (1) { - int last_data = 0; - unsigned char *p; - - if (fgets (buf, sizeof(buf), stdin) == NULL) { - error_msg("%s: Short file", inname); - return FALSE; - } - p = buf; - - if (memcmp (buf, "====", 4) == 0) - break; - if (last_data != 0) { - error_msg("%s: data following `=' padding character", inname); - return FALSE; - } - - /* The following implementation of the base64 decoding might look - a bit clumsy but I only try to follow the POSIX standard: - ``All line breaks or other characters not found in the table - [with base64 characters] shall be ignored by decoding - software.'' */ - while (*p != '\n') { - char c1, c2, c3; - - while ((b64_tab[*p] & '\100') != 0) - if (*p == '\n' || *p++ == '=') - break; - if (*p == '\n') - /* This leaves the loop. */ - continue; - c1 = b64_tab[*p++]; - - while ((b64_tab[*p] & '\100') != 0) - if (*p == '\n' || *p++ == '=') { - error_msg("%s: illegal line", inname); - return FALSE; - } - c2 = b64_tab[*p++]; - - while (b64_tab[*p] == '\177') - if (*p++ == '\n') { - error_msg("%s: illegal line", inname); - return FALSE; - } - if (*p == '=') { - putchar (c1 << 2 | c2 >> 4); - last_data = 1; - break; - } - c3 = b64_tab[*p++]; - - while (b64_tab[*p] == '\177') - if (*p++ == '\n') { - error_msg("%s: illegal line", inname); - return FALSE; - } - putchar (c1 << 2 | c2 >> 4); - putchar (c2 << 4 | c3 >> 2); - if (*p == '=') { - last_data = 1; - break; - } - else - putchar (c3 << 6 | b64_tab[*p++]); - } - } - - return TRUE; -} - -static int decode (const char *inname, - const char *forced_outname) -{ - struct passwd *pw; - register char *p; - int mode; - char buf[2 * BUFSIZ]; - char *outname; - int do_base64 = 0; - int res; - int dofre; - - /* Search for header line. */ - - while (1) { - if (fgets (buf, sizeof (buf), stdin) == NULL) { - error_msg("%s: No `begin' line", inname); - return FALSE; - } - - if (strncmp (buf, "begin", 5) == 0) { - if (sscanf (buf, "begin-base64 %o %s", &mode, buf) == 2) { - do_base64 = 1; - break; - } else if (sscanf (buf, "begin %o %s", &mode, buf) == 2) - break; - } - } - - /* If the output file name is given on the command line this rules. */ - dofre = FALSE; - if (forced_outname != NULL) - outname = (char *) forced_outname; - else { - /* Handle ~user/file format. */ - if (buf[0] != '~') - outname = buf; - else { - p = buf + 1; - while (*p != '/') - ++p; - if (*p == '\0') { - error_msg("%s: Illegal ~user", inname); - return FALSE; - } - *p++ = '\0'; - pw = getpwnam (buf + 1); - if (pw == NULL) { - error_msg("%s: No user `%s'", inname, buf + 1); - return FALSE; - } - outname = concat_path_file(pw->pw_dir, p); - dofre = TRUE; - } - } - - /* Create output file and set mode. */ - if (strcmp (outname, "/dev/stdout") != 0 && strcmp (outname, "-") != 0 - && (freopen (outname, "w", stdout) == NULL - || chmod (outname, mode & (S_IRWXU | S_IRWXG | S_IRWXO)) - )) { - perror_msg("%s", outname); /* */ - if (dofre) - free(outname); - return FALSE; - } - - /* We differenciate decoding standard UU encoding and base64. A - common function would only slow down the program. */ - - /* For each input line: */ - if (do_base64) - res = read_base64 (inname); - else - res = read_stduu (inname); - if (dofre) - free(outname); - return res; -} - -int uudecode_main (int argc, - char **argv) -{ - int opt; - int exit_status; - const char *outname; - outname = NULL; - - while ((opt = getopt(argc, argv, "o:")) != EOF) { - switch (opt) { - case 0: - break; - - case 'o': - outname = optarg; - break; - - default: - show_usage(); - } - } - - if (optind == argc) - exit_status = decode ("stdin", outname) == 0 ? EXIT_SUCCESS : EXIT_FAILURE; - else { - exit_status = EXIT_SUCCESS; - do { - if (freopen (argv[optind], "r", stdin) != NULL) { - if (decode (argv[optind], outname) != 0) - exit_status = FALSE; - } else { - perror_msg("%s", argv[optind]); - exit_status = EXIT_FAILURE; - } - optind++; - } - while (optind < argc); - } - return(exit_status); -} - -/* Copyright (c) 1983 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change - * ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change> - * - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - - diff --git a/uuencode.c b/uuencode.c deleted file mode 100644 index fc037403a..000000000 --- a/uuencode.c +++ /dev/null @@ -1,180 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Copyright (C) 2000 by Glenn McGrath - * - * based on the function base64_encode from http.c in wget v1.6 - * Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ -#include <getopt.h> -#include <stdio.h> -#include <stdlib.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include "busybox.h" - -/* Conversion table. for base 64 */ -static char tbl_base64[64] = { - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', - 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', - 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', - 'w', 'x', 'y', 'z', '0', '1', '2', '3', - '4', '5', '6', '7', '8', '9', '+', '/' -}; - -static char tbl_std[64] = { - '`', '!', '"', '#', '$', '%', '&', '\'', - '(', ')', '*', '+', ',', '-', '.', '/', - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', ':', ';', '<', '=', '>', '?', - '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', - 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', - 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', - 'X', 'Y', 'Z', '[', '\\', ']', '^', '_' -}; - -/* - * Encode the string S of length LENGTH to base64 format and place it - * to STORE. STORE will be 0-terminated, and must point to a writable - * buffer of at least 1+BASE64_LENGTH(length) bytes. - * where BASE64_LENGTH(len) = (4 * ((LENGTH + 2) / 3)) - */ -static void uuencode (const char *s, const char *store, const int length, const char *tbl) -{ - int i; - unsigned char *p = (unsigned char *)store; - - /* Transform the 3x8 bits to 4x6 bits, as required by base64. */ - for (i = 0; i < length; i += 3) { - *p++ = tbl[s[0] >> 2]; - *p++ = tbl[((s[0] & 3) << 4) + (s[1] >> 4)]; - *p++ = tbl[((s[1] & 0xf) << 2) + (s[2] >> 6)]; - *p++ = tbl[s[2] & 0x3f]; - s += 3; - } - /* Pad the result if necessary... */ - if (i == length + 1) { - *(p - 1) = '='; - } - else if (i == length + 2) { - *(p - 1) = *(p - 2) = '='; - } - /* ...and zero-terminate it. */ - *p = '\0'; -} - -int uuencode_main(int argc, char **argv) -{ - const int src_buf_size = 60; // This *MUST* be a multiple of 3 - const int dst_buf_size = 4 * ((src_buf_size + 2) / 3); - RESERVE_BB_BUFFER(src_buf, src_buf_size + 1); - RESERVE_BB_BUFFER(dst_buf, dst_buf_size + 1); - struct stat stat_buf; - FILE *src_stream = stdin; - char *tbl = tbl_std; - size_t size; - mode_t mode; - int opt; - int column = 0; - int write_size = 0; - int remaining; - int buffer_offset = 0; - - while ((opt = getopt(argc, argv, "m")) != -1) { - switch (opt) { - case 'm': - tbl = tbl_base64; - break; - default: - show_usage(); - } - } - - switch (argc - optind) { - case 2: - src_stream = xfopen(argv[optind], "r"); - stat(argv[optind], &stat_buf); - mode = stat_buf.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); - if (src_stream == stdout) { - printf("NULL\n"); - } - break; - case 1: - mode = 0666 & ~umask(0666); - break; - default: - show_usage(); - } - - printf("begin%s %o %s", tbl == tbl_std ? "" : "-base64", mode, argv[argc - 1]); - - while ((size = fread(src_buf, 1, src_buf_size, src_stream)) > 0) { - /* Encode the buffer we just read in */ - uuencode(src_buf, dst_buf, size, tbl); - - /* Write the buffer to stdout, wrapping at 60 chars. - * This looks overly complex, but it gets tricky as - * the line has to continue to wrap correctly if we - * have to refill the buffer - * - * Improvments most welcome - */ - - /* Initialise values for the new buffer */ - remaining = 4 * ((size + 2) / 3); - buffer_offset = 0; - - /* Write the buffer to stdout, wrapping at 60 chars - * starting from the column the last buffer ran out - */ - do { - if (remaining > (60 - column)) { - write_size = 60 - column; - } - else if (remaining < 60) { - write_size = remaining; - } else { - write_size = 60; - } - - /* Setup a new row if required */ - if (column == 0) { - putchar('\n'); - if (tbl == tbl_std) { - putchar('M'); - } - } - /* Write to the 60th column */ - if (fwrite(&dst_buf[buffer_offset], 1, write_size, stdout) != write_size) { - perror("Couldnt finish writing"); - } - /* Update variables based on last write */ - buffer_offset += write_size; - remaining -= write_size; - column += write_size; - if (column % 60 == 0) { - column = 0; - } - } while (remaining > 0); - } - printf(tbl == tbl_std ? "\n`\nend\n" : "\n====\n"); - - return(EXIT_SUCCESS); -} diff --git a/vi.c b/vi.c deleted file mode 100644 index 8d7506d0f..000000000 --- a/vi.c +++ /dev/null @@ -1,3947 +0,0 @@ -/* vi: set sw=8 ts=8: */ -/* - * tiny vi.c: A small 'vi' clone - * Copyright (C) 2000, 2001 Sterling Huxley <sterling@europa.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -static const char vi_Version[] = - "$Id: vi.c,v 1.15 2001/08/02 05:26:41 andersen Exp $"; - -/* - * To compile for standalone use: - * gcc -Wall -Os -s -DSTANDALONE -o vi vi.c - * or - * gcc -Wall -Os -s -DSTANDALONE -DBB_FEATURE_VI_CRASHME -o vi vi.c # include testing features - * strip vi - */ - -/* - * Things To Do: - * EXINIT - * $HOME/.exrc and ./.exrc - * add magic to search /foo.*bar - * add :help command - * :map macros - * how about mode lines: vi: set sw=8 ts=8: - * if mark[] values were line numbers rather than pointers - * it would be easier to change the mark when add/delete lines - * More intelligence in refresh() - * ":r !cmd" and "!cmd" to filter text through an external command - * A true "undo" facility - * An "ex" line oriented mode- maybe using "cmdedit" - */ - -//---- Feature -------------- Bytes to immplement -#ifdef STANDALONE -#define vi_main main -#define BB_FEATURE_VI_COLON // 4288 -#define BB_FEATURE_VI_YANKMARK // 1408 -#define BB_FEATURE_VI_SEARCH // 1088 -#define BB_FEATURE_VI_USE_SIGNALS // 1056 -#define BB_FEATURE_VI_DOT_CMD // 576 -#define BB_FEATURE_VI_READONLY // 128 -#define BB_FEATURE_VI_SETOPTS // 576 -#define BB_FEATURE_VI_SET // 224 -#define BB_FEATURE_VI_WIN_RESIZE // 256 WIN_RESIZE -// To test editor using CRASHME: -// vi -C filename -// To stop testing, wait until all to text[] is deleted, or -// Ctrl-Z and kill -9 %1 -// while in the editor Ctrl-T will toggle the crashme function on and off. -//#define BB_FEATURE_VI_CRASHME // randomly pick commands to execute -#endif /* STANDALONE */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> -#include <unistd.h> -#include <sys/ioctl.h> -#include <sys/time.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <time.h> -#include <fcntl.h> -#include <signal.h> -#include <setjmp.h> -#include <regex.h> -#include <ctype.h> -#include <assert.h> -#include <errno.h> -#include <stdarg.h> -#ifndef STANDALONE -#include "busybox.h" -#endif /* STANDALONE */ - -#ifndef TRUE -#define TRUE ((int)1) -#define FALSE ((int)0) -#endif /* TRUE */ -#define MAX_SCR_COLS BUFSIZ - -// Misc. non-Ascii keys that report an escape sequence -#define VI_K_UP 128 // cursor key Up -#define VI_K_DOWN 129 // cursor key Down -#define VI_K_RIGHT 130 // Cursor Key Right -#define VI_K_LEFT 131 // cursor key Left -#define VI_K_HOME 132 // Cursor Key Home -#define VI_K_END 133 // Cursor Key End -#define VI_K_INSERT 134 // Cursor Key Insert -#define VI_K_PAGEUP 135 // Cursor Key Page Up -#define VI_K_PAGEDOWN 136 // Cursor Key Page Down -#define VI_K_FUN1 137 // Function Key F1 -#define VI_K_FUN2 138 // Function Key F2 -#define VI_K_FUN3 139 // Function Key F3 -#define VI_K_FUN4 140 // Function Key F4 -#define VI_K_FUN5 141 // Function Key F5 -#define VI_K_FUN6 142 // Function Key F6 -#define VI_K_FUN7 143 // Function Key F7 -#define VI_K_FUN8 144 // Function Key F8 -#define VI_K_FUN9 145 // Function Key F9 -#define VI_K_FUN10 146 // Function Key F10 -#define VI_K_FUN11 147 // Function Key F11 -#define VI_K_FUN12 148 // Function Key F12 - -static const int YANKONLY = FALSE; -static const int YANKDEL = TRUE; -static const int FORWARD = 1; // code depends on "1" for array index -static const int BACK = -1; // code depends on "-1" for array index -static const int LIMITED = 0; // how much of text[] in char_search -static const int FULL = 1; // how much of text[] in char_search - -static const int S_BEFORE_WS = 1; // used in skip_thing() for moving "dot" -static const int S_TO_WS = 2; // used in skip_thing() for moving "dot" -static const int S_OVER_WS = 3; // used in skip_thing() for moving "dot" -static const int S_END_PUNCT = 4; // used in skip_thing() for moving "dot" -static const int S_END_ALNUM = 5; // used in skip_thing() for moving "dot" - -typedef unsigned char Byte; - - -static int editing; // >0 while we are editing a file -static int cmd_mode; // 0=command 1=insert -static int file_modified; // buffer contents changed -static int err_method; // indicate error with beep or flash -static int fn_start; // index of first cmd line file name -static int save_argc; // how many file names on cmd line -static int cmdcnt; // repetition count -static fd_set rfds; // use select() for small sleeps -static struct timeval tv; // use select() for small sleeps -static char erase_char; // the users erase character -static int rows, columns; // the terminal screen is this size -static int crow, ccol, offset; // cursor is on Crow x Ccol with Horz Ofset -static char *SOs, *SOn; // terminal standout start/normal ESC sequence -static char *bell; // terminal bell sequence -static char *Ceol, *Ceos; // Clear-end-of-line and Clear-end-of-screen ESC sequence -static char *CMrc; // Cursor motion arbitrary destination ESC sequence -static char *CMup, *CMdown; // Cursor motion up and down ESC sequence -static Byte *status_buffer; // mesages to the user -static Byte last_input_char; // last char read from user -static Byte last_forward_char; // last char searched for with 'f' -static Byte *cfn; // previous, current, and next file name -static Byte *text, *end, *textend; // pointers to the user data in memory -static Byte *screen; // pointer to the virtual screen buffer -static int screensize; // and its size -static Byte *screenbegin; // index into text[], of top line on the screen -static Byte *dot; // where all the action takes place -static int tabstop; -static struct termios term_orig, term_vi; // remember what the cooked mode was - -#ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR -static int last_row; // where the cursor was last moved to -#endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */ -#ifdef BB_FEATURE_VI_USE_SIGNALS -static jmp_buf restart; // catch_sig() -#endif /* BB_FEATURE_VI_USE_SIGNALS */ -#ifdef BB_FEATURE_VI_WIN_RESIZE -static struct winsize winsize; // remember the window size -#endif /* BB_FEATURE_VI_WIN_RESIZE */ -#ifdef BB_FEATURE_VI_DOT_CMD -static int adding2q; // are we currently adding user input to q -static Byte *last_modifying_cmd; // last modifying cmd for "." -static Byte *ioq, *ioq_start; // pointer to string for get_one_char to "read" -#endif /* BB_FEATURE_VI_DOT_CMD */ -#if defined(BB_FEATURE_VI_DOT_CMD) || defined(BB_FEATURE_VI_YANKMARK) -static Byte *modifying_cmds; // cmds that modify text[] -#endif /* BB_FEATURE_VI_DOT_CMD || BB_FEATURE_VI_YANKMARK */ -#ifdef BB_FEATURE_VI_READONLY -static int vi_readonly, readonly; -#endif /* BB_FEATURE_VI_READONLY */ -#ifdef BB_FEATURE_VI_SETOPTS -static int autoindent; -static int showmatch; -static int ignorecase; -#endif /* BB_FEATURE_VI_SETOPTS */ -#ifdef BB_FEATURE_VI_YANKMARK -static Byte *reg[28]; // named register a-z, "D", and "U" 0-25,26,27 -static int YDreg, Ureg; // default delete register and orig line for "U" -static Byte *mark[28]; // user marks points somewhere in text[]- a-z and previous context '' -static Byte *context_start, *context_end; -#endif /* BB_FEATURE_VI_YANKMARK */ -#ifdef BB_FEATURE_VI_SEARCH -static Byte *last_search_pattern; // last pattern from a '/' or '?' search -#endif /* BB_FEATURE_VI_SEARCH */ - - -static void edit_file(Byte *); // edit one file -static void do_cmd(Byte); // execute a command -static void sync_cursor(Byte *, int *, int *); // synchronize the screen cursor to dot -static Byte *begin_line(Byte *); // return pointer to cur line B-o-l -static Byte *end_line(Byte *); // return pointer to cur line E-o-l -static Byte *dollar_line(Byte *); // return pointer to just before NL -static Byte *prev_line(Byte *); // return pointer to prev line B-o-l -static Byte *next_line(Byte *); // return pointer to next line B-o-l -static Byte *end_screen(void); // get pointer to last char on screen -static int count_lines(Byte *, Byte *); // count line from start to stop -static Byte *find_line(int); // find begining of line #li -static Byte *move_to_col(Byte *, int); // move "p" to column l -static int isblnk(Byte); // is the char a blank or tab -static void dot_left(void); // move dot left- dont leave line -static void dot_right(void); // move dot right- dont leave line -static void dot_begin(void); // move dot to B-o-l -static void dot_end(void); // move dot to E-o-l -static void dot_next(void); // move dot to next line B-o-l -static void dot_prev(void); // move dot to prev line B-o-l -static void dot_scroll(int, int); // move the screen up or down -static void dot_skip_over_ws(void); // move dot pat WS -static void dot_delete(void); // delete the char at 'dot' -static Byte *bound_dot(Byte *); // make sure text[0] <= P < "end" -static Byte *new_screen(int, int); // malloc virtual screen memory -static Byte *new_text(int); // malloc memory for text[] buffer -static Byte *char_insert(Byte *, Byte); // insert the char c at 'p' -static Byte *stupid_insert(Byte *, Byte); // stupidly insert the char c at 'p' -static Byte find_range(Byte **, Byte **, Byte); // return pointers for an object -static int st_test(Byte *, int, int, Byte *); // helper for skip_thing() -static Byte *skip_thing(Byte *, int, int, int); // skip some object -static Byte *find_pair(Byte *, Byte); // find matching pair () [] {} -static Byte *text_hole_delete(Byte *, Byte *); // at "p", delete a 'size' byte hole -static Byte *text_hole_make(Byte *, int); // at "p", make a 'size' byte hole -static Byte *yank_delete(Byte *, Byte *, int, int); // yank text[] into register then delete -static void show_help(void); // display some help info -static void print_literal(Byte *, Byte *); // copy s to buf, convert unprintable -static void rawmode(void); // set "raw" mode on tty -static void cookmode(void); // return to "cooked" mode on tty -static int mysleep(int); // sleep for 'h' 1/100 seconds -static Byte readit(void); // read (maybe cursor) key from stdin -static Byte get_one_char(void); // read 1 char from stdin -static int file_size(Byte *); // what is the byte size of "fn" -static int file_insert(Byte *, Byte *, int); -static int file_write(Byte *, Byte *, Byte *); -static void place_cursor(int, int, int); -static void screen_erase(); -static void clear_to_eol(void); -static void clear_to_eos(void); -static void standout_start(void); // send "start reverse video" sequence -static void standout_end(void); // send "end reverse video" sequence -static void flash(int); // flash the terminal screen -static void beep(void); // beep the terminal -static void indicate_error(char); // use flash or beep to indicate error -static void show_status_line(void); // put a message on the bottom line -static void psb(char *, ...); // Print Status Buf -static void psbs(char *, ...); // Print Status Buf in standout mode -static void ni(Byte *); // display messages -static void edit_status(void); // show file status on status line -static void redraw(int); // force a full screen refresh -static void format_line(Byte*, Byte*, int); -static void refresh(int); // update the terminal from screen[] - -#ifdef BB_FEATURE_VI_SEARCH -static Byte *char_search(Byte *, Byte *, int, int); // search for pattern starting at p -static int mycmp(Byte *, Byte *, int); // string cmp based in "ignorecase" -#endif /* BB_FEATURE_VI_SEARCH */ -#ifdef BB_FEATURE_VI_COLON -static void Hit_Return(void); -static Byte *get_one_address(Byte *, int *); // get colon addr, if present -static Byte *get_address(Byte *, int *, int *); // get two colon addrs, if present -static void colon(Byte *); // execute the "colon" mode cmds -#endif /* BB_FEATURE_VI_COLON */ -static Byte *get_input_line(Byte *); // get input line- use "status line" -#ifdef BB_FEATURE_VI_USE_SIGNALS -static void winch_sig(int); // catch window size changes -static void suspend_sig(int); // catch ctrl-Z -static void alarm_sig(int); // catch alarm time-outs -static void catch_sig(int); // catch ctrl-C -static void core_sig(int); // catch a core dump signal -#endif /* BB_FEATURE_VI_USE_SIGNALS */ -#ifdef BB_FEATURE_VI_DOT_CMD -static void start_new_cmd_q(Byte); // new queue for command -static void end_cmd_q(); // stop saving input chars -#else /* BB_FEATURE_VI_DOT_CMD */ -#define end_cmd_q() -#endif /* BB_FEATURE_VI_DOT_CMD */ -#ifdef BB_FEATURE_VI_WIN_RESIZE -static void window_size_get(int); // find out what size the window is -#endif /* BB_FEATURE_VI_WIN_RESIZE */ -#ifdef BB_FEATURE_VI_SETOPTS -static void showmatching(Byte *); // show the matching pair () [] {} -#endif /* BB_FEATURE_VI_SETOPTS */ -#if defined(BB_FEATURE_VI_YANKMARK) || defined(BB_FEATURE_VI_COLON) || defined(BB_FEATURE_VI_CRASHME) -static Byte *string_insert(Byte *, Byte *); // insert the string at 'p' -#endif /* BB_FEATURE_VI_YANKMARK || BB_FEATURE_VI_COLON || BB_FEATURE_VI_CRASHME */ -#ifdef BB_FEATURE_VI_YANKMARK -static Byte *text_yank(Byte *, Byte *, int); // save copy of "p" into a register -static Byte what_reg(void); // what is letter of current YDreg -static void check_context(Byte); // remember context for '' command -static Byte *swap_context(Byte *); // goto new context for '' command -#endif /* BB_FEATURE_VI_YANKMARK */ -#ifdef BB_FEATURE_VI_CRASHME -static void crash_dummy(); -static void crash_test(); -static int crashme = 0; -#endif /* BB_FEATURE_VI_CRASHME */ - - -extern int vi_main(int argc, char **argv) -{ - int c; - -#ifdef BB_FEATURE_VI_YANKMARK - int i; -#endif /* BB_FEATURE_VI_YANKMARK */ - - CMrc= "\033[%d;%dH"; // Terminal Crusor motion ESC sequence - CMup= "\033[A"; // move cursor up one line, same col - CMdown="\n"; // move cursor down one line, same col - Ceol= "\033[0K"; // Clear from cursor to end of line - Ceos= "\033[0J"; // Clear from cursor to end of screen - SOs = "\033[7m"; // Terminal standout mode on - SOn = "\033[0m"; // Terminal standout mode off - bell= "\007"; // Terminal bell sequence -#ifdef BB_FEATURE_VI_CRASHME - (void) srand((long) getpid()); -#endif /* BB_FEATURE_VI_CRASHME */ - status_buffer = (Byte *) malloc(200); // hold messages to user -#ifdef BB_FEATURE_VI_READONLY - vi_readonly = readonly = FALSE; - if (strncmp(argv[0], "view", 4) == 0) { - readonly = TRUE; - vi_readonly = TRUE; - } -#endif /* BB_FEATURE_VI_READONLY */ -#ifdef BB_FEATURE_VI_SETOPTS - autoindent = 1; - ignorecase = 1; - showmatch = 1; -#endif /* BB_FEATURE_VI_SETOPTS */ -#ifdef BB_FEATURE_VI_YANKMARK - for (i = 0; i < 28; i++) { - reg[i] = 0; - } // init the yank regs -#endif /* BB_FEATURE_VI_YANKMARK */ -#ifdef BB_FEATURE_VI_DOT_CMD - modifying_cmds = (Byte *) "aAcCdDiIJoOpPrRsxX<>~"; // cmds modifying text[] -#endif /* BB_FEATURE_VI_DOT_CMD */ - - // 1- process $HOME/.exrc file - // 2- process EXINIT variable from environment - // 3- process command line args - while ((c = getopt(argc, argv, "hCR")) != -1) { - switch (c) { -#ifdef BB_FEATURE_VI_CRASHME - case 'C': - crashme = 1; - break; -#endif /* BB_FEATURE_VI_CRASHME */ -#ifdef BB_FEATURE_VI_READONLY - case 'R': // Read-only flag - readonly = TRUE; - break; -#endif /* BB_FEATURE_VI_READONLY */ - //case 'r': // recover flag- ignore- we don't use tmp file - //case 'x': // encryption flag- ignore - //case 'c': // execute command first - //case 'h': // help -- just use default - default: - show_help(); - return 1; - } - } - - // The argv array can be used by the ":next" and ":rewind" commands - // save optind. - fn_start = optind; // remember first file name for :next and :rew - save_argc = argc; - - //----- This is the main file handling loop -------------- - if (optind >= argc) { - editing = 1; // 0= exit, 1= one file, 2= multiple files - edit_file(0); - } else { - for (; optind < argc; optind++) { - editing = 1; // 0=exit, 1=one file, 2+ =many files - if (cfn != 0) - free(cfn); - cfn = (Byte *) strdup(argv[optind]); - edit_file(cfn); - } - } - //----------------------------------------------------------- - - return (0); -} - -static void edit_file(Byte * fn) -{ - char c; - int cnt, size, ch; - -#ifdef BB_FEATURE_VI_USE_SIGNALS - char *msg; - int sig; -#endif /* BB_FEATURE_VI_USE_SIGNALS */ -#ifdef BB_FEATURE_VI_YANKMARK - static Byte *cur_line; -#endif /* BB_FEATURE_VI_YANKMARK */ - - rawmode(); - rows = 24; - columns = 80; - ch= -1; -#ifdef BB_FEATURE_VI_WIN_RESIZE - window_size_get(0); -#endif /* BB_FEATURE_VI_WIN_RESIZE */ - new_screen(rows, columns); // get memory for virtual screen - - cnt = file_size(fn); // file size - size = 2 * cnt; // 200% of file size - new_text(size); // get a text[] buffer - screenbegin = dot = end = text; - if (fn != 0) { - ch= file_insert(fn, text, cnt); - } - if (ch < 1) { - (void) char_insert(text, '\n'); // start empty buf with dummy line - } - file_modified = FALSE; -#ifdef BB_FEATURE_VI_YANKMARK - YDreg = 26; // default Yank/Delete reg - Ureg = 27; // hold orig line for "U" cmd - for (cnt = 0; cnt < 28; cnt++) { - mark[cnt] = 0; - } // init the marks - mark[26] = mark[27] = text; // init "previous context" -#endif /* BB_FEATURE_VI_YANKMARK */ - - err_method = 1; // flash - last_forward_char = last_input_char = '\0'; - crow = 0; - ccol = 0; - edit_status(); - -#ifdef BB_FEATURE_VI_USE_SIGNALS - signal(SIGHUP, catch_sig); - signal(SIGINT, catch_sig); - signal(SIGALRM, alarm_sig); - signal(SIGTERM, catch_sig); - signal(SIGQUIT, core_sig); - signal(SIGILL, core_sig); - signal(SIGTRAP, core_sig); - signal(SIGIOT, core_sig); - signal(SIGABRT, core_sig); - signal(SIGFPE, core_sig); - signal(SIGBUS, core_sig); - signal(SIGSEGV, core_sig); -#ifdef SIGSYS - signal(SIGSYS, core_sig); -#endif - signal(SIGWINCH, winch_sig); - signal(SIGTSTP, suspend_sig); - sig = setjmp(restart); - if (sig != 0) { - msg = ""; - if (sig == SIGWINCH) - msg = "(window resize)"; - if (sig == SIGHUP) - msg = "(hangup)"; - if (sig == SIGINT) - msg = "(interrupt)"; - if (sig == SIGTERM) - msg = "(terminate)"; - if (sig == SIGBUS) - msg = "(bus error)"; - if (sig == SIGSEGV) - msg = "(I tried to touch invalid memory)"; - if (sig == SIGALRM) - msg = "(alarm)"; - - psbs("-- caught signal %d %s--", sig, msg); - screenbegin = dot = text; - } -#endif /* BB_FEATURE_VI_USE_SIGNALS */ - - editing = 1; - cmd_mode = 0; // 0=command 1=insert 2='R'eplace - cmdcnt = 0; - tabstop = 8; - offset = 0; // no horizontal offset - c = '\0'; -#ifdef BB_FEATURE_VI_DOT_CMD - if (last_modifying_cmd != 0) - free(last_modifying_cmd); - if (ioq_start != NULL) - free(ioq_start); - ioq = ioq_start = last_modifying_cmd = 0; - adding2q = 0; -#endif /* BB_FEATURE_VI_DOT_CMD */ - redraw(FALSE); // dont force every col re-draw - show_status_line(); - - //------This is the main Vi cmd handling loop ----------------------- - while (editing > 0) { -#ifdef BB_FEATURE_VI_CRASHME - if (crashme > 0) { - if ((end - text) > 1) { - crash_dummy(); // generate a random command - } else { - crashme = 0; - dot = - string_insert(text, (Byte *) "\n\n##### Ran out of text to work on. #####\n\n"); // insert the string - refresh(FALSE); - } - } -#endif /* BB_FEATURE_VI_CRASHME */ - last_input_char = c = get_one_char(); // get a cmd from user -#ifdef BB_FEATURE_VI_YANKMARK - // save a copy of the current line- for the 'U" command - if (begin_line(dot) != cur_line) { - cur_line = begin_line(dot); - text_yank(begin_line(dot), end_line(dot), Ureg); - } -#endif /* BB_FEATURE_VI_YANKMARK */ -#ifdef BB_FEATURE_VI_DOT_CMD - // These are commands that change text[]. - // Remember the input for the "." command - if (!adding2q && ioq_start == 0 - && strchr((char *) modifying_cmds, c) != NULL) { - start_new_cmd_q(c); - } -#endif /* BB_FEATURE_VI_DOT_CMD */ - do_cmd(c); // execute the user command - // - // poll to see if there is input already waiting. if we are - // not able to display output fast enough to keep up, skip - // the display update until we catch up with input. - if (mysleep(0) == 0) { - // no input pending- so update output - refresh(FALSE); - show_status_line(); - } -#ifdef BB_FEATURE_VI_CRASHME - if (crashme > 0) - crash_test(); // test editor variables -#endif /* BB_FEATURE_VI_CRASHME */ - } - //------------------------------------------------------------------- - - place_cursor(rows, 0, FALSE); // go to bottom of screen - clear_to_eol(); // Erase to end of line - cookmode(); -} - -static Byte readbuffer[BUFSIZ]; - -#ifdef BB_FEATURE_VI_CRASHME -static int totalcmds = 0; -static int Mp = 85; // Movement command Probability -static int Np = 90; // Non-movement command Probability -static int Dp = 96; // Delete command Probability -static int Ip = 97; // Insert command Probability -static int Yp = 98; // Yank command Probability -static int Pp = 99; // Put command Probability -static int M = 0, N = 0, I = 0, D = 0, Y = 0, P = 0, U = 0; -char chars[20] = "\t012345 abcdABCD-=.$"; -char *words[20] = { "this", "is", "a", "test", - "broadcast", "the", "emergency", "of", - "system", "quick", "brown", "fox", - "jumped", "over", "lazy", "dogs", - "back", "January", "Febuary", "March" -}; -char *lines[20] = { - "You should have received a copy of the GNU General Public License\n", - "char c, cm, *cmd, *cmd1;\n", - "generate a command by percentages\n", - "Numbers may be typed as a prefix to some commands.\n", - "Quit, discarding changes!\n", - "Forced write, if permission originally not valid.\n", - "In general, any ex or ed command (such as substitute or delete).\n", - "I have tickets available for the Blazers vs LA Clippers for Monday, Janurary 1 at 1:00pm.\n", - "Please get w/ me and I will go over it with you.\n", - "The following is a list of scheduled, committed changes.\n", - "1. Launch Norton Antivirus (Start, Programs, Norton Antivirus)\n", - "Reminder....Town Meeting in Central Perk cafe today at 3:00pm.\n", - "Any question about transactions please contact Sterling Huxley.\n", - "I will try to get back to you by Friday, December 31.\n", - "This Change will be implemented on Friday.\n", - "Let me know if you have problems accessing this;\n", - "Sterling Huxley recently added you to the access list.\n", - "Would you like to go to lunch?\n", - "The last command will be automatically run.\n", - "This is too much english for a computer geek.\n", -}; -char *multilines[20] = { - "You should have received a copy of the GNU General Public License\n", - "char c, cm, *cmd, *cmd1;\n", - "generate a command by percentages\n", - "Numbers may be typed as a prefix to some commands.\n", - "Quit, discarding changes!\n", - "Forced write, if permission originally not valid.\n", - "In general, any ex or ed command (such as substitute or delete).\n", - "I have tickets available for the Blazers vs LA Clippers for Monday, Janurary 1 at 1:00pm.\n", - "Please get w/ me and I will go over it with you.\n", - "The following is a list of scheduled, committed changes.\n", - "1. Launch Norton Antivirus (Start, Programs, Norton Antivirus)\n", - "Reminder....Town Meeting in Central Perk cafe today at 3:00pm.\n", - "Any question about transactions please contact Sterling Huxley.\n", - "I will try to get back to you by Friday, December 31.\n", - "This Change will be implemented on Friday.\n", - "Let me know if you have problems accessing this;\n", - "Sterling Huxley recently added you to the access list.\n", - "Would you like to go to lunch?\n", - "The last command will be automatically run.\n", - "This is too much english for a computer geek.\n", -}; - -// create a random command to execute -static void crash_dummy() -{ - static int sleeptime; // how long to pause between commands - char c, cm, *cmd, *cmd1; - int i, cnt, thing, rbi, startrbi, percent; - - // "dot" movement commands - cmd1 = " \n\r\002\004\005\006\025\0310^$-+wWeEbBhjklHL"; - - // is there already a command running? - if (strlen((char *) readbuffer) > 0) - goto cd1; - cd0: - startrbi = rbi = 0; - sleeptime = 0; // how long to pause between commands - memset(readbuffer, '\0', BUFSIZ - 1); // clear the read buffer - // generate a command by percentages - percent = (int) lrand48() % 100; // get a number from 0-99 - if (percent < Mp) { // Movement commands - // available commands - cmd = cmd1; - M++; - } else if (percent < Np) { // non-movement commands - cmd = "mz<>\'\""; // available commands - N++; - } else if (percent < Dp) { // Delete commands - cmd = "dx"; // available commands - D++; - } else if (percent < Ip) { // Inset commands - cmd = "iIaAsrJ"; // available commands - I++; - } else if (percent < Yp) { // Yank commands - cmd = "yY"; // available commands - Y++; - } else if (percent < Pp) { // Put commands - cmd = "pP"; // available commands - P++; - } else { - // We do not know how to handle this command, try again - U++; - goto cd0; - } - // randomly pick one of the available cmds from "cmd[]" - i = (int) lrand48() % strlen(cmd); - cm = cmd[i]; - if (strchr(":\024", cm)) - goto cd0; // dont allow colon or ctrl-T commands - readbuffer[rbi++] = cm; // put cmd into input buffer - - // now we have the command- - // there are 1, 2, and multi char commands - // find out which and generate the rest of command as necessary - if (strchr("dmryz<>\'\"", cm)) { // 2-char commands - cmd1 = " \n\r0$^-+wWeEbBhjklHL"; - if (cm == 'm' || cm == '\'' || cm == '\"') { // pick a reg[] - cmd1 = "abcdefghijklmnopqrstuvwxyz"; - } - thing = (int) lrand48() % strlen(cmd1); // pick a movement command - c = cmd1[thing]; - readbuffer[rbi++] = c; // add movement to input buffer - } - if (strchr("iIaAsc", cm)) { // multi-char commands - if (cm == 'c') { - // change some thing - thing = (int) lrand48() % strlen(cmd1); // pick a movement command - c = cmd1[thing]; - readbuffer[rbi++] = c; // add movement to input buffer - } - thing = (int) lrand48() % 4; // what thing to insert - cnt = (int) lrand48() % 10; // how many to insert - for (i = 0; i < cnt; i++) { - if (thing == 0) { // insert chars - readbuffer[rbi++] = chars[((int) lrand48() % strlen(chars))]; - } else if (thing == 1) { // insert words - strcat((char *) readbuffer, words[(int) lrand48() % 20]); - strcat((char *) readbuffer, " "); - sleeptime = 0; // how fast to type - } else if (thing == 2) { // insert lines - strcat((char *) readbuffer, lines[(int) lrand48() % 20]); - sleeptime = 0; // how fast to type - } else { // insert multi-lines - strcat((char *) readbuffer, multilines[(int) lrand48() % 20]); - sleeptime = 0; // how fast to type - } - } - strcat((char *) readbuffer, "\033"); - } - cd1: - totalcmds++; - if (sleeptime > 0) - (void) mysleep(sleeptime); // sleep 1/100 sec -} - -// test to see if there are any errors -static void crash_test() -{ - static time_t oldtim; - time_t tim; - char d[2], buf[BUFSIZ], msg[BUFSIZ]; - - msg[0] = '\0'; - if (end < text) { - strcat((char *) msg, "end<text "); - } - if (end > textend) { - strcat((char *) msg, "end>textend "); - } - if (dot < text) { - strcat((char *) msg, "dot<text "); - } - if (dot > end) { - strcat((char *) msg, "dot>end "); - } - if (screenbegin < text) { - strcat((char *) msg, "screenbegin<text "); - } - if (screenbegin > end - 1) { - strcat((char *) msg, "screenbegin>end-1 "); - } - - if (strlen(msg) > 0) { - alarm(0); - sprintf(buf, "\n\n%d: \'%c\' %s\n\n\n%s[Hit return to continue]%s", - totalcmds, last_input_char, msg, SOs, SOn); - write(1, buf, strlen(buf)); - while (read(0, d, 1) > 0) { - if (d[0] == '\n' || d[0] == '\r') - break; - } - alarm(3); - } - tim = (time_t) time((time_t *) 0); - if (tim >= (oldtim + 3)) { - sprintf((char *) status_buffer, - "Tot=%d: M=%d N=%d I=%d D=%d Y=%d P=%d U=%d size=%d", - totalcmds, M, N, I, D, Y, P, U, end - text + 1); - oldtim = tim; - } - return; -} -#endif /* BB_FEATURE_VI_CRASHME */ - -//--------------------------------------------------------------------- -//----- the Ascii Chart ----------------------------------------------- -// -// 00 nul 01 soh 02 stx 03 etx 04 eot 05 enq 06 ack 07 bel -// 08 bs 09 ht 0a nl 0b vt 0c np 0d cr 0e so 0f si -// 10 dle 11 dc1 12 dc2 13 dc3 14 dc4 15 nak 16 syn 17 etb -// 18 can 19 em 1a sub 1b esc 1c fs 1d gs 1e rs 1f us -// 20 sp 21 ! 22 " 23 # 24 $ 25 % 26 & 27 ' -// 28 ( 29 ) 2a * 2b + 2c , 2d - 2e . 2f / -// 30 0 31 1 32 2 33 3 34 4 35 5 36 6 37 7 -// 38 8 39 9 3a : 3b ; 3c < 3d = 3e > 3f ? -// 40 @ 41 A 42 B 43 C 44 D 45 E 46 F 47 G -// 48 H 49 I 4a J 4b K 4c L 4d M 4e N 4f O -// 50 P 51 Q 52 R 53 S 54 T 55 U 56 V 57 W -// 58 X 59 Y 5a Z 5b [ 5c \ 5d ] 5e ^ 5f _ -// 60 ` 61 a 62 b 63 c 64 d 65 e 66 f 67 g -// 68 h 69 i 6a j 6b k 6c l 6d m 6e n 6f o -// 70 p 71 q 72 r 73 s 74 t 75 u 76 v 77 w -// 78 x 79 y 7a z 7b { 7c | 7d } 7e ~ 7f del -//--------------------------------------------------------------------- - -//----- Execute a Vi Command ----------------------------------- -static void do_cmd(Byte c) -{ - Byte c1, *p, *q, *msg, buf[9], *save_dot; - int cnt, i, j, dir, yf; - - c1 = c; // quiet the compiler - cnt = yf = dir = 0; // quiet the compiler - p = q = save_dot = msg = buf; // quiet the compiler - memset(buf, '\0', 9); // clear buf - if (cmd_mode == 2) { - // we are 'R'eplacing the current *dot with new char - if (*dot == '\n') { - // don't Replace past E-o-l - cmd_mode = 1; // convert to insert - } else { - if (1 <= c && c <= 127) { // only ASCII chars - if (c != 27) - dot = yank_delete(dot, dot, 0, YANKDEL); // delete char - dot = char_insert(dot, c); // insert new char - } - goto dc1; - } - } - if (cmd_mode == 1) { - // hitting "Insert" twice means "R" replace mode - if (c == VI_K_INSERT) goto dc5; - // insert the char c at "dot" - if (1 <= c && c <= 127) { - dot = char_insert(dot, c); // only ASCII chars - } - goto dc1; - } - - switch (c) { - //case 0x01: // soh - //case 0x09: // ht - //case 0x0b: // vt - //case 0x0e: // so - //case 0x0f: // si - //case 0x10: // dle - //case 0x11: // dc1 - //case 0x13: // dc3 -#ifdef BB_FEATURE_VI_CRASHME - case 0x14: // dc4 ctrl-T - crashme = (crashme == 0) ? 1 : 0; - break; -#endif /* BB_FEATURE_VI_CRASHME */ - //case 0x16: // syn - //case 0x17: // etb - //case 0x18: // can - //case 0x1c: // fs - //case 0x1d: // gs - //case 0x1e: // rs - //case 0x1f: // us - //case '!': // !- - //case '#': // #- - //case '&': // &- - //case '(': // (- - //case ')': // )- - //case '*': // *- - //case ',': // ,- - //case '=': // =- - //case '@': // @- - //case 'F': // F- - //case 'K': // K- - //case 'Q': // Q- - //case 'S': // S- - //case 'T': // T- - //case 'V': // V- - //case '[': // [- - //case '\\': // \- - //case ']': // ]- - //case '_': // _- - //case '`': // `- - //case 'g': // g- - //case 'u': // u- FIXME- there is no undo - //case 'v': // v- - default: // unrecognised command - buf[0] = c; - buf[1] = '\0'; - if (c <= ' ') { - buf[0] = '^'; - buf[1] = c + '@'; - buf[2] = '\0'; - } - ni((Byte *) buf); - end_cmd_q(); // stop adding to q - case 0x00: // nul- ignore - break; - case 2: // ctrl-B scroll up full screen - case VI_K_PAGEUP: // Cursor Key Page Up - dot_scroll(rows - 2, -1); - break; -#ifdef BB_FEATURE_VI_USE_SIGNALS - case 0x03: // ctrl-C interrupt - longjmp(restart, 1); - break; - case 26: // ctrl-Z suspend - suspend_sig(SIGTSTP); - break; -#endif /* BB_FEATURE_VI_USE_SIGNALS */ - case 4: // ctrl-D scroll down half screen - dot_scroll((rows - 2) / 2, 1); - break; - case 5: // ctrl-E scroll down one line - dot_scroll(1, 1); - break; - case 6: // ctrl-F scroll down full screen - case VI_K_PAGEDOWN: // Cursor Key Page Down - dot_scroll(rows - 2, 1); - break; - case 7: // ctrl-G show current status - edit_status(); - break; - case 'h': // h- move left - case VI_K_LEFT: // cursor key Left - case 8: // ctrl-H- move left (This may be ERASE char) - case 127: // DEL- move left (This may be ERASE char) - if (cmdcnt-- > 1) { - do_cmd(c); - } // repeat cnt - dot_left(); - break; - case 10: // Newline ^J - case 'j': // j- goto next line, same col - case VI_K_DOWN: // cursor key Down - if (cmdcnt-- > 1) { - do_cmd(c); - } // repeat cnt - dot_next(); // go to next B-o-l - dot = move_to_col(dot, ccol + offset); // try stay in same col - break; - case 12: // ctrl-L force redraw whole screen - case 18: // ctrl-R force redraw - place_cursor(0, 0, FALSE); // put cursor in correct place - clear_to_eos(); // tel terminal to erase display - (void) mysleep(10); - screen_erase(); // erase the internal screen buffer - refresh(TRUE); // this will redraw the entire display - break; - case 13: // Carriage Return ^M - case '+': // +- goto next line - if (cmdcnt-- > 1) { - do_cmd(c); - } // repeat cnt - dot_next(); - dot_skip_over_ws(); - break; - case 21: // ctrl-U scroll up half screen - dot_scroll((rows - 2) / 2, -1); - break; - case 25: // ctrl-Y scroll up one line - dot_scroll(1, -1); - break; - case 27: // esc - if (cmd_mode == 0) - indicate_error(c); - cmd_mode = 0; // stop insrting - end_cmd_q(); - *status_buffer = '\0'; // clear status buffer - break; - case ' ': // move right - case 'l': // move right - case VI_K_RIGHT: // Cursor Key Right - if (cmdcnt-- > 1) { - do_cmd(c); - } // repeat cnt - dot_right(); - break; -#ifdef BB_FEATURE_VI_YANKMARK - case '"': // "- name a register to use for Delete/Yank - c1 = get_one_char(); - c1 = tolower(c1); - if (islower(c1)) { - YDreg = c1 - 'a'; - } else { - indicate_error(c); - } - break; - case '\'': // '- goto a specific mark - c1 = get_one_char(); - c1 = tolower(c1); - if (islower(c1)) { - c1 = c1 - 'a'; - // get the b-o-l - q = mark[(int) c1]; - if (text <= q && q < end) { - dot = q; - dot_begin(); // go to B-o-l - dot_skip_over_ws(); - } - } else if (c1 == '\'') { // goto previous context - dot = swap_context(dot); // swap current and previous context - dot_begin(); // go to B-o-l - dot_skip_over_ws(); - } else { - indicate_error(c); - } - break; - case 'm': // m- Mark a line - // this is really stupid. If there are any inserts or deletes - // between text[0] and dot then this mark will not point to the - // correct location! It could be off by many lines! - // Well..., at least its quick and dirty. - c1 = get_one_char(); - c1 = tolower(c1); - if (islower(c1)) { - c1 = c1 - 'a'; - // remember the line - mark[(int) c1] = dot; - } else { - indicate_error(c); - } - break; - case 'P': // P- Put register before - case 'p': // p- put register after - p = reg[YDreg]; - if (p == 0) { - psbs("Nothing in register %c", what_reg()); - break; - } - // are we putting whole lines or strings - if (strchr((char *) p, '\n') != NULL) { - if (c == 'P') { - dot_begin(); // putting lines- Put above - } - if (c == 'p') { - // are we putting after very last line? - if (end_line(dot) == (end - 1)) { - dot = end; // force dot to end of text[] - } else { - dot_next(); // next line, then put before - } - } - } else { - if (c == 'p') - dot_right(); // move to right, can move to NL - } - dot = string_insert(dot, p); // insert the string - end_cmd_q(); // stop adding to q - break; - case 'U': // U- Undo; replace current line with original version - if (reg[Ureg] != 0) { - p = begin_line(dot); - q = end_line(dot); - p = text_hole_delete(p, q); // delete cur line - p = string_insert(p, reg[Ureg]); // insert orig line - dot = p; - dot_skip_over_ws(); - } - break; -#endif /* BB_FEATURE_VI_YANKMARK */ - case '$': // $- goto end of line - case VI_K_END: // Cursor Key End - if (cmdcnt-- > 1) { - do_cmd(c); - } // repeat cnt - dot = end_line(dot + 1); - break; - case '%': // %- find matching char of pair () [] {} - for (q = dot; q < end && *q != '\n'; q++) { - if (strchr("()[]{}", *q) != NULL) { - // we found half of a pair - p = find_pair(q, *q); - if (p == NULL) { - indicate_error(c); - } else { - dot = p; - } - break; - } - } - if (*q == '\n') - indicate_error(c); - break; - case 'f': // f- forward to a user specified char - last_forward_char = get_one_char(); // get the search char - // - // dont seperate these two commands. 'f' depends on ';' - // - //**** fall thru to ... 'i' - case ';': // ;- look at rest of line for last forward char - if (cmdcnt-- > 1) { - do_cmd(';'); - } // repeat cnt - if (last_forward_char == 0) break; - q = dot + 1; - while (q < end - 1 && *q != '\n' && *q != last_forward_char) { - q++; - } - if (*q == last_forward_char) - dot = q; - break; - case '-': // -- goto prev line - if (cmdcnt-- > 1) { - do_cmd(c); - } // repeat cnt - dot_prev(); - dot_skip_over_ws(); - break; -#ifdef BB_FEATURE_VI_DOT_CMD - case '.': // .- repeat the last modifying command - // Stuff the last_modifying_cmd back into stdin - // and let it be re-executed. - if (last_modifying_cmd != 0) { - ioq = ioq_start = (Byte *) strdup((char *) last_modifying_cmd); - } - break; -#endif /* BB_FEATURE_VI_DOT_CMD */ -#ifdef BB_FEATURE_VI_SEARCH - case '?': // /- search for a pattern - case '/': // /- search for a pattern - buf[0] = c; - buf[1] = '\0'; - q = get_input_line(buf); // get input line- use "status line" - if (strlen((char *) q) == 1) - goto dc3; // if no pat re-use old pat - if (strlen((char *) q) > 1) { // new pat- save it and find - // there is a new pat - if (last_search_pattern != 0) { - free(last_search_pattern); - } - last_search_pattern = (Byte *) strdup((char *) q); - goto dc3; // now find the pattern - } - // user changed mind and erased the "/"- do nothing - break; - case 'N': // N- backward search for last pattern - if (cmdcnt-- > 1) { - do_cmd(c); - } // repeat cnt - dir = BACK; // assume BACKWARD search - p = dot - 1; - if (last_search_pattern[0] == '?') { - dir = FORWARD; - p = dot + 1; - } - goto dc4; // now search for pattern - break; - case 'n': // n- repeat search for last pattern - // search rest of text[] starting at next char - // if search fails return orignal "p" not the "p+1" address - if (cmdcnt-- > 1) { - do_cmd(c); - } // repeat cnt - dc3: - if (last_search_pattern == 0) { - msg = (Byte *) "No previous regular expression"; - goto dc2; - } - if (last_search_pattern[0] == '/') { - dir = FORWARD; // assume FORWARD search - p = dot + 1; - } - if (last_search_pattern[0] == '?') { - dir = BACK; - p = dot - 1; - } - dc4: - q = char_search(p, last_search_pattern + 1, dir, FULL); - if (q != NULL) { - dot = q; // good search, update "dot" - msg = (Byte *) ""; - goto dc2; - } - // no pattern found between "dot" and "end"- continue at top - p = text; - if (dir == BACK) { - p = end - 1; - } - q = char_search(p, last_search_pattern + 1, dir, FULL); - if (q != NULL) { // found something - dot = q; // found new pattern- goto it - msg = (Byte *) "search hit BOTTOM, continuing at TOP"; - if (dir == BACK) { - msg = (Byte *) "search hit TOP, continuing at BOTTOM"; - } - } else { - msg = (Byte *) "Pattern not found"; - } - dc2: - psbs("%s", msg); - break; - case '{': // {- move backward paragraph - q = char_search(dot, (Byte *) "\n\n", BACK, FULL); - if (q != NULL) { // found blank line - dot = next_line(q); // move to next blank line - } - break; - case '}': // }- move forward paragraph - q = char_search(dot, (Byte *) "\n\n", FORWARD, FULL); - if (q != NULL) { // found blank line - dot = next_line(q); // move to next blank line - } - break; -#endif /* BB_FEATURE_VI_SEARCH */ - case '0': // 0- goto begining of line - case '1': // 1- - case '2': // 2- - case '3': // 3- - case '4': // 4- - case '5': // 5- - case '6': // 6- - case '7': // 7- - case '8': // 8- - case '9': // 9- - if (c == '0' && cmdcnt < 1) { - dot_begin(); // this was a standalone zero - } else { - cmdcnt = cmdcnt * 10 + (c - '0'); // this 0 is part of a number - } - break; - case ':': // :- the colon mode commands - p = get_input_line((Byte *) ":"); // get input line- use "status line" -#ifdef BB_FEATURE_VI_COLON - colon(p); // execute the command -#else /* BB_FEATURE_VI_COLON */ - if (*p == ':') - p++; // move past the ':' - cnt = strlen((char *) p); - if (cnt <= 0) - break; - if (strncasecmp((char *) p, "quit", cnt) == 0 || - strncasecmp((char *) p, "q!", cnt) == 0) { // delete lines - if (file_modified == TRUE && p[1] != '!') { - psbs("No write since last change (:quit! overrides)"); - } else { - editing = 0; - } - } else if (strncasecmp((char *) p, "write", cnt) == 0 || - strncasecmp((char *) p, "wq", cnt) == 0) { - cnt = file_write(cfn, text, end - 1); - file_modified = FALSE; - psb("\"%s\" %dL, %dC", cfn, count_lines(text, end - 1), cnt); - if (p[1] == 'q') { - editing = 0; - } - } else if (strncasecmp((char *) p, "file", cnt) == 0 ) { - edit_status(); // show current file status - } else if (sscanf((char *) p, "%d", &j) > 0) { - dot = find_line(j); // go to line # j - dot_skip_over_ws(); - } else { // unrecognised cmd - ni((Byte *) p); - } -#endif /* BB_FEATURE_VI_COLON */ - break; - case '<': // <- Left shift something - case '>': // >- Right shift something - cnt = count_lines(text, dot); // remember what line we are on - c1 = get_one_char(); // get the type of thing to delete - find_range(&p, &q, c1); - (void) yank_delete(p, q, 1, YANKONLY); // save copy before change - p = begin_line(p); - q = end_line(q); - i = count_lines(p, q); // # of lines we are shifting - for ( ; i > 0; i--, p = next_line(p)) { - if (c == '<') { - // shift left- remove tab or 8 spaces - if (*p == '\t') { - // shrink buffer 1 char - (void) text_hole_delete(p, p); - } else if (*p == ' ') { - // we should be calculating columns, not just SPACE - for (j = 0; *p == ' ' && j < tabstop; j++) { - (void) text_hole_delete(p, p); - } - } - } else if (c == '>') { - // shift right -- add tab or 8 spaces - (void) char_insert(p, '\t'); - } - } - dot = find_line(cnt); // what line were we on - dot_skip_over_ws(); - end_cmd_q(); // stop adding to q - break; - case 'A': // A- append at e-o-l - dot_end(); // go to e-o-l - //**** fall thru to ... 'a' - case 'a': // a- append after current char - if (*dot != '\n') - dot++; - goto dc_i; - break; - case 'B': // B- back a blank-delimited Word - case 'E': // E- end of a blank-delimited word - case 'W': // W- forward a blank-delimited word - if (cmdcnt-- > 1) { - do_cmd(c); - } // repeat cnt - dir = FORWARD; - if (c == 'B') - dir = BACK; - if (c == 'W' || isspace(dot[dir])) { - dot = skip_thing(dot, 1, dir, S_TO_WS); - dot = skip_thing(dot, 2, dir, S_OVER_WS); - } - if (c != 'W') - dot = skip_thing(dot, 1, dir, S_BEFORE_WS); - break; - case 'C': // C- Change to e-o-l - case 'D': // D- delete to e-o-l - save_dot = dot; - dot = dollar_line(dot); // move to before NL - // copy text into a register and delete - dot = yank_delete(save_dot, dot, 0, YANKDEL); // delete to e-o-l - if (c == 'C') - goto dc_i; // start inserting -#ifdef BB_FEATURE_VI_DOT_CMD - if (c == 'D') - end_cmd_q(); // stop adding to q -#endif /* BB_FEATURE_VI_DOT_CMD */ - break; - case 'G': // G- goto to a line number (default= E-O-F) - dot = end - 1; // assume E-O-F - if (cmdcnt > 0) { - dot = find_line(cmdcnt); // what line is #cmdcnt - } - dot_skip_over_ws(); - break; - case 'H': // H- goto top line on screen - dot = screenbegin; - if (cmdcnt > (rows - 1)) { - cmdcnt = (rows - 1); - } - if (cmdcnt-- > 1) { - do_cmd('+'); - } // repeat cnt - dot_skip_over_ws(); - break; - case 'I': // I- insert before first non-blank - dot_begin(); // 0 - dot_skip_over_ws(); - //**** fall thru to ... 'i' - case 'i': // i- insert before current char - case VI_K_INSERT: // Cursor Key Insert - dc_i: - cmd_mode = 1; // start insrting - psb("-- Insert --"); - break; - case 'J': // J- join current and next lines together - if (cmdcnt-- > 2) { - do_cmd(c); - } // repeat cnt - dot_end(); // move to NL - if (dot < end - 1) { // make sure not last char in text[] - *dot++ = ' '; // replace NL with space - while (isblnk(*dot)) { // delete leading WS - dot_delete(); - } - } - end_cmd_q(); // stop adding to q - break; - case 'L': // L- goto bottom line on screen - dot = end_screen(); - if (cmdcnt > (rows - 1)) { - cmdcnt = (rows - 1); - } - if (cmdcnt-- > 1) { - do_cmd('-'); - } // repeat cnt - dot_begin(); - dot_skip_over_ws(); - break; - case 'M': // M- goto middle line on screen - dot = screenbegin; - for (cnt = 0; cnt < (rows-1) / 2; cnt++) - dot = next_line(dot); - break; - case 'O': // O- open a empty line above - // 0i\n ESC -i - p = begin_line(dot); - if (p[-1] == '\n') { - dot_prev(); - case 'o': // o- open a empty line below; Yes, I know it is in the middle of the "if (..." - dot_end(); - dot = char_insert(dot, '\n'); - } else { - dot_begin(); // 0 - dot = char_insert(dot, '\n'); // i\n ESC - dot_prev(); // - - } - goto dc_i; - break; - case 'R': // R- continuous Replace char - dc5: - cmd_mode = 2; - psb("-- Replace --"); - break; - case 'X': // X- delete char before dot - case 'x': // x- delete the current char - case 's': // s- substitute the current char - if (cmdcnt-- > 1) { - do_cmd(c); - } // repeat cnt - dir = 0; - if (c == 'X') - dir = -1; - if (dot[dir] != '\n') { - if (c == 'X') - dot--; // delete prev char - dot = yank_delete(dot, dot, 0, YANKDEL); // delete char - } - if (c == 's') - goto dc_i; // start insrting - end_cmd_q(); // stop adding to q - break; - case 'Z': // Z- if modified, {write}; exit - // ZZ means to save file (if necessary), then exit - c1 = get_one_char(); - if (c1 != 'Z') { - indicate_error(c); - break; - } - if (file_modified == TRUE -#ifdef BB_FEATURE_VI_READONLY - && vi_readonly == FALSE - && readonly == FALSE -#endif /* BB_FEATURE_VI_READONLY */ - ) { - cnt = file_write(cfn, text, end - 1); - if (cnt == (end - 1 - text + 1)) { - editing = 0; - } - } else { - editing = 0; - } - break; - case '^': // ^- move to first non-blank on line - dot_begin(); - dot_skip_over_ws(); - break; - case 'b': // b- back a word - case 'e': // e- end of word - if (cmdcnt-- > 1) { - do_cmd(c); - } // repeat cnt - dir = FORWARD; - if (c == 'b') - dir = BACK; - if ((dot + dir) < text || (dot + dir) > end - 1) - break; - dot += dir; - if (isspace(*dot)) { - dot = skip_thing(dot, (c == 'e') ? 2 : 1, dir, S_OVER_WS); - } - if (isalnum(*dot) || *dot == '_') { - dot = skip_thing(dot, 1, dir, S_END_ALNUM); - } else if (ispunct(*dot)) { - dot = skip_thing(dot, 1, dir, S_END_PUNCT); - } - break; - case 'c': // c- change something - case 'd': // d- delete something -#ifdef BB_FEATURE_VI_YANKMARK - case 'y': // y- yank something - case 'Y': // Y- Yank a line -#endif /* BB_FEATURE_VI_YANKMARK */ - yf = YANKDEL; // assume either "c" or "d" -#ifdef BB_FEATURE_VI_YANKMARK - if (c == 'y' || c == 'Y') - yf = YANKONLY; -#endif /* BB_FEATURE_VI_YANKMARK */ - c1 = 'y'; - if (c != 'Y') - c1 = get_one_char(); // get the type of thing to delete - find_range(&p, &q, c1); - if (c1 == 27) { // ESC- user changed mind and wants out - c = c1 = 27; // Escape- do nothing - } else if (strchr("wW", c1)) { - if (c == 'c') { - // don't include trailing WS as part of word - while (isblnk(*q)) { - if (q <= text || q[-1] == '\n') - break; - q--; - } - } - dot = yank_delete(p, q, 0, yf); // delete word - } else if (strchr("^0bBeEft$", c1)) { - // single line copy text into a register and delete - dot = yank_delete(p, q, 0, yf); // delete word - } else if (strchr("cdykjHL%+-{}\r\n", c1)) { - // multiple line copy text into a register and delete - dot = yank_delete(p, q, 1, yf); // delete lines - if (c == 'c') { - dot = char_insert(dot, '\n'); - // on the last line of file don't move to prev line - if (dot != (end-1)) { - dot_prev(); - } - } else if (c == 'd') { - dot_begin(); - dot_skip_over_ws(); - } - } else { - // could not recognize object - c = c1 = 27; // error- - indicate_error(c); - } - if (c1 != 27) { - // if CHANGING, not deleting, start inserting after the delete - if (c == 'c') { - strcpy((char *) buf, "Change"); - goto dc_i; // start inserting - } - if (c == 'd') { - strcpy((char *) buf, "Delete"); - } -#ifdef BB_FEATURE_VI_YANKMARK - if (c == 'y' || c == 'Y') { - strcpy((char *) buf, "Yank"); - } - p = reg[YDreg]; - q = p + strlen((char *) p); - for (cnt = 0; p <= q; p++) { - if (*p == '\n') - cnt++; - } - psb("%s %d lines (%d chars) using [%c]", - buf, cnt, strlen((char *) reg[YDreg]), what_reg()); -#endif /* BB_FEATURE_VI_YANKMARK */ - end_cmd_q(); // stop adding to q - } - break; - case 'k': // k- goto prev line, same col - case VI_K_UP: // cursor key Up - if (cmdcnt-- > 1) { - do_cmd(c); - } // repeat cnt - dot_prev(); - dot = move_to_col(dot, ccol + offset); // try stay in same col - break; - case 'r': // r- replace the current char with user input - c1 = get_one_char(); // get the replacement char - if (*dot != '\n') { - *dot = c1; - file_modified = TRUE; // has the file been modified - } - end_cmd_q(); // stop adding to q - break; - case 't': // t- move to char prior to next x - last_forward_char = get_one_char(); - do_cmd(';'); - if (*dot == last_forward_char) - dot_left(); - last_forward_char= 0; - break; - case 'w': // w- forward a word - if (cmdcnt-- > 1) { - do_cmd(c); - } // repeat cnt - if (isalnum(*dot) || *dot == '_') { // we are on ALNUM - dot = skip_thing(dot, 1, FORWARD, S_END_ALNUM); - } else if (ispunct(*dot)) { // we are on PUNCT - dot = skip_thing(dot, 1, FORWARD, S_END_PUNCT); - } - if (dot < end - 1) - dot++; // move over word - if (isspace(*dot)) { - dot = skip_thing(dot, 2, FORWARD, S_OVER_WS); - } - break; - case 'z': // z- - c1 = get_one_char(); // get the replacement char - cnt = 0; - if (c1 == '.') - cnt = (rows - 2) / 2; // put dot at center - if (c1 == '-') - cnt = rows - 2; // put dot at bottom - screenbegin = begin_line(dot); // start dot at top - dot_scroll(cnt, -1); - break; - case '|': // |- move to column "cmdcnt" - dot = move_to_col(dot, cmdcnt - 1); // try to move to column - break; - case '~': // ~- flip the case of letters a-z -> A-Z - if (cmdcnt-- > 1) { - do_cmd(c); - } // repeat cnt - if (islower(*dot)) { - *dot = toupper(*dot); - file_modified = TRUE; // has the file been modified - } else if (isupper(*dot)) { - *dot = tolower(*dot); - file_modified = TRUE; // has the file been modified - } - dot_right(); - end_cmd_q(); // stop adding to q - break; - //----- The Cursor and Function Keys ----------------------------- - case VI_K_HOME: // Cursor Key Home - dot_begin(); - break; - // The Fn keys could point to do_macro which could translate them - case VI_K_FUN1: // Function Key F1 - case VI_K_FUN2: // Function Key F2 - case VI_K_FUN3: // Function Key F3 - case VI_K_FUN4: // Function Key F4 - case VI_K_FUN5: // Function Key F5 - case VI_K_FUN6: // Function Key F6 - case VI_K_FUN7: // Function Key F7 - case VI_K_FUN8: // Function Key F8 - case VI_K_FUN9: // Function Key F9 - case VI_K_FUN10: // Function Key F10 - case VI_K_FUN11: // Function Key F11 - case VI_K_FUN12: // Function Key F12 - break; - } - - dc1: - // if text[] just became empty, add back an empty line - if (end == text) { - (void) char_insert(text, '\n'); // start empty buf with dummy line - dot = text; - } - // it is OK for dot to exactly equal to end, otherwise check dot validity - if (dot != end) { - dot = bound_dot(dot); // make sure "dot" is valid - } -#ifdef BB_FEATURE_VI_YANKMARK - check_context(c); // update the current context -#endif /* BB_FEATURE_VI_YANKMARK */ - - if (!isdigit(c)) - cmdcnt = 0; // cmd was not a number, reset cmdcnt - cnt = dot - begin_line(dot); - // Try to stay off of the Newline - if (*dot == '\n' && cnt > 0 && cmd_mode == 0) - dot--; -} - -//----- The Colon commands ------------------------------------- -#ifdef BB_FEATURE_VI_COLON -static Byte *get_one_address(Byte * p, int *addr) // get colon addr, if present -{ - int st; - Byte *q; - -#ifdef BB_FEATURE_VI_YANKMARK - Byte c; -#endif /* BB_FEATURE_VI_YANKMARK */ -#ifdef BB_FEATURE_VI_SEARCH - Byte *pat, buf[BUFSIZ]; -#endif /* BB_FEATURE_VI_SEARCH */ - - *addr = -1; // assume no addr - if (*p == '.') { // the current line - p++; - q = begin_line(dot); - *addr = count_lines(text, q); -#ifdef BB_FEATURE_VI_YANKMARK - } else if (*p == '\'') { // is this a mark addr - p++; - c = tolower(*p); - p++; - if (c >= 'a' && c <= 'z') { - // we have a mark - c = c - 'a'; - q = mark[(int) c]; - if (q != NULL) { // is mark valid - *addr = count_lines(text, q); // count lines - } - } -#endif /* BB_FEATURE_VI_YANKMARK */ -#ifdef BB_FEATURE_VI_SEARCH - } else if (*p == '/') { // a search pattern - q = buf; - for (p++; *p; p++) { - if (*p == '/') - break; - *q++ = *p; - *q = '\0'; - } - pat = (Byte *) strdup((char *) buf); // save copy of pattern - if (*p == '/') - p++; - q = char_search(dot, pat, FORWARD, FULL); - if (q != NULL) { - *addr = count_lines(text, q); - } - free(pat); -#endif /* BB_FEATURE_VI_SEARCH */ - } else if (*p == '$') { // the last line in file - p++; - q = begin_line(end - 1); - *addr = count_lines(text, q); - } else if (isdigit(*p)) { // specific line number - sscanf((char *) p, "%d%n", addr, &st); - p += st; - } else { // I don't reconise this - // unrecognised address- assume -1 - *addr = -1; - } - return (p); -} - -static Byte *get_address(Byte *p, int *b, int *e) // get two colon addrs, if present -{ - //----- get the address' i.e., 1,3 'a,'b ----- - // get FIRST addr, if present - while (isblnk(*p)) - p++; // skip over leading spaces - if (*p == '%') { // alias for 1,$ - p++; - *b = 1; - *e = count_lines(text, end-1); - goto ga0; - } - p = get_one_address(p, b); - while (isblnk(*p)) - p++; - if (*p == ',') { // is there a address seperator - p++; - while (isblnk(*p)) - p++; - // get SECOND addr, if present - p = get_one_address(p, e); - } -ga0: - while (isblnk(*p)) - p++; // skip over trailing spaces - return (p); -} - -static void colon(Byte * buf) -{ - Byte c, *orig_buf, *buf1, *q, *r; - Byte *fn, cmd[BUFSIZ], args[BUFSIZ]; - int i, l, li, ch, st, b, e; - int useforce, forced; - struct stat st_buf; - - // :3154 // if (-e line 3154) goto it else stay put - // :4,33w! foo // write a portion of buffer to file "foo" - // :w // write all of buffer to current file - // :q // quit - // :q! // quit- dont care about modified file - // :'a,'z!sort -u // filter block through sort - // :'f // goto mark "f" - // :'fl // list literal the mark "f" line - // :.r bar // read file "bar" into buffer before dot - // :/123/,/abc/d // delete lines from "123" line to "abc" line - // :/xyz/ // goto the "xyz" line - // :s/find/replace/ // substitute pattern "find" with "replace" - // :!<cmd> // run <cmd> then return - // - if (strlen((char *) buf) <= 0) - goto vc1; - if (*buf == ':') - buf++; // move past the ':' - - forced = useforce = FALSE; - li = st = ch = i = 0; - b = e = -1; - q = text; // assume 1,$ for the range - r = end - 1; - li = count_lines(text, end - 1); - fn = cfn; // default to current file - memset(cmd, '\0', BUFSIZ); // clear cmd[] - memset(args, '\0', BUFSIZ); // clear args[] - - // look for optional address(es) :. :1 :1,9 :'q,'a :% - buf = get_address(buf, &b, &e); - - // remember orig command line - orig_buf = buf; - - // get the COMMAND into cmd[] - buf1 = cmd; - while (*buf != '\0') { - if (isspace(*buf)) - break; - *buf1++ = *buf++; - } - // get any ARGuments - while (isblnk(*buf)) - buf++; - strcpy((char *) args, (char *) buf); - buf1 = last_char_is((char *)cmd, '!'); - if (buf1) { - useforce = TRUE; - *buf1 = '\0'; // get rid of ! - } - if (b >= 0) { - // if there is only one addr, then the addr - // is the line number of the single line the - // user wants. So, reset the end - // pointer to point at end of the "b" line - q = find_line(b); // what line is #b - r = end_line(q); - li = 1; - } - if (e >= 0) { - // we were given two addrs. change the - // end pointer to the addr given by user. - r = find_line(e); // what line is #e - r = end_line(r); - li = e - b + 1; - } - // ------------ now look for the command ------------ - i = strlen((char *) cmd); - if (i == 0) { // :123CR goto line #123 - if (b >= 0) { - dot = find_line(b); // what line is #b - dot_skip_over_ws(); - } - } else if (strncmp((char *) cmd, "!", 1) == 0) { // run a cmd - // :!ls run the <cmd> - (void) alarm(0); // wait for input- no alarms - place_cursor(rows - 1, 0, FALSE); // go to Status line - clear_to_eol(); // clear the line - cookmode(); - system(orig_buf+1); // run the cmd - rawmode(); - Hit_Return(); // let user see results - (void) alarm(3); // done waiting for input - } else if (strncmp((char *) cmd, "=", i) == 0) { // where is the address - if (b < 0) { // no addr given- use defaults - b = e = count_lines(text, dot); - } - psb("%d", b); - } else if (strncasecmp((char *) cmd, "delete", i) == 0) { // delete lines - if (b < 0) { // no addr given- use defaults - q = begin_line(dot); // assume .,. for the range - r = end_line(dot); - } - dot = yank_delete(q, r, 1, YANKDEL); // save, then delete lines - dot_skip_over_ws(); - } else if (strncasecmp((char *) cmd, "edit", i) == 0) { // Edit a file - int sr; - sr= 0; - // don't edit, if the current file has been modified - if (file_modified == TRUE && useforce != TRUE) { - psbs("No write since last change (:edit! overrides)"); - goto vc1; - } - if (strlen(args) > 0) { - // the user supplied a file name - fn= args; - } else if (cfn != 0 && strlen(cfn) > 0) { - // no user supplied name- use the current filename - fn= cfn; - goto vc5; - } else { - // no user file name, no current name- punt - psbs("No current filename"); - goto vc1; - } - - // see if file exists- if not, its just a new file request - if ((sr=stat((char*)fn, &st_buf)) < 0) { - // This is just a request for a new file creation. - // The file_insert below will fail but we get - // an empty buffer with a file name. Then the "write" - // command can do the create. - } else { - if ((st_buf.st_mode & (S_IFREG)) == 0) { - // This is not a regular file - psbs("\"%s\" is not a regular file", fn); - goto vc1; - } - if ((st_buf.st_mode & (S_IRUSR | S_IRGRP | S_IROTH)) == 0) { - // dont have any read permissions - psbs("\"%s\" is not readable", fn); - goto vc1; - } - } - - // There is a read-able regular file - // make this the current file - q = (Byte *) strdup((char *) fn); // save the cfn - if (cfn != 0) - free(cfn); // free the old name - cfn = q; // remember new cfn - - vc5: - // delete all the contents of text[] - new_text(2 * file_size(fn)); - screenbegin = dot = end = text; - - // insert new file - ch = file_insert(fn, text, file_size(fn)); - - if (ch < 1) { - // start empty buf with dummy line - (void) char_insert(text, '\n'); - ch= 1; - } - file_modified = FALSE; -#ifdef BB_FEATURE_VI_YANKMARK - if (Ureg >= 0 && Ureg < 28 && reg[Ureg] != 0) { - free(reg[Ureg]); // free orig line reg- for 'U' - reg[Ureg]= 0; - } - if (YDreg >= 0 && YDreg < 28 && reg[YDreg] != 0) { - free(reg[YDreg]); // free default yank/delete register - reg[YDreg]= 0; - } - for (li = 0; li < 28; li++) { - mark[li] = 0; - } // init the marks -#endif /* BB_FEATURE_VI_YANKMARK */ - // how many lines in text[]? - li = count_lines(text, end - 1); - psb("\"%s\"%s" -#ifdef BB_FEATURE_VI_READONLY - "%s" -#endif /* BB_FEATURE_VI_READONLY */ - " %dL, %dC", cfn, - (sr < 0 ? " [New file]" : ""), -#ifdef BB_FEATURE_VI_READONLY - ((vi_readonly == TRUE || readonly == TRUE) ? " [Read only]" : ""), -#endif /* BB_FEATURE_VI_READONLY */ - li, ch); - } else if (strncasecmp((char *) cmd, "file", i) == 0) { // what File is this - if (b != -1 || e != -1) { - ni((Byte *) "No address allowed on this command"); - goto vc1; - } - if (strlen((char *) args) > 0) { - // user wants a new filename - if (cfn != NULL) - free(cfn); - cfn = (Byte *) strdup((char *) args); - } else { - // user wants file status info - edit_status(); - } - } else if (strncasecmp((char *) cmd, "features", i) == 0) { // what features are available - // print out values of all features - place_cursor(rows - 1, 0, FALSE); // go to Status line, bottom of screen - clear_to_eol(); // clear the line - cookmode(); - show_help(); - rawmode(); - Hit_Return(); - } else if (strncasecmp((char *) cmd, "list", i) == 0) { // literal print line - if (b < 0) { // no addr given- use defaults - q = begin_line(dot); // assume .,. for the range - r = end_line(dot); - } - place_cursor(rows - 1, 0, FALSE); // go to Status line, bottom of screen - clear_to_eol(); // clear the line - write(1, "\r\n", 2); - for (; q <= r; q++) { - c = *q; - if (c > '~') - standout_start(); - if (c == '\n') { - write(1, "$\r", 2); - } else if (*q < ' ') { - write(1, "^", 1); - c += '@'; - } - write(1, &c, 1); - if (c > '~') - standout_end(); - } -#ifdef BB_FEATURE_VI_SET - vc2: -#endif /* BB_FEATURE_VI_SET */ - Hit_Return(); - } else if ((strncasecmp((char *) cmd, "quit", i) == 0) || // Quit - (strncasecmp((char *) cmd, "next", i) == 0)) { // edit next file - if (useforce == TRUE) { - // force end of argv list - if (*cmd == 'q') { - optind = save_argc; - } - editing = 0; - goto vc1; - } - // don't exit if the file been modified - if (file_modified == TRUE) { - psbs("No write since last change (:%s! overrides)", - (*cmd == 'q' ? "quit" : "next")); - goto vc1; - } - // are there other file to edit - if (*cmd == 'q' && optind < save_argc - 1) { - psbs("%d more file to edit", (save_argc - optind - 1)); - goto vc1; - } - if (*cmd == 'n' && optind >= save_argc - 1) { - psbs("No more files to edit"); - goto vc1; - } - editing = 0; - } else if (strncasecmp((char *) cmd, "read", i) == 0) { // read file into text[] - fn = args; - if (strlen((char *) fn) <= 0) { - psbs("No filename given"); - goto vc1; - } - if (b < 0) { // no addr given- use defaults - q = begin_line(dot); // assume "dot" - } - // read after current line- unless user said ":0r foo" - if (b != 0) - q = next_line(q); -#ifdef BB_FEATURE_VI_READONLY - l= readonly; // remember current files' status -#endif - ch = file_insert(fn, q, file_size(fn)); -#ifdef BB_FEATURE_VI_READONLY - readonly= l; -#endif - if (ch < 0) - goto vc1; // nothing was inserted - // how many lines in text[]? - li = count_lines(q, q + ch - 1); - psb("\"%s\"" -#ifdef BB_FEATURE_VI_READONLY - "%s" -#endif /* BB_FEATURE_VI_READONLY */ - " %dL, %dC", fn, -#ifdef BB_FEATURE_VI_READONLY - ((vi_readonly == TRUE || readonly == TRUE) ? " [Read only]" : ""), -#endif /* BB_FEATURE_VI_READONLY */ - li, ch); - if (ch > 0) { - // if the insert is before "dot" then we need to update - if (q <= dot) - dot += ch; - file_modified = TRUE; - } - } else if (strncasecmp((char *) cmd, "rewind", i) == 0) { // rewind cmd line args - if (file_modified == TRUE && useforce != TRUE) { - psbs("No write since last change (:rewind! overrides)"); - } else { - // reset the filenames to edit - optind = fn_start - 1; - editing = 0; - } -#ifdef BB_FEATURE_VI_SET - } else if (strncasecmp((char *) cmd, "set", i) == 0) { // set or clear features - i = 0; // offset into args - if (strlen((char *) args) == 0) { - // print out values of all options - place_cursor(rows - 1, 0, FALSE); // go to Status line, bottom of screen - clear_to_eol(); // clear the line - printf("----------------------------------------\r\n"); -#ifdef BB_FEATURE_VI_SETOPTS - if (!autoindent) - printf("no"); - printf("autoindent "); - if (!err_method) - printf("no"); - printf("flash "); - if (!ignorecase) - printf("no"); - printf("ignorecase "); - if (!showmatch) - printf("no"); - printf("showmatch "); - printf("tabstop=%d ", tabstop); -#endif /* BB_FEATURE_VI_SETOPTS */ - printf("\r\n"); - goto vc2; - } - if (strncasecmp((char *) args, "no", 2) == 0) - i = 2; // ":set noautoindent" -#ifdef BB_FEATURE_VI_SETOPTS - if (strncasecmp((char *) args + i, "autoindent", 10) == 0 || - strncasecmp((char *) args + i, "ai", 2) == 0) { - autoindent = (i == 2) ? 0 : 1; - } - if (strncasecmp((char *) args + i, "flash", 5) == 0 || - strncasecmp((char *) args + i, "fl", 2) == 0) { - err_method = (i == 2) ? 0 : 1; - } - if (strncasecmp((char *) args + i, "ignorecase", 10) == 0 || - strncasecmp((char *) args + i, "ic", 2) == 0) { - ignorecase = (i == 2) ? 0 : 1; - } - if (strncasecmp((char *) args + i, "showmatch", 9) == 0 || - strncasecmp((char *) args + i, "sm", 2) == 0) { - showmatch = (i == 2) ? 0 : 1; - } - if (strncasecmp((char *) args + i, "tabstop", 7) == 0) { - sscanf(strchr((char *) args + i, '='), "=%d", &ch); - if (ch > 0 && ch < columns - 1) - tabstop = ch; - } -#endif /* BB_FEATURE_VI_SETOPTS */ -#endif /* BB_FEATURE_VI_SET */ -#ifdef BB_FEATURE_VI_SEARCH - } else if (strncasecmp((char *) cmd, "s", 1) == 0) { // substitute a pattern with a replacement pattern - Byte *ls, *F, *R; - int gflag; - - // F points to the "find" pattern - // R points to the "replace" pattern - // replace the cmd line delimiters "/" with NULLs - gflag = 0; // global replace flag - c = orig_buf[1]; // what is the delimiter - F = orig_buf + 2; // start of "find" - R = (Byte *) strchr((char *) F, c); // middle delimiter - if (!R) goto colon_s_fail; - *R++ = '\0'; // terminate "find" - buf1 = (Byte *) strchr((char *) R, c); - if (!buf1) goto colon_s_fail; - *buf1++ = '\0'; // terminate "replace" - if (*buf1 == 'g') { // :s/foo/bar/g - buf1++; - gflag++; // turn on gflag - } - q = begin_line(q); - if (b < 0) { // maybe :s/foo/bar/ - q = begin_line(dot); // start with cur line - b = count_lines(text, q); // cur line number - } - if (e < 0) - e = b; // maybe :.s/foo/bar/ - for (i = b; i <= e; i++) { // so, :20,23 s \0 find \0 replace \0 - ls = q; // orig line start - vc4: - buf1 = char_search(q, F, FORWARD, LIMITED); // search cur line only for "find" - if (buf1 != NULL) { - // we found the "find" pattern- delete it - (void) text_hole_delete(buf1, buf1 + strlen((char *) F) - 1); - // inset the "replace" patern - (void) string_insert(buf1, R); // insert the string - // check for "global" :s/foo/bar/g - if (gflag == 1) { - if ((buf1 + strlen((char *) R)) < end_line(ls)) { - q = buf1 + strlen((char *) R); - goto vc4; // don't let q move past cur line - } - } - } - q = next_line(ls); - } -#endif /* BB_FEATURE_VI_SEARCH */ - } else if (strncasecmp((char *) cmd, "version", i) == 0) { // show software version - psb("%s", vi_Version); - } else if ((strncasecmp((char *) cmd, "write", i) == 0) || // write text to file - (strncasecmp((char *) cmd, "wq", i) == 0)) { // write text to file - // is there a file name to write to? - if (strlen((char *) args) > 0) { - fn = args; - } -#ifdef BB_FEATURE_VI_READONLY - if ((vi_readonly == TRUE || readonly == TRUE) && useforce == FALSE) { - psbs("\"%s\" File is read only", fn); - goto vc3; - } -#endif /* BB_FEATURE_VI_READONLY */ - // how many lines in text[]? - li = count_lines(q, r); - ch = r - q + 1; - // see if file exists- if not, its just a new file request - if (useforce == TRUE) { - // if "fn" is not write-able, chmod u+w - // sprintf(syscmd, "chmod u+w %s", fn); - // system(syscmd); - forced = TRUE; - } - l = file_write(fn, q, r); - if (useforce == TRUE && forced == TRUE) { - // chmod u-w - // sprintf(syscmd, "chmod u-w %s", fn); - // system(syscmd); - forced = FALSE; - } - psb("\"%s\" %dL, %dC", fn, li, l); - if (q == text && r == end - 1 && l == ch) - file_modified = FALSE; - if (cmd[1] == 'q' && l == ch) { - editing = 0; - } -#ifdef BB_FEATURE_VI_READONLY - vc3:; -#endif /* BB_FEATURE_VI_READONLY */ -#ifdef BB_FEATURE_VI_YANKMARK - } else if (strncasecmp((char *) cmd, "yank", i) == 0) { // yank lines - if (b < 0) { // no addr given- use defaults - q = begin_line(dot); // assume .,. for the range - r = end_line(dot); - } - text_yank(q, r, YDreg); - li = count_lines(q, r); - psb("Yank %d lines (%d chars) into [%c]", - li, strlen((char *) reg[YDreg]), what_reg()); -#endif /* BB_FEATURE_VI_YANKMARK */ - } else { - // cmd unknown - ni((Byte *) cmd); - } - vc1: - dot = bound_dot(dot); // make sure "dot" is valid - return; -#ifdef BB_FEATURE_VI_SEARCH -colon_s_fail: - psb(":s expression missing delimiters"); - return; -#endif - -} - -static void Hit_Return(void) -{ - char c; - - standout_start(); // start reverse video - write(1, "[Hit return to continue]", 24); - standout_end(); // end reverse video - while ((c = get_one_char()) != '\n' && c != '\r') /*do nothing */ - ; - redraw(TRUE); // force redraw all -} -#endif /* BB_FEATURE_VI_COLON */ - -//----- Synchronize the cursor to Dot -------------------------- -static void sync_cursor(Byte * d, int *row, int *col) -{ - Byte *beg_cur, *end_cur; // begin and end of "d" line - Byte *beg_scr, *end_scr; // begin and end of screen - Byte *tp; - int cnt, ro, co; - - beg_cur = begin_line(d); // first char of cur line - end_cur = end_line(d); // last char of cur line - - beg_scr = end_scr = screenbegin; // first char of screen - end_scr = end_screen(); // last char of screen - - if (beg_cur < screenbegin) { - // "d" is before top line on screen - // how many lines do we have to move - cnt = count_lines(beg_cur, screenbegin); - sc1: - screenbegin = beg_cur; - if (cnt > (rows - 1) / 2) { - // we moved too many lines. put "dot" in middle of screen - for (cnt = 0; cnt < (rows - 1) / 2; cnt++) { - screenbegin = prev_line(screenbegin); - } - } - } else if (beg_cur > end_scr) { - // "d" is after bottom line on screen - // how many lines do we have to move - cnt = count_lines(end_scr, beg_cur); - if (cnt > (rows - 1) / 2) - goto sc1; // too many lines - for (ro = 0; ro < cnt - 1; ro++) { - // move screen begin the same amount - screenbegin = next_line(screenbegin); - // now, move the end of screen - end_scr = next_line(end_scr); - end_scr = end_line(end_scr); - } - } - // "d" is on screen- find out which row - tp = screenbegin; - for (ro = 0; ro < rows - 1; ro++) { // drive "ro" to correct row - if (tp == beg_cur) - break; - tp = next_line(tp); - } - - // find out what col "d" is on - co = 0; - do { // drive "co" to correct column - if (*tp == '\n' || *tp == '\0') - break; - if (*tp == '\t') { - // 7 - (co % 8 ) - co += ((tabstop - 1) - (co % tabstop)); - } else if (*tp < ' ') { - co++; // display as ^X, use 2 columns - } - } while (tp++ < d && ++co); - - // "co" is the column where "dot" is. - // The screen has "columns" columns. - // The currently displayed columns are 0+offset -- columns+ofset - // |-------------------------------------------------------------| - // ^ ^ ^ - // offset | |------- columns ----------------| - // - // If "co" is already in this range then we do not have to adjust offset - // but, we do have to subtract the "offset" bias from "co". - // If "co" is outside this range then we have to change "offset". - // If the first char of a line is a tab the cursor will try to stay - // in column 7, but we have to set offset to 0. - - if (co < 0 + offset) { - offset = co; - } - if (co >= columns + offset) { - offset = co - columns + 1; - } - // if the first char of the line is a tab, and "dot" is sitting on it - // force offset to 0. - if (d == beg_cur && *d == '\t') { - offset = 0; - } - co -= offset; - - *row = ro; - *col = co; -} - -//----- Text Movement Routines --------------------------------- -static Byte *begin_line(Byte * p) // return pointer to first char cur line -{ - while (p > text && p[-1] != '\n') - p--; // go to cur line B-o-l - return (p); -} - -static Byte *end_line(Byte * p) // return pointer to NL of cur line line -{ - while (p < end - 1 && *p != '\n') - p++; // go to cur line E-o-l - return (p); -} - -static Byte *dollar_line(Byte * p) // return pointer to just before NL line -{ - while (p < end - 1 && *p != '\n') - p++; // go to cur line E-o-l - // Try to stay off of the Newline - if (*p == '\n' && (p - begin_line(p)) > 0) - p--; - return (p); -} - -static Byte *prev_line(Byte * p) // return pointer first char prev line -{ - p = begin_line(p); // goto begining of cur line - if (p[-1] == '\n' && p > text) - p--; // step to prev line - p = begin_line(p); // goto begining of prev line - return (p); -} - -static Byte *next_line(Byte * p) // return pointer first char next line -{ - p = end_line(p); - if (*p == '\n' && p < end - 1) - p++; // step to next line - return (p); -} - -//----- Text Information Routines ------------------------------ -static Byte *end_screen(void) -{ - Byte *q; - int cnt; - - // find new bottom line - q = screenbegin; - for (cnt = 0; cnt < rows - 2; cnt++) - q = next_line(q); - q = end_line(q); - return (q); -} - -static int count_lines(Byte * start, Byte * stop) // count line from start to stop -{ - Byte *q; - int cnt; - - if (stop < start) { // start and stop are backwards- reverse them - q = start; - start = stop; - stop = q; - } - cnt = 0; - stop = end_line(stop); // get to end of this line - for (q = start; q <= stop && q <= end - 1; q++) { - if (*q == '\n') - cnt++; - } - return (cnt); -} - -static Byte *find_line(int li) // find begining of line #li -{ - Byte *q; - - for (q = text; li > 1; li--) { - q = next_line(q); - } - return (q); -} - -//----- Dot Movement Routines ---------------------------------- -static void dot_left(void) -{ - if (dot > text && dot[-1] != '\n') - dot--; -} - -static void dot_right(void) -{ - if (dot < end - 1 && *dot != '\n') - dot++; -} - -static void dot_begin(void) -{ - dot = begin_line(dot); // return pointer to first char cur line -} - -static void dot_end(void) -{ - dot = end_line(dot); // return pointer to last char cur line -} - -static Byte *move_to_col(Byte * p, int l) -{ - int co; - - p = begin_line(p); - co = 0; - do { - if (*p == '\n' || *p == '\0') - break; - if (*p == '\t') { - // 7 - (co % 8 ) - co += ((tabstop - 1) - (co % tabstop)); - } else if (*p < ' ') { - co++; // display as ^X, use 2 columns - } - } while (++co <= l && p++ < end); - return (p); -} - -static void dot_next(void) -{ - dot = next_line(dot); -} - -static void dot_prev(void) -{ - dot = prev_line(dot); -} - -static void dot_scroll(int cnt, int dir) -{ - Byte *q; - - for (; cnt > 0; cnt--) { - if (dir < 0) { - // scroll Backwards - // ctrl-Y scroll up one line - screenbegin = prev_line(screenbegin); - } else { - // scroll Forwards - // ctrl-E scroll down one line - screenbegin = next_line(screenbegin); - } - } - // make sure "dot" stays on the screen so we dont scroll off - if (dot < screenbegin) - dot = screenbegin; - q = end_screen(); // find new bottom line - if (dot > q) - dot = begin_line(q); // is dot is below bottom line? - dot_skip_over_ws(); -} - -static void dot_skip_over_ws(void) -{ - // skip WS - while (isspace(*dot) && *dot != '\n' && dot < end - 1) - dot++; -} - -static void dot_delete(void) // delete the char at 'dot' -{ - (void) text_hole_delete(dot, dot); -} - -static Byte *bound_dot(Byte * p) // make sure text[0] <= P < "end" -{ - if (p >= end && end > text) { - p = end - 1; - indicate_error('1'); - } - if (p < text) { - p = text; - indicate_error('2'); - } - return (p); -} - -//----- Helper Utility Routines -------------------------------- - -//---------------------------------------------------------------- -//----- Char Routines -------------------------------------------- -/* Chars that are part of a word- - * 0123456789_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz - * Chars that are Not part of a word (stoppers) - * !"#$%&'()*+,-./:;<=>?@[\]^`{|}~ - * Chars that are WhiteSpace - * TAB NEWLINE VT FF RETURN SPACE - * DO NOT COUNT NEWLINE AS WHITESPACE - */ - -static Byte *new_screen(int ro, int co) -{ - int li; - - if (screen != 0) - free(screen); - screensize = ro * co + 8; - screen = (Byte *) malloc(screensize); - // initialize the new screen. assume this will be a empty file. - screen_erase(); - // non-existant text[] lines start with a tilde (~). - for (li = 1; li < ro - 1; li++) { - screen[(li * co) + 0] = '~'; - } - return (screen); -} - -static Byte *new_text(int size) -{ - if (size < 10240) - size = 10240; // have a minimum size for new files - if (text != 0) { - //text -= 4; - free(text); - } - text = (Byte *) malloc(size + 8); - memset(text, '\0', size); // clear new text[] - //text += 4; // leave some room for "oops" - textend = text + size - 1; - //textend -= 4; // leave some root for "oops" - return (text); -} - -#ifdef BB_FEATURE_VI_SEARCH -static int mycmp(Byte * s1, Byte * s2, int len) -{ - int i; - - i = strncmp((char *) s1, (char *) s2, len); -#ifdef BB_FEATURE_VI_SETOPTS - if (ignorecase) { - i = strncasecmp((char *) s1, (char *) s2, len); - } -#endif /* BB_FEATURE_VI_SETOPTS */ - return (i); -} - -static Byte *char_search(Byte * p, Byte * pat, int dir, int range) // search for pattern starting at p -{ -#ifndef REGEX_SEARCH - Byte *start, *stop; - int len; - - len = strlen((char *) pat); - if (dir == FORWARD) { - stop = end - 1; // assume range is p - end-1 - if (range == LIMITED) - stop = next_line(p); // range is to next line - for (start = p; start < stop; start++) { - if (mycmp(start, pat, len) == 0) { - return (start); - } - } - } else if (dir == BACK) { - stop = text; // assume range is text - p - if (range == LIMITED) - stop = prev_line(p); // range is to prev line - for (start = p - len; start >= stop; start--) { - if (mycmp(start, pat, len) == 0) { - return (start); - } - } - } - // pattern not found - return (NULL); -#else /*REGEX_SEARCH */ - char *q; - struct re_pattern_buffer preg; - int i; - int size, range; - - re_syntax_options = RE_SYNTAX_POSIX_EXTENDED; - preg.translate = 0; - preg.fastmap = 0; - preg.buffer = 0; - preg.allocated = 0; - - // assume a LIMITED forward search - q = next_line(p); - q = end_line(q); - q = end - 1; - if (dir == BACK) { - q = prev_line(p); - q = text; - } - // count the number of chars to search over, forward or backward - size = q - p; - if (size < 0) - size = p - q; - // RANGE could be negative if we are searching backwards - range = q - p; - - q = (char *) re_compile_pattern(pat, strlen((char *) pat), &preg); - if (q != 0) { - // The pattern was not compiled - psbs("bad search pattern: \"%s\": %s", pat, q); - i = 0; // return p if pattern not compiled - goto cs1; - } - - q = p; - if (range < 0) { - q = p - size; - if (q < text) - q = text; - } - // search for the compiled pattern, preg, in p[] - // range < 0- search backward - // range > 0- search forward - // 0 < start < size - // re_search() < 0 not found or error - // re_search() > 0 index of found pattern - // struct pattern char int int int struct reg - // re_search (*pattern_buffer, *string, size, start, range, *regs) - i = re_search(&preg, q, size, 0, range, 0); - if (i == -1) { - p = 0; - i = 0; // return NULL if pattern not found - } - cs1: - if (dir == FORWARD) { - p = p + i; - } else { - p = p - i; - } - return (p); -#endif /*REGEX_SEARCH */ -} -#endif /* BB_FEATURE_VI_SEARCH */ - -static Byte *char_insert(Byte * p, Byte c) // insert the char c at 'p' -{ - if (c == 22) { // Is this an ctrl-V? - p = stupid_insert(p, '^'); // use ^ to indicate literal next - p--; // backup onto ^ - refresh(FALSE); // show the ^ - c = get_one_char(); - *p = c; - p++; - file_modified = TRUE; // has the file been modified - } else if (c == 27) { // Is this an ESC? - cmd_mode = 0; - cmdcnt = 0; - end_cmd_q(); // stop adding to q - strcpy((char *) status_buffer, " "); // clear the status buffer - if ((p[-1] != '\n') && (dot>text)) { - p--; - } - } else if (c == erase_char) { // Is this a BS - // 123456789 - if ((p[-1] != '\n') && (dot>text)) { - p--; - p = text_hole_delete(p, p); // shrink buffer 1 char -#ifdef BB_FEATURE_VI_DOT_CMD - // also rmove char from last_modifying_cmd - if (strlen((char *) last_modifying_cmd) > 0) { - Byte *q; - - q = last_modifying_cmd; - q[strlen((char *) q) - 1] = '\0'; // erase BS - q[strlen((char *) q) - 1] = '\0'; // erase prev char - } -#endif /* BB_FEATURE_VI_DOT_CMD */ - } - } else { - // insert a char into text[] - Byte *sp; // "save p" - - if (c == 13) - c = '\n'; // translate \r to \n - sp = p; // remember addr of insert - p = stupid_insert(p, c); // insert the char -#ifdef BB_FEATURE_VI_SETOPTS - if (showmatch && strchr(")]}", *sp) != NULL) { - showmatching(sp); - } - if (autoindent && c == '\n') { // auto indent the new line - Byte *q; - - q = prev_line(p); // use prev line as templet - for (; isblnk(*q); q++) { - p = stupid_insert(p, *q); // insert the char - } - } -#endif /* BB_FEATURE_VI_SETOPTS */ - } - return (p); -} - -static Byte *stupid_insert(Byte * p, Byte c) // stupidly insert the char c at 'p' -{ - p = text_hole_make(p, 1); - if (p != 0) { - *p = c; - file_modified = TRUE; // has the file been modified - p++; - } - return (p); -} - -static Byte find_range(Byte ** start, Byte ** stop, Byte c) -{ - Byte *save_dot, *p, *q; - int cnt; - - save_dot = dot; - p = q = dot; - - if (strchr("cdy><", c)) { - // these cmds operate on whole lines - p = q = begin_line(p); - for (cnt = 1; cnt < cmdcnt; cnt++) { - q = next_line(q); - } - q = end_line(q); - } else if (strchr("^%$0bBeEft", c)) { - // These cmds operate on char positions - do_cmd(c); // execute movement cmd - q = dot; - } else if (strchr("wW", c)) { - do_cmd(c); // execute movement cmd - if (dot > text) - dot--; // move back off of next word - if (dot > text && *dot == '\n') - dot--; // stay off NL - q = dot; - } else if (strchr("H-k{", c)) { - // these operate on multi-lines backwards - q = end_line(dot); // find NL - do_cmd(c); // execute movement cmd - dot_begin(); - p = dot; - } else if (strchr("L+j}\r\n", c)) { - // these operate on multi-lines forwards - p = begin_line(dot); - do_cmd(c); // execute movement cmd - dot_end(); // find NL - q = dot; - } else { - c = 27; // error- return an ESC char - //break; - } - *start = p; - *stop = q; - if (q < p) { - *start = q; - *stop = p; - } - dot = save_dot; - return (c); -} - -static int st_test(Byte * p, int type, int dir, Byte * tested) -{ - Byte c, c0, ci; - int test, inc; - - inc = dir; - c = c0 = p[0]; - ci = p[inc]; - test = 0; - - if (type == S_BEFORE_WS) { - c = ci; - test = ((!isspace(c)) || c == '\n'); - } - if (type == S_TO_WS) { - c = c0; - test = ((!isspace(c)) || c == '\n'); - } - if (type == S_OVER_WS) { - c = c0; - test = ((isspace(c))); - } - if (type == S_END_PUNCT) { - c = ci; - test = ((ispunct(c))); - } - if (type == S_END_ALNUM) { - c = ci; - test = ((isalnum(c)) || c == '_'); - } - *tested = c; - return (test); -} - -static Byte *skip_thing(Byte * p, int linecnt, int dir, int type) -{ - Byte c; - - while (st_test(p, type, dir, &c)) { - // make sure we limit search to correct number of lines - if (c == '\n' && --linecnt < 1) - break; - if (dir >= 0 && p >= end - 1) - break; - if (dir < 0 && p <= text) - break; - p += dir; // move to next char - } - return (p); -} - -// find matching char of pair () [] {} -static Byte *find_pair(Byte * p, Byte c) -{ - Byte match, *q; - int dir, level; - - match = ')'; - level = 1; - dir = 1; // assume forward - switch (c) { - case '(': - match = ')'; - break; - case '[': - match = ']'; - break; - case '{': - match = '}'; - break; - case ')': - match = '('; - dir = -1; - break; - case ']': - match = '['; - dir = -1; - break; - case '}': - match = '{'; - dir = -1; - break; - } - for (q = p + dir; text <= q && q < end; q += dir) { - // look for match, count levels of pairs (( )) - if (*q == c) - level++; // increase pair levels - if (*q == match) - level--; // reduce pair level - if (level == 0) - break; // found matching pair - } - if (level != 0) - q = NULL; // indicate no match - return (q); -} - -#ifdef BB_FEATURE_VI_SETOPTS -// show the matching char of a pair, () [] {} -static void showmatching(Byte * p) -{ - Byte *q, *save_dot; - - // we found half of a pair - q = find_pair(p, *p); // get loc of matching char - if (q == NULL) { - indicate_error('3'); // no matching char - } else { - // "q" now points to matching pair - save_dot = dot; // remember where we are - dot = q; // go to new loc - refresh(FALSE); // let the user see it - (void) mysleep(40); // give user some time - dot = save_dot; // go back to old loc - refresh(FALSE); - } -} -#endif /* BB_FEATURE_VI_SETOPTS */ - -// open a hole in text[] -static Byte *text_hole_make(Byte * p, int size) // at "p", make a 'size' byte hole -{ - Byte *src, *dest; - int cnt; - - if (size <= 0) - goto thm0; - src = p; - dest = p + size; - cnt = end - src; // the rest of buffer - if (memmove(dest, src, cnt) != dest) { - psbs("can't create room for new characters"); - } - memset(p, ' ', size); // clear new hole - end = end + size; // adjust the new END - file_modified = TRUE; // has the file been modified - thm0: - return (p); -} - -// close a hole in text[] -static Byte *text_hole_delete(Byte * p, Byte * q) // delete "p" thru "q", inclusive -{ - Byte *src, *dest; - int cnt, hole_size; - - // move forwards, from beginning - // assume p <= q - src = q + 1; - dest = p; - if (q < p) { // they are backward- swap them - src = p + 1; - dest = q; - } - hole_size = q - p + 1; - cnt = end - src; - if (src < text || src > end) - goto thd0; - if (dest < text || dest >= end) - goto thd0; - if (src >= end) - goto thd_atend; // just delete the end of the buffer - if (memmove(dest, src, cnt) != dest) { - psbs("can't delete the character"); - } - thd_atend: - end = end - hole_size; // adjust the new END - if (dest >= end) - dest = end - 1; // make sure dest in below end-1 - if (end <= text) - dest = end = text; // keep pointers valid - file_modified = TRUE; // has the file been modified - thd0: - return (dest); -} - -// copy text into register, then delete text. -// if dist <= 0, do not include, or go past, a NewLine -// -static Byte *yank_delete(Byte * start, Byte * stop, int dist, int yf) -{ - Byte *p; - - // make sure start <= stop - if (start > stop) { - // they are backwards, reverse them - p = start; - start = stop; - stop = p; - } - if (dist <= 0) { - // we can not cross NL boundaries - p = start; - if (*p == '\n') - return (p); - // dont go past a NewLine - for (; p + 1 <= stop; p++) { - if (p[1] == '\n') { - stop = p; // "stop" just before NewLine - break; - } - } - } - p = start; -#ifdef BB_FEATURE_VI_YANKMARK - text_yank(start, stop, YDreg); -#endif /* BB_FEATURE_VI_YANKMARK */ - if (yf == YANKDEL) { - p = text_hole_delete(start, stop); - } // delete lines - return (p); -} - -static void show_help(void) -{ - puts("These features are available:" -#ifdef BB_FEATURE_VI_SEARCH - "\n\tPattern searches with / and ?" -#endif /* BB_FEATURE_VI_SEARCH */ -#ifdef BB_FEATURE_VI_DOT_CMD - "\n\tLast command repeat with \'.\'" -#endif /* BB_FEATURE_VI_DOT_CMD */ -#ifdef BB_FEATURE_VI_YANKMARK - "\n\tLine marking with 'x" - "\n\tNamed buffers with \"x" -#endif /* BB_FEATURE_VI_YANKMARK */ -#ifdef BB_FEATURE_VI_READONLY - "\n\tReadonly if vi is called as \"view\"" - "\n\tReadonly with -R command line arg" -#endif /* BB_FEATURE_VI_READONLY */ -#ifdef BB_FEATURE_VI_SET - "\n\tSome colon mode commands with \':\'" -#endif /* BB_FEATURE_VI_SET */ -#ifdef BB_FEATURE_VI_SETOPTS - "\n\tSettable options with \":set\"" -#endif /* BB_FEATURE_VI_SETOPTS */ -#ifdef BB_FEATURE_VI_USE_SIGNALS - "\n\tSignal catching- ^C" - "\n\tJob suspend and resume with ^Z" -#endif /* BB_FEATURE_VI_USE_SIGNALS */ -#ifdef BB_FEATURE_VI_WIN_RESIZE - "\n\tAdapt to window re-sizes" -#endif /* BB_FEATURE_VI_WIN_RESIZE */ - ); -} - -static void print_literal(Byte * buf, Byte * s) // copy s to buf, convert unprintable -{ - Byte c, b[2]; - - b[1] = '\0'; - strcpy((char *) buf, ""); // init buf - if (strlen((char *) s) <= 0) - s = (Byte *) "(NULL)"; - for (; *s > '\0'; s++) { - c = *s; - if (*s > '~') { - strcat((char *) buf, SOs); - c = *s - 128; - } - if (*s < ' ') { - strcat((char *) buf, "^"); - c += '@'; - } - b[0] = c; - strcat((char *) buf, (char *) b); - if (*s > '~') - strcat((char *) buf, SOn); - if (*s == '\n') { - strcat((char *) buf, "$"); - } - } -} - -#ifdef BB_FEATURE_VI_DOT_CMD -static void start_new_cmd_q(Byte c) -{ - // release old cmd - if (last_modifying_cmd != 0) - free(last_modifying_cmd); - // get buffer for new cmd - last_modifying_cmd = (Byte *) malloc(BUFSIZ); - memset(last_modifying_cmd, '\0', BUFSIZ); // clear new cmd queue - // if there is a current cmd count put it in the buffer first - if (cmdcnt > 0) - sprintf((char *) last_modifying_cmd, "%d", cmdcnt); - // save char c onto queue - last_modifying_cmd[strlen((char *) last_modifying_cmd)] = c; - adding2q = 1; - return; -} - -static void end_cmd_q() -{ -#ifdef BB_FEATURE_VI_YANKMARK - YDreg = 26; // go back to default Yank/Delete reg -#endif /* BB_FEATURE_VI_YANKMARK */ - adding2q = 0; - return; -} -#endif /* BB_FEATURE_VI_DOT_CMD */ - -#if defined(BB_FEATURE_VI_YANKMARK) || defined(BB_FEATURE_VI_COLON) || defined(BB_FEATURE_VI_CRASHME) -static Byte *string_insert(Byte * p, Byte * s) // insert the string at 'p' -{ - int cnt, i; - - i = strlen((char *) s); - p = text_hole_make(p, i); - strncpy((char *) p, (char *) s, i); - for (cnt = 0; *s != '\0'; s++) { - if (*s == '\n') - cnt++; - } -#ifdef BB_FEATURE_VI_YANKMARK - psb("Put %d lines (%d chars) from [%c]", cnt, i, what_reg()); -#endif /* BB_FEATURE_VI_YANKMARK */ - return (p); -} -#endif /* BB_FEATURE_VI_YANKMARK || BB_FEATURE_VI_COLON || BB_FEATURE_VI_CRASHME */ - -#ifdef BB_FEATURE_VI_YANKMARK -static Byte *text_yank(Byte * p, Byte * q, int dest) // copy text into a register -{ - Byte *t; - int cnt; - - if (q < p) { // they are backwards- reverse them - t = q; - q = p; - p = t; - } - cnt = q - p + 1; - t = reg[dest]; - if (t != 0) { // if already a yank register - free(t); // free it - } - t = (Byte *) malloc(cnt + 1); // get a new register - memset(t, '\0', cnt + 1); // clear new text[] - strncpy((char *) t, (char *) p, cnt); // copy text[] into bufer - reg[dest] = t; - return (p); -} - -static Byte what_reg(void) -{ - Byte c; - int i; - - i = 0; - c = 'D'; // default to D-reg - if (0 <= YDreg && YDreg <= 25) - c = 'a' + (Byte) YDreg; - if (YDreg == 26) - c = 'D'; - if (YDreg == 27) - c = 'U'; - return (c); -} - -static void check_context(Byte cmd) -{ - // A context is defined to be "modifying text" - // Any modifying command establishes a new context. - - if (dot < context_start || dot > context_end) { - if (strchr((char *) modifying_cmds, cmd) != NULL) { - // we are trying to modify text[]- make this the current context - mark[27] = mark[26]; // move cur to prev - mark[26] = dot; // move local to cur - context_start = prev_line(prev_line(dot)); - context_end = next_line(next_line(dot)); - //loiter= start_loiter= now; - } - } - return; -} - -static Byte *swap_context(Byte * p) // goto new context for '' command make this the current context -{ - Byte *tmp; - - // the current context is in mark[26] - // the previous context is in mark[27] - // only swap context if other context is valid - if (text <= mark[27] && mark[27] <= end - 1) { - tmp = mark[27]; - mark[27] = mark[26]; - mark[26] = tmp; - p = mark[26]; // where we are going- previous context - context_start = prev_line(prev_line(prev_line(p))); - context_end = next_line(next_line(next_line(p))); - } - return (p); -} -#endif /* BB_FEATURE_VI_YANKMARK */ - -static int isblnk(Byte c) // is the char a blank or tab -{ - return (c == ' ' || c == '\t'); -} - -//----- Set terminal attributes -------------------------------- -static void rawmode(void) -{ - tcgetattr(0, &term_orig); - term_vi = term_orig; - term_vi.c_lflag &= (~ICANON & ~ECHO); // leave ISIG ON- allow intr's - term_vi.c_iflag &= (~IXON & ~ICRNL); - term_vi.c_oflag &= (~ONLCR); -#ifndef linux - term_vi.c_cc[VMIN] = 1; - term_vi.c_cc[VTIME] = 0; -#endif - erase_char = term_vi.c_cc[VERASE]; - tcsetattr(0, TCSANOW, &term_vi); -} - -static void cookmode(void) -{ - tcsetattr(0, TCSANOW, &term_orig); -} - -#ifdef BB_FEATURE_VI_WIN_RESIZE -//----- See what the window size currently is -------------------- -static void window_size_get(int sig) -{ - int i; - - i = ioctl(0, TIOCGWINSZ, &winsize); - if (i != 0) { - // force 24x80 - winsize.ws_row = 24; - winsize.ws_col = 80; - } - if (winsize.ws_row <= 1) { - winsize.ws_row = 24; - } - if (winsize.ws_col <= 1) { - winsize.ws_col = 80; - } - rows = (int) winsize.ws_row; - columns = (int) winsize.ws_col; -} -#endif /* BB_FEATURE_VI_WIN_RESIZE */ - -//----- Come here when we get a window resize signal --------- -#ifdef BB_FEATURE_VI_USE_SIGNALS -static void winch_sig(int sig) -{ - signal(SIGWINCH, winch_sig); -#ifdef BB_FEATURE_VI_WIN_RESIZE - window_size_get(0); -#endif /* BB_FEATURE_VI_WIN_RESIZE */ - new_screen(rows, columns); // get memory for virtual screen - redraw(TRUE); // re-draw the screen -} - -//----- Come here when we get a continue signal ------------------- -static void cont_sig(int sig) -{ - rawmode(); // terminal to "raw" - *status_buffer = '\0'; // clear the status buffer - redraw(TRUE); // re-draw the screen - - signal(SIGTSTP, suspend_sig); - signal(SIGCONT, SIG_DFL); - kill(getpid(), SIGCONT); -} - -//----- Come here when we get a Suspend signal ------------------- -static void suspend_sig(int sig) -{ - place_cursor(rows - 1, 0, FALSE); // go to bottom of screen - clear_to_eol(); // Erase to end of line - cookmode(); // terminal to "cooked" - - signal(SIGCONT, cont_sig); - signal(SIGTSTP, SIG_DFL); - kill(getpid(), SIGTSTP); -} - -//----- Come here when we get a signal --------------------------- -static void catch_sig(int sig) -{ - signal(SIGHUP, catch_sig); - signal(SIGINT, catch_sig); - signal(SIGTERM, catch_sig); - longjmp(restart, sig); -} - -static void alarm_sig(int sig) -{ - signal(SIGALRM, catch_sig); - longjmp(restart, sig); -} - -//----- Come here when we get a core dump signal ----------------- -static void core_sig(int sig) -{ - signal(SIGQUIT, core_sig); - signal(SIGILL, core_sig); - signal(SIGTRAP, core_sig); - signal(SIGIOT, core_sig); - signal(SIGABRT, core_sig); - signal(SIGFPE, core_sig); - signal(SIGBUS, core_sig); - signal(SIGSEGV, core_sig); -#ifdef SIGSYS - signal(SIGSYS, core_sig); -#endif - - dot = bound_dot(dot); // make sure "dot" is valid - - longjmp(restart, sig); -} -#endif /* BB_FEATURE_VI_USE_SIGNALS */ - -static int mysleep(int hund) // sleep for 'h' 1/100 seconds -{ - // Don't hang- Wait 5/100 seconds- 1 Sec= 1000000 - FD_ZERO(&rfds); - FD_SET(0, &rfds); - tv.tv_sec = 0; - tv.tv_usec = hund * 10000; - select(1, &rfds, NULL, NULL, &tv); - return (FD_ISSET(0, &rfds)); -} - -//----- IO Routines -------------------------------------------- -static Byte readit(void) // read (maybe cursor) key from stdin -{ - Byte c; - int i, bufsiz, cnt, cmdindex; - struct esc_cmds { - Byte *seq; - Byte val; - }; - - static struct esc_cmds esccmds[] = { - {(Byte *) "OA", (Byte) VI_K_UP}, // cursor key Up - {(Byte *) "OB", (Byte) VI_K_DOWN}, // cursor key Down - {(Byte *) "OC", (Byte) VI_K_RIGHT}, // Cursor Key Right - {(Byte *) "OD", (Byte) VI_K_LEFT}, // cursor key Left - {(Byte *) "OH", (Byte) VI_K_HOME}, // Cursor Key Home - {(Byte *) "OF", (Byte) VI_K_END}, // Cursor Key End - {(Byte *) "", (Byte) VI_K_UP}, // cursor key Up - {(Byte *) "", (Byte) VI_K_DOWN}, // cursor key Down - {(Byte *) "", (Byte) VI_K_RIGHT}, // Cursor Key Right - {(Byte *) "", (Byte) VI_K_LEFT}, // cursor key Left - {(Byte *) "", (Byte) VI_K_HOME}, // Cursor Key Home - {(Byte *) "", (Byte) VI_K_END}, // Cursor Key End - {(Byte *) "[2~", (Byte) VI_K_INSERT}, // Cursor Key Insert - {(Byte *) "[5~", (Byte) VI_K_PAGEUP}, // Cursor Key Page Up - {(Byte *) "[6~", (Byte) VI_K_PAGEDOWN}, // Cursor Key Page Down - {(Byte *) "OP", (Byte) VI_K_FUN1}, // Function Key F1 - {(Byte *) "OQ", (Byte) VI_K_FUN2}, // Function Key F2 - {(Byte *) "OR", (Byte) VI_K_FUN3}, // Function Key F3 - {(Byte *) "OS", (Byte) VI_K_FUN4}, // Function Key F4 - {(Byte *) "[15~", (Byte) VI_K_FUN5}, // Function Key F5 - {(Byte *) "[17~", (Byte) VI_K_FUN6}, // Function Key F6 - {(Byte *) "[18~", (Byte) VI_K_FUN7}, // Function Key F7 - {(Byte *) "[19~", (Byte) VI_K_FUN8}, // Function Key F8 - {(Byte *) "[20~", (Byte) VI_K_FUN9}, // Function Key F9 - {(Byte *) "[21~", (Byte) VI_K_FUN10}, // Function Key F10 - {(Byte *) "[23~", (Byte) VI_K_FUN11}, // Function Key F11 - {(Byte *) "[24~", (Byte) VI_K_FUN12}, // Function Key F12 - {(Byte *) "[11~", (Byte) VI_K_FUN1}, // Function Key F1 - {(Byte *) "[12~", (Byte) VI_K_FUN2}, // Function Key F2 - {(Byte *) "[13~", (Byte) VI_K_FUN3}, // Function Key F3 - {(Byte *) "[14~", (Byte) VI_K_FUN4}, // Function Key F4 - }; - -#define ESCCMDS_COUNT (sizeof(esccmds)/sizeof(struct esc_cmds)) - - (void) alarm(0); // turn alarm OFF while we wait for input - // get input from User- are there already input chars in Q? - bufsiz = strlen((char *) readbuffer); - if (bufsiz <= 0) { - ri0: - // the Q is empty, wait for a typed char - bufsiz = read(0, readbuffer, BUFSIZ - 1); - if (bufsiz < 0) { - if (errno == EINTR) - goto ri0; // interrupted sys call - if (errno == EBADF) - editing = 0; - if (errno == EFAULT) - editing = 0; - if (errno == EINVAL) - editing = 0; - if (errno == EIO) - editing = 0; - errno = 0; - bufsiz = 0; - } - readbuffer[bufsiz] = '\0'; - } - // return char if it is not part of ESC sequence - if (readbuffer[0] != 27) - goto ri1; - - // This is an ESC char. Is this Esc sequence? - // Could be bare Esc key. See if there are any - // more chars to read after the ESC. This would - // be a Function or Cursor Key sequence. - FD_ZERO(&rfds); - FD_SET(0, &rfds); - tv.tv_sec = 0; - tv.tv_usec = 50000; // Wait 5/100 seconds- 1 Sec=1000000 - - // keep reading while there are input chars and room in buffer - while (select(1, &rfds, NULL, NULL, &tv) > 0 && bufsiz <= (BUFSIZ - 5)) { - // read the rest of the ESC string - i = read(0, (void *) (readbuffer + bufsiz), BUFSIZ - bufsiz); - if (i > 0) { - bufsiz += i; - readbuffer[bufsiz] = '\0'; // Terminate the string - } - } - // Maybe cursor or function key? - for (cmdindex = 0; cmdindex < ESCCMDS_COUNT; cmdindex++) { - cnt = strlen((char *) esccmds[cmdindex].seq); - i = strncmp((char *) esccmds[cmdindex].seq, (char *) readbuffer, cnt); - if (i == 0) { - // is a Cursor key- put derived value back into Q - readbuffer[0] = esccmds[cmdindex].val; - // squeeze out the ESC sequence - for (i = 1; i < cnt; i++) { - memmove(readbuffer + 1, readbuffer + 2, BUFSIZ - 2); - readbuffer[BUFSIZ - 1] = '\0'; - } - break; - } - } - ri1: - c = readbuffer[0]; - // remove one char from Q - memmove(readbuffer, readbuffer + 1, BUFSIZ - 1); - readbuffer[BUFSIZ - 1] = '\0'; - (void) alarm(3); // we are done waiting for input, turn alarm ON - return (c); -} - -//----- IO Routines -------------------------------------------- -static Byte get_one_char() -{ - static Byte c; - -#ifdef BB_FEATURE_VI_DOT_CMD - // ! adding2q && ioq == 0 read() - // ! adding2q && ioq != 0 *ioq - // adding2q *last_modifying_cmd= read() - if (!adding2q) { - // we are not adding to the q. - // but, we may be reading from a q - if (ioq == 0) { - // there is no current q, read from STDIN - c = readit(); // get the users input - } else { - // there is a queue to get chars from first - c = *ioq++; - if (c == '\0') { - // the end of the q, read from STDIN - free(ioq_start); - ioq_start = ioq = 0; - c = readit(); // get the users input - } - } - } else { - // adding STDIN chars to q - c = readit(); // get the users input - if (last_modifying_cmd != 0) { - // add new char to q - last_modifying_cmd[strlen((char *) last_modifying_cmd)] = c; - } - } -#else /* BB_FEATURE_VI_DOT_CMD */ - c = readit(); // get the users input -#endif /* BB_FEATURE_VI_DOT_CMD */ - return (c); // return the char, where ever it came from -} - -static Byte *get_input_line(Byte * prompt) // get input line- use "status line" -{ - Byte buf[BUFSIZ]; - Byte c; - int i; - static Byte *obufp = NULL; - - strcpy((char *) buf, (char *) prompt); - *status_buffer = '\0'; // clear the status buffer - place_cursor(rows - 1, 0, FALSE); // go to Status line, bottom of screen - clear_to_eol(); // clear the line - write(1, prompt, strlen((char *) prompt)); // write out the :, /, or ? prompt - - for (i = strlen((char *) buf); i < BUFSIZ;) { - c = get_one_char(); // read user input - if (c == '\n' || c == '\r' || c == 27) - break; // is this end of input - if (c == erase_char) { // user wants to erase prev char - i--; // backup to prev char - buf[i] = '\0'; // erase the char - buf[i + 1] = '\0'; // null terminate buffer - write(1, " ", 3); // erase char on screen - if (i <= 0) { // user backs up before b-o-l, exit - break; - } - } else { - buf[i] = c; // save char in buffer - buf[i + 1] = '\0'; // make sure buffer is null terminated - write(1, buf + i, 1); // echo the char back to user - i++; - } - } - refresh(FALSE); - if (obufp != NULL) - free(obufp); - obufp = (Byte *) strdup((char *) buf); - return (obufp); -} - -static int file_size(Byte * fn) // what is the byte size of "fn" -{ - struct stat st_buf; - int cnt, sr; - - if (fn == 0 || strlen(fn) <= 0) - return (-1); - cnt = -1; - sr = stat((char *) fn, &st_buf); // see if file exists - if (sr >= 0) { - cnt = (int) st_buf.st_size; - } - return (cnt); -} - -static int file_insert(Byte * fn, Byte * p, int size) -{ - int fd, cnt; - - cnt = -1; -#ifdef BB_FEATURE_VI_READONLY - readonly = FALSE; -#endif /* BB_FEATURE_VI_READONLY */ - if (fn == 0 || strlen((char*) fn) <= 0) { - psbs("No filename given"); - goto fi0; - } - if (size == 0) { - // OK- this is just a no-op - cnt = 0; - goto fi0; - } - if (size < 0) { - psbs("Trying to insert a negative number (%d) of characters", size); - goto fi0; - } - if (p < text || p > end) { - psbs("Trying to insert file outside of memory"); - goto fi0; - } - - // see if we can open the file -#ifdef BB_FEATURE_VI_READONLY - if (vi_readonly == TRUE) goto fi1; // do not try write-mode -#endif - fd = open((char *) fn, O_RDWR); // assume read & write - if (fd < 0) { - // could not open for writing- maybe file is read only -#ifdef BB_FEATURE_VI_READONLY - fi1: -#endif - fd = open((char *) fn, O_RDONLY); // try read-only - if (fd < 0) { - psbs("\"%s\" %s", fn, "could not open file"); - goto fi0; - } -#ifdef BB_FEATURE_VI_READONLY - // got the file- read-only - readonly = TRUE; -#endif /* BB_FEATURE_VI_READONLY */ - } - p = text_hole_make(p, size); - cnt = read(fd, p, size); - close(fd); - if (cnt < 0) { - cnt = -1; - p = text_hole_delete(p, p + size - 1); // un-do buffer insert - psbs("could not read file \"%s\"", fn); - } else if (cnt < size) { - // There was a partial read, shrink unused space text[] - p = text_hole_delete(p + cnt, p + (size - cnt) - 1); // un-do buffer insert - psbs("could not read all of file \"%s\"", fn); - } - if (cnt >= size) - file_modified = TRUE; - fi0: - return (cnt); -} - -static int file_write(Byte * fn, Byte * first, Byte * last) -{ - int fd, cnt, charcnt; - - if (fn == 0) { - psbs("No current filename"); - return (-1); - } - charcnt = 0; - // FIXIT- use the correct umask() - fd = open((char *) fn, (O_WRONLY | O_CREAT | O_TRUNC), 0664); - if (fd < 0) - return (-1); - cnt = last - first + 1; - charcnt = write(fd, first, cnt); - if (charcnt == cnt) { - // good write - //file_modified= FALSE; // the file has not been modified - } else { - charcnt = 0; - } - close(fd); - return (charcnt); -} - -//----- Terminal Drawing --------------------------------------- -// The terminal is made up of 'rows' line of 'columns' columns. -// classicly this would be 24 x 80. -// screen coordinates -// 0,0 ... 0,79 -// 1,0 ... 1,79 -// . ... . -// . ... . -// 22,0 ... 22,79 -// 23,0 ... 23,79 status line -// - -//----- Move the cursor to row x col (count from 0, not 1) ------- -static void place_cursor(int row, int col, int opti) -{ - char cm1[BUFSIZ]; - char *cm; - int l; -#ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR - char cm2[BUFSIZ]; - Byte *screenp; - // char cm3[BUFSIZ]; - int Rrow= last_row; -#endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */ - - memset(cm1, '\0', BUFSIZ - 1); // clear the buffer - - if (row < 0) row = 0; - if (row >= rows) row = rows - 1; - if (col < 0) col = 0; - if (col >= columns) col = columns - 1; - - //----- 1. Try the standard terminal ESC sequence - sprintf((char *) cm1, CMrc, row + 1, col + 1); - cm= cm1; - if (opti == FALSE) goto pc0; - -#ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR - //----- find the minimum # of chars to move cursor ------------- - //----- 2. Try moving with discreet chars (Newline, [back]space, ...) - memset(cm2, '\0', BUFSIZ - 1); // clear the buffer - - // move to the correct row - while (row < Rrow) { - // the cursor has to move up - strcat(cm2, CMup); - Rrow--; - } - while (row > Rrow) { - // the cursor has to move down - strcat(cm2, CMdown); - Rrow++; - } - - // now move to the correct column - strcat(cm2, "\r"); // start at col 0 - // just send out orignal source char to get to correct place - screenp = &screen[row * columns]; // start of screen line - strncat(cm2, screenp, col); - - //----- 3. Try some other way of moving cursor - //--------------------------------------------- - - // pick the shortest cursor motion to send out - cm= cm1; - if (strlen(cm2) < strlen(cm)) { - cm= cm2; - } /* else if (strlen(cm3) < strlen(cm)) { - cm= cm3; - } */ -#endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */ - pc0: - l= strlen(cm); - if (l) write(1, cm, l); // move the cursor -} - -//----- Erase from cursor to end of line ----------------------- -static void clear_to_eol() -{ - write(1, Ceol, strlen(Ceol)); // Erase from cursor to end of line -} - -//----- Erase from cursor to end of screen ----------------------- -static void clear_to_eos() -{ - write(1, Ceos, strlen(Ceos)); // Erase from cursor to end of screen -} - -//----- Start standout mode ------------------------------------ -static void standout_start() // send "start reverse video" sequence -{ - write(1, SOs, strlen(SOs)); // Start reverse video mode -} - -//----- End standout mode -------------------------------------- -static void standout_end() // send "end reverse video" sequence -{ - write(1, SOn, strlen(SOn)); // End reverse video mode -} - -//----- Flash the screen -------------------------------------- -static void flash(int h) -{ - standout_start(); // send "start reverse video" sequence - redraw(TRUE); - (void) mysleep(h); - standout_end(); // send "end reverse video" sequence - redraw(TRUE); -} - -static void beep() -{ - write(1, bell, strlen(bell)); // send out a bell character -} - -static void indicate_error(char c) -{ -#ifdef BB_FEATURE_VI_CRASHME - if (crashme > 0) - return; // generate a random command -#endif /* BB_FEATURE_VI_CRASHME */ - if (err_method == 0) { - beep(); - } else { - flash(10); - } -} - -//----- Screen[] Routines -------------------------------------- -//----- Erase the Screen[] memory ------------------------------ -static void screen_erase() -{ - memset(screen, ' ', screensize); // clear new screen -} - -//----- Draw the status line at bottom of the screen ------------- -static void show_status_line(void) -{ - static int last_cksum; - int l, cnt, cksum; - - cnt = strlen((char *) status_buffer); - for (cksum= l= 0; l < cnt; l++) { cksum += (int)(status_buffer[l]); } - // don't write the status line unless it changes - if (cnt > 0 && last_cksum != cksum) { - last_cksum= cksum; // remember if we have seen this line - place_cursor(rows - 1, 0, FALSE); // put cursor on status line - write(1, status_buffer, cnt); - clear_to_eol(); - place_cursor(crow, ccol, FALSE); // put cursor back in correct place - } -} - -//----- format the status buffer, the bottom line of screen ------ -// print status buffer, with STANDOUT mode -static void psbs(char *format, ...) -{ - va_list args; - - va_start(args, format); - strcpy((char *) status_buffer, SOs); // Terminal standout mode on - vsprintf((char *) status_buffer + strlen((char *) status_buffer), format, - args); - strcat((char *) status_buffer, SOn); // Terminal standout mode off - va_end(args); - - return; -} - -// print status buffer -static void psb(char *format, ...) -{ - va_list args; - - va_start(args, format); - vsprintf((char *) status_buffer, format, args); - va_end(args); - return; -} - -static void ni(Byte * s) // display messages -{ - Byte buf[BUFSIZ]; - - print_literal(buf, s); - psbs("\'%s\' is not implemented", buf); -} - -static void edit_status(void) // show file status on status line -{ - int cur, tot, percent; - - cur = count_lines(text, dot); - tot = count_lines(text, end - 1); - // current line percent - // ------------- ~~ ---------- - // total lines 100 - if (tot > 0) { - percent = (100 * cur) / tot; - } else { - cur = tot = 0; - percent = 100; - } - psb("\"%s\"" -#ifdef BB_FEATURE_VI_READONLY - "%s" -#endif /* BB_FEATURE_VI_READONLY */ - "%s line %d of %d --%d%%--", - (cfn != 0 ? (char *) cfn : "No file"), -#ifdef BB_FEATURE_VI_READONLY - ((vi_readonly == TRUE || readonly == TRUE) ? " [Read only]" : ""), -#endif /* BB_FEATURE_VI_READONLY */ - (file_modified == TRUE ? " [modified]" : ""), - cur, tot, percent); -} - -//----- Force refresh of all Lines ----------------------------- -static void redraw(int full_screen) -{ - place_cursor(0, 0, FALSE); // put cursor in correct place - clear_to_eos(); // tel terminal to erase display - screen_erase(); // erase the internal screen buffer - refresh(full_screen); // this will redraw the entire display -} - -//----- Format a text[] line into a buffer --------------------- -static void format_line(Byte *dest, Byte *src, int li) -{ - int co; - Byte c; - - for (co= 0; co < MAX_SCR_COLS; co++) { - c= ' '; // assume blank - if (li > 0 && co == 0) { - c = '~'; // not first line, assume Tilde - } - // are there chars in text[] and have we gone past the end - if (text < end && src < end) { - c = *src++; - } - if (c == '\n') - break; - if (c < ' ' || c > '~') { - if (c == '\t') { - c = ' '; - // co % 8 != 7 - for (; (co % tabstop) != (tabstop - 1); co++) { - dest[co] = c; - } - } else { - dest[co++] = '^'; - c |= '@'; // make it visible - c &= 0x7f; // get rid of hi bit - } - } - // the co++ is done here so that the column will - // not be overwritten when we blank-out the rest of line - dest[co] = c; - if (src >= end) - break; - } -} - -//----- Refresh the changed screen lines ----------------------- -// Copy the source line from text[] into the buffer and note -// if the current screenline is different from the new buffer. -// If they differ then that line needs redrawing on the terminal. -// -static void refresh(int full_screen) -{ - static int old_offset; - int li, changed; - Byte buf[MAX_SCR_COLS]; - Byte *tp, *sp; // pointer into text[] and screen[] -#ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR - int last_li= -2; // last line that changed- for optimizing cursor movement -#endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */ - -#ifdef BB_FEATURE_VI_WIN_RESIZE - window_size_get(0); -#endif /* BB_FEATURE_VI_WIN_RESIZE */ - sync_cursor(dot, &crow, &ccol); // where cursor will be (on "dot") - tp = screenbegin; // index into text[] of top line - - // compare text[] to screen[] and mark screen[] lines that need updating - for (li = 0; li < rows - 1; li++) { - int cs, ce; // column start & end - memset(buf, ' ', MAX_SCR_COLS); // blank-out the buffer - buf[MAX_SCR_COLS-1] = 0; // NULL terminate the buffer - // format current text line into buf - format_line(buf, tp, li); - - // skip to the end of the current text[] line - while (tp < end && *tp++ != '\n') /*no-op*/ ; - - // see if there are any changes between vitual screen and buf - changed = FALSE; // assume no change - cs= 0; - ce= columns-1; - sp = &screen[li * columns]; // start of screen line - if (full_screen == TRUE) { - // force re-draw of every single column from 0 - columns-1 - goto re0; - } - // compare newly formatted buffer with virtual screen - // look forward for first difference between buf and screen - for ( ; cs <= ce; cs++) { - if (buf[cs + offset] != sp[cs]) { - changed = TRUE; // mark for redraw - break; - } - } - - // look backward for last difference between buf and screen - for ( ; ce >= cs; ce--) { - if (buf[ce + offset] != sp[ce]) { - changed = TRUE; // mark for redraw - break; - } - } - // now, cs is index of first diff, and ce is index of last diff - - // if horz offset has changed, force a redraw - if (offset != old_offset) { - re0: - changed = TRUE; - } - - // make a sanity check of columns indexes - if (cs < 0) cs= 0; - if (ce > columns-1) ce= columns-1; - if (cs > ce) { cs= 0; ce= columns-1; } - // is there a change between vitual screen and buf - if (changed == TRUE) { - // copy changed part of buffer to virtual screen - memmove(sp+cs, buf+(cs+offset), ce-cs+1); - - // move cursor to column of first change - if (offset != old_offset) { - // opti_cur_move is still too stupid - // to handle offsets correctly - place_cursor(li, cs, FALSE); - } else { -#ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR - // if this just the next line - // try to optimize cursor movement - // otherwise, use standard ESC sequence - place_cursor(li, cs, li == (last_li+1) ? TRUE : FALSE); - last_li= li; -#else /* BB_FEATURE_VI_OPTIMIZE_CURSOR */ - place_cursor(li, cs, FALSE); // use standard ESC sequence -#endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */ - } - - // write line out to terminal - write(1, sp+cs, ce-cs+1); -#ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR - last_row = li; -#endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */ - } - } - -#ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR - place_cursor(crow, ccol, (crow == last_row) ? TRUE : FALSE); - last_row = crow; -#else - place_cursor(crow, ccol, FALSE); -#endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */ - - if (offset != old_offset) - old_offset = offset; -} diff --git a/watchdog.c b/watchdog.c deleted file mode 100644 index f0b0ebd0e..000000000 --- a/watchdog.c +++ /dev/null @@ -1,49 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini watchdog implementation for busybox - * - * Copyright (C) 2000 spoon <spoon@ix.netcom.com>. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* getopt not needed */ - -#include <stdio.h> -#include <fcntl.h> -#include <unistd.h> -#include <stdlib.h> -#include "busybox.h" - -extern int watchdog_main(int argc, char **argv) -{ - int fd; - - if (argc != 2) { - show_usage(); - } - - if ((fd=open(argv[1], O_WRONLY)) == -1) { - perror_msg_and_die(argv[1]); - } - - while (1) { - sleep(30); - write(fd, "\0", 1); - } - - return EXIT_FAILURE; -} diff --git a/wc.c b/wc.c deleted file mode 100644 index 695e7e7d4..000000000 --- a/wc.c +++ /dev/null @@ -1,156 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini wc implementation for busybox - * - * Copyright (C) 2000 Edward Betts <edward@debian.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <stdio.h> -#include <getopt.h> -#include <string.h> -#include <stdlib.h> -#include "busybox.h" - -static int total_lines, total_words, total_chars, max_length; -static int print_lines, print_words, print_chars, print_length; - -static void print_counts(int lines, int words, int chars, int length, - const char *name) -{ - char const *space = ""; - - if (print_lines) { - printf("%7d", lines); - space = " "; - } - if (print_words) { - printf("%s%7d", space, words); - space = " "; - } - if (print_chars) { - printf("%s%7d", space, chars); - space = " "; - } - if (print_length) - printf("%s%7d", space, length); - if (*name) - printf(" %s", name); - putchar('\n'); -} - -static void wc_file(FILE * file, const char *name) -{ - int lines, words, chars, length; - int in_word = 0, linepos = 0; - int c; - - lines = words = chars = length = 0; - while ((c = getc(file)) != EOF) { - chars++; - switch (c) { - case '\n': - lines++; - case '\r': - case '\f': - if (linepos > length) - length = linepos; - linepos = 0; - goto word_separator; - case '\t': - linepos += 8 - (linepos % 8); - goto word_separator; - case ' ': - linepos++; - case '\v': - word_separator: - if (in_word) { - in_word = 0; - words++; - } - break; - default: - linepos++; - in_word = 1; - break; - } - } - if (linepos > length) - length = linepos; - if (in_word) - words++; - print_counts(lines, words, chars, length, name); - total_lines += lines; - total_words += words; - total_chars += chars; - if (length > max_length) - max_length = length; - fclose(file); - fflush(stdout); -} - -int wc_main(int argc, char **argv) -{ - FILE *file; - unsigned int num_files_counted = 0; - int opt, status = EXIT_SUCCESS; - - total_lines = total_words = total_chars = max_length = 0; - print_lines = print_words = print_chars = print_length = 0; - - while ((opt = getopt(argc, argv, "clLw")) > 0) { - switch (opt) { - case 'c': - print_chars = 1; - break; - case 'l': - print_lines = 1; - break; - case 'L': - print_length = 1; - break; - case 'w': - print_words = 1; - break; - default: - show_usage(); - } - } - - if (!print_lines && !print_words && !print_chars && !print_length) - print_lines = print_words = print_chars = 1; - - if (argv[optind] == NULL || strcmp(argv[optind], "-") == 0) { - wc_file(stdin, ""); - return EXIT_SUCCESS; - } else { - while (optind < argc) { - if ((file = wfopen(argv[optind], "r")) != NULL) - wc_file(file, argv[optind]); - else - status = EXIT_FAILURE; - num_files_counted++; - optind++; - } - } - - if (num_files_counted > 1) - print_counts(total_lines, total_words, total_chars, - max_length, "total"); - - return status; -} diff --git a/wget.c b/wget.c deleted file mode 100644 index 59373d1d9..000000000 --- a/wget.c +++ /dev/null @@ -1,834 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * wget - retrieve a file using HTTP or FTP - * - * Chip Rosenthal Covad Communications <chip@laserlink.net> - * - */ - -#include <stdio.h> -#include <errno.h> -#include <stdlib.h> -#include <unistd.h> -#include <ctype.h> -#include <string.h> -#include <unistd.h> -#include <signal.h> -#include <sys/ioctl.h> - -#include <sys/time.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <netdb.h> - -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif -#include <getopt.h> - -#include "busybox.h" - -/* Stupid libc5 doesn't define this... */ -#ifndef timersub -#define timersub(a, b, result) \ - do { \ - (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ - (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ - if ((result)->tv_usec < 0) { \ - --(result)->tv_sec; \ - (result)->tv_usec += 1000000; \ - } \ - } while (0) -#endif - -struct host_info { - char *host; - int port; - char *path; - int is_ftp; - char *user; -}; - -static void parse_url(char *url, struct host_info *h); -static FILE *open_socket(char *host, int port); -static char *gethdr(char *buf, size_t bufsiz, FILE *fp, int *istrunc); -static int ftpcmd(char *s1, char *s2, FILE *fp, char *buf); - -/* Globals (can be accessed from signal handlers */ -static off_t filesize = 0; /* content-length of the file */ -static int chunked = 0; /* chunked transfer encoding */ -#ifdef BB_FEATURE_WGET_STATUSBAR -static void progressmeter(int flag); -static char *curfile; /* Name of current file being transferred. */ -static struct timeval start; /* Time a transfer started. */ -static volatile unsigned long statbytes = 0; /* Number of bytes transferred so far. */ -/* For progressmeter() -- number of seconds before xfer considered "stalled" */ -static const int STALLTIME = 5; -#endif - -static void close_and_delete_outfile(FILE* output, char *fname_out, int do_continue) -{ - if (output != stdout && do_continue==0) { - fclose(output); - unlink(fname_out); - } -} - -/* Read NMEMB elements of SIZE bytes into PTR from STREAM. Returns the - * number of elements read, and a short count if an eof or non-interrupt - * error is encountered. */ -static size_t safe_fread(void *ptr, size_t size, size_t nmemb, FILE *stream) -{ - size_t ret = 0; - - do { - clearerr(stream); - ret += fread((char *)ptr + (ret * size), size, nmemb - ret, stream); - } while (ret < nmemb && ferror(stream) && errno == EINTR); - - return ret; -} - -/* Write NMEMB elements of SIZE bytes from PTR to STREAM. Returns the - * number of elements written, and a short count if an eof or non-interrupt - * error is encountered. */ -static size_t safe_fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream) -{ - size_t ret = 0; - - do { - clearerr(stream); - ret += fwrite((char *)ptr + (ret * size), size, nmemb - ret, stream); - } while (ret < nmemb && ferror(stream) && errno == EINTR); - - return ret; -} - -/* Read a line or SIZE - 1 bytes into S, whichever is less, from STREAM. - * Returns S, or NULL if an eof or non-interrupt error is encountered. */ -static char *safe_fgets(char *s, int size, FILE *stream) -{ - char *ret; - - do { - clearerr(stream); - ret = fgets(s, size, stream); - } while (ret == NULL && ferror(stream) && errno == EINTR); - - return ret; -} - -#define close_delete_and_die(s...) { \ - close_and_delete_outfile(output, fname_out, do_continue); \ - error_msg_and_die(s); } - - -#ifdef BB_FEATURE_WGET_AUTHENTICATION -/* - * Base64-encode character string - * oops... isn't something similar in uuencode.c? - * It would be better to use already existing code - */ -char *base64enc(char *p, char *buf, int len) { - - char al[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" - "0123456789+/"; - char *s = buf; - - while(*p) { - if (s >= buf+len-4) - error_msg_and_die("buffer overflow"); - *(s++) = al[(*p >> 2) & 0x3F]; - *(s++) = al[((*p << 4) & 0x30) | ((*(p+1) >> 4) & 0x0F)]; - *s = *(s+1) = '='; - *(s+2) = 0; - if (! *(++p)) break; - *(s++) = al[((*p << 2) & 0x3C) | ((*(p+1) >> 6) & 0x03)]; - if (! *(++p)) break; - *(s++) = al[*(p++) & 0x3F]; - } - - return buf; -} -#endif - -int wget_main(int argc, char **argv) -{ - int n, try=5, status; - int port; - char *proxy; - char *dir_prefix=NULL; - char *s, buf[512]; - struct stat sbuf; - char extra_headers[1024]; - char *extra_headers_ptr = extra_headers; - int extra_headers_left = sizeof(extra_headers); - int which_long_opt = 0, option_index = -1; - struct host_info server, target; - - FILE *sfp = NULL; /* socket to web/ftp server */ - FILE *dfp = NULL; /* socket to ftp server (data) */ - char *fname_out = NULL; /* where to direct output (-O) */ - int do_continue = 0; /* continue a prev transfer (-c) */ - long beg_range = 0L; /* range at which continue begins */ - int got_clen = 0; /* got content-length: from server */ - FILE *output; /* socket to web server */ - int quiet_flag = FALSE; /* Be verry, verry quiet... */ - -#define LONG_HEADER 1 - struct option long_options[] = { - { "continue", 0, NULL, 'c' }, - { "quiet", 0, NULL, 'q' }, - { "output-document", 1, NULL, 'O' }, - { "header", 1, &which_long_opt, LONG_HEADER }, - { 0, 0, 0, 0 } - }; - /* - * Crack command line. - */ - while ((n = getopt_long(argc, argv, "cqO:P:", long_options, &option_index)) != EOF) { - switch (n) { - case 'c': - ++do_continue; - break; - case 'P': - dir_prefix = optarg; - break; - case 'q': - quiet_flag = TRUE; - break; - case 'O': - /* can't set fname_out to NULL if outputting to stdout, because - * this gets interpreted as the auto-gen output filename - * case below - tausq@debian.org - */ - fname_out = optarg; - break; - case 0: - switch (which_long_opt) { - case LONG_HEADER: { - int arglen = strlen(optarg); - if(extra_headers_left - arglen - 2 <= 0) - error_msg_and_die("extra_headers buffer too small(need %i)", extra_headers_left - arglen); - strcpy(extra_headers_ptr, optarg); - extra_headers_ptr += arglen; - extra_headers_left -= ( arglen + 2 ); - *extra_headers_ptr++ = '\r'; - *extra_headers_ptr++ = '\n'; - *(extra_headers_ptr + 1) = 0; - break; - } - } - break; - default: - show_usage(); - } - } - - if (argc - optind != 1) - show_usage(); - - parse_url(argv[optind], &target); - server.host = target.host; - server.port = target.port; - - /* - * Use the proxy if necessary. - */ - proxy = getenv(target.is_ftp ? "ftp_proxy" : "http_proxy"); - if (proxy) - parse_url(xstrdup(proxy), &server); - - /* Guess an output filename */ - if (!fname_out) { - fname_out = -#ifdef BB_FEATURE_WGET_STATUSBAR - curfile = -#endif - get_last_path_component(target.path); - if (fname_out==NULL || strlen(fname_out)<1) { - fname_out = -#ifdef BB_FEATURE_WGET_STATUSBAR - curfile = -#endif - "index.html"; - } - if (dir_prefix != NULL) - fname_out = concat_path_file(dir_prefix, fname_out); -#ifdef BB_FEATURE_WGET_STATUSBAR - } else { - curfile = get_last_path_component(fname_out); -#endif - } - if (do_continue && !fname_out) - error_msg_and_die("cannot specify continue (-c) without a filename (-O)"); - - - /* - * Open the output file stream. - */ - if (strcmp(fname_out, "-") == 0) { - output = stdout; - quiet_flag = TRUE; - } else { - output = xfopen(fname_out, (do_continue ? "a" : "w")); - } - - /* - * Determine where to start transfer. - */ - if (do_continue) { - if (fstat(fileno(output), &sbuf) < 0) - perror_msg_and_die("fstat()"); - if (sbuf.st_size > 0) - beg_range = sbuf.st_size; - else - do_continue = 0; - } - - if (proxy || !target.is_ftp) { - /* - * HTTP session - */ - do { - if (! --try) - close_delete_and_die("too many redirections"); - - /* - * Open socket to http server - */ - if (sfp) fclose(sfp); - sfp = open_socket(server.host, server.port); - - /* - * Send HTTP request. - */ - if (proxy) { - fprintf(sfp, "GET %stp://%s:%d/%s HTTP/1.1\r\n", - target.is_ftp ? "f" : "ht", target.host, - target.port, target.path); - } else { - fprintf(sfp, "GET /%s HTTP/1.1\r\n", target.path); - } - - fprintf(sfp, "Host: %s\r\nUser-Agent: Wget\r\n", target.host); - -#ifdef BB_FEATURE_WGET_AUTHENTICATION - if (target.user) { - fprintf(sfp, "Authorization: Basic %s\r\n", - base64enc(target.user, buf, sizeof(buf))); - } - if (proxy && server.user) { - fprintf(sfp, "Proxy-Authorization: Basic %s\r\n", - base64enc(server.user, buf, sizeof(buf))); - } -#endif - - if (do_continue) - fprintf(sfp, "Range: bytes=%ld-\r\n", beg_range); - if(extra_headers_left < sizeof(extra_headers)) - fputs(extra_headers,sfp); - fprintf(sfp,"Connection: close\r\n\r\n"); - - /* - * Retrieve HTTP response line and check for "200" status code. - */ -read_response: if (fgets(buf, sizeof(buf), sfp) == NULL) - close_delete_and_die("no response from server"); - - for (s = buf ; *s != '\0' && !isspace(*s) ; ++s) - ; - for ( ; isspace(*s) ; ++s) - ; - switch (status = atoi(s)) { - case 0: - case 100: - while (gethdr(buf, sizeof(buf), sfp, &n) != NULL); - goto read_response; - case 200: - if (do_continue && output != stdout) - output = freopen(fname_out, "w", output); - do_continue = 0; - break; - case 300: /* redirection */ - case 301: - case 302: - case 303: - break; - case 206: - if (do_continue) - break; - /*FALLTHRU*/ - default: - chomp(buf); - close_delete_and_die("server returned error %d: %s", atoi(s), buf); - } - - /* - * Retrieve HTTP headers. - */ - while ((s = gethdr(buf, sizeof(buf), sfp, &n)) != NULL) { - if (strcasecmp(buf, "content-length") == 0) { - filesize = atol(s); - got_clen = 1; - continue; - } - if (strcasecmp(buf, "transfer-encoding") == 0) { - if (strcasecmp(s, "chunked") == 0) { - chunked = got_clen = 1; - } else { - close_delete_and_die("server wants to do %s transfer encoding", s); - } - } - if (strcasecmp(buf, "location") == 0) { - if (s[0] == '/') - target.path = xstrdup(s+1); - else { - parse_url(xstrdup(s), &target); - if (!proxy) { - server.host = target.host; - server.port = target.port; - } - } - } - } - } while(status >= 300); - - dfp = sfp; - } - else - { - /* - * FTP session - */ - if (! target.user) - target.user = xstrdup("anonymous:busybox@"); - - sfp = open_socket(server.host, server.port); - if (ftpcmd(NULL, NULL, sfp, buf) != 220) - close_delete_and_die("%s", buf+4); - - /* - * Splitting username:password pair, - * trying to log in - */ - s = strchr(target.user, ':'); - if (s) - *(s++) = '\0'; - switch(ftpcmd("USER ", target.user, sfp, buf)) { - case 230: - break; - case 331: - if (ftpcmd("PASS ", s, sfp, buf) == 230) - break; - /* FALLTHRU (failed login) */ - default: - close_delete_and_die("ftp login: %s", buf+4); - } - - ftpcmd("CDUP", NULL, sfp, buf); - ftpcmd("TYPE I", NULL, sfp, buf); - - /* - * Querying file size - */ - if (ftpcmd("SIZE /", target.path, sfp, buf) == 213) { - filesize = atol(buf+4); - got_clen = 1; - } - - /* - * Entering passive mode - */ - if (ftpcmd("PASV", NULL, sfp, buf) != 227) - close_delete_and_die("PASV: %s", buf+4); - s = strrchr(buf, ','); - *s = 0; - port = atoi(s+1); - s = strrchr(buf, ','); - port += atoi(s+1) * 256; - dfp = open_socket(server.host, port); - - if (do_continue) { - sprintf(buf, "REST %ld", beg_range); - if (ftpcmd(buf, NULL, sfp, buf) != 350) { - if (output != stdout) - output = freopen(fname_out, "w", output); - do_continue = 0; - } else - filesize -= beg_range; - } - - if (ftpcmd("RETR /", target.path, sfp, buf) > 150) - close_delete_and_die("RETR: %s", buf+4); - - } - - - /* - * Retrieve file - */ - if (chunked) { - fgets(buf, sizeof(buf), dfp); - filesize = strtol(buf, (char **) NULL, 16); - } -#ifdef BB_FEATURE_WGET_STATUSBAR - if (quiet_flag==FALSE) - progressmeter(-1); -#endif - do { - while ((filesize > 0 || !got_clen) && (n = safe_fread(buf, 1, chunked ? (filesize > sizeof(buf) ? sizeof(buf) : filesize) : sizeof(buf), dfp)) > 0) { - safe_fwrite(buf, 1, n, output); -#ifdef BB_FEATURE_WGET_STATUSBAR - statbytes+=n; -#endif - if (got_clen) - filesize -= n; - } - - if (chunked) { - safe_fgets(buf, sizeof(buf), dfp); /* This is a newline */ - safe_fgets(buf, sizeof(buf), dfp); - filesize = strtol(buf, (char **) NULL, 16); - if (filesize==0) chunked = 0; /* all done! */ - } - - if (n == 0 && ferror(dfp)) - perror_msg_and_die("network read error"); - } while (chunked); -#ifdef BB_FEATURE_WGET_STATUSBAR - if (quiet_flag==FALSE) - progressmeter(1); -#endif - if (!proxy && target.is_ftp) { - fclose(dfp); - if (ftpcmd(NULL, NULL, sfp, buf) != 226) - error_msg_and_die("ftp error: %s", buf+4); - ftpcmd("QUIT", NULL, sfp, buf); - } - exit(EXIT_SUCCESS); -} - - -void parse_url(char *url, struct host_info *h) -{ - char *cp, *sp, *up; - - if (strncmp(url, "http://", 7) == 0) { - h->port = 80; - h->host = url + 7; - h->is_ftp = 0; - } else if (strncmp(url, "ftp://", 6) == 0) { - h->port = 21; - h->host = url + 6; - h->is_ftp = 1; - } else - error_msg_and_die("not an http or ftp url: %s", url); - - sp = strchr(h->host, '/'); - if (sp != NULL) { - *sp++ = '\0'; - h->path = sp; - } else - h->path = ""; - - up = strrchr(h->host, '@'); - if (up != NULL) { - h->user = h->host; - *up++ = '\0'; - h->host = up; - } else - h->user = NULL; - - cp = strchr(h->host, ':'); - if (cp != NULL) { - *cp++ = '\0'; - h->port = atoi(cp); - } - -} - - -FILE *open_socket(char *host, int port) -{ - struct sockaddr_in s_in; - struct hostent *hp; - int fd; - FILE *fp; - - memset(&s_in, 0, sizeof(s_in)); - s_in.sin_family = AF_INET; - hp = xgethostbyname(host); - memcpy(&s_in.sin_addr, hp->h_addr_list[0], hp->h_length); - s_in.sin_port = htons(port); - - /* - * Get the server onto a stdio stream. - */ - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) - perror_msg_and_die("socket()"); - if (connect(fd, (struct sockaddr *) &s_in, sizeof(s_in)) < 0) - perror_msg_and_die("connect(%s)", host); - if ((fp = fdopen(fd, "r+")) == NULL) - perror_msg_and_die("fdopen()"); - - return fp; -} - - -char *gethdr(char *buf, size_t bufsiz, FILE *fp, int *istrunc) -{ - char *s, *hdrval; - int c; - - *istrunc = 0; - - /* retrieve header line */ - if (fgets(buf, bufsiz, fp) == NULL) - return NULL; - - /* see if we are at the end of the headers */ - for (s = buf ; *s == '\r' ; ++s) - ; - if (s[0] == '\n') - return NULL; - - /* convert the header name to lower case */ - for (s = buf ; isalnum(*s) || *s == '-' ; ++s) - *s = tolower(*s); - - /* verify we are at the end of the header name */ - if (*s != ':') - error_msg_and_die("bad header line: %s", buf); - - /* locate the start of the header value */ - for (*s++ = '\0' ; *s == ' ' || *s == '\t' ; ++s) - ; - hdrval = s; - - /* locate the end of header */ - while (*s != '\0' && *s != '\r' && *s != '\n') - ++s; - - /* end of header found */ - if (*s != '\0') { - *s = '\0'; - return hdrval; - } - - /* Rats! The buffer isn't big enough to hold the entire header value. */ - while (c = getc(fp), c != EOF && c != '\n') - ; - *istrunc = 1; - return hdrval; -} - -static int ftpcmd(char *s1, char *s2, FILE *fp, char *buf) -{ - char *p; - - if (s1) { - if (!s2) s2=""; - fprintf(fp, "%s%s\n", s1, s2); - fflush(fp); - } - - do { - p = fgets(buf, 510, fp); - if (!p) - perror_msg_and_die("fgets()"); - } while (! isdigit(buf[0]) || buf[3] != ' '); - - return atoi(buf); -} - -#ifdef BB_FEATURE_WGET_STATUSBAR -/* Stuff below is from BSD rcp util.c, as added to openshh. - * Original copyright notice is retained at the end of this file. - * - */ - - -static int -getttywidth(void) -{ - struct winsize winsize; - - if (ioctl(fileno(stdout), TIOCGWINSZ, &winsize) != -1) - return (winsize.ws_col ? winsize.ws_col : 80); - else - return (80); -} - -static void -updateprogressmeter(int ignore) -{ - int save_errno = errno; - - progressmeter(0); - errno = save_errno; -} - -static void -alarmtimer(int wait) -{ - struct itimerval itv; - - itv.it_value.tv_sec = wait; - itv.it_value.tv_usec = 0; - itv.it_interval = itv.it_value; - setitimer(ITIMER_REAL, &itv, NULL); -} - - -static void -progressmeter(int flag) -{ - static const char prefixes[] = " KMGTP"; - static struct timeval lastupdate; - static off_t lastsize, totalsize; - struct timeval now, td, wait; - off_t cursize, abbrevsize; - double elapsed; - int ratio, barlength, i, remaining; - char buf[256]; - - if (flag == -1) { - (void) gettimeofday(&start, (struct timezone *) 0); - lastupdate = start; - lastsize = 0; - totalsize = filesize; /* as filesize changes.. */ - } - - (void) gettimeofday(&now, (struct timezone *) 0); - cursize = statbytes; - if (totalsize != 0 && !chunked) { - ratio = 100.0 * cursize / totalsize; - ratio = MAX(ratio, 0); - ratio = MIN(ratio, 100); - } else - ratio = 100; - - snprintf(buf, sizeof(buf), "\r%-20.20s %3d%% ", curfile, ratio); - - barlength = getttywidth() - 51; - if (barlength > 0) { - i = barlength * ratio / 100; - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), - "|%.*s%*s|", i, - "*****************************************************************************" - "*****************************************************************************", - barlength - i, ""); - } - i = 0; - abbrevsize = cursize; - while (abbrevsize >= 100000 && i < sizeof(prefixes)) { - i++; - abbrevsize >>= 10; - } - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %5d %c%c ", - (int) abbrevsize, prefixes[i], prefixes[i] == ' ' ? ' ' : - 'B'); - - timersub(&now, &lastupdate, &wait); - if (cursize > lastsize) { - lastupdate = now; - lastsize = cursize; - if (wait.tv_sec >= STALLTIME) { - start.tv_sec += wait.tv_sec; - start.tv_usec += wait.tv_usec; - } - wait.tv_sec = 0; - } - timersub(&now, &start, &td); - elapsed = td.tv_sec + (td.tv_usec / 1000000.0); - - if (wait.tv_sec >= STALLTIME) { - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), - " - stalled -"); - } else if (statbytes <= 0 || elapsed <= 0.0 || cursize > totalsize || chunked) { - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), - " --:-- ETA"); - } else { - remaining = (int) (totalsize / (statbytes / elapsed) - elapsed); - i = remaining / 3600; - if (i) - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), - "%2d:", i); - else - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), - " "); - i = remaining % 3600; - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), - "%02d:%02d ETA", i / 60, i % 60); - } - write(fileno(stderr), buf, strlen(buf)); - - if (flag == -1) { - struct sigaction sa; - sa.sa_handler = updateprogressmeter; - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_RESTART; - sigaction(SIGALRM, &sa, NULL); - alarmtimer(1); - } else if (flag == 1) { - alarmtimer(0); - statbytes = 0; - putc('\n', stderr); - } -} -#endif - -/* Original copyright notice which applies to the BB_FEATURE_WGET_STATUSBAR stuff, - * much of which was blatently stolen from openssh. */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change - * ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change> - * - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id: wget.c,v 1.45 2001/07/19 22:28:01 andersen Exp $ - */ - - - -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ - - - diff --git a/which.c b/which.c deleted file mode 100644 index c460ffdd1..000000000 --- a/which.c +++ /dev/null @@ -1,80 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Which implementation for busybox - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* getopt not needed */ -#include <string.h> -#include <stdio.h> -#include <stdlib.h> -#include "busybox.h" - -extern int which_main(int argc, char **argv) -{ - char *path_list, *path_n; - struct stat filestat; - int i, count=1, found, status = EXIT_SUCCESS; - - if (argc <= 1 || **(argv + 1) == '-') - show_usage(); - argc--; - - path_list = getenv("PATH"); - if (!path_list) - path_list = "/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin"; - - /* Replace colons with zeros in path_parsed and count them */ - for(i=strlen(path_list); i > 0; i--) - if (path_list[i]==':') { - path_list[i]=0; - count++; - } - - while(argc-- > 0) { - path_n = path_list; - argv++; - found = 0; - for (i = 0; i < count; i++) { - char *buf; - buf = concat_path_file(path_n, *argv); - if (stat (buf, &filestat) == 0 - && filestat.st_mode & S_IXUSR) - { - puts(buf); - found = 1; - break; - } - free(buf); - path_n += (strlen(path_n) + 1); - } - if (!found) - status = EXIT_FAILURE; - } - return status; -} - -/* -Local Variables: -c-file-style: "linux" -c-basic-offset: 4 -tab-width: 4 -End: -*/ diff --git a/whoami.c b/whoami.c deleted file mode 100644 index c3b1140e6..000000000 --- a/whoami.c +++ /dev/null @@ -1,44 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini whoami implementation for busybox - * - * Copyright (C) 2000 Edward Betts <edward@debian.org>. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* getopt not needed */ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include "busybox.h" - -extern int whoami_main(int argc, char **argv) -{ - char user[9]; - uid_t uid = geteuid(); - - if (argc > 1) - show_usage(); - - my_getpwuid(user, uid); - if (*user) { - puts(user); - return EXIT_SUCCESS; - } - error_msg_and_die("cannot find username for UID %u", (unsigned) uid); -} diff --git a/xargs.c b/xargs.c deleted file mode 100644 index 48adae90a..000000000 --- a/xargs.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Mini xargs implementation for busybox - * - * Copyright (C) 1999,2000,2001 by Lineo, inc. - * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org> - * Remixed by Mark Whitley <markw@lineo.com>, <markw@codepoet.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include "busybox.h" - -int xargs_main(int argc, char **argv) -{ - char *cmd_to_be_executed = NULL; - char *file_to_act_on = NULL; - - /* - * No options are supported in this version of xargs; no getopt. - * - * Re: The missing -t flag: Most programs that produce output also print - * the filename, so xargs doesn't really need to do it again. Supporting - * the -t flag =greatly= bloats up the size of this app and the memory it - * uses because you have to buffer all the input file strings in memory. If - * you really want to see the filenames that xargs will act on, just run it - * once with no args and xargs will echo the filename. Simple. - */ - - /* Store the command to be executed (taken from the command line) */ - if (argc == 1) { - /* default behavior is to echo all the filenames */ - cmd_to_be_executed = xstrdup("/bin/echo "); - } else { - /* concatenate all the arguments passed to xargs together */ - int i; - int len = 1; /* for the '\0' */ - for (i = 1; i < argc; i++) { - len += strlen(argv[i]); - len += 1; /* for the space between the args */ - cmd_to_be_executed = xrealloc(cmd_to_be_executed, len); - strcat(cmd_to_be_executed, argv[i]); - strcat(cmd_to_be_executed, " "); - } - } - - /* Now, read in one line at a time from stdin, and store this - * line to be used later as an argument to the command */ - while ((file_to_act_on = get_line_from_file(stdin)) !=NULL) { - - FILE *cmd_output = NULL; - char *output_line = NULL; - char *execstr = NULL; - - /* eat the newline off the filename. */ - chomp(file_to_act_on); - - /* eat blank lines */ - if (strlen(file_to_act_on) == 0) - continue; - - /* assemble the command and execute it */ - execstr = xcalloc(strlen(cmd_to_be_executed) + - strlen(file_to_act_on) + 1, sizeof(char)); - strcat(execstr, cmd_to_be_executed); - strcat(execstr, file_to_act_on); - cmd_output = popen(execstr, "r"); - if (cmd_output == NULL) - perror_msg_and_die("popen"); - - /* harvest the output */ - while ((output_line = get_line_from_file(cmd_output)) != NULL) { - fputs(output_line, stdout); - free(output_line); - } - - /* clean up */ - pclose(cmd_output); - free(execstr); - free(file_to_act_on); - } - -#ifdef BB_FEATURE_CLEAN_UP - free(cmd_to_be_executed); -#endif - - return 0; -} - -/* vi: set sw=4 ts=4: */ diff --git a/yes.c b/yes.c deleted file mode 100644 index 7d9596d0b..000000000 --- a/yes.c +++ /dev/null @@ -1,53 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Mini yes implementation for busybox - * - * Copyright (C) 2000 Edward Betts <edward@debian.org>. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* getopt not needed */ - -#include <stdio.h> -#include <stdlib.h> -#include "busybox.h" - -extern int yes_main(int argc, char **argv) -{ - int i; - - if (argc >= 2 && *argv[1] == '-') - show_usage(); - - if (argc == 1) { - while (1) - if (puts("y") == EOF) { - perror("yes"); - return EXIT_FAILURE; - } - } - - while (1) - for (i = 1; i < argc; i++) - if (fputs(argv[i], stdout) == EOF - || putchar(i == argc - 1 ? '\n' : ' ') == EOF) { - perror("yes"); - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -}