From bdfd0d78bc44e73d693510e70087857785b3b521 Mon Sep 17 00:00:00 2001 From: Eric Andersen Date: Wed, 24 Oct 2001 05:00:29 +0000 Subject: [PATCH] Major rework of the directory structure and the entire build system. -Erik --- .cvsignore | 1 + AUTHORS | 2 +- Changelog | 66 +- Config.h | 494 - LICENSE | 9 +- Makefile | 331 +- README | 15 +- addgroup.c | 178 - adduser.c | 366 - adjtimex.c | 176 - applets.c | 116 - applets.h | 500 - applets/busybox.c | 14 +- applets/busybox.sh | 4 +- applets/usage.h | 54 +- ar.c | 89 - archival/Makefile | 43 + archival/config.in | 19 + archival/gzip.c | 2 +- archival/tar.c | 32 +- ash.c | 12825 ---------------- basename.c | 52 - bunzip2.c | 2340 --- busybox.c | 181 - busybox.h | 106 - busybox.mkll | 24 - busybox.sh | 16 - busybox.spec | 44 - cat.c | 53 - chgrp.c | 91 - chmod.c | 85 - chown.c | 113 - chroot.c | 75 - chvt.c | 43 - clear.c | 34 - cmdedit.c | 1521 -- cmdedit.h | 6 - cmp.c | 80 - console-tools/Makefile | 43 + console-tools/clear.c | 5 +- console-tools/config.in | 18 + console-tools/reset.c | 7 +- coreutils/basename.c | 4 +- coreutils/cat.c | 4 +- coreutils/chgrp.c | 7 +- coreutils/chmod.c | 7 +- coreutils/chown.c | 7 +- coreutils/chroot.c | 7 +- coreutils/cmp.c | 4 +- coreutils/df.c | 12 +- coreutils/dirname.c | 4 +- coreutils/du.c | 15 +- coreutils/head.c | 5 +- coreutils/ln.c | 4 +- coreutils/ls.c | 116 +- coreutils/rmdir.c | 5 +- coreutils/sort.c | 14 +- coreutils/tail.c | 12 +- coreutils/tee.c | 3 +- coreutils/touch.c | 5 +- coreutils/tr.c | 10 +- coreutils/uniq.c | 5 +- coreutils/uuencode.c | 4 +- cp.c | 114 - cpio.c | 95 - cut.c | 356 - date.c | 247 - dc.c | 182 - dd.c | 154 - deallocvt.c | 43 - debian/Config.h-deb | 498 +- debian/Config.h-static | 498 +- debian/Config.h-udeb | 498 +- debian/rules | 14 +- deluser.c | 175 - df.c | 158 - dirname.c | 40 - dmesg.c | 95 - docs/autodocifier.pl | 4 +- docs/busybox.net/index.html | 3 +- docs/busybox.net/oldnews.html | 23 +- docs/new-applet-HOWTO.txt | 4 +- docs/style-guide.txt | 10 +- dos2unix.c | 194 - dpkg.c | 1509 -- dpkg_deb.c | 130 - du.c | 257 - dumpkmap.c | 95 - dutmp.c | 64 - echo.c | 152 - editors/Makefile | 36 + editors/config.in | 12 + editors/sed.c | 8 +- editors/vi.c | 450 +- env.c | 106 - examples/inittab | 4 +- examples/kernel-patches/devps.patch.9_25_2000 | 12 +- examples/mk2knr.pl | 2 +- expr.c | 535 - fbset.c | 424 - fdflush.c | 47 - find.c | 200 - findutils/Makefile | 39 + findutils/config.in | 14 + findutils/find.c | 24 +- findutils/grep.c | 36 +- findutils/which.c | 4 +- findutils/xargs.c | 8 +- free.c | 69 - freeramdisk.c | 64 - fsck_minix.c | 1478 -- getopt.c | 402 - getty.c | 1232 -- grep.c | 358 - gunzip.c | 183 - gzip.c | 2568 ---- halt.c | 41 - head.c | 97 - hostid.c | 32 - hostname.c | 128 - hush.c | 2695 ---- id.c | 97 - ifconfig.c | 492 - include/applets.h | 302 +- include/busybox.h | 28 +- include/grp.h | 6 +- include/libbb.h | 14 +- include/pwd.h | 6 +- include/usage.h | 54 +- init.c | 1045 -- init/Makefile | 39 + init/config.in | 25 + init/halt.c | 2 +- init/init.c | 32 +- init/poweroff.c | 2 +- init/reboot.c | 2 +- insmod.c | 3485 ----- install.sh | 52 - kill.c | 142 - klogd.c | 153 - lash.c | 1640 -- length.c | 13 - libbb/Makefile | 78 +- libbb/ask_confirmation.c | 16 +- libbb/chomp.c | 16 +- libbb/concat_path_file.c | 25 +- libbb/copy_file.c | 1 - libbb/copy_file_chunk.c | 16 +- libbb/copyfd.c | 2 +- libbb/device_open.c | 8 +- libbb/error_msg.c | 8 +- libbb/error_msg_and_die.c | 8 +- libbb/fgets_str.c | 28 +- libbb/find_mount_point.c | 8 +- libbb/find_pid_by_name.c | 14 +- libbb/find_root_device.c | 6 +- libbb/full_read.c | 8 +- libbb/full_write.c | 8 +- libbb/get_console.c | 9 +- libbb/get_last_path_component.c | 8 +- libbb/get_line_from_file.c | 9 +- libbb/gz_open.c | 23 + libbb/herror_msg.c | 8 +- libbb/herror_msg_and_die.c | 9 +- libbb/inode_hash.c | 16 +- libbb/interface.c | 25 +- libbb/isdirectory.c | 9 +- libbb/kernel_version.c | 8 +- libbb/libbb.h | 326 - libbb/loop.c | 8 +- libbb/messages.c | 5 +- libbb/mode_string.c | 16 +- libbb/module_syscalls.c | 4 +- libbb/mtab.c | 20 + libbb/mtab_file.c | 12 +- libbb/my_getgrgid.c | 12 +- libbb/my_getgrnam.c | 13 +- libbb/my_getpwnam.c | 13 +- libbb/my_getpwnamegid.c | 12 +- libbb/my_getpwuid.c | 12 +- libbb/parse_mode.c | 16 +- libbb/parse_number.c | 16 +- libbb/perror_msg.c | 8 +- libbb/perror_msg_and_die.c | 8 +- libbb/print_file.c | 2 +- libbb/read_package_field.c | 23 + libbb/recursive_action.c | 8 +- libbb/remove_file.c | 3 - libbb/safe_read.c | 8 +- libbb/safe_strncpy.c | 8 +- libbb/syscalls.c | 4 +- libbb/syslog_msg_with_name.c | 8 +- libbb/time_string.c | 8 +- libbb/trim.c | 16 +- libbb/u_signal_names.c | 23 + libbb/vdprintf.c | 8 +- libbb/verror_msg.c | 8 +- libbb/vherror_msg.c | 8 +- libbb/vperror_msg.c | 8 +- libbb/wfopen.c | 8 +- libbb/xfuncs.c | 8 +- libbb/xgethostbyname.c | 1 - libbb/xregcomp.c | 16 +- ln.c | 131 - loadacm.c | 357 - loadfont.c | 209 - loadkmap.c | 89 - logger.c | 200 - logname.c | 41 - logread.c | 144 - ls.c | 937 -- lsmod.c | 166 - makedevs.c | 95 - md5sum.c | 1074 -- miscutils/Makefile | 44 + miscutils/config.in | 20 + miscutils/readlink.c | 6 +- mk_loop_h.sh | 37 - mkdir.c | 64 - mkfifo.c | 60 - mkfs_minix.c | 847 - mknod.c | 92 - mkswap.c | 422 - mktemp.c | 40 - modprobe.c | 121 - modutils/Makefile | 39 + modutils/config.in | 22 + modutils/insmod.c | 131 +- modutils/lsmod.c | 10 +- modutils/rmmod.c | 4 +- more.c | 217 - mount.c | 498 - msh.c | 4870 ------ mt.c | 121 - mv.c | 168 - nc.c | 137 - networking/Makefile | 45 + networking/config.in | 21 + networking/hostname.c | 4 +- networking/ifconfig.c | 30 +- networking/nslookup.c | 6 +- networking/ping.c | 8 +- networking/telnet.c | 12 +- networking/tftp.c | 38 +- networking/traceroute.c | 26 +- networking/wget.c | 24 +- nfsmount.c | 977 -- nfsmount.h | 242 - nslookup.c | 183 - pidof.c | 79 - ping.c | 555 - pivot_root.c | 35 - poweroff.c | 41 - printf.c | 455 - pristine_setup.sh | 46 - procps/Makefile | 40 + procps/config.in | 17 + procps/free.c | 4 +- procps/kill.c | 4 +- procps/pidof.c | 4 +- procps/ps.c | 32 +- procps/uptime.c | 6 +- ps.c | 266 - pwd.c | 44 - rdate.c | 116 - readlink.c | 48 - reboot.c | 49 - renice.c | 54 - reset.c | 35 - rm.c | 77 - rmdir.c | 97 - rmmod.c | 62 - route.c | 452 - rpm2cpio.c | 91 - scripts/Configure | 705 + scripts/Menuconfig | 1285 ++ scripts/depmod.pl | 227 - scripts/inittab | 86 - scripts/lxdialog/BIG.FAT.WARNING | 4 + scripts/lxdialog/Makefile | 46 + scripts/lxdialog/Makefile-2.5 | 71 + scripts/lxdialog/checklist.c | 369 + scripts/lxdialog/colors.h | 161 + scripts/lxdialog/dialog.h | 184 + scripts/lxdialog/inputbox.c | 240 + scripts/lxdialog/lxdialog.c | 226 + scripts/lxdialog/menubox.c | 443 + scripts/lxdialog/msgbox.c | 85 + scripts/lxdialog/textbox.c | 556 + scripts/lxdialog/util.c | 359 + scripts/lxdialog/yesno.c | 118 + scripts/mk2knr.pl | 84 - scripts/mkdep.c | 628 + scripts/split-include.c | 226 + scripts/undeb | 53 - scripts/unrpm | 48 - sed.c | 850 - setkeycodes.c | 72 - shell/Makefile | 40 + shell/ash.c | 34 +- shell/cmdedit.c | 94 +- shell/config.in | 51 + shell/hush.c | 21 +- shell/lash.c | 38 +- shell/msh.c | 26 +- sleep.c | 38 - sort.c | 106 - start_stop_daemon.c | 271 - stty.c | 1376 -- swaponoff.c | 115 - sync.c | 35 - sysdeps/linux/config.in | 23 + sysdeps/linux/defconfig | 0 sysklogd/Makefile | 38 + sysklogd/config.in | 16 + sysklogd/klogd.c | 4 +- sysklogd/logger.c | 6 +- sysklogd/logread.c | 2 +- sysklogd/syslogd.c | 30 +- syslogd.c | 641 - tail.c | 251 - tar.c | 745 - tee.c | 67 - telnet.c | 711 - test.c | 579 - tests/multibuild.pl | 8 +- tests/multifeat.pl | 8 +- tests/testcases | 2 +- tests/tester.sh | 14 +- tftp.c | 574 - touch.c | 75 - tr.c | 248 - traceroute.c | 652 - true_false.c | 39 - tty.c | 44 - umount.c | 298 - uname.c | 156 - uniq.c | 89 - update.c | 112 - uptime.c | 77 - usage.c | 10 - usage.h | 1894 --- usleep.c | 38 - util-linux/Makefile | 48 + util-linux/config.in | 27 + util-linux/fbset.c | 12 +- util-linux/fsck_minix.c | 42 +- util-linux/mkfs_minix.c | 20 +- util-linux/more.c | 12 +- util-linux/mount.c | 26 +- util-linux/swaponoff.c | 5 +- util-linux/umount.c | 29 +- uudecode.c | 353 - uuencode.c | 180 - vi.c | 3947 ----- watchdog.c | 49 - wc.c | 156 - wget.c | 834 - which.c | 80 - whoami.c | 44 - xargs.c | 105 - yes.c | 53 - 362 files changed, 8837 insertions(+), 75874 deletions(-) delete mode 100644 Config.h delete mode 100644 addgroup.c delete mode 100644 adduser.c delete mode 100644 adjtimex.c delete mode 100644 applets.c delete mode 100644 applets.h delete mode 100644 ar.c create mode 100644 archival/Makefile create mode 100644 archival/config.in delete mode 100644 ash.c delete mode 100644 basename.c delete mode 100644 bunzip2.c delete mode 100644 busybox.c delete mode 100644 busybox.h delete mode 100755 busybox.mkll delete mode 100755 busybox.sh delete mode 100644 busybox.spec delete mode 100644 cat.c delete mode 100644 chgrp.c delete mode 100644 chmod.c delete mode 100644 chown.c delete mode 100644 chroot.c delete mode 100644 chvt.c delete mode 100644 clear.c delete mode 100644 cmdedit.c delete mode 100644 cmdedit.h delete mode 100644 cmp.c create mode 100644 console-tools/Makefile create mode 100644 console-tools/config.in delete mode 100644 cp.c delete mode 100644 cpio.c delete mode 100644 cut.c delete mode 100644 date.c delete mode 100644 dc.c delete mode 100644 dd.c delete mode 100644 deallocvt.c delete mode 100644 deluser.c delete mode 100644 df.c delete mode 100644 dirname.c delete mode 100644 dmesg.c delete mode 100644 dos2unix.c delete mode 100644 dpkg.c delete mode 100644 dpkg_deb.c delete mode 100644 du.c delete mode 100644 dumpkmap.c delete mode 100644 dutmp.c delete mode 100644 echo.c create mode 100644 editors/Makefile create mode 100644 editors/config.in delete mode 100644 env.c delete mode 100644 expr.c delete mode 100644 fbset.c delete mode 100644 fdflush.c delete mode 100644 find.c create mode 100644 findutils/Makefile create mode 100644 findutils/config.in delete mode 100644 free.c delete mode 100644 freeramdisk.c delete mode 100644 fsck_minix.c delete mode 100644 getopt.c delete mode 100644 getty.c delete mode 100644 grep.c delete mode 100644 gunzip.c delete mode 100644 gzip.c delete mode 100644 halt.c delete mode 100644 head.c delete mode 100644 hostid.c delete mode 100644 hostname.c delete mode 100644 hush.c delete mode 100644 id.c delete mode 100644 ifconfig.c delete mode 100644 init.c create mode 100644 init/Makefile create mode 100644 init/config.in delete mode 100644 insmod.c delete mode 100755 install.sh delete mode 100644 kill.c delete mode 100644 klogd.c delete mode 100644 lash.c delete mode 100644 length.c delete mode 100644 libbb/libbb.h delete mode 100644 ln.c delete mode 100644 loadacm.c delete mode 100644 loadfont.c delete mode 100644 loadkmap.c delete mode 100644 logger.c delete mode 100644 logname.c delete mode 100644 logread.c delete mode 100644 ls.c delete mode 100644 lsmod.c delete mode 100644 makedevs.c delete mode 100644 md5sum.c create mode 100644 miscutils/Makefile create mode 100644 miscutils/config.in delete mode 100755 mk_loop_h.sh delete mode 100644 mkdir.c delete mode 100644 mkfifo.c delete mode 100644 mkfs_minix.c delete mode 100644 mknod.c delete mode 100644 mkswap.c delete mode 100644 mktemp.c delete mode 100644 modprobe.c create mode 100644 modutils/Makefile create mode 100644 modutils/config.in delete mode 100644 more.c delete mode 100644 mount.c delete mode 100644 msh.c delete mode 100644 mt.c delete mode 100644 mv.c delete mode 100644 nc.c create mode 100644 networking/Makefile create mode 100644 networking/config.in delete mode 100644 nfsmount.c delete mode 100644 nfsmount.h delete mode 100644 nslookup.c delete mode 100644 pidof.c delete mode 100644 ping.c delete mode 100644 pivot_root.c delete mode 100644 poweroff.c delete mode 100644 printf.c delete mode 100755 pristine_setup.sh create mode 100644 procps/Makefile create mode 100644 procps/config.in delete mode 100644 ps.c delete mode 100644 pwd.c delete mode 100644 rdate.c delete mode 100644 readlink.c delete mode 100644 reboot.c delete mode 100644 renice.c delete mode 100644 reset.c delete mode 100644 rm.c delete mode 100644 rmdir.c delete mode 100644 rmmod.c delete mode 100644 route.c delete mode 100644 rpm2cpio.c create mode 100644 scripts/Configure create mode 100644 scripts/Menuconfig delete mode 100755 scripts/depmod.pl delete mode 100644 scripts/inittab create mode 100644 scripts/lxdialog/BIG.FAT.WARNING create mode 100644 scripts/lxdialog/Makefile create mode 100644 scripts/lxdialog/Makefile-2.5 create mode 100644 scripts/lxdialog/checklist.c create mode 100644 scripts/lxdialog/colors.h create mode 100644 scripts/lxdialog/dialog.h create mode 100644 scripts/lxdialog/inputbox.c create mode 100644 scripts/lxdialog/lxdialog.c create mode 100644 scripts/lxdialog/menubox.c create mode 100644 scripts/lxdialog/msgbox.c create mode 100644 scripts/lxdialog/textbox.c create mode 100644 scripts/lxdialog/util.c create mode 100644 scripts/lxdialog/yesno.c delete mode 100755 scripts/mk2knr.pl create mode 100644 scripts/mkdep.c create mode 100644 scripts/split-include.c delete mode 100644 scripts/undeb delete mode 100644 scripts/unrpm delete mode 100644 sed.c delete mode 100644 setkeycodes.c create mode 100644 shell/Makefile create mode 100644 shell/config.in delete mode 100644 sleep.c delete mode 100644 sort.c delete mode 100644 start_stop_daemon.c delete mode 100644 stty.c delete mode 100644 swaponoff.c delete mode 100644 sync.c create mode 100644 sysdeps/linux/config.in create mode 100644 sysdeps/linux/defconfig create mode 100644 sysklogd/Makefile create mode 100644 sysklogd/config.in delete mode 100644 syslogd.c delete mode 100644 tail.c delete mode 100644 tar.c delete mode 100644 tee.c delete mode 100644 telnet.c delete mode 100644 test.c delete mode 100644 tftp.c delete mode 100644 touch.c delete mode 100644 tr.c delete mode 100644 traceroute.c delete mode 100644 true_false.c delete mode 100644 tty.c delete mode 100644 umount.c delete mode 100644 uname.c delete mode 100644 uniq.c delete mode 100644 update.c delete mode 100644 uptime.c delete mode 100644 usage.c delete mode 100644 usage.h delete mode 100644 usleep.c create mode 100644 util-linux/Makefile create mode 100644 util-linux/config.in delete mode 100644 uudecode.c delete mode 100644 uuencode.c delete mode 100644 vi.c delete mode 100644 watchdog.c delete mode 100644 wc.c delete mode 100644 wget.c delete mode 100644 which.c delete mode 100644 whoami.c delete mode 100644 xargs.c delete mode 100644 yes.c 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; -}