From f49df5de66d4ac16eec6eca19e68f06018348a34 Mon Sep 17 00:00:00 2001
From: Keith Moyer
Date: Sat, 23 May 2009 16:40:45 -0500
Subject: [PATCH] Tomato 1.24
---
release/src/Makefile | 40 +-
release/src/linux/linux/.config | 6 +-
.../src/linux/linux/Documentation/Configure.help | 34 +
.../arch/mips/brcm-boards/bcm947xx/prom-orig.c | 41 +
.../linux/arch/mips/brcm-boards/bcm947xx/prom.c | 43 +-
release/src/linux/linux/arch/mips/kernel/branch.c | 2 +-
.../src/linux/linux/arch/mips/math-emu/cp1emu.c | 5 +-
.../src/linux/linux/drivers/mtd/chips/gen_probe.c | 1 +
.../linux/include/linux/netfilter_ipv4/ipt_ROUTE.h | 23 +
.../linux/include/linux/netfilter_ipv4/ipt_ipp2p.h | 31 +
.../include/linux/netfilter_ipv6/ip6t_ROUTE.h | 23 +
release/src/linux/linux/net/ipv4/arp.c | 24 +-
release/src/linux/linux/net/ipv4/igmp.c | 5 +-
.../src/linux/linux/net/ipv4/netfilter/Config.in | 4 +-
.../src/linux/linux/net/ipv4/netfilter/Makefile | 2 +
.../src/linux/linux/net/ipv4/netfilter/ipt_ROUTE.c | 422 +
.../linux/linux/net/ipv4/netfilter/ipt_connlimit.c | 1 +
.../src/linux/linux/net/ipv4/netfilter/ipt_ipp2p.c | 868 ++
release/src/linux/linux/net/ipv4/route.c | 10 -
release/src/linux/linux/net/ipv4/sysctl_net_ipv4.c | 12 -
release/src/linux/linux/net/ipv4/tcp_input.c | 311 +-
release/src/linux/linux/net/ipv4/tcp_minisocks.c | 3 +-
release/src/linux/linux/net/ipv4/tcp_output.c | 20 +-
.../src/linux/linux/net/ipv6/netfilter/Config.in | 2 +
.../src/linux/linux/net/ipv6/netfilter/Makefile | 1 +
.../linux/linux/net/ipv6/netfilter/ip6t_ROUTE.c | 308 +
release/src/router/Makefile | 73 +-
release/src/router/busybox/.config | 883 +++
release/src/router/busybox/AUTHORS | 2 +-
release/src/router/busybox/Config.in | 52 +-
release/src/router/busybox/Makefile | 14 +-
release/src/router/busybox/Makefile.custom | 6 +
release/src/router/busybox/Makefile.flags | 12 +-
release/src/router/busybox/Makefile.help | 1 +
release/src/router/busybox/README | 2 +-
release/src/router/busybox/TODO | 23 +-
release/src/router/busybox/TODO_config_nommu | 167 +-
release/src/router/busybox/applets/usage.c | 5 +
.../src/router/busybox/applets/usage_compressed | 2 +-
release/src/router/busybox/archival/Config.in | 12 +-
release/src/router/busybox/archival/bbunzip.c | 32 +-
release/src/router/busybox/archival/bzip2.c | 3 +-
release/src/router/busybox/archival/cpio.c | 251 +-
release/src/router/busybox/archival/dpkg.c | 135 +-
release/src/router/busybox/archival/gzip.c | 3 +-
.../archival/libunarchive/data_extract_all.c | 4 +-
.../archival/libunarchive/decompress_unzip.c | 31 +-
.../archival/libunarchive/get_header_cpio.c | 3 +-
.../busybox/archival/libunarchive/get_header_tar.c | 77 +-
.../archival/libunarchive/header_verbose_list.c | 4 +-
release/src/router/busybox/archival/rpm.c | 30 +-
release/src/router/busybox/archival/tar.c | 9 +-
release/src/router/busybox/archival/unzip.c | 243 +-
release/src/router/busybox/config_g | 853 --
release/src/router/busybox/console-tools/Config.in | 15 +
.../src/router/busybox/console-tools/kbd_mode.c | 21 +-
.../src/router/busybox/console-tools/loadfont.c | 196 +-
.../src/router/busybox/console-tools/loadkmap.c | 10 +-
release/src/router/busybox/console-tools/resize.c | 2 +-
.../src/router/busybox/console-tools/setconsole.c | 2 +-
release/src/router/busybox/console-tools/showkey.c | 6 +-
release/src/router/busybox/coreutils/Config.in | 24 +-
release/src/router/busybox/coreutils/Kbuild | 3 +
release/src/router/busybox/coreutils/basename.c | 1 +
release/src/router/busybox/coreutils/cksum.c | 25 +-
release/src/router/busybox/coreutils/cp.c | 50 +-
release/src/router/busybox/coreutils/cut.c | 2 +-
release/src/router/busybox/coreutils/date.c | 2 +-
release/src/router/busybox/coreutils/dd.c | 1 -
release/src/router/busybox/coreutils/df.c | 98 +-
release/src/router/busybox/coreutils/du.c | 82 +-
release/src/router/busybox/coreutils/env.c | 18 +-
release/src/router/busybox/coreutils/expand.c | 120 +-
release/src/router/busybox/coreutils/expr.c | 23 +-
release/src/router/busybox/coreutils/head.c | 8 +-
release/src/router/busybox/coreutils/id.c | 340 +-
release/src/router/busybox/coreutils/id_test.sh | 244 +
release/src/router/busybox/coreutils/install.c | 61 +-
release/src/router/busybox/coreutils/length.c | 3 +
.../busybox/coreutils/libcoreutils/coreutils.h | 10 +-
release/src/router/busybox/coreutils/ls.c | 490 +-
.../src/router/busybox/coreutils/md5_sha1_sum.c | 35 +-
release/src/router/busybox/coreutils/nohup.c | 2 +-
release/src/router/busybox/coreutils/printenv.c | 6 +-
release/src/router/busybox/coreutils/printf.c | 133 +-
release/src/router/busybox/coreutils/rm.c | 5 +-
release/src/router/busybox/coreutils/seq.c | 23 +-
release/src/router/busybox/coreutils/split.c | 2 +-
release/src/router/busybox/coreutils/stat.c | 27 +-
release/src/router/busybox/coreutils/tail.c | 2 +-
release/src/router/busybox/coreutils/tee.c | 1 -
release/src/router/busybox/coreutils/test.c | 2 +-
release/src/router/busybox/coreutils/touch.c | 20 +-
release/src/router/busybox/coreutils/tr.c | 297 +-
release/src/router/busybox/coreutils/tty.c | 2 +-
release/src/router/busybox/coreutils/uname.c | 123 +-
release/src/router/busybox/coreutils/uniq.c | 2 +-
release/src/router/busybox/coreutils/who.c | 1 -
release/src/router/busybox/coreutils/whoami.c | 2 +-
release/src/router/busybox/debianutils/Config.in | 1 +
release/src/router/busybox/debianutils/run_parts.c | 2 +-
.../router/busybox/debianutils/start_stop_daemon.c | 8 +-
.../busybox/docs/Serial-Programming-HOWTO.txt | 424 +
release/src/router/busybox/docs/autodocifier.pl | 4 +
.../src/router/busybox/docs/busybox.net/FAQ.html | 89 +-
.../src/router/busybox/docs/busybox.net/about.html | 2 +-
.../router/busybox/docs/busybox.net/download.html | 34 +-
.../src/router/busybox/docs/busybox.net/fix.html | 2 +-
.../router/busybox/docs/busybox.net/footer.html | 20 +-
.../router/busybox/docs/busybox.net/header.html | 45 +-
.../router/busybox/docs/busybox.net/license.html | 30 +-
.../src/router/busybox/docs/busybox.net/links.html | 4 +-
.../src/router/busybox/docs/busybox.net/lists.html | 4 +-
.../src/router/busybox/docs/busybox.net/news.html | 820 +-
.../router/busybox/docs/busybox.net/oldnews.html | 449 +-
.../router/busybox/docs/busybox.net/products.html | 335 +-
.../router/busybox/docs/busybox.net/sponsors.html | 18 +-
.../busybox/docs/busybox.net/subversion.html | 6 +-
.../router/busybox/docs/busybox.net/svnindex.css | 92 +
.../router/busybox/docs/busybox.net/svnindex.xsl | 108 +
.../router/busybox/docs/busybox.net/tinyutils.html | 22 +-
release/src/router/busybox/docs/busybox_header.pod | 11 +-
.../busybox/docs/logging_and_backgrounding.txt | 96 +
release/src/router/busybox/docs/mdev.txt | 6 +-
release/src/router/busybox/e2fsprogs/e2fs_defs.h | 6 +-
release/src/router/busybox/e2fsprogs/e2fs_lib.c | 3 +-
release/src/router/busybox/e2fsprogs/e2fs_lib.h | 8 +-
release/src/router/busybox/e2fsprogs/fsck.c | 9 +-
.../busybox/e2fsprogs/old_e2fsprogs/blkid/blkid.h | 7 +-
.../busybox/e2fsprogs/old_e2fsprogs/blkid/blkidP.h | 7 +-
.../e2fsprogs/old_e2fsprogs/blkid/devname.c | 4 +-
.../busybox/e2fsprogs/old_e2fsprogs/blkid/list.h | 4 +-
.../busybox/e2fsprogs/old_e2fsprogs/blkid/probe.c | 4 +-
.../busybox/e2fsprogs/old_e2fsprogs/blkid/probe.h | 17 +-
.../busybox/e2fsprogs/old_e2fsprogs/e2fsbb.h | 6 +-
.../busybox/e2fsprogs/old_e2fsprogs/e2fsck.c | 56 +-
.../e2fsprogs/old_e2fsprogs/ext2fs/bb_inode.c | 4 +-
.../e2fsprogs/old_e2fsprogs/ext2fs/dirhash.c | 2 +-
.../e2fsprogs/old_e2fsprogs/ext2fs/ext2_fs.h | 7 +-
.../e2fsprogs/old_e2fsprogs/ext2fs/ext2_io.h | 8 +-
.../e2fsprogs/old_e2fsprogs/ext2fs/ext2fs.h | 7 +-
.../e2fsprogs/old_e2fsprogs/ext2fs/kernel-jbd.h | 7 +-
.../e2fsprogs/old_e2fsprogs/ext2fs/kernel-list.h | 4 +-
.../e2fsprogs/old_e2fsprogs/ext2fs/mkjournal.c | 2 +-
.../e2fsprogs/old_e2fsprogs/ext2fs/res_gdt.c | 6 +-
.../router/busybox/e2fsprogs/old_e2fsprogs/fsck.c | 35 +-
.../busybox/e2fsprogs/old_e2fsprogs/mke2fs.c | 7 +-
.../busybox/e2fsprogs/old_e2fsprogs/tune2fs.c | 5 +-
.../router/busybox/e2fsprogs/old_e2fsprogs/util.c | 21 +-
.../e2fsprogs/old_e2fsprogs/uuid/gen_uuid.c | 2 +-
.../busybox/e2fsprogs/old_e2fsprogs/uuid/uuid.h | 5 +-
release/src/router/busybox/editors/Config.in | 4 +-
release/src/router/busybox/editors/awk.c | 117 +-
release/src/router/busybox/editors/diff.c | 18 +-
release/src/router/busybox/editors/vi.c | 500 +-
release/src/router/busybox/examples/depmod-t.pl | 293 +
release/src/router/busybox/findutils/Config.in | 2 +-
release/src/router/busybox/findutils/find.c | 22 +-
release/src/router/busybox/findutils/grep.c | 21 +-
release/src/router/busybox/include/applets.h | 23 +-
release/src/router/busybox/include/busybox.h | 14 +-
release/src/router/busybox/include/dump.h | 8 +-
release/src/router/busybox/include/grp_.h | 43 +-
release/src/router/busybox/include/libbb.h | 225 +-
release/src/router/busybox/include/platform.h | 77 +-
release/src/router/busybox/include/pwd_.h | 41 +-
release/src/router/busybox/include/rtc_.h | 49 +-
release/src/router/busybox/include/shadow_.h | 45 +-
release/src/router/busybox/include/unarchive.h | 23 +-
release/src/router/busybox/include/usage.h | 733 +-
release/src/router/busybox/include/volume_id.h | 1 +
release/src/router/busybox/include/xatonum.h | 8 +-
release/src/router/busybox/include/xregex.h | 12 +-
release/src/router/busybox/init/Config.in | 15 +-
release/src/router/busybox/init/halt.c | 79 +-
release/src/router/busybox/init/init.c | 926 ++-
release/src/router/busybox/init/mesg.c | 2 +-
release/src/router/busybox/libbb/Kbuild | 13 +-
release/src/router/busybox/libbb/appletlib.c | 6 +-
release/src/router/busybox/libbb/bb_askpass.c | 18 +-
release/src/router/busybox/libbb/bb_pwd.c | 211 +-
release/src/router/busybox/libbb/bb_strtod.c | 3 +-
.../src/router/busybox/libbb/correct_password.c | 2 +-
release/src/router/busybox/libbb/crc32.c | 2 +
.../src/router/busybox/libbb/create_icmp6_socket.c | 2 +
.../src/router/busybox/libbb/create_icmp_socket.c | 2 +
release/src/router/busybox/libbb/crypt_make_salt.c | 45 -
.../src/router/busybox/libbb/die_if_bad_username.c | 2 +-
release/src/router/busybox/libbb/dump.c | 17 +-
release/src/router/busybox/libbb/fgets_str.c | 26 +-
.../src/router/busybox/libbb/find_pid_by_name.c | 15 +-
release/src/router/busybox/libbb/get_console.c | 2 -
release/src/router/busybox/libbb/getopt32.c | 14 +-
release/src/router/busybox/libbb/human_readable.c | 35 +-
release/src/router/busybox/libbb/inet_common.c | 5 +-
release/src/router/busybox/libbb/info_msg.c | 26 +
release/src/router/busybox/libbb/inode_hash.c | 2 +-
release/src/router/busybox/libbb/lineedit.c | 154 +-
release/src/router/busybox/libbb/llist.c | 68 +-
release/src/router/busybox/libbb/make_directory.c | 2 +-
release/src/router/busybox/libbb/match_fstype.c | 36 +-
release/src/router/busybox/libbb/md5.c | 875 +--
release/src/router/busybox/libbb/md5prime.c | 460 ++
release/src/router/busybox/libbb/parse_config.c | 3 +-
.../router/busybox/libbb/process_escape_sequence.c | 17 +-
release/src/router/busybox/libbb/procps.c | 45 +-
release/src/router/busybox/libbb/pw_encrypt.c | 93 +-
release/src/router/busybox/libbb/pw_encrypt_des.c | 70 +-
release/src/router/busybox/libbb/pw_encrypt_md5.c | 809 +-
release/src/router/busybox/libbb/pw_encrypt_sha.c | 286 +
release/src/router/busybox/libbb/read.c | 6 +-
release/src/router/busybox/libbb/read_key.c | 157 +
release/src/router/busybox/libbb/rtc.c | 2 +
release/src/router/busybox/libbb/selinux_common.c | 2 +
release/src/router/busybox/libbb/sha1.c | 635 +-
release/src/router/busybox/libbb/signals.c | 10 +-
release/src/router/busybox/libbb/speed_table.c | 1 -
release/src/router/busybox/libbb/strrstr.c | 2 +-
release/src/router/busybox/libbb/update_passwd.c | 167 +-
.../src/router/busybox/libbb/vfork_daemon_rexec.c | 27 +-
release/src/router/busybox/libbb/wfopen.c | 2 +-
release/src/router/busybox/libbb/write.c | 7 +-
.../src/router/busybox/libbb/xatonum_template.c | 4 +
release/src/router/busybox/libbb/xconnect.c | 45 +-
release/src/router/busybox/libbb/xfuncs.c | 24 +
release/src/router/busybox/libbb/xfuncs_printf.c | 29 +-
release/src/router/busybox/libbb/xgetcwd.c | 4 +-
release/src/router/busybox/libbb/xreadlink.c | 12 +-
release/src/router/busybox/libpwdgrp/pwd_grp.c | 68 +-
release/src/router/busybox/libpwdgrp/uidgid_get.c | 5 +-
release/src/router/busybox/loginutils/Config.in | 29 +-
release/src/router/busybox/loginutils/addgroup.c | 78 +-
release/src/router/busybox/loginutils/adduser.c | 52 +-
release/src/router/busybox/loginutils/chpasswd.c | 5 +-
release/src/router/busybox/loginutils/cryptpw.c | 175 +-
release/src/router/busybox/loginutils/deluser.c | 181 +-
release/src/router/busybox/loginutils/getty.c | 45 +-
release/src/router/busybox/loginutils/login.c | 227 +-
release/src/router/busybox/loginutils/passwd.c | 23 +-
release/src/router/busybox/loginutils/su.c | 6 +-
release/src/router/busybox/loginutils/sulogin.c | 9 +-
release/src/router/busybox/loginutils/vlock.c | 11 +-
release/src/router/busybox/mailutils/Config.in | 53 +
release/src/router/busybox/mailutils/Kbuild | 11 +
release/src/router/busybox/mailutils/mail.c | 248 +
release/src/router/busybox/mailutils/mail.h | 35 +
release/src/router/busybox/mailutils/mime.c | 354 +
release/src/router/busybox/mailutils/popmaildir.c | 235 +
release/src/router/busybox/mailutils/sendmail.c | 259 +
release/src/router/busybox/miscutils/Config.in | 91 +-
release/src/router/busybox/miscutils/Kbuild | 4 +
release/src/router/busybox/miscutils/chat.c | 97 +-
release/src/router/busybox/miscutils/chrt.c | 2 +-
release/src/router/busybox/miscutils/crond.c | 48 +-
release/src/router/busybox/miscutils/crontab.c | 20 +-
release/src/router/busybox/miscutils/dc.c | 46 +-
release/src/router/busybox/miscutils/devmem.c | 128 +
release/src/router/busybox/miscutils/fbsplash.c | 62 +-
.../src/router/busybox/miscutils/flash_eraseall.c | 194 +
release/src/router/busybox/miscutils/hdparm.c | 16 +-
release/src/router/busybox/miscutils/inotifyd.c | 132 +-
release/src/router/busybox/miscutils/ionice.c | 99 +
release/src/router/busybox/miscutils/less.c | 681 +-
release/src/router/busybox/miscutils/man.c | 107 +-
release/src/router/busybox/miscutils/microcom.c | 20 +-
release/src/router/busybox/miscutils/mountpoint.c | 138 +-
release/src/router/busybox/miscutils/raidautorun.c | 2 +-
release/src/router/busybox/miscutils/runlevel.c | 2 +-
release/src/router/busybox/miscutils/setsid.c | 3 +-
release/src/router/busybox/miscutils/strings.c | 9 +-
release/src/router/busybox/miscutils/taskset.c | 2 +-
release/src/router/busybox/miscutils/time.c | 4 +-
release/src/router/busybox/miscutils/timeout.c | 115 +
release/src/router/busybox/miscutils/watchdog.c | 72 +-
release/src/router/busybox/modutils/Config.in | 215 +-
release/src/router/busybox/modutils/Kbuild | 27 +-
release/src/router/busybox/modutils/depmod.c | 520 +-
release/src/router/busybox/modutils/insmod.c | 4328 +---------
release/src/router/busybox/modutils/lsmod.c | 273 +-
.../src/router/busybox/modutils/modprobe-small.c | 49 +-
release/src/router/busybox/modutils/modprobe.c | 1350 +---
release/src/router/busybox/modutils/modutils-24.c | 3905 +++++++++
release/src/router/busybox/modutils/modutils.c | 129 +
release/src/router/busybox/modutils/modutils.h | 64 +
release/src/router/busybox/modutils/rmmod.c | 153 +-
release/src/router/busybox/networking/Config.in | 84 +-
release/src/router/busybox/networking/Kbuild | 5 +-
release/src/router/busybox/networking/arp.c | 72 +-
release/src/router/busybox/networking/arping.c | 28 +-
release/src/router/busybox/networking/brctl.c | 20 +-
release/src/router/busybox/networking/dnsd.c | 898 ++-
release/src/router/busybox/networking/ether-wake.c | 4 +-
release/src/router/busybox/networking/ftpd.c | 1346 ++++
release/src/router/busybox/networking/httpd.c | 191 +-
release/src/router/busybox/networking/ifconfig.c | 2 +-
release/src/router/busybox/networking/ifenslave.c | 18 +-
release/src/router/busybox/networking/ifupdown.c | 32 +-
release/src/router/busybox/networking/inetd.c | 146 +-
release/src/router/busybox/networking/interface.c | 182 +-
release/src/router/busybox/networking/ip.c | 4 +-
release/src/router/busybox/networking/isrv.h | 8 +-
.../src/router/busybox/networking/isrv_identd.c | 2 +-
.../busybox/networking/libiproute/ip_common.h | 14 +-
.../busybox/networking/libiproute/ipaddress.c | 11 +-
.../router/busybox/networking/libiproute/iplink.c | 28 +-
.../router/busybox/networking/libiproute/iproute.c | 16 +-
.../router/busybox/networking/libiproute/iprule.c | 10 +-
.../busybox/networking/libiproute/iptunnel.c | 91 +-
.../busybox/networking/libiproute/libnetlink.c | 4 +-
.../busybox/networking/libiproute/libnetlink.h | 15 +-
.../router/busybox/networking/libiproute/ll_addr.c | 38 +-
.../router/busybox/networking/libiproute/ll_map.c | 4 +-
.../router/busybox/networking/libiproute/ll_map.h | 14 +-
.../busybox/networking/libiproute/ll_proto.c | 15 +-
.../busybox/networking/libiproute/rt_names.h | 15 +-
.../router/busybox/networking/libiproute/rtm_map.h | 14 +-
.../router/busybox/networking/libiproute/utils.c | 205 +-
.../router/busybox/networking/libiproute/utils.h | 38 +-
release/src/router/busybox/networking/nameif.c | 6 +-
release/src/router/busybox/networking/nc.c | 3 +-
release/src/router/busybox/networking/nslookup.c | 59 +-
release/src/router/busybox/networking/ping.c | 67 +-
release/src/router/busybox/networking/route.c | 6 +-
release/src/router/busybox/networking/sendmail.c | 675 --
release/src/router/busybox/networking/slattach.c | 2 +
release/src/router/busybox/networking/tc.c | 543 ++
release/src/router/busybox/networking/tcpudp.c | 11 +-
.../src/router/busybox/networking/tcpudp_perhost.h | 8 +-
release/src/router/busybox/networking/telnet.c | 252 +-
release/src/router/busybox/networking/telnetd.c | 159 +-
.../router/busybox/networking/telnetd.ctrlSQ.patch | 175 +
release/src/router/busybox/networking/tftp.c | 49 +-
release/src/router/busybox/networking/traceroute.c | 897 +--
release/src/router/busybox/networking/tunctl.c | 139 +
.../src/router/busybox/networking/udhcp/Config.in | 6 +-
release/src/router/busybox/networking/udhcp/Kbuild | 2 +-
.../src/router/busybox/networking/udhcp/arpping.c | 4 +-
.../router/busybox/networking/udhcp/clientpacket.c | 61 +-
.../router/busybox/networking/udhcp/clientsocket.c | 2 +-
.../src/router/busybox/networking/udhcp/common.h | 83 +-
.../src/router/busybox/networking/udhcp/dhcpc.c | 71 +-
.../src/router/busybox/networking/udhcp/dhcpc.h | 29 +-
.../src/router/busybox/networking/udhcp/dhcpd.c | 54 +-
.../src/router/busybox/networking/udhcp/dhcpd.h | 83 +-
.../router/busybox/networking/udhcp/dhcprelay.c | 135 +-
.../router/busybox/networking/udhcp/domain_codec.c | 8 +-
.../router/busybox/networking/udhcp/dumpleases.c | 67 +-
.../src/router/busybox/networking/udhcp/files.c | 158 +-
.../src/router/busybox/networking/udhcp/leases.c | 105 +-
.../src/router/busybox/networking/udhcp/options.c | 117 +-
.../src/router/busybox/networking/udhcp/options.h | 237 +-
.../src/router/busybox/networking/udhcp/packet.c | 27 +-
.../src/router/busybox/networking/udhcp/script.c | 86 +-
.../router/busybox/networking/udhcp/serverpacket.c | 91 +-
.../router/busybox/networking/udhcp/signalpipe.c | 6 +-
.../src/router/busybox/networking/udhcp/socket.c | 15 +-
.../busybox/networking/udhcp/static_leases.c | 72 +-
release/src/router/busybox/networking/vconfig.c | 13 +-
release/src/router/busybox/networking/wget.c | 115 +-
release/src/router/busybox/networking/zcip.c | 142 +-
release/src/router/busybox/printutils/Config.in | 5 +
release/src/router/busybox/printutils/lpr.c | 2 +-
release/src/router/busybox/procps/Config.in | 31 +-
release/src/router/busybox/procps/fuser.c | 5 +-
release/src/router/busybox/procps/kill.c | 67 +-
release/src/router/busybox/procps/nmeter.c | 46 +-
release/src/router/busybox/procps/pidof.c | 10 +-
release/src/router/busybox/procps/sysctl.c | 526 +-
release/src/router/busybox/procps/top.c | 378 +-
release/src/router/busybox/runit/Config.in | 17 +
release/src/router/busybox/runit/runit_lib.h | 8 +-
release/src/router/busybox/runit/runsv.c | 34 +-
release/src/router/busybox/runit/runsvdir.c | 294 +-
release/src/router/busybox/runit/sv.c | 6 +-
release/src/router/busybox/runit/svlogd.c | 16 +-
release/src/router/busybox/scripts/Makefile.lib | 8 +-
release/src/router/busybox/scripts/checkhelp.awk | 2 +-
release/src/router/busybox/scripts/defconfig | 276 +-
.../src/router/busybox/scripts/kconfig/confdata.c | 2 +
.../busybox/scripts/kconfig/lxdialog/Makefile | 2 +-
.../scripts/kconfig/lxdialog/check-lxdialog.sh | 48 +-
release/src/router/busybox/scripts/kconfig/util.c | 8 +-
release/src/router/busybox/scripts/objsizes | 2 +-
release/src/router/busybox/scripts/randomtest | 92 +
release/src/router/busybox/scripts/randomtest.loop | 10 +
release/src/router/busybox/scripts/trylink | 9 +-
release/src/router/busybox/selinux/Config.in | 2 +-
release/src/router/busybox/selinux/chcon.c | 2 +
release/src/router/busybox/selinux/getenforce.c | 1 +
release/src/router/busybox/selinux/getsebool.c | 1 +
release/src/router/busybox/selinux/load_policy.c | 2 +
release/src/router/busybox/selinux/matchpathcon.c | 1 +
release/src/router/busybox/selinux/runcon.c | 2 +
.../src/router/busybox/selinux/selinuxenabled.c | 1 +
release/src/router/busybox/selinux/sestatus.c | 7 +-
release/src/router/busybox/selinux/setenforce.c | 1 +
release/src/router/busybox/selinux/setsebool.c | 2 +
release/src/router/busybox/shell/Config.in | 81 +-
release/src/router/busybox/shell/Kbuild | 3 +-
release/src/router/busybox/shell/ash.c | 2179 +++---
release/src/router/busybox/shell/ash_doc.txt | 91 +
.../busybox/shell/ash_test/ash-misc/last_amp.right | 2 +
.../busybox/shell/ash_test/ash-misc/last_amp.tests | 8 +
.../busybox/shell/ash_test/ash-read/read_ifs.right | 7 +
.../busybox/shell/ash_test/ash-read/read_ifs.tests | 7 +
.../busybox/shell/ash_test/ash-signals/reap1.right | 1 +
.../busybox/shell/ash_test/ash-signals/reap1.tests | 14 +
.../ash-standalone/noexec_gets_no_env.right | 4 +
.../ash-standalone/noexec_gets_no_env.tests | 5 +
.../ash-standalone/nofork_trashes_getopt.right | 1 +
.../ash-standalone/nofork_trashes_getopt.tests | 6 +
release/src/router/busybox/shell/hush.c | 8280 +++++++++++++-------
release/src/router/busybox/shell/hush_leaktool.sh | 6 +-
.../busybox/shell/hush_test/hush-arith/arith.right | 138 +
.../busybox/shell/hush_test/hush-arith/arith.tests | 302 +
.../busybox/shell/hush_test/hush-arith/arith1.sub | 40 +
.../busybox/shell/hush_test/hush-arith/arith2.sub | 57 +
.../hush-bugs/and_or_and_backgrounding.right | 4 +
.../hush-bugs/and_or_and_backgrounding.tests | 31 +
.../leak_var.right => hush-leak/leak_argv1.right} | 0
.../shell/hush_test/hush-leak/leak_argv1.tests | 117 +
.../busybox/shell/hush_test/hush-misc/and-or.right | 18 +
.../busybox/shell/hush_test/hush-misc/and-or.tests | 34 +
.../shell/hush_test/hush-misc/continue2.right | 1 +
.../shell/hush_test/hush-misc/continue2.tests | 3 +
.../shell/hush_test/hush-misc/continue3.right | 2 +
.../shell/hush_test/hush-misc/continue3.tests | 3 +
.../busybox/shell/hush_test/hush-misc/exec.right | 6 +
.../busybox/shell/hush_test/hush-misc/exec.tests | 30 +
.../busybox/shell/hush_test/hush-misc/exit1.right | 1 +
.../busybox/shell/hush_test/hush-misc/exit1.tests | 4 +
.../busybox/shell/hush_test/hush-misc/export.right | 6 +
.../busybox/shell/hush_test/hush-misc/export.tests | 7 +
.../hush_test/hush-misc/for_with_bslashes.right | 8 +
.../hush_test/hush-misc/for_with_bslashes.tests | 10 +
.../busybox/shell/hush_test/hush-misc/func1.right | 6 +
.../busybox/shell/hush_test/hush-misc/func1.tests | 16 +
.../busybox/shell/hush_test/hush-misc/func2.right | 5 +
.../busybox/shell/hush_test/hush-misc/func2.tests | 9 +
.../shell/hush_test/hush-misc/heredoc1.right | 5 +
.../shell/hush_test/hush-misc/heredoc1.tests | 9 +
.../shell/hush_test/hush-misc/heredoc2.right | 9 +
.../shell/hush_test/hush-misc/heredoc2.tests | 12 +
.../shell/hush_test/hush-misc/heredoc3.right | 9 +
.../shell/hush_test/hush-misc/heredoc3.tests | 12 +
.../shell/hush_test/hush-misc/heredoc_huge.right | 3 +
.../shell/hush_test/hush-misc/heredoc_huge.tests | 9 +
.../hush_test/hush-misc/if_false_exitcode.right | 1 +
.../hush_test/hush-misc/if_false_exitcode.tests | 2 +
.../busybox/shell/hush_test/hush-misc/redir1.right | 12 +
.../busybox/shell/hush_test/hush-misc/redir1.tests | 40 +
.../busybox/shell/hush_test/hush-misc/redir2.right | 1 +
.../busybox/shell/hush_test/hush-misc/redir2.tests | 2 +
.../busybox/shell/hush_test/hush-misc/redir3.right | 14 +
.../busybox/shell/hush_test/hush-misc/redir3.tests | 9 +
.../busybox/shell/hush_test/hush-misc/redir4.right | 18 +
.../busybox/shell/hush_test/hush-misc/redir4.tests | 85 +
.../shell/hush_test/hush-misc/syntax_err.right | 2 +
.../hush_test/hush-misc/syntax_err_negate.right | 2 +-
.../busybox/shell/hush_test/hush-misc/until1.right | 3 +
.../busybox/shell/hush_test/hush-misc/until1.tests | 11 +
.../busybox/shell/hush_test/hush-misc/while2.right | 2 +
.../busybox/shell/hush_test/hush-misc/while2.tests | 2 +
.../shell/hush_test/hush-parsing/escape1.tests | 2 +
.../shell/hush_test/hush-parsing/escape3.tests | 2 +
.../shell/hush_test/hush-parsing/negate.tests | 32 +-
.../shell/hush_test/hush-parsing/starquoted2.right | 3 +
.../shell/hush_test/hush-parsing/starquoted2.tests | 5 +
.../shell/hush_test/hush-psubst/tick3.tests | 2 +
.../shell/hush_test/hush-psubst/tick_huge.right | 3 +
.../shell/hush_test/hush-psubst/tick_huge.tests | 7 +
.../busybox/shell/hush_test/hush-trap/catch.right | 4 +
.../busybox/shell/hush_test/hush-trap/catch.tests | 20 +
.../busybox/shell/hush_test/hush-trap/exit.right | 2 +
.../busybox/shell/hush_test/hush-trap/exit.tests | 3 +
.../shell/hush_test/hush-trap/save-ret.right | 2 +
.../shell/hush_test/hush-trap/save-ret.tests | 4 +
.../busybox/shell/hush_test/hush-trap/usage.right | 14 +
.../busybox/shell/hush_test/hush-trap/usage.tests | 23 +
.../hush_test/hush-vars/param_expand_alt.right | 8 +
.../hush_test/hush-vars/param_expand_alt.tests | 22 +
.../hush_test/hush-vars/param_expand_assign.right | 27 +
.../hush_test/hush-vars/param_expand_assign.tests | 38 +
.../hush_test/hush-vars/param_expand_default.right | 8 +
.../hush_test/hush-vars/param_expand_default.tests | 22 +
.../hush-vars/param_expand_indicate_error.right | 29 +
.../hush-vars/param_expand_indicate_error.tests | 40 +
.../hush_test/hush-vars/param_expand_len.right | 4 +
.../hush_test/hush-vars/param_expand_len.tests | 12 +
.../shell/hush_test/hush-vars/param_subshell.right | 7 +
.../shell/hush_test/hush-vars/param_subshell.tests | 15 +
.../busybox/shell/hush_test/hush-vars/unset.right | 19 +
.../busybox/shell/hush_test/hush-vars/unset.tests | 36 +
.../busybox/shell/hush_test/hush-vars/var3.right | 3 +
.../busybox/shell/hush_test/hush-vars/var3.tests | 4 +
.../shell/hush_test/hush-vars/var_in_pipes.right | 6 +
.../shell/hush_test/hush-vars/var_in_pipes.tests | 7 +
.../shell/hush_test/hush-vars/var_leaks.right | 1 +
.../shell/hush_test/hush-vars/var_leaks.tests | 14 +
.../shell/hush_test/hush-vars/var_posix1.right | 33 +
.../shell/hush_test/hush-vars/var_posix1.tests | 43 +
.../shell/hush_test/hush-vars/var_preserved.right | 4 +
.../shell/hush_test/hush-vars/var_preserved.tests | 16 +
.../shell/hush_test/hush-z_slow/leak_all1.right | 3 +
.../shell/hush_test/hush-z_slow/leak_all1.tests | 145 +
.../shell/hush_test/hush-z_slow/leak_all2.right | 3 +
.../shell/hush_test/hush-z_slow/leak_all2.tests | 93 +
.../hush_test/hush-z_slow/leak_heredoc1.right | 3 +
.../hush_test/hush-z_slow/leak_heredoc1.tests | 34 +
.../shell/hush_test/hush-z_slow/leak_var.right | 2 +-
.../shell/hush_test/hush-z_slow/leak_var.tests | 56 +-
.../shell/hush_test/hush-z_slow/leak_var2.right | 3 +
.../shell/hush_test/hush-z_slow/leak_var2.tests | 40 +
.../shell/hush_test/hush-z_slow/leak_var3.right | 3 +
.../shell/hush_test/hush-z_slow/leak_var3.tests | 41 +
release/src/router/busybox/shell/hush_test/run-all | 26 +-
release/src/router/busybox/shell/lash_unused.c | 5 +-
release/src/router/busybox/shell/match.c | 140 +
release/src/router/busybox/shell/match.h | 26 +
release/src/router/busybox/shell/math.c | 700 ++
release/src/router/busybox/shell/math.h | 103 +
release/src/router/busybox/shell/msh.c | 15 +-
.../msh_test/msh-execution/exitcode_EACCES.right | 2 +-
release/src/router/busybox/shell/msh_test/run-all | 4 +-
release/src/router/busybox/sysklogd/klogd.c | 83 +-
release/src/router/busybox/sysklogd/logger.c | 13 +-
release/src/router/busybox/sysklogd/syslogd.c | 93 +-
release/src/router/busybox/testsuite/awk.tests | 24 +
release/src/router/busybox/testsuite/expand.tests | 15 +
.../busybox/testsuite/makedevs.device_table.txt | 8 +-
release/src/router/busybox/testsuite/mdev.tests | 29 +-
release/src/router/busybox/testsuite/pidof.tests | 2 +-
release/src/router/busybox/testsuite/seq.tests | 7 +-
release/src/router/busybox/testsuite/sum.tests | 2 +-
release/src/router/busybox/testsuite/taskset.tests | 2 +-
release/src/router/busybox/testsuite/tr.tests | 31 +
.../src/router/busybox/testsuite/unexpand.tests | 30 +
release/src/router/busybox/util-linux/Config.in | 47 +-
release/src/router/busybox/util-linux/Kbuild | 3 +
release/src/router/busybox/util-linux/acpid.c | 167 +
release/src/router/busybox/util-linux/blkid.c | 18 +
release/src/router/busybox/util-linux/dmesg.c | 2 +-
release/src/router/busybox/util-linux/fbset.c | 281 +-
release/src/router/busybox/util-linux/fdformat.c | 7 +-
release/src/router/busybox/util-linux/fdisk.c | 2 +-
release/src/router/busybox/util-linux/fdisk_aix.c | 4 +-
release/src/router/busybox/util-linux/fdisk_osf.c | 2 +-
release/src/router/busybox/util-linux/fdisk_sgi.c | 12 +-
release/src/router/busybox/util-linux/fdisk_sun.c | 27 +-
release/src/router/busybox/util-linux/fsck_minix.c | 6 +-
release/src/router/busybox/util-linux/getopt.c | 9 +
release/src/router/busybox/util-linux/mdev.c | 344 +-
release/src/router/busybox/util-linux/mkfs_minix.c | 7 +-
release/src/router/busybox/util-linux/mkfs_vfat.c | 614 ++
release/src/router/busybox/util-linux/more.c | 4 -
release/src/router/busybox/util-linux/mount.c | 365 +-
release/src/router/busybox/util-linux/rtcwake.c | 4 +-
release/src/router/busybox/util-linux/script.c | 5 +-
release/src/router/busybox/util-linux/setarch.c | 30 +-
release/src/router/busybox/util-linux/umount.c | 6 +-
.../src/router/busybox/util-linux/volume_id/Kbuild | 1 +
.../router/busybox/util-linux/volume_id/cramfs.c | 3 +-
.../src/router/busybox/util-linux/volume_id/ext.c | 3 +-
.../src/router/busybox/util-linux/volume_id/fat.c | 139 +-
.../busybox/util-linux/volume_id/get_devname.c | 281 +-
.../src/router/busybox/util-linux/volume_id/hfs.c | 3 +-
.../router/busybox/util-linux/volume_id/iso9660.c | 3 +-
.../src/router/busybox/util-linux/volume_id/jfs.c | 3 +-
.../busybox/util-linux/volume_id/linux_raid.c | 5 +-
.../busybox/util-linux/volume_id/linux_swap.c | 3 +-
.../src/router/busybox/util-linux/volume_id/luks.c | 53 +-
.../src/router/busybox/util-linux/volume_id/ntfs.c | 3 +-
.../router/busybox/util-linux/volume_id/ocfs2.c | 3 +-
.../router/busybox/util-linux/volume_id/reiserfs.c | 3 +-
.../router/busybox/util-linux/volume_id/romfs.c | 3 +-
.../src/router/busybox/util-linux/volume_id/sysv.c | 3 +-
.../src/router/busybox/util-linux/volume_id/udf.c | 3 +-
.../src/router/busybox/util-linux/volume_id/util.c | 101 +-
.../busybox/util-linux/volume_id/volume_id.c | 49 +-
.../util-linux/volume_id/volume_id_internal.h | 100 +-
.../src/router/busybox/util-linux/volume_id/xfs.c | 3 +-
release/src/router/common.mak | 20 +-
release/src/router/config/config.in | 8 -
release/src/router/config_g | 1 -
release/src/router/dnsmasq/CHANGELOG | 92 +-
release/src/router/dnsmasq/Makefile | 6 +-
.../src/router/dnsmasq/contrib/lease-access/README | 20 +
.../contrib/lease-access/lease.access.patch | 578 ++
release/src/router/dnsmasq/dbus/dnsmasq.conf | 2 -
release/src/router/dnsmasq/dnsmasq.conf.example | 19 +-
release/src/router/dnsmasq/doc.html | 6 +-
release/src/router/dnsmasq/man/dnsmasq.8 | 64 +-
release/src/router/dnsmasq/man/fr/dnsmasq.8 | 149 +-
release/src/router/dnsmasq/po/de.po | 282 +-
release/src/router/dnsmasq/po/es.po | 284 +-
release/src/router/dnsmasq/po/fi.po | 282 +-
release/src/router/dnsmasq/po/fr.po | 472 +-
release/src/router/dnsmasq/po/id.po | 284 +-
release/src/router/dnsmasq/po/it.po | 282 +-
release/src/router/dnsmasq/po/no.po | 283 +-
release/src/router/dnsmasq/po/pl.po | 291 +-
release/src/router/dnsmasq/po/pt_BR.po | 282 +-
release/src/router/dnsmasq/po/ro.po | 283 +-
release/src/router/dnsmasq/src/bpf.c | 18 +-
release/src/router/dnsmasq/src/cache.c | 6 +-
release/src/router/dnsmasq/src/config.h | 36 +-
release/src/router/dnsmasq/src/dbus.c | 52 +-
release/src/router/dnsmasq/src/dhcp.c | 22 +-
release/src/router/dnsmasq/src/dnsmasq.c | 9 +-
release/src/router/dnsmasq/src/dnsmasq.h | 26 +-
release/src/router/dnsmasq/src/forward.c | 6 +-
release/src/router/dnsmasq/src/helper.c | 8 +-
release/src/router/dnsmasq/src/lease.c | 6 +-
release/src/router/dnsmasq/src/log.c | 6 +-
release/src/router/dnsmasq/src/netlink.c | 6 +-
release/src/router/dnsmasq/src/network.c | 63 +-
release/src/router/dnsmasq/src/option.c | 158 +-
release/src/router/dnsmasq/src/rfc1035.c | 34 +-
release/src/router/dnsmasq/src/rfc2131.c | 280 +-
release/src/router/dnsmasq/src/tftp.c | 6 +-
release/src/router/dnsmasq/src/util.c | 10 +-
release/src/router/httpd/Makefile | 9 -
release/src/router/httpd/blackhole.c | 24 +-
release/src/router/httpd/bwm.c | 14 +-
release/src/router/httpd/config.c | 32 +-
release/src/router/httpd/ctnf.c | 32 +-
release/src/router/httpd/ddns.c | 8 +-
release/src/router/httpd/devlist.c | 6 +-
release/src/router/httpd/dhcp.c | 4 +-
release/src/router/httpd/httpd.c | 294 +-
release/src/router/httpd/httpd.h | 3 +-
release/src/router/httpd/log.c | 8 +-
release/src/router/httpd/misc.c | 32 +-
release/src/router/httpd/nvram.c | 2 +-
release/src/router/httpd/parser.c | 56 +-
release/src/router/httpd/tomato.c | 139 +-
release/src/router/httpd/tomato.h | 7 +-
release/src/router/httpd/traceping.c | 4 +-
release/src/router/httpd/upgrade.c | 16 +-
release/src/router/httpd/upnp.c | 43 +-
release/src/router/httpd/version.c | 6 +-
release/src/router/httpd/webio.c | 55 +-
release/src/router/httpd/webmsg.c | 2 +-
release/src/router/httpd/wl.c | 44 +-
release/src/router/ipp2p/COPYING | 339 -
release/src/router/ipp2p/Makefile | 29 -
release/src/router/ipp2p/README | 110 -
release/src/router/ipp2p/ipt_ipp2p.c | 895 ---
release/src/router/ipp2p/ipt_ipp2p.h | 31 -
release/src/router/ipp2p/libipt_ipp2p.c | 401 -
release/src/router/iptables/Makefile | 70 +-
release/src/router/iptables/Makefile.orig | 278 -
.../src/router/iptables/extensions/.connlimit-test | 2 +
release/src/router/iptables/extensions/.ipp2p-test | 2 +
release/src/router/iptables/extensions/Makefile | 8 +-
.../src/router/iptables/extensions/libip6t_ROUTE.c | 51 +-
.../src/router/iptables/extensions/libipt_ROUTE.c | 53 +-
.../src/router/iptables/extensions/libipt_ipp2p.c | 424 +
.../router/iptables/extensions/libipt_ipp2p.man | 43 +
release/src/router/iptables/iptables-multi.c | 8 +-
release/src/router/iptables/iptables-multi.c.orig | 31 -
release/src/router/layer7/protocols/CHANGELOG | 6 +
.../src/router/layer7/protocols/extra/gtalk.pat | 11 +
.../layer7/protocols/protocols/battlefield2142.pat | 2 +-
.../router/layer7/protocols/protocols/dazhihui.pat | 11 +
.../layer7/protocols/protocols/replaytv-ivs.pat | 2 +-
.../src/router/layer7/protocols/protocols/rtp.pat | 74 +-
.../layer7/protocols/protocols/runesofmagic.pat | 63 +
.../layer7/protocols/protocols/tonghuashun.pat | 11 +
.../router/layer7/protocols/protocols/xboxlive.pat | 2 +-
release/src/router/layer7/squish.sh | 14 +-
release/src/router/mdu/Makefile | 1 -
release/src/router/mdu/mdu.c | 271 +-
release/src/router/miniupnpd/Changelog.txt | 482 ++
release/src/router/miniupnpd/INSTALL | 115 +
release/src/router/miniupnpd/LICENCE | 26 +
release/src/router/miniupnpd/Makefile | 161 +
release/src/router/miniupnpd/Makefile.linux | 138 +
release/src/router/miniupnpd/Makefile.openwrt | 95 +
release/src/router/miniupnpd/Makefile.tomato | 131 +
release/src/router/miniupnpd/README | 27 +
release/src/router/miniupnpd/README.openwrt | 76 +
release/src/router/miniupnpd/bsd/Makefile | 14 +
release/src/router/miniupnpd/bsd/getifstats.c | 129 +
release/src/router/miniupnpd/bsd/testgetifstats.c | 32 +
release/src/router/miniupnpd/bsdqueue.h | 531 ++
release/src/router/miniupnpd/codelength.h | 24 +
release/src/router/miniupnpd/commonrdr.h | 36 +
release/src/router/miniupnpd/config.h | 58 +
release/src/router/miniupnpd/config.h.openwrt | 27 +
release/src/router/miniupnpd/daemonize.c | 129 +
release/src/router/miniupnpd/daemonize.h | 35 +
release/src/router/miniupnpd/genconfig.sh | 222 +
release/src/router/miniupnpd/getifaddr.c | 57 +
release/src/router/miniupnpd/getifaddr.h | 19 +
release/src/router/miniupnpd/getifstats.h | 25 +
release/src/router/miniupnpd/ipf/Makefile | 16 +
release/src/router/miniupnpd/ipf/ipfrdr.c | 518 ++
release/src/router/miniupnpd/ipf/ipfrdr.h | 55 +
release/src/router/miniupnpd/ipf/testipfrdr.c | 25 +
release/src/router/miniupnpd/linux/getifstats.c | 94 +
.../router/miniupnpd/linux/miniupnpd.init.d.script | 40 +
release/src/router/miniupnpd/minissdp.c | 513 ++
release/src/router/miniupnpd/minissdp.h | 47 +
release/src/router/miniupnpd/miniupnpd.1 | 73 +
release/src/router/miniupnpd/miniupnpd.c | 1343 ++++
release/src/router/miniupnpd/miniupnpd.conf | 99 +
release/src/router/miniupnpd/miniupnpdctl.c | 72 +
release/src/router/miniupnpd/miniupnpdpath.h | 36 +
release/src/router/miniupnpd/miniupnpdtypes.h | 24 +
release/src/router/miniupnpd/minixml.c | 191 +
release/src/router/miniupnpd/minixml.h | 37 +
release/src/router/miniupnpd/natpmp.c | 299 +
release/src/router/miniupnpd/natpmp.h | 20 +
release/src/router/miniupnpd/netfilter/Makefile | 12 +
.../router/miniupnpd/netfilter/iptables_display.sh | 10 +
.../router/miniupnpd/netfilter/iptables_flush.sh | 8 +
.../router/miniupnpd/netfilter/iptables_init.sh | 20 +
.../miniupnpd/netfilter/iptables_removeall.sh | 21 +
release/src/router/miniupnpd/netfilter/iptcrdr.c | 698 ++
release/src/router/miniupnpd/netfilter/iptcrdr.h | 38 +
.../src/router/miniupnpd/netfilter/testiptcrdr.c | 59 +
release/src/router/miniupnpd/options.c | 195 +
release/src/router/miniupnpd/options.h | 74 +
release/src/router/miniupnpd/pf/Makefile | 16 +
release/src/router/miniupnpd/pf/obsdrdr.c | 606 ++
release/src/router/miniupnpd/pf/obsdrdr.h | 63 +
release/src/router/miniupnpd/pf/testobsdrdr.c | 87 +
release/src/router/miniupnpd/solaris/getifstats.c | 100 +
release/src/router/miniupnpd/testgetifaddr.c | 22 +
release/src/router/miniupnpd/testgetifstats.c | 36 +
release/src/router/miniupnpd/testupnpdescgen.c | 141 +
release/src/router/miniupnpd/testupnppermissions.c | 48 +
release/src/router/miniupnpd/upnpdescgen.c | 806 ++
release/src/router/miniupnpd/upnpdescgen.h | 79 +
release/src/router/miniupnpd/upnpdescstrings.h | 39 +
release/src/router/miniupnpd/upnpevents.c | 476 ++
release/src/router/miniupnpd/upnpevents.h | 39 +
release/src/router/miniupnpd/upnpglobalvars.c | 88 +
release/src/router/miniupnpd/upnpglobalvars.h | 100 +
release/src/router/miniupnpd/upnphttp.c | 636 ++
release/src/router/miniupnpd/upnphttp.h | 111 +
release/src/router/miniupnpd/upnppermissions.c | 188 +
release/src/router/miniupnpd/upnppermissions.h | 55 +
release/src/router/miniupnpd/upnpredirect.c | 479 ++
release/src/router/miniupnpd/upnpredirect.h | 92 +
release/src/router/miniupnpd/upnpreplyparse.c | 127 +
release/src/router/miniupnpd/upnpreplyparse.h | 62 +
release/src/router/miniupnpd/upnpsoap.c | 821 ++
release/src/router/miniupnpd/upnpsoap.h | 23 +
release/src/router/mssl/mssl.c | 16 +-
release/src/router/mssl/mssl.h | 6 +-
release/src/router/ntpc/ntpc.c | 47 +-
release/src/router/nvram/defaults.c | 32 +-
release/src/router/nvram/nvram.c | 218 +-
release/src/router/rc/buttons.c | 30 +-
release/src/router/rc/cifs.c | 26 +-
release/src/router/rc/ddns.c | 60 +-
release/src/router/rc/dhcp.c | 89 +-
release/src/router/rc/firewall.c | 217 +-
release/src/router/rc/firewall_br.c | 206 -
release/src/router/rc/forward.c | 16 +-
release/src/router/rc/gpio.c | 6 +-
release/src/router/rc/heartbeat.c | 2 +-
release/src/router/rc/init.c | 127 +-
release/src/router/rc/jffs2.c | 20 +-
release/src/router/rc/led.c | 10 +-
release/src/router/rc/misc.c | 62 +-
release/src/router/rc/mtd.c | 22 +-
release/src/router/rc/network.c | 54 +-
release/src/router/rc/qos.c | 96 +-
release/src/router/rc/rc.c | 2 +-
release/src/router/rc/rc.h | 8 +-
release/src/router/rc/restrict.c | 42 +-
release/src/router/rc/sched.c | 24 +-
release/src/router/rc/services.c | 221 +-
release/src/router/rc/telssh.c | 14 +-
release/src/router/rc/wan.c | 28 +-
release/src/router/rom/Makefile | 4 +-
release/src/router/rstats/rstats.c | 68 +-
release/src/router/shared/Makefile | 2 -
release/src/router/shared/base64.c | 6 +-
release/src/router/shared/files.c | 26 +-
release/src/router/shared/id.c | 33 +-
release/src/router/shared/led.c | 8 +-
release/src/router/shared/misc.c | 65 +-
release/src/router/shared/process.c | 8 +-
release/src/router/shared/shared.h | 12 +-
release/src/router/shared/shutils.c | 2 +-
release/src/router/shared/strings.c | 12 +-
release/src/router/shared/tomato_config.h | 1 -
release/src/router/shared/tomato_version | 2 +-
release/src/router/upnp/Makefile | 54 -
release/src/router/upnp/igd/cablelink.c | 176 -
release/src/router/upnp/igd/etherlink.c | 56 -
release/src/router/upnp/igd/igd.c | 177 -
release/src/router/upnp/igd/igd.h | 87 -
release/src/router/upnp/igd/igd_desc.c | 116 -
release/src/router/upnp/igd/ipt.c | 491 --
release/src/router/upnp/igd/lanhostconfig.c | 60 -
release/src/router/upnp/igd/lanhostconfig.h | 30 -
release/src/router/upnp/igd/layer3.c | 200 -
release/src/router/upnp/igd/linux/Makefile | 131 -
release/src/router/upnp/igd/linux/linux_igd.c | 409 -
release/src/router/upnp/igd/linux/linux_main.c | 146 -
release/src/router/upnp/igd/linux/linux_net.c | 120 -
release/src/router/upnp/igd/mapmgr.1.c | 621 --
release/src/router/upnp/igd/mapmgr.c | 623 --
release/src/router/upnp/igd/mapmgr.h | 31 -
release/src/router/upnp/igd/portmap.c | 570 --
release/src/router/upnp/igd/wancommon.c | 235 -
release/src/router/upnp/igd/wanipc.c | 606 --
release/src/router/upnp/igd/wanipc.h | 64 -
release/src/router/upnp/igd/wanpotslinkconfig.c | 155 -
release/src/router/upnp/igd/wanppp.c | 137 -
release/src/router/upnp/igd/wanppp.h | 42 -
.../router/upnp/igd/x_lanhostconfigmanagement.c | 271 -
.../src/router/upnp/igd/x_wanethernetlinkconfig.c | 80 -
release/src/router/upnp/igd/x_wanpppconnection.c | 299 -
release/src/router/upnp/include/linux_osl.h | 38 -
release/src/router/upnp/include/uio.h | 27 -
release/src/router/upnp/include/upnp.h | 375 -
release/src/router/upnp/include/upnp_dbg.h | 89 -
release/src/router/upnp/include/upnp_osl.h | 44 -
release/src/router/upnp/lib/device.c | 290 -
release/src/router/upnp/lib/gena.c | 811 --
release/src/router/upnp/lib/http.c | 662 --
release/src/router/upnp/lib/linux/Makefile | 73 -
release/src/router/upnp/lib/linux/linux_osl.c | 111 -
release/src/router/upnp/lib/service.c | 244 -
release/src/router/upnp/lib/soap.c | 530 --
release/src/router/upnp/lib/ssdp.c | 536 --
release/src/router/upnp/lib/uio.c | 241 -
release/src/router/upnp/lib/upnp.c | 440 --
release/src/router/www/Makefile | 8 +-
release/src/router/www/about.asp | 18 +-
release/src/router/www/admin-access.asp | 93 +-
release/src/router/www/admin-buttons.asp | 37 +-
release/src/router/www/admin-bwm.asp | 6 +-
release/src/router/www/admin-cifs.asp | 8 +-
release/src/router/www/admin-config.asp | 10 +-
release/src/router/www/admin-debug.asp | 10 +-
release/src/router/www/admin-jffs2.asp | 6 +-
release/src/router/www/admin-log.asp | 30 +-
release/src/router/www/admin-sched.asp | 46 +-
release/src/router/www/admin-scripts.asp | 4 +-
release/src/router/www/admin-upgrade.asp | 2 +-
release/src/router/www/advanced-ctnf.asp | 6 +-
release/src/router/www/advanced-dhcpdns.asp | 8 +-
release/src/router/www/advanced-firewall.asp | 11 +-
release/src/router/www/advanced-mac.asp | 2 +-
release/src/router/www/advanced-misc.asp | 2 +-
release/src/router/www/advanced-routing.asp | 2 +-
release/src/router/www/advanced-wireless.asp | 8 +-
release/src/router/www/basic-ddns.asp | 66 +-
release/src/router/www/basic-ident.asp | 2 +-
release/src/router/www/basic-network.asp | 32 +-
release/src/router/www/basic-static.asp | 4 +-
release/src/router/www/basic-time.asp | 2 +-
release/src/router/www/basic-wfilter.asp | 14 +-
release/src/router/www/bwm-24.asp | 22 +-
release/src/router/www/bwm-common.js | 32 +-
release/src/router/www/bwm-daily.asp | 16 +-
release/src/router/www/bwm-graph.svg | 2 +-
release/src/router/www/bwm-monthly.asp | 10 +-
release/src/router/www/bwm-realtime.asp | 14 +-
release/src/router/www/bwm-weekly.asp | 16 +-
release/src/router/www/clearcookies.asp | 2 +-
release/src/router/www/forward-basic.asp | 8 +-
release/src/router/www/forward-dmz.asp | 23 +-
release/src/router/www/forward-triggered.asp | 4 +-
release/src/router/www/forward-upnp.asp | 67 +-
release/src/router/www/logout.asp | 28 +-
release/src/router/www/mnoise.asp | 2 +-
release/src/router/www/qos-classify.asp | 16 +-
release/src/router/www/qos-detailed.asp | 22 +-
release/src/router/www/qos-graphs.asp | 16 +-
release/src/router/www/qos-settings.asp | 6 +-
release/src/router/www/reboot-default.asp | 2 +-
release/src/router/www/restrict-edit.asp | 20 +-
release/src/router/www/restrict.asp | 2 +-
release/src/router/www/saved-moved.asp | 2 +-
release/src/router/www/saved.asp | 2 +-
release/src/router/www/shutdown.asp | 2 +-
release/src/router/www/status-data.jsx | 6 +-
release/src/router/www/status-devices.asp | 29 +-
release/src/router/www/status-log.asp | 2 +-
release/src/router/www/status-overview.asp | 2 +-
release/src/router/www/tomato.css | 2 +-
release/src/router/www/tomato.js | 163 +-
release/src/router/www/tools-ping.asp | 2 +-
release/src/router/www/tools-survey.asp | 8 +-
release/src/router/www/tools-trace.asp | 2 +-
release/src/router/www/tools-wol.asp | 10 +-
894 files changed, 56239 insertions(+), 39452 deletions(-)
create mode 100644 release/src/linux/linux/arch/mips/brcm-boards/bcm947xx/prom-orig.c
create mode 100644 release/src/linux/linux/include/linux/netfilter_ipv4/ipt_ROUTE.h
create mode 100644 release/src/linux/linux/include/linux/netfilter_ipv4/ipt_ipp2p.h
create mode 100644 release/src/linux/linux/include/linux/netfilter_ipv6/ip6t_ROUTE.h
create mode 100644 release/src/linux/linux/net/ipv4/netfilter/ipt_ROUTE.c
create mode 100644 release/src/linux/linux/net/ipv4/netfilter/ipt_ipp2p.c
create mode 100644 release/src/linux/linux/net/ipv6/netfilter/ip6t_ROUTE.c
create mode 100644 release/src/router/busybox/.config
delete mode 100644 release/src/router/busybox/config_g
rewrite release/src/router/busybox/coreutils/id.c (76%)
create mode 100644 release/src/router/busybox/coreutils/id_test.sh
create mode 100644 release/src/router/busybox/docs/Serial-Programming-HOWTO.txt
rewrite release/src/router/busybox/docs/busybox.net/news.html (93%)
rewrite release/src/router/busybox/docs/busybox.net/products.html (72%)
create mode 100644 release/src/router/busybox/docs/busybox.net/svnindex.css
create mode 100644 release/src/router/busybox/docs/busybox.net/svnindex.xsl
create mode 100644 release/src/router/busybox/docs/logging_and_backgrounding.txt
create mode 100644 release/src/router/busybox/examples/depmod-t.pl
rewrite release/src/router/busybox/libbb/bb_pwd.c (73%)
delete mode 100644 release/src/router/busybox/libbb/crypt_make_salt.c
rewrite release/src/router/busybox/libbb/md5.c (64%)
create mode 100644 release/src/router/busybox/libbb/md5prime.c
rewrite release/src/router/busybox/libbb/pw_encrypt_md5.c (79%)
create mode 100644 release/src/router/busybox/libbb/pw_encrypt_sha.c
create mode 100644 release/src/router/busybox/libbb/read_key.c
rewrite release/src/router/busybox/libbb/sha1.c (79%)
rewrite release/src/router/busybox/loginutils/cryptpw.c (76%)
rewrite release/src/router/busybox/loginutils/deluser.c (85%)
create mode 100644 release/src/router/busybox/mailutils/Config.in
create mode 100644 release/src/router/busybox/mailutils/Kbuild
create mode 100644 release/src/router/busybox/mailutils/mail.c
create mode 100644 release/src/router/busybox/mailutils/mail.h
create mode 100644 release/src/router/busybox/mailutils/mime.c
create mode 100644 release/src/router/busybox/mailutils/popmaildir.c
create mode 100644 release/src/router/busybox/mailutils/sendmail.c
create mode 100644 release/src/router/busybox/miscutils/devmem.c
create mode 100644 release/src/router/busybox/miscutils/flash_eraseall.c
create mode 100644 release/src/router/busybox/miscutils/ionice.c
rewrite release/src/router/busybox/miscutils/mountpoint.c (71%)
create mode 100644 release/src/router/busybox/miscutils/timeout.c
rewrite release/src/router/busybox/modutils/Kbuild (61%)
rewrite release/src/router/busybox/modutils/depmod.c (87%)
rewrite release/src/router/busybox/modutils/insmod.c (99%)
rewrite release/src/router/busybox/modutils/lsmod.c (83%)
rewrite release/src/router/busybox/modutils/modprobe.c (96%)
create mode 100644 release/src/router/busybox/modutils/modutils-24.c
create mode 100644 release/src/router/busybox/modutils/modutils.c
create mode 100644 release/src/router/busybox/modutils/modutils.h
rewrite release/src/router/busybox/modutils/rmmod.c (76%)
rewrite release/src/router/busybox/networking/dnsd.c (64%)
create mode 100644 release/src/router/busybox/networking/ftpd.c
delete mode 100644 release/src/router/busybox/networking/sendmail.c
create mode 100644 release/src/router/busybox/networking/tc.c
create mode 100644 release/src/router/busybox/networking/telnetd.ctrlSQ.patch
create mode 100644 release/src/router/busybox/networking/tunctl.c
rewrite release/src/router/busybox/networking/udhcp/options.h (69%)
rewrite release/src/router/busybox/procps/sysctl.c (79%)
create mode 100644 release/src/router/busybox/scripts/randomtest
create mode 100644 release/src/router/busybox/scripts/randomtest.loop
create mode 100644 release/src/router/busybox/shell/ash_test/ash-misc/last_amp.right
create mode 100644 release/src/router/busybox/shell/ash_test/ash-misc/last_amp.tests
create mode 100644 release/src/router/busybox/shell/ash_test/ash-read/read_ifs.right
create mode 100644 release/src/router/busybox/shell/ash_test/ash-read/read_ifs.tests
create mode 100644 release/src/router/busybox/shell/ash_test/ash-signals/reap1.right
create mode 100644 release/src/router/busybox/shell/ash_test/ash-signals/reap1.tests
create mode 100644 release/src/router/busybox/shell/ash_test/ash-standalone/noexec_gets_no_env.right
create mode 100644 release/src/router/busybox/shell/ash_test/ash-standalone/noexec_gets_no_env.tests
create mode 100644 release/src/router/busybox/shell/ash_test/ash-standalone/nofork_trashes_getopt.right
create mode 100644 release/src/router/busybox/shell/ash_test/ash-standalone/nofork_trashes_getopt.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-arith/arith.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-arith/arith.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-arith/arith1.sub
create mode 100644 release/src/router/busybox/shell/hush_test/hush-arith/arith2.sub
create mode 100644 release/src/router/busybox/shell/hush_test/hush-bugs/and_or_and_backgrounding.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-bugs/and_or_and_backgrounding.tests
copy release/src/router/busybox/shell/hush_test/{hush-z_slow/leak_var.right => hush-leak/leak_argv1.right} (100%)
create mode 100644 release/src/router/busybox/shell/hush_test/hush-leak/leak_argv1.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/and-or.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/and-or.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/continue2.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/continue2.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/continue3.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/continue3.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/exec.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/exec.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/exit1.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/exit1.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/export.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/export.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/for_with_bslashes.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/for_with_bslashes.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/func1.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/func1.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/func2.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/func2.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/heredoc1.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/heredoc1.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/heredoc2.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/heredoc2.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/heredoc3.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/heredoc3.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/heredoc_huge.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/heredoc_huge.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/if_false_exitcode.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/if_false_exitcode.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/redir1.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/redir1.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/redir2.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/redir2.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/redir3.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/redir3.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/redir4.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/redir4.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/until1.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/until1.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/while2.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-misc/while2.tests
rewrite release/src/router/busybox/shell/hush_test/hush-parsing/negate.tests (67%)
create mode 100644 release/src/router/busybox/shell/hush_test/hush-psubst/tick_huge.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-psubst/tick_huge.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-trap/catch.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-trap/catch.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-trap/exit.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-trap/exit.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-trap/save-ret.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-trap/save-ret.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-trap/usage.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-trap/usage.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-vars/param_expand_alt.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-vars/param_expand_alt.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-vars/param_expand_assign.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-vars/param_expand_assign.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-vars/param_expand_default.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-vars/param_expand_default.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-vars/param_expand_indicate_error.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-vars/param_expand_indicate_error.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-vars/param_expand_len.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-vars/param_expand_len.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-vars/param_subshell.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-vars/param_subshell.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-vars/unset.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-vars/unset.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-vars/var3.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-vars/var3.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-vars/var_in_pipes.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-vars/var_in_pipes.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-vars/var_leaks.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-vars/var_leaks.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-vars/var_posix1.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-vars/var_posix1.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-vars/var_preserved.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-vars/var_preserved.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-z_slow/leak_all1.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-z_slow/leak_all1.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-z_slow/leak_all2.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-z_slow/leak_all2.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-z_slow/leak_heredoc1.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-z_slow/leak_heredoc1.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-z_slow/leak_var2.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-z_slow/leak_var2.tests
create mode 100644 release/src/router/busybox/shell/hush_test/hush-z_slow/leak_var3.right
create mode 100644 release/src/router/busybox/shell/hush_test/hush-z_slow/leak_var3.tests
create mode 100644 release/src/router/busybox/shell/match.c
create mode 100644 release/src/router/busybox/shell/match.h
create mode 100644 release/src/router/busybox/shell/math.c
create mode 100644 release/src/router/busybox/shell/math.h
create mode 100644 release/src/router/busybox/testsuite/expand.tests
create mode 100644 release/src/router/busybox/testsuite/tr.tests
create mode 100644 release/src/router/busybox/testsuite/unexpand.tests
create mode 100644 release/src/router/busybox/util-linux/acpid.c
create mode 100644 release/src/router/busybox/util-linux/blkid.c
create mode 100644 release/src/router/busybox/util-linux/mkfs_vfat.c
create mode 100644 release/src/router/dnsmasq/contrib/lease-access/README
create mode 100644 release/src/router/dnsmasq/contrib/lease-access/lease.access.patch
delete mode 100644 release/src/router/ipp2p/COPYING
delete mode 100644 release/src/router/ipp2p/Makefile
delete mode 100644 release/src/router/ipp2p/README
delete mode 100644 release/src/router/ipp2p/ipt_ipp2p.c
delete mode 100644 release/src/router/ipp2p/ipt_ipp2p.h
delete mode 100644 release/src/router/ipp2p/libipt_ipp2p.c
delete mode 100644 release/src/router/iptables/Makefile.orig
create mode 100644 release/src/router/iptables/extensions/.connlimit-test
create mode 100644 release/src/router/iptables/extensions/.ipp2p-test
create mode 100644 release/src/router/iptables/extensions/libipt_ipp2p.c
create mode 100644 release/src/router/iptables/extensions/libipt_ipp2p.man
delete mode 100644 release/src/router/iptables/iptables-multi.c.orig
create mode 100644 release/src/router/layer7/protocols/extra/gtalk.pat
create mode 100644 release/src/router/layer7/protocols/protocols/dazhihui.pat
rewrite release/src/router/layer7/protocols/protocols/rtp.pat (61%)
create mode 100644 release/src/router/layer7/protocols/protocols/runesofmagic.pat
create mode 100644 release/src/router/layer7/protocols/protocols/tonghuashun.pat
create mode 100644 release/src/router/miniupnpd/Changelog.txt
create mode 100644 release/src/router/miniupnpd/INSTALL
create mode 100644 release/src/router/miniupnpd/LICENCE
create mode 100644 release/src/router/miniupnpd/Makefile
create mode 100644 release/src/router/miniupnpd/Makefile.linux
create mode 100644 release/src/router/miniupnpd/Makefile.openwrt
create mode 100644 release/src/router/miniupnpd/Makefile.tomato
create mode 100644 release/src/router/miniupnpd/README
create mode 100644 release/src/router/miniupnpd/README.openwrt
create mode 100644 release/src/router/miniupnpd/bsd/Makefile
create mode 100644 release/src/router/miniupnpd/bsd/getifstats.c
create mode 100644 release/src/router/miniupnpd/bsd/testgetifstats.c
create mode 100644 release/src/router/miniupnpd/bsdqueue.h
create mode 100644 release/src/router/miniupnpd/codelength.h
create mode 100644 release/src/router/miniupnpd/commonrdr.h
create mode 100644 release/src/router/miniupnpd/config.h
create mode 100644 release/src/router/miniupnpd/config.h.openwrt
create mode 100644 release/src/router/miniupnpd/daemonize.c
create mode 100644 release/src/router/miniupnpd/daemonize.h
create mode 100644 release/src/router/miniupnpd/genconfig.sh
create mode 100644 release/src/router/miniupnpd/getifaddr.c
create mode 100644 release/src/router/miniupnpd/getifaddr.h
create mode 100644 release/src/router/miniupnpd/getifstats.h
create mode 100644 release/src/router/miniupnpd/ipf/Makefile
create mode 100644 release/src/router/miniupnpd/ipf/ipfrdr.c
create mode 100644 release/src/router/miniupnpd/ipf/ipfrdr.h
create mode 100644 release/src/router/miniupnpd/ipf/testipfrdr.c
create mode 100644 release/src/router/miniupnpd/linux/getifstats.c
create mode 100644 release/src/router/miniupnpd/linux/miniupnpd.init.d.script
create mode 100644 release/src/router/miniupnpd/minissdp.c
create mode 100644 release/src/router/miniupnpd/minissdp.h
create mode 100644 release/src/router/miniupnpd/miniupnpd.1
create mode 100644 release/src/router/miniupnpd/miniupnpd.c
create mode 100644 release/src/router/miniupnpd/miniupnpd.conf
create mode 100644 release/src/router/miniupnpd/miniupnpdctl.c
create mode 100644 release/src/router/miniupnpd/miniupnpdpath.h
create mode 100644 release/src/router/miniupnpd/miniupnpdtypes.h
create mode 100644 release/src/router/miniupnpd/minixml.c
create mode 100644 release/src/router/miniupnpd/minixml.h
create mode 100644 release/src/router/miniupnpd/natpmp.c
create mode 100644 release/src/router/miniupnpd/natpmp.h
create mode 100644 release/src/router/miniupnpd/netfilter/Makefile
create mode 100644 release/src/router/miniupnpd/netfilter/iptables_display.sh
create mode 100644 release/src/router/miniupnpd/netfilter/iptables_flush.sh
create mode 100644 release/src/router/miniupnpd/netfilter/iptables_init.sh
create mode 100644 release/src/router/miniupnpd/netfilter/iptables_removeall.sh
create mode 100644 release/src/router/miniupnpd/netfilter/iptcrdr.c
create mode 100644 release/src/router/miniupnpd/netfilter/iptcrdr.h
create mode 100644 release/src/router/miniupnpd/netfilter/testiptcrdr.c
create mode 100644 release/src/router/miniupnpd/options.c
create mode 100644 release/src/router/miniupnpd/options.h
create mode 100644 release/src/router/miniupnpd/pf/Makefile
create mode 100644 release/src/router/miniupnpd/pf/obsdrdr.c
create mode 100644 release/src/router/miniupnpd/pf/obsdrdr.h
create mode 100644 release/src/router/miniupnpd/pf/testobsdrdr.c
create mode 100644 release/src/router/miniupnpd/solaris/getifstats.c
create mode 100644 release/src/router/miniupnpd/testgetifaddr.c
create mode 100644 release/src/router/miniupnpd/testgetifstats.c
create mode 100644 release/src/router/miniupnpd/testupnpdescgen.c
create mode 100644 release/src/router/miniupnpd/testupnppermissions.c
create mode 100644 release/src/router/miniupnpd/upnpdescgen.c
create mode 100644 release/src/router/miniupnpd/upnpdescgen.h
create mode 100644 release/src/router/miniupnpd/upnpdescstrings.h
create mode 100644 release/src/router/miniupnpd/upnpevents.c
create mode 100644 release/src/router/miniupnpd/upnpevents.h
create mode 100644 release/src/router/miniupnpd/upnpglobalvars.c
create mode 100644 release/src/router/miniupnpd/upnpglobalvars.h
create mode 100644 release/src/router/miniupnpd/upnphttp.c
create mode 100644 release/src/router/miniupnpd/upnphttp.h
create mode 100644 release/src/router/miniupnpd/upnppermissions.c
create mode 100644 release/src/router/miniupnpd/upnppermissions.h
create mode 100644 release/src/router/miniupnpd/upnpredirect.c
create mode 100644 release/src/router/miniupnpd/upnpredirect.h
create mode 100644 release/src/router/miniupnpd/upnpreplyparse.c
create mode 100644 release/src/router/miniupnpd/upnpreplyparse.h
create mode 100644 release/src/router/miniupnpd/upnpsoap.c
create mode 100644 release/src/router/miniupnpd/upnpsoap.h
delete mode 100644 release/src/router/rc/firewall_br.c
delete mode 100644 release/src/router/upnp/Makefile
delete mode 100644 release/src/router/upnp/igd/cablelink.c
delete mode 100644 release/src/router/upnp/igd/etherlink.c
delete mode 100644 release/src/router/upnp/igd/igd.c
delete mode 100644 release/src/router/upnp/igd/igd.h
delete mode 100644 release/src/router/upnp/igd/igd_desc.c
delete mode 100644 release/src/router/upnp/igd/ipt.c
delete mode 100644 release/src/router/upnp/igd/lanhostconfig.c
delete mode 100644 release/src/router/upnp/igd/lanhostconfig.h
delete mode 100644 release/src/router/upnp/igd/layer3.c
delete mode 100644 release/src/router/upnp/igd/linux/Makefile
delete mode 100644 release/src/router/upnp/igd/linux/linux_igd.c
delete mode 100644 release/src/router/upnp/igd/linux/linux_main.c
delete mode 100644 release/src/router/upnp/igd/linux/linux_net.c
delete mode 100644 release/src/router/upnp/igd/mapmgr.1.c
delete mode 100644 release/src/router/upnp/igd/mapmgr.c
delete mode 100644 release/src/router/upnp/igd/mapmgr.h
delete mode 100644 release/src/router/upnp/igd/portmap.c
delete mode 100644 release/src/router/upnp/igd/wancommon.c
delete mode 100644 release/src/router/upnp/igd/wanipc.c
delete mode 100644 release/src/router/upnp/igd/wanipc.h
delete mode 100644 release/src/router/upnp/igd/wanpotslinkconfig.c
delete mode 100644 release/src/router/upnp/igd/wanppp.c
delete mode 100644 release/src/router/upnp/igd/wanppp.h
delete mode 100644 release/src/router/upnp/igd/x_lanhostconfigmanagement.c
delete mode 100644 release/src/router/upnp/igd/x_wanethernetlinkconfig.c
delete mode 100644 release/src/router/upnp/igd/x_wanpppconnection.c
delete mode 100644 release/src/router/upnp/include/linux_osl.h
delete mode 100644 release/src/router/upnp/include/uio.h
delete mode 100644 release/src/router/upnp/include/upnp.h
delete mode 100644 release/src/router/upnp/include/upnp_dbg.h
delete mode 100644 release/src/router/upnp/include/upnp_osl.h
delete mode 100644 release/src/router/upnp/lib/device.c
delete mode 100644 release/src/router/upnp/lib/gena.c
delete mode 100644 release/src/router/upnp/lib/http.c
delete mode 100644 release/src/router/upnp/lib/linux/Makefile
delete mode 100644 release/src/router/upnp/lib/linux/linux_osl.c
delete mode 100644 release/src/router/upnp/lib/service.c
delete mode 100644 release/src/router/upnp/lib/soap.c
delete mode 100644 release/src/router/upnp/lib/ssdp.c
delete mode 100644 release/src/router/upnp/lib/uio.c
delete mode 100644 release/src/router/upnp/lib/upnp.c
diff --git a/release/src/Makefile b/release/src/Makefile
index 6175b61bb9..2629d6f6ce 100644
--- a/release/src/Makefile
+++ b/release/src/Makefile
@@ -28,9 +28,12 @@ all:
else
all:
- @echo -e "\n\n$(TOMATO_PROFILE_NAME) Profile"
+ @echo ""
+ @echo ""
+ @echo "$(TOMATO_PROFILE_NAME) Profile"
@btools/uversion.pl --gen
- @echo -e "\n\n"
+ @echo ""
+ @echo ""
@$(MAKE) -C router all
@$(MAKE) -C router install
@@ -50,11 +53,13 @@ ifeq ($(wildcard include/bcm20xx.h),)
else
@btools/fpkg -i linux/linux/arch/mips/brcm-boards/bcm947xx/compressed/vmlinuz -i router/mipsel-uclibc/target.image \
-t image/tomato-ND.trx
-# -l WR41,image/WRH54G.bin
endif
-
- @echo -e "\n-----------------\n" `cat router/shared/tomato_version` " ready\n-----------------"
+
+ @echo ""
+ @echo "-----------------"
+ @echo `cat router/shared/tomato_version` " ready"
+ @echo "-----------------"
ifneq ($(NOVERSION),1)
@cp router/shared/tomato_version router/shared/tomato_version_last
@@ -83,8 +88,6 @@ distclean: clean cleankernel cleantools cleanlibc
ifneq ($(INSIDE_MAK),1)
@$(MAKE) -C router $@ INSIDE_MAK=1
endif
- @$(MAKE) -C router/busybox distclean
- @rm -f router/busybox/config_current
@rm -f router/config_current
@rm -f router/.config.cmd router/.config.old
@rm -f router/libfoo_xref.txt
@@ -94,7 +97,8 @@ prepk:
$(MAKE) -C linux/linux oldconfig dep
what:
- @echo -e "\n$(TOMATO_PROFILE_NAME) Profile\n"
+ @echo ""
+ @echo "$(TOMATO_PROFILE_NAME) Profile\n"
endif
@@ -103,7 +107,7 @@ g:
@$(MAKE) setprofile U=G L=g N=G
setprofile:
- @echo -e "\
+ @echo "\
#ifndef TOMATO_PROFILE\n\
#define TOMATO_$(U) 1\n\
#define PROFILE_G 1\n\
@@ -112,7 +116,7 @@ setprofile:
#define TOMATO_PROFILE_NAME \"$(N)\"\n\
#endif\n" > router/shared/tomato_profile.h
- @echo -e "\
+ @echo "\
TOMATO_$(U) = 1\n\
PROFILE_G = 1\n\
PROFILE_N = 2\n\
@@ -128,14 +132,9 @@ TOMATO_PROFILE_U = $(U)\n" > tomato_profile.mak
cp config_$(L) .config
@$(MAKE) -C router oldconfig
- @cd router/busybox && \
- [ -s .config ] && cat .config > config_current; \
- rm -f config_current && \
- ln -s config_$(L) config_current && \
- cp config_$(L) .config
- @$(MAKE) -C router/busybox oldconfig
-
- @echo -e "\nUsing $(N) profile.\n"
+ @echo ""
+ @echo "Using $(N) profile."
+ @echo ""
cleanlibc:
@@ -144,7 +143,10 @@ cleanlibc:
libc: cleanlibc
@$(MAKE) -C ../../tools-src/uClibc
@$(MAKE) -C ../../tools-src/uClibc install
-
+
+echotest:
+ @( echo -e foo | grep "\-e foo" ) && echo bar || echo foo
+
help:
@echo "g use G profile"
@echo "clean -C router clean"
diff --git a/release/src/linux/linux/.config b/release/src/linux/linux/.config
index 87abcd7244..b1f69ac915 100644
--- a/release/src/linux/linux/.config
+++ b/release/src/linux/linux/.config
@@ -311,7 +311,8 @@ CONFIG_IP_NF_PPTP=m
# CONFIG_IP_NF_QUEUE is not set
CONFIG_IP_NF_IPTABLES=y
CONFIG_IP_NF_MATCH_LIMIT=y
-CONFIG_IP_NF_MATCH_GEOIP=m
+CONFIG_IP_NF_MATCH_IPP2P=m
+# CONFIG_IP_NF_MATCH_GEOIP is not set
# CONFIG_IP_NF_MATCH_QUOTA is not set
CONFIG_IP_NF_MATCH_IPRANGE=y
# CONFIG_IP_NF_POOL is not set
@@ -326,7 +327,7 @@ CONFIG_IP_NF_MATCH_RECENT=m
CONFIG_IP_NF_MATCH_CONDITION=m
CONFIG_IP_NF_MATCH_TIME=m
# CONFIG_IP_NF_MATCH_ECN is not set
-# CONFIG_IP_NF_MATCH_DSCP is not set
+CONFIG_IP_NF_MATCH_DSCP=m
# CONFIG_IP_NF_MATCH_AH_ESP is not set
CONFIG_IP_NF_MATCH_LENGTH=m
CONFIG_IP_NF_MATCH_U32=m
@@ -371,6 +372,7 @@ CONFIG_IP_NF_TARGET_TOS=m
# CONFIG_IP_NF_TARGET_ECN is not set
CONFIG_IP_NF_TARGET_DSCP=m
CONFIG_IP_NF_TARGET_MARK=y
+CONFIG_IP_NF_TARGET_ROUTE=m
CONFIG_IP_NF_TARGET_CLASSIFY=m
CONFIG_IP_NF_TARGET_IMQ=m
CONFIG_IP_NF_TARGET_LOG=y
diff --git a/release/src/linux/linux/Documentation/Configure.help b/release/src/linux/linux/Documentation/Configure.help
index 757e7afe4a..1f6261d7c8 100644
--- a/release/src/linux/linux/Documentation/Configure.help
+++ b/release/src/linux/linux/Documentation/Configure.help
@@ -2834,6 +2834,14 @@ CONFIG_IP_NF_MATCH_TOS
If you want to compile it as a module, say M here and read
. If unsure, say `N'.
+IPP2P match support
+CONFIG_IP_NF_MATCH_IPP2P
+ This option makes possible to match some P2P packets
+ therefore helps controlling such traffic.
+
+ If you want to compile it as a module, say M here and read
+ . If unsure, say `N'.
+
geoip match support
CONFIG_IP_NF_MATCH_GEOIP
This option allows you to match a packet by its source or
@@ -3075,6 +3083,21 @@ CONFIG_IP_NF_TARGET_MARK
If you want to compile it as a module, say M here and read
. If unsure, say `N'.
+ROUTE target support
+CONFIG_IP_NF_TARGET_ROUTE
+ This option adds a `ROUTE' target, which enables you to setup unusual
+ routes. For example, the ROUTE lets you route a received packet through
+ an interface or towards a host, even if the regular destination of the
+ packet is the router itself. The ROUTE target is also able to change the
+ incoming interface of a packet.
+
+ The target can be or not a final target. It has to be used inside the
+ mangle table.
+
+ If you want to compile it as a module, say M here and read
+ Documentation/modules.txt. The module will be called ipt_ROUTE.o.
+ If unsure, say `N'.
+
TCPMSS target support
CONFIG_IP_NF_TARGET_TCPMSS
This option adds a `TCPMSS' target, which allows you to alter the
@@ -3286,6 +3309,17 @@ CONFIG_IP6_NF_TARGET_MARK
If you want to compile it as a module, say M here and read
. If unsure, say `N'.
+ROUTE target support
+CONFIG_IP6_NF_TARGET_ROUTE
+ This option adds a `ROUTE' target, which enables you to setup unusual
+ routes. The ROUTE target is also able to change the incoming interface
+ of a packet.
+
+ The target can be or not a final target. It has to be used inside the
+ mangle table.
+
+ Not working as a module.
+
TCP Explicit Congestion Notification support
CONFIG_INET_ECN
Explicit Congestion Notification (ECN) allows routers to notify
diff --git a/release/src/linux/linux/arch/mips/brcm-boards/bcm947xx/prom-orig.c b/release/src/linux/linux/arch/mips/brcm-boards/bcm947xx/prom-orig.c
new file mode 100644
index 0000000000..706dfbf1b3
--- /dev/null
+++ b/release/src/linux/linux/arch/mips/brcm-boards/bcm947xx/prom-orig.c
@@ -0,0 +1,41 @@
+/*
+ * Early initialization code for BCM94710 boards
+ *
+ * Copyright 2006, Broadcom Corporation
+ * All Rights Reserved.
+ *
+ * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
+ * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
+ * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
+ *
+ * $Id$
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+void __init
+prom_init(int argc, const char **argv)
+{
+ unsigned long mem;
+
+ mips_machgroup = MACH_GROUP_BRCM;
+ mips_machtype = MACH_BCM947XX;
+
+ /* Figure out memory size by finding aliases */
+ for (mem = (1 << 20); mem < (128 << 20); mem += (1 << 20)) {
+ if (*(unsigned long *)((unsigned long)(prom_init) + mem) ==
+ *(unsigned long *)(prom_init))
+ break;
+ }
+ add_memory_region(0, mem, BOOT_MEM_RAM);
+}
+
+void __init
+prom_free_prom_memory(void)
+{
+}
diff --git a/release/src/linux/linux/arch/mips/brcm-boards/bcm947xx/prom.c b/release/src/linux/linux/arch/mips/brcm-boards/bcm947xx/prom.c
index 242dafb926..cb35926d19 100644
--- a/release/src/linux/linux/arch/mips/brcm-boards/bcm947xx/prom.c
+++ b/release/src/linux/linux/arch/mips/brcm-boards/bcm947xx/prom.c
@@ -1,7 +1,7 @@
/*
* Early initialization code for BCM94710 boards
*
- * Copyright 2005, Broadcom Corporation
+ * Copyright 2006, Broadcom Corporation
* All Rights Reserved.
*
* THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
@@ -9,7 +9,7 @@
* SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
*
- * $Id: prom.c,v 1.1.1.7 2005/03/07 07:30:37 kanki Exp $
+ * $Id$
*/
#include
@@ -18,24 +18,39 @@
#include
#include
-void __init
-prom_init(int argc, const char **argv)
+void __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
{
- unsigned long mem;
+ unsigned long mem, before, offset;
- mips_machgroup = MACH_GROUP_BRCM;
- mips_machtype = MACH_BCM947XX;
+ mips_machgroup = MACH_GROUP_BRCM;
+ mips_machtype = MACH_BCM947XX;
- /* Figure out memory size by finding aliases */
- for (mem = (1 << 20); mem < (128 << 20); mem += (1 << 20)) {
- if (*(unsigned long *)((unsigned long)(prom_init) + mem) ==
- *(unsigned long *)(prom_init))
+ /* Figure out memory size by finding aliases.
+ *
+ * We assume that there will be no more than 128 MB of memory,
+ * and that the memory size will be a multiple of 1 MB.
+ *
+ * We set 'before' to be the amount of memory (in MB) before this
+ * function, i.e. one MB less than the number of MB of memory that we
+ * *know* we have. And we set 'offset' to be the address of 'prominit'
+ * minus 'before', so that KSEG0 or KSEG1 base + offset < 1 MB.
+ * This prevents us from overrunning 128 MB and causing a bus error.
+ */
+ before = ((unsigned long) &prom_init) & (127 << 20);
+ offset = ((unsigned long) &prom_init) - before;
+ for (mem = before + (1 << 20); mem < (128 << 20); mem += (1 << 20))
+ if (*(unsigned long *)(offset + mem) ==
+ *(unsigned long *)(prom_init)) {
+ /*
+ * We may already be well past the end of memory at
+ * this point, so we'll have to compensate for it.
+ */
+ mem -= before;
break;
- }
+ }
add_memory_region(0, mem, BOOT_MEM_RAM);
}
-void __init
-prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
{
}
diff --git a/release/src/linux/linux/arch/mips/kernel/branch.c b/release/src/linux/linux/arch/mips/kernel/branch.c
index 8165789cbe..738ae74f12 100644
--- a/release/src/linux/linux/arch/mips/kernel/branch.c
+++ b/release/src/linux/linux/arch/mips/kernel/branch.c
@@ -170,7 +170,7 @@ int __compute_return_epc(struct pt_regs *regs)
bit = (insn.i_format.rt >> 2);
bit += (bit != 0);
bit += 23;
- switch (insn.i_format.rt) {
+ switch (insn.i_format.rt & 3) {
case 0: /* bc1f */
case 2: /* bc1fl */
if (~fcr31 & (1 << bit))
diff --git a/release/src/linux/linux/arch/mips/math-emu/cp1emu.c b/release/src/linux/linux/arch/mips/math-emu/cp1emu.c
index be1f732aa0..07f25d7437 100644
--- a/release/src/linux/linux/arch/mips/math-emu/cp1emu.c
+++ b/release/src/linux/linux/arch/mips/math-emu/cp1emu.c
@@ -528,9 +528,8 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
if (MIPSInst_FUNC(ir) != movc_op)
return SIGILL;
cond = fpucondbit[MIPSInst_RT(ir) >> 2];
- if (((ctx->sr & cond) != 0) != ((MIPSInst_RT(ir) & 1) != 0))
- return 0;
- xcp->regs[MIPSInst_RD(ir)] = xcp->regs[MIPSInst_RS(ir)];
+ if (((ctx->sr & cond) != 0) == ((MIPSInst_RT(ir) & 1) != 0))
+ xcp->regs[MIPSInst_RD(ir)] = xcp->regs[MIPSInst_RS(ir)];
break;
#endif
diff --git a/release/src/linux/linux/drivers/mtd/chips/gen_probe.c b/release/src/linux/linux/drivers/mtd/chips/gen_probe.c
index 4bed4f12a1..45ea742b0a 100644
--- a/release/src/linux/linux/drivers/mtd/chips/gen_probe.c
+++ b/release/src/linux/linux/drivers/mtd/chips/gen_probe.c
@@ -287,6 +287,7 @@ static struct mtd_info *check_cmd_set(struct map_info *map, int primary)
#endif
#ifdef CONFIG_MTD_CFI_AMDSTD
case 0x0002:
+ case 0x0006: /* for Winbond W19L320SBT9C */
return cfi_cmdset_0002(map, primary);
#endif
#ifdef CONFIG_MTD_CFI_SSTSTD
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_ROUTE.h b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_ROUTE.h
new file mode 100644
index 0000000000..41b1a9c867
--- /dev/null
+++ b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_ROUTE.h
@@ -0,0 +1,23 @@
+/* Header file for iptables ipt_ROUTE target
+ *
+ * (C) 2002 by Cédric de Launois
+ *
+ * This software is distributed under GNU GPL v2, 1991
+ */
+#ifndef _IPT_ROUTE_H_target
+#define _IPT_ROUTE_H_target
+
+#define IPT_ROUTE_IFNAMSIZ 16
+
+struct ipt_route_target_info {
+ char oif[IPT_ROUTE_IFNAMSIZ]; /* Output Interface Name */
+ char iif[IPT_ROUTE_IFNAMSIZ]; /* Input Interface Name */
+ u_int32_t gw; /* IP address of gateway */
+ u_int8_t flags;
+};
+
+/* Values for "flags" field */
+#define IPT_ROUTE_CONTINUE 0x01
+#define IPT_ROUTE_TEE 0x02
+
+#endif /*_IPT_ROUTE_H_target*/
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_ipp2p.h b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_ipp2p.h
new file mode 100644
index 0000000000..1bd3f649e6
--- /dev/null
+++ b/release/src/linux/linux/include/linux/netfilter_ipv4/ipt_ipp2p.h
@@ -0,0 +1,31 @@
+#ifndef __IPT_IPP2P_H
+#define __IPT_IPP2P_H
+#define IPP2P_VERSION "0.8.1_rc1"
+
+struct ipt_p2p_info {
+ int cmd;
+ int debug;
+};
+
+#endif //__IPT_IPP2P_H
+
+#define SHORT_HAND_IPP2P 1 /* --ipp2p switch*/
+//#define SHORT_HAND_DATA 4 /* --ipp2p-data switch*/
+#define SHORT_HAND_NONE 5 /* no short hand*/
+
+#define IPP2P_EDK (1 << 1)
+#define IPP2P_DATA_KAZAA (1 << 2)
+#define IPP2P_DATA_EDK (1 << 3)
+#define IPP2P_DATA_DC (1 << 4)
+#define IPP2P_DC (1 << 5)
+#define IPP2P_DATA_GNU (1 << 6)
+#define IPP2P_GNU (1 << 7)
+#define IPP2P_KAZAA (1 << 8)
+#define IPP2P_BIT (1 << 9)
+#define IPP2P_APPLE (1 << 10)
+#define IPP2P_SOUL (1 << 11)
+#define IPP2P_WINMX (1 << 12)
+#define IPP2P_ARES (1 << 13)
+#define IPP2P_MUTE (1 << 14)
+#define IPP2P_WASTE (1 << 15)
+#define IPP2P_XDCC (1 << 16)
diff --git a/release/src/linux/linux/include/linux/netfilter_ipv6/ip6t_ROUTE.h b/release/src/linux/linux/include/linux/netfilter_ipv6/ip6t_ROUTE.h
new file mode 100644
index 0000000000..c5ec871b50
--- /dev/null
+++ b/release/src/linux/linux/include/linux/netfilter_ipv6/ip6t_ROUTE.h
@@ -0,0 +1,23 @@
+/* Header file for iptables ip6t_ROUTE target
+ *
+ * (C) 2003 by Cédric de Launois
+ *
+ * This software is distributed under GNU GPL v2, 1991
+ */
+#ifndef _IPT_ROUTE_H_target
+#define _IPT_ROUTE_H_target
+
+#define IP6T_ROUTE_IFNAMSIZ 16
+
+struct ip6t_route_target_info {
+ char oif[IP6T_ROUTE_IFNAMSIZ]; /* Output Interface Name */
+ char iif[IP6T_ROUTE_IFNAMSIZ]; /* Input Interface Name */
+ u_int32_t gw[4]; /* IPv6 address of gateway */
+ u_int8_t flags;
+};
+
+/* Values for "flags" field */
+#define IP6T_ROUTE_CONTINUE 0x01
+#define IP6T_ROUTE_TEE 0x02
+
+#endif /*_IP6T_ROUTE_H_target*/
diff --git a/release/src/linux/linux/net/ipv4/arp.c b/release/src/linux/linux/net/ipv4/arp.c
index e458f7d5e6..aecd020aaa 100644
--- a/release/src/linux/linux/net/ipv4/arp.c
+++ b/release/src/linux/linux/net/ipv4/arp.c
@@ -171,8 +171,8 @@ struct neigh_table arp_tbl = {
id: "arp_cache",
parms: {
tbl: &arp_tbl,
-/*zhijian 2006-10-23 modify to solve arp entry timeout problem(cdrouter3.3 scaling module)*/
-#if 0
+ /*zhijian 2006-10-23 modify to solve arp entry timeout problem(cdrouter3.3 scaling module)*/
+ #if 0
base_reachable_time: 30 * HZ,
retrans_time: 1 * HZ,
gc_staletime: 60 * HZ,
@@ -181,16 +181,16 @@ struct neigh_table arp_tbl = {
queue_len: 3,
ucast_probes: 3,
mcast_probes: 3,
-#else
- base_reachable_time: 60 * HZ,
- retrans_time: 5 * HZ,
- gc_staletime: 120 * HZ,
- reachable_time: 60 * HZ,
- delay_probe_time: 10 * HZ,
- queue_len: 3,
- ucast_probes: 6,
- mcast_probes: 6,
-#endif
+ #else
+ base_reachable_time: 60 * HZ,
+ retrans_time: 5 * HZ,
+ gc_staletime: 120 * HZ,
+ reachable_time: 60 * HZ,
+ delay_probe_time: 10 * HZ,
+ queue_len: 3,
+ ucast_probes: 6,
+ mcast_probes: 6,
+ #endif
anycast_delay: 1 * HZ,
proxy_delay: (8 * HZ) / 10,
proxy_qlen: 64,
diff --git a/release/src/linux/linux/net/ipv4/igmp.c b/release/src/linux/linux/net/ipv4/igmp.c
index c53d8febcd..3f718f2a81 100644
--- a/release/src/linux/linux/net/ipv4/igmp.c
+++ b/release/src/linux/linux/net/ipv4/igmp.c
@@ -677,9 +677,8 @@ int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr)
count++;
}
err = -ENOBUFS;
- // if (iml == NULL || count >= sysctl_igmp_max_memberships)
- // 43011: modify for cdrouter v3.3 item 300(cdrouter_mcast_100) bug
- if (iml == NULL || count > sysctl_igmp_max_memberships)
+ //if (iml == NULL || count >= sysctl_igmp_max_memberships)
+ if (iml == NULL || count > sysctl_igmp_max_memberships)// modify for cdrouter v3.3 item 300(cdrouter_mcast_100) bug
goto done;
memcpy(&iml->multi, imr, sizeof(*imr));
iml->next = sk->protinfo.af_inet.mc_list;
diff --git a/release/src/linux/linux/net/ipv4/netfilter/Config.in b/release/src/linux/linux/net/ipv4/netfilter/Config.in
index 110a3987a9..b1f7f9858c 100644
--- a/release/src/linux/linux/net/ipv4/netfilter/Config.in
+++ b/release/src/linux/linux/net/ipv4/netfilter/Config.in
@@ -28,6 +28,7 @@ tristate 'IP tables support (required for filtering/masq/NAT)' CONFIG_IP_NF_IPTA
if [ "$CONFIG_IP_NF_IPTABLES" != "n" ]; then
# The simple matches.
dep_tristate ' limit match support' CONFIG_IP_NF_MATCH_LIMIT $CONFIG_IP_NF_IPTABLES
+ dep_tristate ' IPP2P match support' CONFIG_IP_NF_MATCH_IPP2P $CONFIG_IP_NF_IPTABLES
dep_tristate ' geoip match support' CONFIG_IP_NF_MATCH_GEOIP $CONFIG_IP_NF_IPTABLES
dep_tristate ' quota match support' CONFIG_IP_NF_MATCH_QUOTA $CONFIG_IP_NF_IPTABLES
dep_tristate ' IP range match support' CONFIG_IP_NF_MATCH_IPRANGE $CONFIG_IP_NF_IPTABLES
@@ -205,7 +206,8 @@ if [ "$CONFIG_IP_NF_IPTABLES" != "n" ]; then
dep_tristate ' DSCP target support' CONFIG_IP_NF_TARGET_DSCP $CONFIG_IP_NF_MANGLE
dep_tristate ' MARK target support' CONFIG_IP_NF_TARGET_MARK $CONFIG_IP_NF_MANGLE
- dep_tristate ' CLASSIFY target support (EXPERIMENTAL)' CONFIG_IP_NF_TARGET_CLASSIFY $CONFIG_IP_NF_FILTER
+ dep_tristate ' ROUTE target support' CONFIG_IP_NF_TARGET_ROUTE $CONFIG_IP_NF_MANGLE
+ dep_tristate ' CLASSIFY target support (EXPERIMENTAL)' CONFIG_IP_NF_TARGET_CLASSIFY $CONFIG_IP_NF_FILTER
dep_tristate ' IMQ target support' CONFIG_IP_NF_TARGET_IMQ $CONFIG_IP_NF_MANGLE
fi
dep_tristate ' LOG target support' CONFIG_IP_NF_TARGET_LOG $CONFIG_IP_NF_IPTABLES
diff --git a/release/src/linux/linux/net/ipv4/netfilter/Makefile b/release/src/linux/linux/net/ipv4/netfilter/Makefile
index 8b4bd57e12..80de56f339 100644
--- a/release/src/linux/linux/net/ipv4/netfilter/Makefile
+++ b/release/src/linux/linux/net/ipv4/netfilter/Makefile
@@ -112,6 +112,7 @@ obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o
# matches
obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
+obj-$(CONFIG_IP_NF_MATCH_IPP2P) += ipt_ipp2p.o
obj-$(CONFIG_IP_NF_MATCH_GEOIP) += ipt_geoip.o
obj-$(CONFIG_IP_NF_MATCH_QUOTA) += ipt_quota.o
obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
@@ -158,6 +159,7 @@ obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
obj-$(CONFIG_IP_NF_TARGET_IMQ) += ipt_IMQ.o
obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
+obj-$(CONFIG_IP_NF_TARGET_ROUTE) += ipt_ROUTE.o
obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ipt_ROUTE.c b/release/src/linux/linux/net/ipv4/netfilter/ipt_ROUTE.c
new file mode 100644
index 0000000000..b97d779260
--- /dev/null
+++ b/release/src/linux/linux/net/ipv4/netfilter/ipt_ROUTE.c
@@ -0,0 +1,422 @@
+/*
+ * This implements the ROUTE target, which enables you to setup unusual
+ * routes not supported by the standard kernel routing table.
+ *
+ * Copyright (C) 2002 Cedric de Launois
+ *
+ * v 1.11 2004/11/23
+ *
+ * This software is distributed under GNU GPL v2, 1991
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+
+/* Try to route the packet according to the routing keys specified in
+ * route_info. Keys are :
+ * - ifindex :
+ * 0 if no oif preferred,
+ * otherwise set to the index of the desired oif
+ * - route_info->gw :
+ * 0 if no gateway specified,
+ * otherwise set to the next host to which the pkt must be routed
+ * If success, skb->dev is the output device to which the packet must
+ * be sent and skb->dst is not NULL
+ *
+ * RETURN: -1 if an error occured
+ * 1 if the packet was succesfully routed to the
+ * destination desired
+ * 0 if the kernel routing table could not route the packet
+ * according to the keys specified
+ */
+static int route(struct sk_buff *skb,
+ unsigned int ifindex,
+ const struct ipt_route_target_info *route_info)
+{
+ int err;
+ struct rtable *rt;
+ struct iphdr *iph = skb->nh.iph;
+ struct rt_key key = {
+ dst:iph->daddr,
+ src:0,
+ oif:ifindex,
+ tos:RT_TOS(iph->tos)
+ };
+
+ /* The destination address may be overloaded by the target */
+ if (route_info->gw)
+ key.dst = route_info->gw;
+
+ /* Trying to route the packet using the standard routing table. */
+ if ((err = ip_route_output_key(&rt, &key))) {
+ if (net_ratelimit())
+ DEBUGP("ipt_ROUTE: couldn't route pkt (err: %i)",err);
+ return -1;
+ }
+
+ /* Drop old route. */
+ dst_release(skb->dst);
+ skb->dst = NULL;
+
+ /* Success if no oif specified or if the oif correspond to the
+ * one desired */
+ if (!ifindex || rt->u.dst.dev->ifindex == ifindex) {
+ skb->dst = &rt->u.dst;
+ skb->dev = skb->dst->dev;
+ return 1;
+ }
+
+ /* The interface selected by the routing table is not the one
+ * specified by the user. This may happen because the dst address
+ * is one of our own addresses.
+ */
+ if (net_ratelimit())
+ DEBUGP("ipt_ROUTE: failed to route as desired gw=%u.%u.%u.%u oif=%i (got oif=%i)\n",
+ NIPQUAD(route_info->gw), ifindex, rt->u.dst.dev->ifindex);
+
+ return 0;
+}
+
+
+/* Stolen from ip_finish_output2
+ * PRE : skb->dev is set to the device we are leaving by
+ * skb->dst is not NULL
+ * POST: the packet is sent with the link layer header pushed
+ * the packet is destroyed
+ */
+static void ip_direct_send(struct sk_buff *skb)
+{
+ struct dst_entry *dst = skb->dst;
+ struct hh_cache *hh = dst->hh;
+
+ if (hh) {
+ read_lock_bh(&hh->hh_lock);
+ memcpy(skb->data - 16, hh->hh_data, 16);
+ read_unlock_bh(&hh->hh_lock);
+ skb_push(skb, hh->hh_len);
+ hh->hh_output(skb);
+ } else if (dst->neighbour)
+ dst->neighbour->output(skb);
+ else {
+ if (net_ratelimit())
+ DEBUGP(KERN_DEBUG "ipt_ROUTE: no hdr & no neighbour cache!\n");
+ kfree_skb(skb);
+ }
+}
+
+
+/* PRE : skb->dev is set to the device we are leaving by
+ * POST: - the packet is directly sent to the skb->dev device, without
+ * pushing the link layer header.
+ * - the packet is destroyed
+ */
+static inline int dev_direct_send(struct sk_buff *skb)
+{
+ return dev_queue_xmit(skb);
+}
+
+
+static unsigned int route_oif(const struct ipt_route_target_info *route_info,
+ struct sk_buff *skb)
+{
+ unsigned int ifindex = 0;
+ struct net_device *dev_out = NULL;
+
+ /* The user set the interface name to use.
+ * Getting the current interface index.
+ */
+ if ((dev_out = dev_get_by_name(route_info->oif))) {
+ ifindex = dev_out->ifindex;
+ } else {
+ /* Unknown interface name : packet dropped */
+ if (net_ratelimit())
+ DEBUGP("ipt_ROUTE: oif interface %s not found\n", route_info->oif);
+ return NF_DROP;
+ }
+
+ /* Trying the standard way of routing packets */
+ switch (route(skb, ifindex, route_info)) {
+ case 1:
+ dev_put(dev_out);
+ if (route_info->flags & IPT_ROUTE_CONTINUE)
+ return IPT_CONTINUE;
+
+ ip_direct_send(skb);
+ return NF_STOLEN;
+
+ case 0:
+ /* Failed to send to oif. Trying the hard way */
+ if (route_info->flags & IPT_ROUTE_CONTINUE)
+ return NF_DROP;
+
+ if (net_ratelimit())
+ DEBUGP("ipt_ROUTE: forcing the use of %i\n",
+ ifindex);
+
+ /* We have to force the use of an interface.
+ * This interface must be a tunnel interface since
+ * otherwise we can't guess the hw address for
+ * the packet. For a tunnel interface, no hw address
+ * is needed.
+ */
+ if ((dev_out->type != ARPHRD_TUNNEL)
+ && (dev_out->type != ARPHRD_IPGRE)) {
+ if (net_ratelimit())
+ DEBUGP("ipt_ROUTE: can't guess the hw addr !\n");
+ dev_put(dev_out);
+ return NF_DROP;
+ }
+
+ /* Send the packet. This will also free skb
+ * Do not go through the POST_ROUTING hook because
+ * skb->dst is not set and because it will probably
+ * get confused by the destination IP address.
+ */
+ skb->dev = dev_out;
+ dev_direct_send(skb);
+ dev_put(dev_out);
+ return NF_STOLEN;
+
+ default:
+ /* Unexpected error */
+ dev_put(dev_out);
+ return NF_DROP;
+ }
+}
+
+
+static unsigned int route_iif(const struct ipt_route_target_info *route_info,
+ struct sk_buff *skb)
+{
+ struct net_device *dev_in = NULL;
+
+ /* Getting the current interface index. */
+ if (!(dev_in = dev_get_by_name(route_info->iif))) {
+ if (net_ratelimit())
+ DEBUGP("ipt_ROUTE: iif interface %s not found\n", route_info->iif);
+ return NF_DROP;
+ }
+
+ skb->dev = dev_in;
+ dst_release(skb->dst);
+ skb->dst = NULL;
+
+ netif_rx(skb);
+ dev_put(dev_in);
+ return NF_STOLEN;
+}
+
+
+static unsigned int route_gw(const struct ipt_route_target_info *route_info,
+ struct sk_buff *skb)
+{
+ if (route(skb, 0, route_info)!=1)
+ return NF_DROP;
+
+ if (route_info->flags & IPT_ROUTE_CONTINUE)
+ return IPT_CONTINUE;
+
+ ip_direct_send(skb);
+ return NF_STOLEN;
+}
+
+/* To detect and deter routed packet loopback when using the --tee option,
+ * we take a page out of the raw.patch book: on the copied skb, we set up
+ * a fake ->nfct entry, pointing to the local &route_tee_track. We skip
+ * routing packets when we see they already have that ->nfct.
+ */
+
+static struct ip_conntrack route_tee_track;
+
+static unsigned int ipt_route_target(struct sk_buff **pskb,
+ unsigned int hooknum,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *targinfo,
+ void *userinfo)
+{
+ const struct ipt_route_target_info *route_info = targinfo;
+ struct sk_buff *skb = *pskb;
+ unsigned int res;
+
+ /* If we are at PREROUTING or INPUT hook
+ * the TTL isn't decreased by the IP stack
+ */
+ if (hooknum == NF_IP_PRE_ROUTING ||
+ hooknum == NF_IP_LOCAL_IN) {
+
+ struct iphdr *iph = skb->nh.iph;
+
+ if (iph->ttl <= 1) {
+ struct rtable *rt;
+
+ if (ip_route_output(&rt, iph->saddr, iph->daddr,
+ RT_TOS(iph->tos) | RTO_CONN,
+ 0)) {
+ return NF_DROP;
+ }
+
+ if (skb->dev == rt->u.dst.dev) {
+ /* Drop old route. */
+ dst_release(skb->dst);
+ skb->dst = &rt->u.dst;
+
+ /* this will traverse normal stack, and
+ * thus call conntrack on the icmp packet */
+ icmp_send(skb, ICMP_TIME_EXCEEDED,
+ ICMP_EXC_TTL, 0);
+ }
+
+ return NF_DROP;
+ }
+
+ /*
+ * If we are at INPUT the checksum must be recalculated since
+ * the length could change as the result of a defragmentation.
+ * -- Rickard Molin
+ */
+ if(hooknum == NF_IP_LOCAL_IN) {
+ iph->ttl = iph->ttl - 1;
+ iph->check = 0;
+ iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
+ } else {
+ ip_decrease_ttl(iph);
+ }
+ }
+
+ if ((route_info->flags & IPT_ROUTE_TEE)) {
+ /*
+ * Copy the *pskb, and route the copy. Will later return
+ * IPT_CONTINUE for the original skb, which should continue
+ * on its way as if nothing happened. The copy should be
+ * independantly delivered to the ROUTE --gw.
+ */
+ skb = skb_copy(*pskb, GFP_ATOMIC);
+ if (!skb) {
+ if (net_ratelimit())
+ DEBUGP(KERN_DEBUG "ipt_ROUTE: copy failed!\n");
+ return IPT_CONTINUE;
+ }
+ }
+
+ /* Tell conntrack to forget this packet since it may get confused
+ * when a packet is leaving with dst address == our address.
+ * Good idea ? Dunno. Need advice.
+ *
+ * NEW: mark the skb with our &route_tee_track, so we avoid looping
+ * on any already routed packet.
+ */
+ if (!(route_info->flags & IPT_ROUTE_CONTINUE)) {
+ nf_conntrack_put(skb->nfct);
+ skb->nfct = &route_tee_track.infos[IP_CT_NEW];
+ nf_conntrack_get(skb->nfct);
+ skb->nfcache = 0;
+#ifdef CONFIG_NETFILTER_DEBUG
+ skb->nf_debug = 0;
+#endif
+ }
+
+ if (route_info->oif[0]) {
+ res = route_oif(route_info, skb);
+ } else if (route_info->iif[0]) {
+ res = route_iif(route_info, skb);
+ } else if (route_info->gw) {
+ res = route_gw(route_info, skb);
+ } else {
+ if (net_ratelimit())
+ DEBUGP(KERN_DEBUG "ipt_ROUTE: no parameter !\n");
+ res = IPT_CONTINUE;
+ }
+
+ if ((route_info->flags & IPT_ROUTE_TEE))
+ res = IPT_CONTINUE;
+
+ return res;
+}
+
+
+static int ipt_route_checkentry(const char *tablename,
+ const struct ipt_entry *e,
+ void *targinfo,
+ unsigned int targinfosize,
+ unsigned int hook_mask)
+{
+ if (strcmp(tablename, "mangle") != 0) {
+ printk("ipt_ROUTE: bad table `%s', use the `mangle' table.\n",
+ tablename);
+ return 0;
+ }
+
+ if (hook_mask & ~( (1 << NF_IP_PRE_ROUTING)
+ | (1 << NF_IP_LOCAL_IN)
+ | (1 << NF_IP_FORWARD)
+ | (1 << NF_IP_LOCAL_OUT)
+ | (1 << NF_IP_POST_ROUTING))) {
+ printk("ipt_ROUTE: bad hook\n");
+ return 0;
+ }
+
+ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_route_target_info))) {
+ printk(KERN_WARNING "ipt_ROUTE: targinfosize %u != %Zu\n",
+ targinfosize,
+ IPT_ALIGN(sizeof(struct ipt_route_target_info)));
+ return 0;
+ }
+
+ return 1;
+}
+
+
+static struct ipt_target ipt_route_reg
+= { { NULL, NULL }, "ROUTE", ipt_route_target, ipt_route_checkentry, NULL,
+ THIS_MODULE };
+
+
+static int __init init(void)
+{
+ /* Set up fake conntrack (stolen from raw.patch):
+ - to never be deleted, not in any hashes */
+ atomic_set(&route_tee_track.ct_general.use, 1);
+ /* - and look it like as a confirmed connection */
+ set_bit(IPS_CONFIRMED_BIT, &route_tee_track.status);
+ /* - and prepare the ctinfo field for REJECT/NAT. */
+ route_tee_track.infos[IP_CT_NEW].master =
+ route_tee_track.infos[IP_CT_RELATED].master =
+ route_tee_track.infos[IP_CT_RELATED + IP_CT_IS_REPLY].master =
+ &route_tee_track.ct_general;
+ /* Initialize fake conntrack so that NAT will skip it */
+ route_tee_track.nat.info.initialized |=
+ (1 << IP_NAT_MANIP_SRC) | (1 << IP_NAT_MANIP_DST);
+
+ if (ipt_register_target(&ipt_route_reg))
+ return -EINVAL;
+
+ return 0;
+}
+
+
+static void __exit fini(void)
+{
+ ipt_unregister_target(&ipt_route_reg);
+}
+
+module_init(init);
+module_exit(fini);
+MODULE_LICENSE("GPL");
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ipt_connlimit.c b/release/src/linux/linux/net/ipv4/netfilter/ipt_connlimit.c
index 568d1bf0af..abf8efff65 100644
--- a/release/src/linux/linux/net/ipv4/netfilter/ipt_connlimit.c
+++ b/release/src/linux/linux/net/ipv4/netfilter/ipt_connlimit.c
@@ -13,6 +13,7 @@
#include
#include
#include
+#include
#include
#include
#include
diff --git a/release/src/linux/linux/net/ipv4/netfilter/ipt_ipp2p.c b/release/src/linux/linux/net/ipv4/netfilter/ipt_ipp2p.c
new file mode 100644
index 0000000000..c36b2005be
--- /dev/null
+++ b/release/src/linux/linux/net/ipv4/netfilter/ipt_ipp2p.c
@@ -0,0 +1,868 @@
+#if defined(MODVERSIONS)
+#include
+#endif
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define get_u8(X,O) (*(__u8 *)(X + O))
+#define get_u16(X,O) (*(__u16 *)(X + O))
+#define get_u32(X,O) (*(__u32 *)(X + O))
+
+MODULE_AUTHOR("Eicke Friedrich/Klaus Degner ");
+MODULE_DESCRIPTION("An extension to iptables to identify P2P traffic.");
+MODULE_LICENSE("GPL");
+
+
+/*Search for UDP eDonkey/eMule/Kad commands*/
+int
+udp_search_edk (unsigned char *haystack, int packet_len)
+{
+ unsigned char *t = haystack;
+ t += 8;
+
+ switch (t[0]) {
+ case 0xe3:
+ { /*edonkey*/
+ switch (t[1])
+ {
+ /* client -> server status request */
+ case 0x96:
+ if (packet_len == 14) return ((IPP2P_EDK * 100) + 50);
+ break;
+ /* server -> client status request */
+ case 0x97: if (packet_len == 42) return ((IPP2P_EDK * 100) + 51);
+ break;
+ /* server description request */
+ /* e3 2a ff f0 .. | size == 6 */
+ case 0xa2: if ( (packet_len == 14) && ( get_u16(t,2) == __constant_htons(0xfff0) ) ) return ((IPP2P_EDK * 100) + 52);
+ break;
+ /* server description response */
+ /* e3 a3 ff f0 .. | size > 40 && size < 200 */
+ //case 0xa3: return ((IPP2P_EDK * 100) + 53);
+ // break;
+ case 0x9a: if (packet_len==26) return ((IPP2P_EDK * 100) + 54);
+ break;
+
+ case 0x92: if (packet_len==18) return ((IPP2P_EDK * 100) + 55);
+ break;
+ }
+ break;
+ }
+ case 0xe4:
+ {
+ switch (t[1])
+ {
+ /* e4 20 .. | size == 43 */
+ case 0x20: if ((packet_len == 43) && (t[2] != 0x00) && (t[34] != 0x00)) return ((IPP2P_EDK * 100) + 60);
+ break;
+ /* e4 00 .. 00 | size == 35 ? */
+ case 0x00: if ((packet_len == 35) && (t[26] == 0x00)) return ((IPP2P_EDK * 100) + 61);
+ break;
+ /* e4 10 .. 00 | size == 35 ? */
+ case 0x10: if ((packet_len == 35) && (t[26] == 0x00)) return ((IPP2P_EDK * 100) + 62);
+ break;
+ /* e4 18 .. 00 | size == 35 ? */
+ case 0x18: if ((packet_len == 35) && (t[26] == 0x00)) return ((IPP2P_EDK * 100) + 63);
+ break;
+ /* e4 52 .. | size = 44 */
+ case 0x52: if (packet_len == 44 ) return ((IPP2P_EDK * 100) + 64);
+ break;
+ /* e4 58 .. | size == 6 */
+ case 0x58: if (packet_len == 14 ) return ((IPP2P_EDK * 100) + 65);
+ break;
+ /* e4 59 .. | size == 2 */
+ case 0x59: if (packet_len == 10 )return ((IPP2P_EDK * 100) + 66);
+ break;
+ /* e4 28 .. | packet_len == 52,77,102,127... */
+ case 0x28: if (((packet_len-52) % 25) == 0) return ((IPP2P_EDK * 100) + 67);
+ break;
+ /* e4 50 xx xx | size == 4 */
+ case 0x50: if (packet_len == 12) return ((IPP2P_EDK * 100) + 68);
+ break;
+ /* e4 40 xx xx | size == 48 */
+ case 0x40: if (packet_len == 56) return ((IPP2P_EDK * 100) + 69);
+ break;
+ }
+ break;
+ }
+ } /* end of switch (t[0]) */
+ return 0;
+}/*udp_search_edk*/
+
+
+/*Search for UDP Gnutella commands*/
+int
+udp_search_gnu (unsigned char *haystack, int packet_len)
+{
+ unsigned char *t = haystack;
+ t += 8;
+
+ if (memcmp(t, "GND", 3) == 0) return ((IPP2P_GNU * 100) + 51);
+ if (memcmp(t, "GNUTELLA ", 9) == 0) return ((IPP2P_GNU * 100) + 52);
+ return 0;
+}/*udp_search_gnu*/
+
+
+/*Search for UDP KaZaA commands*/
+int
+udp_search_kazaa (unsigned char *haystack, int packet_len)
+{
+ unsigned char *t = haystack;
+
+ if (t[packet_len-1] == 0x00){
+ t += (packet_len - 6);
+ if (memcmp(t, "KaZaA", 5) == 0) return (IPP2P_KAZAA * 100 +50);
+ }
+
+ return 0;
+}/*udp_search_kazaa*/
+
+/*Search for UDP DirectConnect commands*/
+int
+udp_search_directconnect (unsigned char *haystack, int packet_len)
+{
+ unsigned char *t = haystack;
+ if ((*(t + 8) == 0x24) && (*(t + packet_len - 1) == 0x7c)) {
+ t+=8;
+ if (memcmp(t, "SR ", 3) == 0) return ((IPP2P_DC * 100) + 60);
+ if (memcmp(t, "Ping ", 5) == 0) return ((IPP2P_DC * 100) + 61);
+ }
+ return 0;
+}/*udp_search_directconnect*/
+
+
+
+/*Search for UDP BitTorrent commands*/
+int
+udp_search_bit (unsigned char *haystack, int packet_len)
+{
+ switch(packet_len)
+ {
+ case 24:
+ /* ^ 00 00 04 17 27 10 19 80 */
+ if ((ntohl(get_u32(haystack, 8)) == 0x00000417) && (ntohl(get_u32(haystack, 12)) == 0x27101980))
+ return (IPP2P_BIT * 100 + 50);
+ break;
+ case 44:
+ if (get_u32(haystack, 16) == __constant_htonl(0x00000400) && get_u32(haystack, 36) == __constant_htonl(0x00000104))
+ return (IPP2P_BIT * 100 + 51);
+ if (get_u32(haystack, 16) == __constant_htonl(0x00000400))
+ return (IPP2P_BIT * 100 + 61);
+ break;
+ case 65:
+ if (get_u32(haystack, 16) == __constant_htonl(0x00000404) && get_u32(haystack, 36) == __constant_htonl(0x00000104))
+ return (IPP2P_BIT * 100 + 52);
+ if (get_u32(haystack, 16) == __constant_htonl(0x00000404))
+ return (IPP2P_BIT * 100 + 62);
+ break;
+ case 67:
+ if (get_u32(haystack, 16) == __constant_htonl(0x00000406) && get_u32(haystack, 36) == __constant_htonl(0x00000104))
+ return (IPP2P_BIT * 100 + 53);
+ if (get_u32(haystack, 16) == __constant_htonl(0x00000406))
+ return (IPP2P_BIT * 100 + 63);
+ break;
+ case 211:
+ if (get_u32(haystack, 8) == __constant_htonl(0x00000405))
+ return (IPP2P_BIT * 100 + 54);
+ break;
+ case 29:
+ if ((get_u32(haystack, 8) == __constant_htonl(0x00000401)))
+ return (IPP2P_BIT * 100 + 55);
+ break;
+ case 52:
+ if (get_u32(haystack,8) == __constant_htonl(0x00000827) &&
+ get_u32(haystack,12) == __constant_htonl(0x37502950))
+ return (IPP2P_BIT * 100 + 80);
+ break;
+ default:
+ /* this packet does not have a constant size */
+ if (packet_len >= 40 && get_u32(haystack, 16) == __constant_htonl(0x00000402) && get_u32(haystack, 36) == __constant_htonl(0x00000104))
+ return (IPP2P_BIT * 100 + 56);
+ break;
+ }
+
+ /* some extra-bitcomet rules:
+ * "d1:" [a|r] "d2:id20:"
+ */
+ if (packet_len > 30 && get_u8(haystack, 8) == 'd' && get_u8(haystack, 9) == '1' && get_u8(haystack, 10) == ':' )
+ {
+ if (get_u8(haystack, 11) == 'a' || get_u8(haystack, 11) == 'r')
+ {
+ if (memcmp(haystack+12,"d2:id20:",8)==0)
+ return (IPP2P_BIT * 100 + 57);
+ }
+ }
+
+#if 0
+ /* bitlord rules */
+ /* packetlen must be bigger than 40 */
+ /* first 4 bytes are zero */
+ if (packet_len > 40 && get_u32(haystack, 8) == 0x00000000)
+ {
+ /* first rule: 00 00 00 00 01 00 00 xx xx xx xx 00 00 00 00*/
+ if (get_u32(haystack, 12) == 0x00000000 &&
+ get_u32(haystack, 16) == 0x00010000 &&
+ get_u32(haystack, 24) == 0x00000000 )
+ return (IPP2P_BIT * 100 + 71);
+
+ /* 00 01 00 00 0d 00 00 xx xx xx xx 00 00 00 00*/
+ if (get_u32(haystack, 12) == 0x00000001 &&
+ get_u32(haystack, 16) == 0x000d0000 &&
+ get_u32(haystack, 24) == 0x00000000 )
+ return (IPP2P_BIT * 100 + 71);
+
+
+ }
+#endif
+
+ return 0;
+}/*udp_search_bit*/
+
+
+
+/*Search for Ares commands*/
+//#define IPP2P_DEBUG_ARES
+int
+search_ares (const unsigned char *payload, const u16 plen)
+//int search_ares (unsigned char *haystack, int packet_len, int head_len)
+{
+// const unsigned char *t = haystack + head_len;
+
+ /* all ares packets start with */
+ if (payload[1] == 0 && (plen - payload[0]) == 3)
+ {
+ switch (payload[2])
+ {
+ case 0x5a:
+ /* ares connect */
+ if ( plen == 6 && payload[5] == 0x05 ) return ((IPP2P_ARES * 100) + 1);
+ break;
+ case 0x09:
+ /* ares search, min 3 chars --> 14 bytes
+ * lets define a search can be up to 30 chars --> max 34 bytes
+ */
+ if ( plen >= 14 && plen <= 34 ) return ((IPP2P_ARES * 100) + 1);
+ break;
+#ifdef IPP2P_DEBUG_ARES
+ default:
+ printk(KERN_DEBUG "Unknown Ares command %x recognized, len: %u \n", (unsigned int) payload[2],plen);
+#endif /* IPP2P_DEBUG_ARES */
+ }
+ }
+
+#if 0
+ /* found connect packet: 03 00 5a 04 03 05 */
+ /* new version ares 1.8: 03 00 5a xx xx 05 */
+ if ((plen) == 6){ /* possible connect command*/
+ if ((payload[0] == 0x03) && (payload[1] == 0x00) && (payload[2] == 0x5a) && (payload[5] == 0x05))
+ return ((IPP2P_ARES * 100) + 1);
+ }
+ if ((plen) == 60){ /* possible download command*/
+ if ((payload[59] == 0x0a) && (payload[58] == 0x0a)){
+ if (memcmp(t, "PUSH SHA1:", 10) == 0) /* found download command */
+ return ((IPP2P_ARES * 100) + 2);
+ }
+ }
+#endif
+
+ return 0;
+} /*search_ares*/
+
+/*Search for SoulSeek commands*/
+int
+search_soul (const unsigned char *payload, const u16 plen)
+{
+//#define IPP2P_DEBUG_SOUL
+ /* match: xx xx xx xx | xx = sizeof(payload) - 4 */
+ if (get_u32(payload, 0) == (plen - 4)){
+ const __u32 m=get_u32(payload, 4);
+ /* match 00 yy yy 00, yy can be everything */
+ if ( get_u8(payload, 4) == 0x00 && get_u8(payload, 7) == 0x00 )
+ {
+#ifdef IPP2P_DEBUG_SOUL
+ printk(KERN_DEBUG "0: Soulseek command 0x%x recognized\n",get_u32(payload, 4));
+#endif /* IPP2P_DEBUG_SOUL */
+ return ((IPP2P_SOUL * 100) + 1);
+ }
+
+ /* next match: 01 yy 00 00 | yy can be everything */
+ if ( get_u8(payload, 4) == 0x01 && get_u16(payload, 6) == 0x0000 )
+ {
+#ifdef IPP2P_DEBUG_SOUL
+ printk(KERN_DEBUG "1: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
+#endif /* IPP2P_DEBUG_SOUL */
+ return ((IPP2P_SOUL * 100) + 2);
+ }
+
+ /* other soulseek commandos are: 1-5,7,9,13-18,22,23,26,28,35-37,40-46,50,51,60,62-69,91,92,1001 */
+ /* try to do this in an intelligent way */
+ /* get all small commandos */
+ switch(m)
+ {
+ case 7:
+ case 9:
+ case 22:
+ case 23:
+ case 26:
+ case 28:
+ case 50:
+ case 51:
+ case 60:
+ case 91:
+ case 92:
+ case 1001:
+#ifdef IPP2P_DEBUG_SOUL
+ printk(KERN_DEBUG "2: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
+#endif /* IPP2P_DEBUG_SOUL */
+ return ((IPP2P_SOUL * 100) + 3);
+ }
+
+ if (m > 0 && m < 6 )
+ {
+#ifdef IPP2P_DEBUG_SOUL
+ printk(KERN_DEBUG "3: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
+#endif /* IPP2P_DEBUG_SOUL */
+ return ((IPP2P_SOUL * 100) + 4);
+ }
+ if (m > 12 && m < 19 )
+ {
+#ifdef IPP2P_DEBUG_SOUL
+ printk(KERN_DEBUG "4: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
+#endif /* IPP2P_DEBUG_SOUL */
+ return ((IPP2P_SOUL * 100) + 5);
+ }
+
+ if (m > 34 && m < 38 )
+ {
+#ifdef IPP2P_DEBUG_SOUL
+ printk(KERN_DEBUG "5: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
+#endif /* IPP2P_DEBUG_SOUL */
+ return ((IPP2P_SOUL * 100) + 6);
+ }
+
+ if (m > 39 && m < 47 )
+ {
+#ifdef IPP2P_DEBUG_SOUL
+ printk(KERN_DEBUG "6: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
+#endif /* IPP2P_DEBUG_SOUL */
+ return ((IPP2P_SOUL * 100) + 7);
+ }
+
+ if (m > 61 && m < 70 )
+ {
+#ifdef IPP2P_DEBUG_SOUL
+ printk(KERN_DEBUG "7: Soulseek command 0x%x recognized\n",get_u16(payload, 4));
+#endif /* IPP2P_DEBUG_SOUL */
+ return ((IPP2P_SOUL * 100) + 8);
+ }
+
+#ifdef IPP2P_DEBUG_SOUL
+ printk(KERN_DEBUG "unknown SOULSEEK command: 0x%x, first 16 bit: 0x%x, first 8 bit: 0x%x ,soulseek ???\n",get_u32(payload, 4),get_u16(payload, 4) >> 16,get_u8(payload, 4) >> 24);
+#endif /* IPP2P_DEBUG_SOUL */
+ }
+
+ /* match 14 00 00 00 01 yy 00 00 00 STRING(YY) 01 00 00 00 00 46|50 00 00 00 00 */
+ /* without size at the beginning !!! */
+ if ( get_u32(payload, 0) == 0x14 && get_u8(payload, 4) == 0x01 )
+ {
+ __u32 y=get_u32(payload, 5);
+ /* we need 19 chars + string */
+ if ( (y + 19) <= (plen) )
+ {
+ const unsigned char *w=payload+9+y;
+ if (get_u32(w, 0) == 0x01 && ( get_u16(w, 4) == 0x4600 || get_u16(w, 4) == 0x5000) && get_u32(w, 6) == 0x00);
+#ifdef IPP2P_DEBUG_SOUL
+ printk(KERN_DEBUG "Soulssek special client command recognized\n");
+#endif /* IPP2P_DEBUG_SOUL */
+ return ((IPP2P_SOUL * 100) + 9);
+ }
+ }
+ return 0;
+}
+
+
+/*Search for WinMX commands*/
+int
+search_winmx (const unsigned char *payload, const u16 plen)
+{
+//#define IPP2P_DEBUG_WINMX
+ if (((plen) == 4) && (memcmp(payload, "SEND", 4) == 0)) return ((IPP2P_WINMX * 100) + 1);
+ if (((plen) == 3) && (memcmp(payload, "GET", 3) == 0)) return ((IPP2P_WINMX * 100) + 2);
+ //if (packet_len < (head_len + 10)) return 0;
+ if (plen < 10) return 0;
+
+ if ((memcmp(payload, "SEND", 4) == 0) || (memcmp(payload, "GET", 3) == 0)){
+ u16 c=4;
+ const u16 end=plen-2;
+ u8 count=0;
+ while (c < end)
+ {
+ if (payload[c]== 0x20 && payload[c+1] == 0x22)
+ {
+ c++;
+ count++;
+ if (count>=2) return ((IPP2P_WINMX * 100) + 3);
+ }
+ c++;
+ }
+ }
+
+ if ( plen == 149 && payload[0] == '8' )
+ {
+#ifdef IPP2P_DEBUG_WINMX
+ printk(KERN_INFO "maybe WinMX\n");
+#endif
+ if (get_u32(payload,17) == 0 && get_u32(payload,21) == 0 && get_u32(payload,25) == 0 &&
+// get_u32(payload,33) == __constant_htonl(0x71182b1a) && get_u32(payload,37) == __constant_htonl(0x05050000) &&
+// get_u32(payload,133) == __constant_htonl(0x31097edf) && get_u32(payload,145) == __constant_htonl(0xdcb8f792))
+ get_u16(payload,39) == 0 && get_u16(payload,135) == __constant_htons(0x7edf) && get_u16(payload,147) == __constant_htons(0xf792))
+
+ {
+#ifdef IPP2P_DEBUG_WINMX
+ printk(KERN_INFO "got WinMX\n");
+#endif
+ return ((IPP2P_WINMX * 100) + 4);
+ }
+ }
+ return 0;
+} /*search_winmx*/
+
+
+/*Search for appleJuice commands*/
+int
+search_apple (const unsigned char *payload, const u16 plen)
+{
+ if ( (plen > 7) && (payload[6] == 0x0d) && (payload[7] == 0x0a) && (memcmp(payload, "ajprot", 6) == 0)) return (IPP2P_APPLE * 100);
+
+ return 0;
+}
+
+
+/*Search for BitTorrent commands*/
+int
+search_bittorrent (const unsigned char *payload, const u16 plen)
+{
+ if (plen > 20)
+ {
+ /* test for match 0x13+"BitTorrent protocol" */
+ if (payload[0] == 0x13)
+ {
+ if (memcmp(payload+1, "BitTorrent protocol", 19) == 0) return (IPP2P_BIT * 100);
+ }
+
+ /* get tracker commandos, all starts with GET /
+ * then it can follow: scrape| announce
+ * and then ?hash_info=
+ */
+ if (memcmp(payload,"GET /",5) == 0)
+ {
+ /* message scrape */
+ if ( memcmp(payload+5,"scrape?info_hash=",17)==0 ) return (IPP2P_BIT * 100 + 1);
+ /* message announce */
+ if ( memcmp(payload+5,"announce?info_hash=",19)==0 ) return (IPP2P_BIT * 100 + 2);
+ }
+ }
+ else
+ {
+ /* bitcomet encryptes the first packet, so we have to detect another
+ * one later in the flow */
+ /* first try failed, too many missdetections */
+ //if ( size == 5 && get_u32(t,0) == __constant_htonl(1) && t[4] < 3) return (IPP2P_BIT * 100 + 3);
+
+ /* second try: block request packets */
+ if ( plen == 17 && get_u32(payload,0) == __constant_htonl(0x0d) && payload[4] == 0x06 && get_u32(payload,13) == __constant_htonl(0x4000) ) return (IPP2P_BIT * 100 + 3);
+ }
+
+ return 0;
+}
+
+
+
+/*check for Kazaa get command*/
+int
+search_kazaa (const unsigned char *payload, const u16 plen)
+
+{
+ if ((payload[plen-2] == 0x0d) && (payload[plen-1] == 0x0a) && memcmp(payload, "GET /.hash=", 11) == 0)
+ return (IPP2P_DATA_KAZAA * 100);
+
+ return 0;
+}
+
+
+/*check for gnutella get command*/
+int
+search_gnu (const unsigned char *payload, const u16 plen)
+{
+ if ((payload[plen-2] == 0x0d) && (payload[plen-1] == 0x0a))
+ {
+ if (memcmp(payload, "GET /get/", 9) == 0) return ((IPP2P_DATA_GNU * 100) + 1);
+ if (memcmp(payload, "GET /uri-res/", 13) == 0) return ((IPP2P_DATA_GNU * 100) + 2);
+ }
+ return 0;
+}
+
+
+/*check for gnutella get commands and other typical data*/
+int
+search_all_gnu (const unsigned char *payload, const u16 plen)
+{
+
+ if ((payload[plen-2] == 0x0d) && (payload[plen-1] == 0x0a))
+ {
+
+ if (memcmp(payload, "GNUTELLA CONNECT/", 17) == 0) return ((IPP2P_GNU * 100) + 1);
+ if (memcmp(payload, "GNUTELLA/", 9) == 0) return ((IPP2P_GNU * 100) + 2);
+
+
+ if ((memcmp(payload, "GET /get/", 9) == 0) || (memcmp(payload, "GET /uri-res/", 13) == 0))
+ {
+ u16 c=8;
+ const u16 end=plen-22;
+ while (c < end) {
+ if ( payload[c] == 0x0a && payload[c+1] == 0x0d && ((memcmp(&payload[c+2], "X-Gnutella-", 11) == 0) || (memcmp(&payload[c+2], "X-Queue:", 8) == 0)))
+ return ((IPP2P_GNU * 100) + 3);
+ c++;
+ }
+ }
+ }
+ return 0;
+}
+
+
+/*check for KaZaA download commands and other typical data*/
+int
+search_all_kazaa (const unsigned char *payload, const u16 plen)
+{
+ if ((payload[plen-2] == 0x0d) && (payload[plen-1] == 0x0a))
+ {
+
+ if (memcmp(payload, "GIVE ", 5) == 0) return ((IPP2P_KAZAA * 100) + 1);
+
+ if (memcmp(payload, "GET /", 5) == 0) {
+ u16 c = 8;
+ const u16 end=plen-22;
+ while (c < end) {
+ if ( payload[c] == 0x0a && payload[c+1] == 0x0d && ((memcmp(&payload[c+2], "X-Kazaa-Username: ", 18) == 0) || (memcmp(&payload[c+2], "User-Agent: PeerEnabler/", 24) == 0)))
+ return ((IPP2P_KAZAA * 100) + 2);
+ c++;
+ }
+ }
+ }
+ return 0;
+}
+
+/*fast check for edonkey file segment transfer command*/
+int
+search_edk (const unsigned char *payload, const u16 plen)
+{
+ if (payload[0] != 0xe3)
+ return 0;
+ else {
+ if (payload[5] == 0x47)
+ return (IPP2P_DATA_EDK * 100);
+ else
+ return 0;
+ }
+}
+
+
+
+/*intensive but slower search for some edonkey packets including size-check*/
+int
+search_all_edk (const unsigned char *payload, const u16 plen)
+{
+ if (payload[0] != 0xe3)
+ return 0;
+ else {
+ //t += head_len;
+ const u16 cmd = get_u16(payload, 1);
+ if (cmd == (plen - 5)) {
+ switch (payload[5]) {
+ case 0x01: return ((IPP2P_EDK * 100) + 1); /*Client: hello or Server:hello*/
+ case 0x4c: return ((IPP2P_EDK * 100) + 9); /*Client: Hello-Answer*/
+ }
+ }
+ return 0;
+ }
+}
+
+
+/*fast check for Direct Connect send command*/
+int
+search_dc (const unsigned char *payload, const u16 plen)
+{
+
+ if (payload[0] != 0x24 )
+ return 0;
+ else {
+ if (memcmp(&payload[1], "Send|", 5) == 0)
+ return (IPP2P_DATA_DC * 100);
+ else
+ return 0;
+ }
+
+}
+
+
+/*intensive but slower check for all direct connect packets*/
+int
+search_all_dc (const unsigned char *payload, const u16 plen)
+{
+// unsigned char *t = haystack;
+
+ if (payload[0] == 0x24 && payload[plen-1] == 0x7c)
+ {
+ const unsigned char *t=&payload[1];
+ /* Client-Hub-Protocol */
+ if (memcmp(t, "Lock ", 5) == 0) return ((IPP2P_DC * 100) + 1);
+ /* Client-Client-Protocol, some are already recognized by client-hub (like lock) */
+ if (memcmp(t, "MyNick ", 7) == 0) return ((IPP2P_DC * 100) + 38);
+ }
+ return 0;
+}
+
+/*check for mute*/
+int
+search_mute (const unsigned char *payload, const u16 plen)
+{
+ if ( plen == 209 || plen == 345 || plen == 473 || plen == 609 || plen == 1121 )
+ {
+ //printk(KERN_DEBUG "size hit: %u",size);
+ if (memcmp(payload,"PublicKey: ",11) == 0 )
+ {
+ return ((IPP2P_MUTE * 100) + 0);
+
+/* if (memcmp(t+size-14,"\x0aEndPublicKey\x0a",14) == 0)
+ {
+ printk(KERN_DEBUG "end pubic key hit: %u",size);
+
+ }*/
+ }
+ }
+ return 0;
+}
+
+
+/* check for xdcc */
+int
+search_xdcc (const unsigned char *payload, const u16 plen)
+{
+ /* search in small packets only */
+ if (plen > 20 && plen < 200 && payload[plen-1] == 0x0a && payload[plen-2] == 0x0d && memcmp(payload,"PRIVMSG ",8) == 0)
+ {
+
+ u16 x=10;
+ const u16 end=plen - 13;
+
+ /* is seems to be a irc private massage, chedck for xdcc command */
+ while (x < end)
+ {
+ if (payload[x] == ':')
+ {
+ if ( memcmp(&payload[x+1],"xdcc send #",11) == 0 )
+ return ((IPP2P_XDCC * 100) + 0);
+ }
+ x++;
+ }
+ }
+ return 0;
+}
+
+/* search for waste */
+int search_waste(const unsigned char *payload, const u16 plen)
+{
+ if ( plen >= 8 && memcmp(payload,"GET.sha1:",9) == 0)
+ return ((IPP2P_WASTE * 100) + 0);
+
+ return 0;
+}
+
+
+static struct {
+ int command;
+ __u8 short_hand; /*for fucntions included in short hands*/
+ int packet_len;
+ int (*function_name) (const unsigned char *, const u16);
+} matchlist[] = {
+ {IPP2P_EDK,SHORT_HAND_IPP2P,20, &search_all_edk},
+// {IPP2P_DATA_KAZAA,SHORT_HAND_DATA,200, &search_kazaa},
+// {IPP2P_DATA_EDK,SHORT_HAND_DATA,60, &search_edk},
+// {IPP2P_DATA_DC,SHORT_HAND_DATA,26, &search_dc},
+ {IPP2P_DC,SHORT_HAND_IPP2P,5, search_all_dc},
+// {IPP2P_DATA_GNU,SHORT_HAND_DATA,40, &search_gnu},
+ {IPP2P_GNU,SHORT_HAND_IPP2P,5, &search_all_gnu},
+ {IPP2P_KAZAA,SHORT_HAND_IPP2P,5, &search_all_kazaa},
+ {IPP2P_BIT,SHORT_HAND_IPP2P,20, &search_bittorrent},
+ {IPP2P_APPLE,SHORT_HAND_IPP2P,5, &search_apple},
+ {IPP2P_SOUL,SHORT_HAND_IPP2P,5, &search_soul},
+ {IPP2P_WINMX,SHORT_HAND_IPP2P,2, &search_winmx},
+ {IPP2P_ARES,SHORT_HAND_IPP2P,5, &search_ares},
+ {IPP2P_MUTE,SHORT_HAND_NONE,200, &search_mute},
+ {IPP2P_WASTE,SHORT_HAND_NONE,5, &search_waste},
+ {IPP2P_XDCC,SHORT_HAND_NONE,5, &search_xdcc},
+ {0,0,0,NULL}
+};
+
+
+static struct {
+ int command;
+ __u8 short_hand; /*for fucntions included in short hands*/
+ int packet_len;
+ int (*function_name) (unsigned char *, int);
+} udp_list[] = {
+ {IPP2P_KAZAA,SHORT_HAND_IPP2P,14, &udp_search_kazaa},
+ {IPP2P_BIT,SHORT_HAND_IPP2P,23, &udp_search_bit},
+ {IPP2P_GNU,SHORT_HAND_IPP2P,11, &udp_search_gnu},
+ {IPP2P_EDK,SHORT_HAND_IPP2P,9, &udp_search_edk},
+ {IPP2P_DC,SHORT_HAND_IPP2P,12, &udp_search_directconnect},
+ {0,0,0,NULL}
+};
+
+
+static int
+match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *matchinfo,
+ int offset,
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+ const void *hdr,
+ u_int16_t datalen,
+#endif
+
+ int *hotdrop)
+{
+ const struct ipt_p2p_info *info = matchinfo;
+ unsigned char *haystack;
+ struct iphdr *ip = skb->nh.iph;
+ int p2p_result = 0, i = 0;
+// int head_len;
+ int hlen = ntohs(ip->tot_len)-(ip->ihl*4); /*hlen = packet-data length*/
+
+ /*must not be a fragment*/
+ if (offset) {
+ if (info->debug) printk("IPP2P.match: offset found %i \n",offset);
+ return 0;
+ }
+
+ /*make sure that skb is linear*/
+ if(skb_is_nonlinear(skb)){
+ if (info->debug) printk("IPP2P.match: nonlinear skb found\n");
+ return 0;
+ }
+
+
+ haystack=(char *)ip+(ip->ihl*4); /*haystack = packet data*/
+
+ switch (ip->protocol){
+ case IPPROTO_TCP: /*what to do with a TCP packet*/
+ {
+ struct tcphdr *tcph = (void *) ip + ip->ihl * 4;
+
+ if (tcph->fin) return 0; /*if FIN bit is set bail out*/
+ if (tcph->syn) return 0; /*if SYN bit is set bail out*/
+ if (tcph->rst) return 0; /*if RST bit is set bail out*/
+
+ haystack += tcph->doff * 4; /*get TCP-Header-Size*/
+ hlen -= tcph->doff * 4;
+ while (matchlist[i].command) {
+ if ((((info->cmd & matchlist[i].command) == matchlist[i].command) ||
+ ((info->cmd & matchlist[i].short_hand) == matchlist[i].short_hand)) &&
+ (hlen > matchlist[i].packet_len)) {
+ p2p_result = matchlist[i].function_name(haystack, hlen);
+ if (p2p_result)
+ {
+ if (info->debug) printk("IPP2P.debug:TCP-match: %i from: %u.%u.%u.%u:%i to: %u.%u.%u.%u:%i Length: %i\n",
+ p2p_result, NIPQUAD(ip->saddr),ntohs(tcph->source), NIPQUAD(ip->daddr),ntohs(tcph->dest),hlen);
+ return p2p_result;
+ }
+ }
+ i++;
+ }
+ return p2p_result;
+ }
+
+ case IPPROTO_UDP: /*what to do with an UDP packet*/
+ {
+ struct udphdr *udph = (void *) ip + ip->ihl * 4;
+
+ while (udp_list[i].command){
+ if ((((info->cmd & udp_list[i].command) == udp_list[i].command) ||
+ ((info->cmd & udp_list[i].short_hand) == udp_list[i].short_hand)) &&
+ (hlen > udp_list[i].packet_len)) {
+ p2p_result = udp_list[i].function_name(haystack, hlen);
+ if (p2p_result){
+ if (info->debug) printk("IPP2P.debug:UDP-match: %i from: %u.%u.%u.%u:%i to: %u.%u.%u.%u:%i Length: %i\n",
+ p2p_result, NIPQUAD(ip->saddr),ntohs(udph->source), NIPQUAD(ip->daddr),ntohs(udph->dest),hlen);
+ return p2p_result;
+ }
+ }
+ i++;
+ }
+ return p2p_result;
+ }
+
+ default: return 0;
+ }
+}
+
+
+
+static int
+checkentry(const char *tablename,
+ const struct ipt_ip *ip,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+ /* Must specify -p tcp */
+/* if (ip->proto != IPPROTO_TCP || (ip->invflags & IPT_INV_PROTO)) {
+ * printk("ipp2p: Only works on TCP packets, use -p tcp\n");
+ * return 0;
+ * }*/
+ return 1;
+}
+
+
+
+
+static struct ipt_match ipp2p_match = {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+ { NULL, NULL },
+ "ipp2p",
+ &match,
+ &checkentry,
+ NULL,
+ THIS_MODULE
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ .name = "ipp2p",
+ .match = &match,
+ .checkentry = &checkentry,
+ .me = THIS_MODULE,
+#endif
+};
+
+
+static int __init init(void)
+{
+ printk(KERN_INFO "IPP2P v%s loading\n", IPP2P_VERSION);
+ return ipt_register_match(&ipp2p_match);
+}
+
+static void __exit fini(void)
+{
+ ipt_unregister_match(&ipp2p_match);
+ printk(KERN_INFO "IPP2P v%s unloaded\n", IPP2P_VERSION);
+}
+
+module_init(init);
+module_exit(fini);
+
+
diff --git a/release/src/linux/linux/net/ipv4/route.c b/release/src/linux/linux/net/ipv4/route.c
index f3cf20dfc4..dfae08719b 100644
--- a/release/src/linux/linux/net/ipv4/route.c
+++ b/release/src/linux/linux/net/ipv4/route.c
@@ -2465,7 +2465,6 @@ void __init ip_rt_init(void)
panic("IP: failed to allocate ip_dst_cache\n");
goal = num_physpages >> (26 - PAGE_SHIFT);
-// goal = num_physpages >> (21 - PAGE_SHIFT);
for (order = 0; (1UL << order) < goal; order++)
/* NOTHING */;
@@ -2495,18 +2494,9 @@ void __init ip_rt_init(void)
rt_hash_table[i].chain = NULL;
}
-// ip_rt_max_size = (rt_hash_mask + 1) * 2;
-// ipv4_dst_ops.gc_thresh = (ip_rt_max_size / 4);
-
ipv4_dst_ops.gc_thresh = (rt_hash_mask + 1);
ip_rt_max_size = (rt_hash_mask + 1) * 16;
-// printk("gc_thresh=%d\n", ipv4_dst_ops.gc_thresh);
-// printk("ip_rt_max_size=%d\n", ip_rt_max_size);
-// printk("rt_hash_mask=%d\n", rt_hash_mask);
-// printk("goal=%d\n", goal);
-
-
devinet_init();
ip_fib_init();
diff --git a/release/src/linux/linux/net/ipv4/sysctl_net_ipv4.c b/release/src/linux/linux/net/ipv4/sysctl_net_ipv4.c
index 7fe1644556..1f4081a911 100644
--- a/release/src/linux/linux/net/ipv4/sysctl_net_ipv4.c
+++ b/release/src/linux/linux/net/ipv4/sysctl_net_ipv4.c
@@ -221,18 +221,6 @@ ctl_table ipv4_table[] = {
&sysctl_icmp_ratemask, sizeof(int), 0644, NULL, &proc_dointvec},
{NET_TCP_TW_REUSE, "tcp_tw_reuse",
&sysctl_tcp_tw_reuse, sizeof(int), 0644, NULL, &proc_dointvec},
- {NET_TCP_VEGAS, "tcp_vegas_cong_avoid",
- &sysctl_tcp_vegas_cong_avoid, sizeof(int), 0644, NULL,
- &proc_dointvec},
- {NET_TCP_VEGAS_ALPHA, "tcp_vegas_alpha",
- &sysctl_tcp_vegas_alpha, sizeof(int), 0644, NULL,
- &proc_dointvec},
- {NET_TCP_VEGAS_BETA, "tcp_vegas_beta",
- &sysctl_tcp_vegas_beta, sizeof(int), 0644, NULL,
- &proc_dointvec},
- {NET_TCP_VEGAS_GAMMA, "tcp_vegas_gamma",
- &sysctl_tcp_vegas_gamma, sizeof(int), 0644, NULL,
- &proc_dointvec},
{0}
};
diff --git a/release/src/linux/linux/net/ipv4/tcp_input.c b/release/src/linux/linux/net/ipv4/tcp_input.c
index 243e2991d1..8c99dd52e7 100644
--- a/release/src/linux/linux/net/ipv4/tcp_input.c
+++ b/release/src/linux/linux/net/ipv4/tcp_input.c
@@ -87,16 +87,6 @@ int sysctl_tcp_stdurg = 0;
int sysctl_tcp_rfc1337 = 0;
int sysctl_tcp_max_orphans = NR_FILE;
-int sysctl_tcp_vegas_cong_avoid = 0;
-
-/* Default values of the Vegas variables, in fixed-point representation
- * with V_PARAM_SHIFT bits to the right of the binary point.
- */
-#define V_PARAM_SHIFT 1
-int sysctl_tcp_vegas_alpha = 1<vegas.do_vegas = 1;
- tp->vegas.baseRTT = 0x7fffffff;
- tcp_vegas_enable(tp);
- } else
- tcp_vegas_disable(tp);
-}
-
-/* Do RTT sampling needed for Vegas.
- * Basically we:
- * o min-filter RTT samples from within an RTT to get the current
- * propagation delay + queuing delay (we are min-filtering to try to
- * avoid the effects of delayed ACKs)
- * o min-filter RTT samples from a much longer window (forever for now)
- * to find the propagation delay (baseRTT)
- */
-static inline void vegas_rtt_calc(struct tcp_opt *tp, __u32 rtt)
-{
- __u32 vrtt = rtt + 1; /* Never allow zero rtt or baseRTT */
-
- /* Filter to find propagation delay: */
- if (vrtt < tp->vegas.baseRTT)
- tp->vegas.baseRTT = vrtt;
-
- /* Find the min RTT during the last RTT to find
- * the current prop. delay + queuing delay:
- */
- tp->vegas.minRTT = min(tp->vegas.minRTT, vrtt);
- tp->vegas.cntRTT++;
-}
-
/* Called to compute a smoothed rtt estimate. The data fed to this
* routine either comes from timestamps, or from segments that were
* known _not_ to have been retransmitted [see Karn/Partridge
@@ -458,9 +412,6 @@ static __inline__ void tcp_rtt_estimator(struct tcp_opt *tp, __u32 mrtt)
{
long m = mrtt; /* RTT */
- if (tcp_vegas_enabled(tp))
- vegas_rtt_calc(tp, mrtt);
-
/* The following amusing code comes from Jacobson's
* article in SIGCOMM '88. Note that rtt and mdev
* are scaled versions of rtt and mean deviation.
@@ -1062,7 +1013,7 @@ void tcp_enter_loss(struct sock *sk, int how)
tcp_sync_left_out(tp);
tp->reordering = min_t(unsigned int, tp->reordering, sysctl_tcp_reordering);
- tcp_set_ca_state(tp, TCP_CA_Loss);
+ tp->ca_state = TCP_CA_Loss;
tp->high_seq = tp->snd_nxt;
TCP_ECN_queue_cwr(tp);
}
@@ -1424,7 +1375,7 @@ static int tcp_try_undo_recovery(struct sock *sk, struct tcp_opt *tp)
tcp_moderate_cwnd(tp);
return 1;
}
- tcp_set_ca_state(tp, TCP_CA_Open);
+ tp->ca_state = TCP_CA_Open;
return 0;
}
@@ -1484,7 +1435,7 @@ static int tcp_try_undo_loss(struct sock *sk, struct tcp_opt *tp)
tp->retransmits = 0;
tp->undo_marker = 0;
if (!IsReno(tp))
- tcp_set_ca_state(tp, TCP_CA_Open);
+ tp->ca_state = TCP_CA_Open;
return 1;
}
return 0;
@@ -1515,7 +1466,7 @@ static void tcp_try_to_open(struct sock *sk, struct tcp_opt *tp, int flag)
state = TCP_CA_Disorder;
if (tp->ca_state != state) {
- tcp_set_ca_state(tp, state);
+ tp->ca_state = state;
tp->high_seq = tp->snd_nxt;
}
tcp_moderate_cwnd(tp);
@@ -1589,7 +1540,7 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
* is ACKed for CWR bit to reach receiver. */
if (tp->snd_una != tp->high_seq) {
tcp_complete_cwr(tp);
- tcp_set_ca_state(tp, TCP_CA_Open);
+ tp->ca_state = TCP_CA_Open;
}
break;
@@ -1600,7 +1551,7 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
* catching for all duplicate ACKs. */
IsReno(tp) || tp->snd_una != tp->high_seq) {
tp->undo_marker = 0;
- tcp_set_ca_state(tp, TCP_CA_Open);
+ tp->ca_state = TCP_CA_Open;
}
break;
@@ -1674,7 +1625,7 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
}
tp->snd_cwnd_cnt = 0;
- tcp_set_ca_state(tp, TCP_CA_Recovery);
+ tp->ca_state = TCP_CA_Recovery;
}
if (is_dupack || tcp_head_timedout(sk, tp))
@@ -1745,7 +1696,7 @@ tcp_ack_update_rtt(struct tcp_opt *tp, int flag, s32 seq_rtt)
/* This is Jacobson's slow start and congestion avoidance.
* SIGCOMM '88, p. 328.
*/
-static __inline__ void reno_cong_avoid(struct tcp_opt *tp)
+static __inline__ void tcp_cong_avoid(struct tcp_opt *tp)
{
if (tp->snd_cwnd <= tp->snd_ssthresh) {
/* In "safe" area, increase. */
@@ -1765,236 +1716,6 @@ static __inline__ void reno_cong_avoid(struct tcp_opt *tp)
tp->snd_cwnd_stamp = tcp_time_stamp;
}
-/* This is based on the congestion detection/avoidance scheme described in
- * Lawrence S. Brakmo and Larry L. Peterson.
- * "TCP Vegas: End to end congestion avoidance on a global internet."
- * IEEE Journal on Selected Areas in Communication, 13(8):1465--1480,
- * October 1995. Available from:
- * ftp://ftp.cs.arizona.edu/xkernel/Papers/jsac.ps
- *
- * See http://www.cs.arizona.edu/xkernel/ for their implementation.
- * The main aspects that distinguish this implementation from the
- * Arizona Vegas implementation are:
- * o We do not change the loss detection or recovery mechanisms of
- * Linux in any way. Linux already recovers from losses quite well,
- * using fine-grained timers, NewReno, and FACK.
- * o To avoid the performance penalty imposed by increasing cwnd
- * only every-other RTT during slow start, we increase during
- * every RTT during slow start, just like Reno.
- * o Largely to allow continuous cwnd growth during slow start,
- * we use the rate at which ACKs come back as the "actual"
- * rate, rather than the rate at which data is sent.
- * o To speed convergence to the right rate, we set the cwnd
- * to achieve the right ("actual") rate when we exit slow start.
- * o To filter out the noise caused by delayed ACKs, we use the
- * minimum RTT sample observed during the last RTT to calculate
- * the actual rate.
- * o When the sender re-starts from idle, it waits until it has
- * received ACKs for an entire flight of new data before making
- * a cwnd adjustment decision. The original Vegas implementation
- * assumed senders never went idle.
- */
-static void vegas_cong_avoid(struct tcp_opt *tp, u32 ack, u32 seq_rtt)
-{
- /* The key players are v_beg_snd_una and v_beg_snd_nxt.
- *
- * These are so named because they represent the approximate values
- * of snd_una and snd_nxt at the beginning of the current RTT. More
- * precisely, they represent the amount of data sent during the RTT.
- * At the end of the RTT, when we receive an ACK for v_beg_snd_nxt,
- * we will calculate that (v_beg_snd_nxt - v_beg_snd_una) outstanding
- * bytes of data have been ACKed during the course of the RTT, giving
- * an "actual" rate of:
- *
- * (v_beg_snd_nxt - v_beg_snd_una) / (rtt duration)
- *
- * Unfortunately, v_beg_snd_una is not exactly equal to snd_una,
- * because delayed ACKs can cover more than one segment, so they
- * don't line up nicely with the boundaries of RTTs.
- *
- * Another unfortunate fact of life is that delayed ACKs delay the
- * advance of the left edge of our send window, so that the number
- * of bytes we send in an RTT is often less than our cwnd will allow.
- * So we keep track of our cwnd separately, in v_beg_snd_cwnd.
- */
-
- if (after(ack, tp->vegas.beg_snd_nxt)) {
- /* Do the Vegas once-per-RTT cwnd adjustment. */
- u32 old_wnd, old_snd_cwnd;
-
-
- /* Here old_wnd is essentially the window of data that was
- * sent during the previous RTT, and has all
- * been acknowledged in the course of the RTT that ended
- * with the ACK we just received. Likewise, old_snd_cwnd
- * is the cwnd during the previous RTT.
- */
- old_wnd = (tp->vegas.beg_snd_nxt - tp->vegas.beg_snd_una) /
- tp->mss_cache;
- old_snd_cwnd = tp->vegas.beg_snd_cwnd;
-
- /* Save the extent of the current window so we can use this
- * at the end of the next RTT.
- */
- tp->vegas.beg_snd_una = tp->vegas.beg_snd_nxt;
- tp->vegas.beg_snd_nxt = tp->snd_nxt;
- tp->vegas.beg_snd_cwnd = tp->snd_cwnd;
-
- /* Take into account the current RTT sample too, to
- * decrease the impact of delayed acks. This double counts
- * this sample since we count it for the next window as well,
- * but that's not too awful, since we're taking the min,
- * rather than averaging.
- */
- vegas_rtt_calc(tp, seq_rtt);
-
- /* We do the Vegas calculations only if we got enough RTT
- * samples that we can be reasonably sure that we got
- * at least one RTT sample that wasn't from a delayed ACK.
- * If we only had 2 samples total,
- * then that means we're getting only 1 ACK per RTT, which
- * means they're almost certainly delayed ACKs.
- * If we have 3 samples, we should be OK.
- */
-
- if (tp->vegas.cntRTT <= 2) {
- /* We don't have enough RTT samples to do the Vegas
- * calculation, so we'll behave like Reno.
- */
- if (tp->snd_cwnd > tp->snd_ssthresh)
- tp->snd_cwnd++;
- } else {
- u32 rtt, target_cwnd, diff;
-
- /* We have enough RTT samples, so, using the Vegas
- * algorithm, we determine if we should increase or
- * decrease cwnd, and by how much.
- */
-
- /* Pluck out the RTT we are using for the Vegas
- * calculations. This is the min RTT seen during the
- * last RTT. Taking the min filters out the effects
- * of delayed ACKs, at the cost of noticing congestion
- * a bit later.
- */
- rtt = tp->vegas.minRTT;
-
- /* Calculate the cwnd we should have, if we weren't
- * going too fast.
- *
- * This is:
- * (actual rate in segments) * baseRTT
- * We keep it as a fixed point number with
- * V_PARAM_SHIFT bits to the right of the binary point.
- */
- target_cwnd = ((old_wnd * tp->vegas.baseRTT)
- << V_PARAM_SHIFT) / rtt;
-
- /* Calculate the difference between the window we had,
- * and the window we would like to have. This quantity
- * is the "Diff" from the Arizona Vegas papers.
- *
- * Again, this is a fixed point number with
- * V_PARAM_SHIFT bits to the right of the binary
- * point.
- */
- diff = (old_wnd << V_PARAM_SHIFT) - target_cwnd;
-
- if (tp->snd_cwnd < tp->snd_ssthresh) {
- /* Slow start. */
- if (diff > sysctl_tcp_vegas_gamma) {
- /* Going too fast. Time to slow down
- * and switch to congestion avoidance.
- */
- tp->snd_ssthresh = 2;
-
- /* Set cwnd to match the actual rate
- * exactly:
- * cwnd = (actual rate) * baseRTT
- * Then we add 1 because the integer
- * truncation robs us of full link
- * utilization.
- */
- tp->snd_cwnd = min(tp->snd_cwnd,
- (target_cwnd >>
- V_PARAM_SHIFT)+1);
-
- }
- } else {
- /* Congestion avoidance. */
- u32 next_snd_cwnd;
-
- /* Figure out where we would like cwnd
- * to be.
- */
- if (diff > sysctl_tcp_vegas_beta) {
- /* The old window was too fast, so
- * we slow down.
- */
- next_snd_cwnd = old_snd_cwnd - 1;
- } else if (diff < sysctl_tcp_vegas_alpha) {
- /* We don't have enough extra packets
- * in the network, so speed up.
- */
- next_snd_cwnd = old_snd_cwnd + 1;
- } else {
- /* Sending just as fast as we
- * should be.
- */
- next_snd_cwnd = old_snd_cwnd;
- }
-
- /* Adjust cwnd upward or downward, toward the
- * desired value.
- */
- if (next_snd_cwnd > tp->snd_cwnd)
- tp->snd_cwnd++;
- else if (next_snd_cwnd < tp->snd_cwnd)
- tp->snd_cwnd--;
- }
- }
-
- /* Wipe the slate clean for the next RTT. */
- tp->vegas.cntRTT = 0;
- tp->vegas.minRTT = 0x7fffffff;
- }
-
- /* The following code is executed for every ack we receive,
- * except for conditions checked in should_advance_cwnd()
- * before the call to tcp_cong_avoid(). Mainly this means that
- * we only execute this code if the ack actually acked some
- * data.
- */
-
- /* If we are in slow start, increase our cwnd in response to this ACK.
- * (If we are not in slow start then we are in congestion avoidance,
- * and adjust our congestion window only once per RTT. See the code
- * above.)
- */
- if (tp->snd_cwnd <= tp->snd_ssthresh)
- tp->snd_cwnd++;
-
- /* to keep cwnd from growing without bound */
- tp->snd_cwnd = min_t(u32, tp->snd_cwnd, tp->snd_cwnd_clamp);
-
- /* Make sure that we are never so timid as to reduce our cwnd below
- * 2 MSS.
- *
- * Going below 2 MSS would risk huge delayed ACKs from our receiver.
- */
- tp->snd_cwnd = max(tp->snd_cwnd, 2U);
-
- tp->snd_cwnd_stamp = tcp_time_stamp;
-}
-
-static inline void tcp_cong_avoid(struct tcp_opt *tp, u32 ack, u32 seq_rtt)
-{
- if (tcp_vegas_enabled(tp))
- vegas_cong_avoid(tp, ack, seq_rtt);
- else
- reno_cong_avoid(tp);
-}
-
/* Restart timer after forward progress on connection.
* RFC2988 recommends to restart timer to now+rto.
*/
@@ -2009,7 +1730,7 @@ static __inline__ void tcp_ack_packets_out(struct sock *sk, struct tcp_opt *tp)
}
/* Remove acknowledged frames from the retransmission queue. */
-static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
+static int tcp_clean_rtx_queue(struct sock *sk)
{
struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
struct sk_buff *skb;
@@ -2092,7 +1813,6 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
}
}
#endif
- *seq_rtt_p = seq_rtt;
return acked;
}
@@ -2180,7 +1900,6 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
u32 ack_seq = TCP_SKB_CB(skb)->seq;
u32 ack = TCP_SKB_CB(skb)->ack_seq;
u32 prior_in_flight;
- s32 seq_rtt;
int prior_packets;
/* If the ack is newer than sent or older than previous acks
@@ -2228,19 +1947,17 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
prior_in_flight = tcp_packets_in_flight(tp);
/* See if we can take anything off of the retransmit queue. */
- flag |= tcp_clean_rtx_queue(sk, &seq_rtt);
+ flag |= tcp_clean_rtx_queue(sk);
if (tcp_ack_is_dubious(tp, flag)) {
/* Advanve CWND, if state allows this. */
- if ((flag&FLAG_DATA_ACKED) &&
- (tcp_vegas_enabled(tp) || prior_in_flight >= tp->snd_cwnd) &&
+ if ((flag&FLAG_DATA_ACKED) && prior_in_flight >= tp->snd_cwnd &&
tcp_may_raise_cwnd(tp, flag))
- tcp_cong_avoid(tp, ack, seq_rtt);
+ tcp_cong_avoid(tp);
tcp_fastretrans_alert(sk, prior_snd_una, prior_packets, flag);
} else {
- if ((flag & FLAG_DATA_ACKED) &&
- (tcp_vegas_enabled(tp) || prior_in_flight >= tp->snd_cwnd))
- tcp_cong_avoid(tp, ack, seq_rtt);
+ if ((flag&FLAG_DATA_ACKED) && prior_in_flight >= tp->snd_cwnd)
+ tcp_cong_avoid(tp);
}
if ((flag & FLAG_FORWARD_PROGRESS) || !(flag&FLAG_NOT_DUP))
diff --git a/release/src/linux/linux/net/ipv4/tcp_minisocks.c b/release/src/linux/linux/net/ipv4/tcp_minisocks.c
index 6fdb768113..b69cc32c67 100644
--- a/release/src/linux/linux/net/ipv4/tcp_minisocks.c
+++ b/release/src/linux/linux/net/ipv4/tcp_minisocks.c
@@ -715,7 +715,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req,
newtp->snd_cwnd = 2;
newtp->snd_cwnd_cnt = 0;
- tcp_set_ca_state(newtp, TCP_CA_Open);
+ newtp->ca_state = TCP_CA_Open;
tcp_init_xmit_timers(newsk);
skb_queue_head_init(&newtp->out_of_order_queue);
newtp->send_head = NULL;
@@ -783,7 +783,6 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req,
newtp->mss_clamp = req->mss;
TCP_ECN_openreq_child(newtp, req);
- tcp_vegas_init(newtp);
TCP_INC_STATS_BH(TcpPassiveOpens);
}
return newsk;
diff --git a/release/src/linux/linux/net/ipv4/tcp_output.c b/release/src/linux/linux/net/ipv4/tcp_output.c
index 3fd4871ff5..35cbbbf727 100644
--- a/release/src/linux/linux/net/ipv4/tcp_output.c
+++ b/release/src/linux/linux/net/ipv4/tcp_output.c
@@ -105,9 +105,6 @@ static void tcp_cwnd_restart(struct tcp_opt *tp)
u32 restart_cwnd = tcp_init_cwnd(tp);
u32 cwnd = tp->snd_cwnd;
- if (tcp_is_vegas(tp))
- tcp_vegas_enable(tp);
-
tp->snd_ssthresh = tcp_current_ssthresh(tp);
restart_cwnd = min(restart_cwnd, cwnd);
@@ -226,19 +223,6 @@ int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb)
tcp_header_size += (TCPOLEN_SACK_BASE_ALIGNED +
(tp->eff_sacks * TCPOLEN_SACK_PERBLOCK));
}
-
- /*
- * If the connection is idle and we are restarting,
- * then we don't want to do any Vegas calculations
- * until we get fresh RTT samples. So when we
- * restart, we reset our Vegas state to a clean
- * slate. After we get acks for this flight of
- * packets, _then_ we can make Vegas calculations
- * again.
- */
- if (tcp_is_vegas(tp) && tcp_packets_in_flight(tp) == 0)
- tcp_vegas_enable(tp);
-
th = (struct tcphdr *) skb_push(skb, tcp_header_size);
skb->h.th = th;
skb_set_owner_w(skb, sk);
@@ -816,7 +800,7 @@ void tcp_simple_retransmit(struct sock *sk)
tp->snd_ssthresh = tcp_current_ssthresh(tp);
tp->prior_ssthresh = 0;
tp->undo_marker = 0;
- tcp_set_ca_state(tp, TCP_CA_Loss);
+ tp->ca_state = TCP_CA_Loss;
}
tcp_xmit_retransmit_queue(sk);
}
@@ -1197,7 +1181,6 @@ static inline void tcp_connect_init(struct sock *sk)
tp->window_clamp = dst->window;
tp->advmss = dst->advmss;
tcp_initialize_rcv_mss(sk);
- tcp_vegas_init(tp);
tcp_select_initial_window(tcp_full_space(sk),
tp->advmss - (tp->ts_recent_stamp ? tp->tcp_header_len - sizeof(struct tcphdr) : 0),
@@ -1248,7 +1231,6 @@ int tcp_connect(struct sock *sk)
TCP_SKB_CB(buff)->end_seq = tp->write_seq;
tp->snd_nxt = tp->write_seq;
tp->pushed_seq = tp->write_seq;
- tcp_vegas_init(tp);
/* Send it off. */
TCP_SKB_CB(buff)->when = tcp_time_stamp;
diff --git a/release/src/linux/linux/net/ipv6/netfilter/Config.in b/release/src/linux/linux/net/ipv6/netfilter/Config.in
index c2311736d7..5d2dac2f3b 100644
--- a/release/src/linux/linux/net/ipv6/netfilter/Config.in
+++ b/release/src/linux/linux/net/ipv6/netfilter/Config.in
@@ -56,6 +56,8 @@ if [ "$CONFIG_IP6_NF_IPTABLES" != "n" ]; then
if [ "$CONFIG_IP6_NF_MANGLE" != "n" ]; then
# dep_tristate ' TOS target support' CONFIG_IP6_NF_TARGET_TOS $CONFIG_IP_NF_MANGLE
dep_tristate ' MARK target support' CONFIG_IP6_NF_TARGET_MARK $CONFIG_IP6_NF_MANGLE
+ dep_tristate ' ROUTE target support' CONFIG_IP6_NF_TARGET_ROUTE $CONFIG_IP6_NF_MANGLE
+
dep_tristate ' IMQ target support' CONFIG_IP6_NF_TARGET_IMQ $CONFIG_IP6_NF_MANGLE
fi
#dep_tristate ' LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_IPTABLES
diff --git a/release/src/linux/linux/net/ipv6/netfilter/Makefile b/release/src/linux/linux/net/ipv6/netfilter/Makefile
index 91cc75bcfd..2bd664f484 100644
--- a/release/src/linux/linux/net/ipv6/netfilter/Makefile
+++ b/release/src/linux/linux/net/ipv6/netfilter/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
+obj-$(CONFIG_IP6_NF_TARGET_ROUTE) += ip6t_ROUTE.o
obj-$(CONFIG_IP6_NF_TARGET_IMQ) += ip6t_IMQ.o
obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
diff --git a/release/src/linux/linux/net/ipv6/netfilter/ip6t_ROUTE.c b/release/src/linux/linux/net/ipv6/netfilter/ip6t_ROUTE.c
new file mode 100644
index 0000000000..bb6d11f83e
--- /dev/null
+++ b/release/src/linux/linux/net/ipv6/netfilter/ip6t_ROUTE.c
@@ -0,0 +1,308 @@
+/*
+ * This implements the ROUTE v6 target, which enables you to setup unusual
+ * routes not supported by the standard kernel routing table.
+ *
+ * Copyright (C) 2003 Cedric de Launois
+ *
+ * v 1.1 2004/11/23
+ *
+ * This software is distributed under GNU GPL v2, 1991
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#if 1
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+#define NIP6(addr) \
+ ntohs((addr).s6_addr16[0]), \
+ ntohs((addr).s6_addr16[1]), \
+ ntohs((addr).s6_addr16[2]), \
+ ntohs((addr).s6_addr16[3]), \
+ ntohs((addr).s6_addr16[4]), \
+ ntohs((addr).s6_addr16[5]), \
+ ntohs((addr).s6_addr16[6]), \
+ ntohs((addr).s6_addr16[7])
+
+/* Route the packet according to the routing keys specified in
+ * route_info. Keys are :
+ * - ifindex :
+ * 0 if no oif preferred,
+ * otherwise set to the index of the desired oif
+ * - route_info->gw :
+ * 0 if no gateway specified,
+ * otherwise set to the next host to which the pkt must be routed
+ * If success, skb->dev is the output device to which the packet must
+ * be sent and skb->dst is not NULL
+ *
+ * RETURN: 1 if the packet was succesfully routed to the
+ * destination desired
+ * 0 if the kernel routing table could not route the packet
+ * according to the keys specified
+ */
+static int
+route6(struct sk_buff *skb,
+ unsigned int ifindex,
+ const struct ip6t_route_target_info *route_info)
+{
+ struct rt6_info *rt = NULL;
+ struct ipv6hdr *ipv6h = skb->nh.ipv6h;
+ struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
+
+ DEBUGP("ip6t_ROUTE: called with: ");
+ DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->daddr));
+ DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(*gw));
+ DEBUGP("OUT=%s\n", route_info->oif);
+
+ if (ipv6_addr_any(gw))
+ rt = rt6_lookup(&ipv6h->daddr, &ipv6h->saddr, ifindex, 1);
+ else
+ rt = rt6_lookup(gw, &ipv6h->saddr, ifindex, 1);
+
+ if (!rt)
+ goto no_route;
+
+ DEBUGP("ip6t_ROUTE: routing gives: ");
+ DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_dst.addr));
+ DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_gateway));
+ DEBUGP("OUT=%s\n", rt->rt6i_dev->name);
+
+ if (ifindex && rt->rt6i_dev->ifindex!=ifindex)
+ goto wrong_route;
+
+ if (!rt->rt6i_nexthop) {
+ DEBUGP("ip6t_ROUTE: discovering neighbour\n");
+ rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_dst.addr);
+ }
+
+ /* Drop old route. */
+ dst_release(skb->dst);
+ skb->dst = &rt->u.dst;
+ skb->dev = rt->rt6i_dev;
+ return 1;
+
+ wrong_route:
+ dst_release(&rt->u.dst);
+ no_route:
+ if (!net_ratelimit())
+ return 0;
+
+ printk("ip6t_ROUTE: no explicit route found ");
+ if (ifindex)
+ printk("via interface %s ", route_info->oif);
+ if (!ipv6_addr_any(gw))
+ printk("via gateway %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", NIP6(*gw));
+ printk("\n");
+ return 0;
+}
+
+
+/* Stolen from ip6_output_finish
+ * PRE : skb->dev is set to the device we are leaving by
+ * skb->dst is not NULL
+ * POST: the packet is sent with the link layer header pushed
+ * the packet is destroyed
+ */
+static void ip_direct_send(struct sk_buff *skb)
+{
+ struct dst_entry *dst = skb->dst;
+ struct hh_cache *hh = dst->hh;
+
+ if (hh) {
+ read_lock_bh(&hh->hh_lock);
+ memcpy(skb->data - 16, hh->hh_data, 16);
+ read_unlock_bh(&hh->hh_lock);
+ skb_push(skb, hh->hh_len);
+ hh->hh_output(skb);
+ } else if (dst->neighbour)
+ dst->neighbour->output(skb);
+ else {
+ if (net_ratelimit())
+ DEBUGP(KERN_DEBUG "ip6t_ROUTE: no hdr & no neighbour cache!\n");
+ kfree_skb(skb);
+ }
+}
+
+
+static unsigned int
+route6_oif(const struct ip6t_route_target_info *route_info,
+ struct sk_buff *skb)
+{
+ unsigned int ifindex = 0;
+ struct net_device *dev_out = NULL;
+
+ /* The user set the interface name to use.
+ * Getting the current interface index.
+ */
+ if ((dev_out = dev_get_by_name(route_info->oif))) {
+ ifindex = dev_out->ifindex;
+ } else {
+ /* Unknown interface name : packet dropped */
+ if (net_ratelimit())
+ DEBUGP("ip6t_ROUTE: oif interface %s not found\n", route_info->oif);
+
+ if (route_info->flags & IP6T_ROUTE_CONTINUE)
+ return IP6T_CONTINUE;
+ else
+ return NF_DROP;
+ }
+
+ /* Trying the standard way of routing packets */
+ if (route6(skb, ifindex, route_info)) {
+ dev_put(dev_out);
+ if (route_info->flags & IP6T_ROUTE_CONTINUE)
+ return IP6T_CONTINUE;
+
+ ip_direct_send(skb);
+ return NF_STOLEN;
+ } else
+ return NF_DROP;
+}
+
+
+static unsigned int
+route6_gw(const struct ip6t_route_target_info *route_info,
+ struct sk_buff *skb)
+{
+ if (route6(skb, 0, route_info)) {
+ if (route_info->flags & IP6T_ROUTE_CONTINUE)
+ return IP6T_CONTINUE;
+
+ ip_direct_send(skb);
+ return NF_STOLEN;
+ } else
+ return NF_DROP;
+}
+
+
+static unsigned int
+ip6t_route_target(struct sk_buff **pskb,
+ unsigned int hooknum,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *targinfo,
+ void *userinfo)
+{
+ const struct ip6t_route_target_info *route_info = targinfo;
+ struct sk_buff *skb = *pskb;
+ struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
+ unsigned int res;
+
+ if (route_info->flags & IP6T_ROUTE_CONTINUE)
+ goto do_it;
+
+ /* If we are at PREROUTING or INPUT hook
+ * the TTL isn't decreased by the IP stack
+ */
+ if (hooknum == NF_IP6_PRE_ROUTING ||
+ hooknum == NF_IP6_LOCAL_IN) {
+
+ struct ipv6hdr *ipv6h = skb->nh.ipv6h;
+
+ if (ipv6h->hop_limit <= 1) {
+ /* Force OUTPUT device used as source address */
+ skb->dev = skb->dst->dev;
+
+ icmpv6_send(skb, ICMPV6_TIME_EXCEED,
+ ICMPV6_EXC_HOPLIMIT, 0, skb->dev);
+
+ return NF_DROP;
+ }
+
+ ipv6h->hop_limit--;
+ }
+
+ if ((route_info->flags & IP6T_ROUTE_TEE)) {
+ /*
+ * Copy the *pskb, and route the copy. Will later return
+ * IP6T_CONTINUE for the original skb, which should continue
+ * on its way as if nothing happened. The copy should be
+ * independantly delivered to the ROUTE --gw.
+ */
+ skb = skb_copy(*pskb, GFP_ATOMIC);
+ if (!skb) {
+ if (net_ratelimit())
+ DEBUGP(KERN_DEBUG "ip6t_ROUTE: copy failed!\n");
+ return IP6T_CONTINUE;
+ }
+ }
+
+do_it:
+ if (route_info->oif[0]) {
+ res = route6_oif(route_info, skb);
+ } else if (!ipv6_addr_any(gw)) {
+ res = route6_gw(route_info, skb);
+ } else {
+ if (net_ratelimit())
+ DEBUGP(KERN_DEBUG "ip6t_ROUTE: no parameter !\n");
+ res = IP6T_CONTINUE;
+ }
+
+ if ((route_info->flags & IP6T_ROUTE_TEE))
+ res = IP6T_CONTINUE;
+
+ return res;
+}
+
+
+static int
+ip6t_route_checkentry(const char *tablename,
+ const struct ip6t_entry *e,
+ void *targinfo,
+ unsigned int targinfosize,
+ unsigned int hook_mask)
+{
+ if (strcmp(tablename, "mangle") != 0) {
+ printk("ip6t_ROUTE: can only be called from \"mangle\" table.\n");
+ return 0;
+ }
+
+ if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_route_target_info))) {
+ printk(KERN_WARNING "ip6t_ROUTE: targinfosize %u != %Zu\n",
+ targinfosize,
+ IP6T_ALIGN(sizeof(struct ip6t_route_target_info)));
+ return 0;
+ }
+
+ return 1;
+}
+
+
+static struct ip6t_target ip6t_route_reg = {
+ .name = "ROUTE",
+ .target = ip6t_route_target,
+ .checkentry = ip6t_route_checkentry,
+ .me = THIS_MODULE
+};
+
+
+static int __init init(void)
+{
+ printk(KERN_DEBUG "registering ipv6 ROUTE target\n");
+ if (ip6t_register_target(&ip6t_route_reg))
+ return -EINVAL;
+
+ return 0;
+}
+
+
+static void __exit fini(void)
+{
+ ip6t_unregister_target(&ip6t_route_reg);
+}
+
+module_init(init);
+module_exit(fini);
+MODULE_LICENSE("GPL");
diff --git a/release/src/router/Makefile b/release/src/router/Makefile
index b6f75696bf..beb754ee55 100644
--- a/release/src/router/Makefile
+++ b/release/src/router/Makefile
@@ -13,15 +13,12 @@
include common.mak
+# TOMATO_EXPERIMENTAL=1
#
#
#
-ifeq ($(TOMATO_DEV),jon)
-SEP=echo -e "\033[41;1m $@ \033[0m"
-else
-SEP=true
-endif
+SEP=echo "\033[41;1m $@ \033[0m"
#
# standard packages
@@ -45,20 +42,11 @@ obj-y += ppp
obj-y += ttcp
obj-y += ntpc
obj-y += rstats
-# obj-y += ebtables
-# obj-y += libbcm
-# obj-y += libbcmcrypto
-# obj-y += nas
-# obj-y += wlconf
-
obj-y += mssl
obj-y += mdu
-ifeq ($(TEST_MINIUPNPD),1)
obj-y += miniupnpd
-else
-obj-y += upnp
-endif
+# obj-y += upnp
#
@@ -66,13 +54,11 @@ endif
#
obj-$(TCONFIG_L2TP) += rp-l2tp
obj-$(TCONFIG_PPTP) += pptp-client
-# obj-$(TCONFIG_HEARTBEAT) += bpalogin
-# obj-$(TCONFIG_DDNS) += ipupdate
obj-$(TCONFIG_HTTPS) += openssl
obj-$(TCONFIG_HTTPS) += matrixssl
obj-$(TCONFIG_SSH) += dropbear
obj-$(TCONFIG_ZEBRA) += zebra
-obj-$(TCONFIG_IPP2P) += ipp2p
+# obj-$(TCONFIG_IPP2P) += ipp2p
ifeq ($(TCONFIG_L2TP),y)
NEED_PPPD = y
@@ -109,8 +95,9 @@ kernel: $(LINUXDIR)/.config
kmod: dummy
$(MAKE) -C $(LINUXDIR) modules
-fooit:
- @../btools/libfoo.pl
+testfind:
+ cd $(TARGETDIR)/lib/modules/2.4.20 && find -name "*.o" -exec mv -i {} . \; || true
+ cd $(TARGETDIR)/lib/modules/2.4.20 && find -type d -delete || true
install package: $(obj-install) $(LINUXDIR)/.config
@$(SEP)
@@ -165,13 +152,15 @@ endif
install $(LIBDIR)/libc.so.0 $(TARGETDIR)/lib/
install $(LIBDIR)/libdl.so.0 $(TARGETDIR)/lib/
install $(LIBDIR)/libm.so.0 $(TARGETDIR)/lib/
- install $(LIBDIR)/libutil.so.0 $(TARGETDIR)/lib/
install $(LIBDIR)/libnsl.so.0 $(TARGETDIR)/lib/
+ifeq ($(TCONFIG_SSH),y)
+ install $(LIBDIR)/libutil.so.0 $(TARGETDIR)/lib/
+endif
@cd $(TARGETDIR) && $(TOP)/others/rootprep.sh
@echo ---
- busybox/examples/depmod.pl -k $(LINUXDIR)/vmlinux -b $(TARGETDIR)/lib/modules/2.4.20/
+ busybox/examples/depmod-t.pl -k $(LINUXDIR)/vmlinux -b $(TARGETDIR)/lib/modules/2.4.20/
@echo ---
@rm -f $(TARGETDIR)/lib/modules/2.4.20/build
@@ -262,31 +251,35 @@ oldconfig oldconf: roldconf koldconf
# overrides and extra dependencies
#
-busybox: dummy
- $(MAKE) -C busybox CFLAGS="-Os"
+busybox:
+ @cd busybox && [ -s .config ] || ( cp config.save .config; $(MAKE) oldconfig )
+ @$(MAKE) -C busybox CFLAGS="-Os"
+ @cp busybox/.config busybox/config.save
+
# V=1
busybox-install:
rm -rf $(INSTALLDIR)/busybox
$(MAKE) -C busybox install CONFIG_PREFIX=$(INSTALLDIR)/busybox CFLAGS="-Os"
+busybox-clean:
+ cd busybox && [ -s .config ] && cp .config config.save
+ $(MAKE) -C busybox distclean
+ cd busybox && mv config.save .config
+
+busybox-config:
+ $(MAKE) -C busybox menuconfig
+
busybox-test: dummy
$(MAKE) -C busybox objsizes CFLAGS="-Os"
-# 1.2:
-# busybox: busybox/include/bb_config.h
-# @$(MAKE) -C busybox CROSS_CFLAGS="-mips2"
-# busybox/include/bb_config.h:
-# @$(MAKE) -C busybox oldconfig
-# @$(MAKE) -C busybox clean
-# busybox-install:
-# rm -rf $(INSTALLDIR)/busybox
-# $(MAKE) -C busybox install PREFIX=$(INSTALLDIR)/busybox
httpd: matrixssl shared nvram mssl
@$(SEP)
@$(MAKE) -C httpd
+www-install:
+ @$(MAKE) -C www install INSTALLDIR=$(INSTALLDIR)/www TOMATO_EXPERIMENTAL=$(TOMATO_EXPERIMENTAL)
matrixssl:
@$(SEP)
@@ -364,12 +357,18 @@ ppp-%:
$(MAKE) -C ppp/pppoecd $* INSTALLDIR=$(INSTALLDIR)/ppp
-
upnp: nvram shared iptables
-# miniupnpd-install:
-# install -D miniupnpd/miniupnpd $(INSTALLDIR)/miniupnpd/usr/sbin/miniupnpd
-# $(STRIP) $(INSTALLDIR)/miniupnpd/usr/sbin/miniupnpd
+miniupnpd: iptables
+ @$(SEP)
+ $(MAKE) -C miniupnpd -f Makefile.tomato
+
+miniupnpd-clean:
+ -$(MAKE) -C miniupnpd -f Makefile.tomato clean
+
+miniupnpd-install:
+ install -D miniupnpd/miniupnpd $(INSTALLDIR)/miniupnpd/usr/sbin/miniupnpd
+ $(STRIP) $(INSTALLDIR)/miniupnpd/usr/sbin/miniupnpd
nvram: shared
diff --git a/release/src/router/busybox/.config b/release/src/router/busybox/.config
new file mode 100644
index 0000000000..472a37fb98
--- /dev/null
+++ b/release/src/router/busybox/.config
@@ -0,0 +1,883 @@
+#
+# Automatically generated make config: don't edit
+# Busybox version: 1.14.0
+# Fri May 22 20:36:33 2009
+#
+CONFIG_HAVE_DOT_CONFIG=y
+
+#
+# Busybox Settings
+#
+
+#
+# General Configuration
+#
+# CONFIG_DESKTOP is not set
+# CONFIG_EXTRA_COMPAT is not set
+# CONFIG_FEATURE_ASSUME_UNICODE is not set
+CONFIG_FEATURE_BUFFERS_USE_MALLOC=y
+# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set
+# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set
+CONFIG_SHOW_USAGE=y
+CONFIG_FEATURE_VERBOSE_USAGE=y
+CONFIG_FEATURE_COMPRESS_USAGE=y
+# CONFIG_FEATURE_INSTALLER is not set
+# CONFIG_LOCALE_SUPPORT is not set
+CONFIG_GETOPT_LONG=y
+CONFIG_FEATURE_DEVPTS=y
+# CONFIG_FEATURE_CLEAN_UP is not set
+CONFIG_FEATURE_PIDFILE=y
+CONFIG_FEATURE_SUID=y
+# CONFIG_FEATURE_SUID_CONFIG is not set
+# CONFIG_FEATURE_SUID_CONFIG_QUIET is not set
+# CONFIG_SELINUX is not set
+# CONFIG_FEATURE_PREFER_APPLETS is not set
+CONFIG_BUSYBOX_EXEC_PATH="/proc/self/exe"
+CONFIG_FEATURE_SYSLOG=y
+# CONFIG_FEATURE_HAVE_RPC is not set
+
+#
+# Build Options
+#
+# CONFIG_STATIC is not set
+# CONFIG_PIE is not set
+# CONFIG_NOMMU is not set
+# CONFIG_BUILD_LIBBUSYBOX is not set
+# CONFIG_FEATURE_INDIVIDUAL is not set
+# CONFIG_FEATURE_SHARED_BUSYBOX is not set
+CONFIG_LFS=y
+CONFIG_CROSS_COMPILER_PREFIX="mipsel-uclibc-"
+CONFIG_EXTRA_CFLAGS=""
+
+#
+# Debugging Options
+#
+# CONFIG_DEBUG is not set
+# CONFIG_DEBUG_PESSIMIZE is not set
+# CONFIG_WERROR is not set
+CONFIG_NO_DEBUG_LIB=y
+# CONFIG_DMALLOC is not set
+# CONFIG_EFENCE is not set
+# CONFIG_INCLUDE_SUSv2 is not set
+
+#
+# Installation Options
+#
+# CONFIG_INSTALL_NO_USR is not set
+CONFIG_INSTALL_APPLET_SYMLINKS=y
+# CONFIG_INSTALL_APPLET_HARDLINKS is not set
+# CONFIG_INSTALL_APPLET_SCRIPT_WRAPPERS is not set
+# CONFIG_INSTALL_APPLET_DONT is not set
+# CONFIG_INSTALL_SH_APPLET_SYMLINK is not set
+# CONFIG_INSTALL_SH_APPLET_HARDLINK is not set
+# CONFIG_INSTALL_SH_APPLET_SCRIPT_WRAPPER is not set
+CONFIG_PREFIX="./_install"
+
+#
+# Busybox Library Tuning
+#
+CONFIG_PASSWORD_MINLEN=6
+CONFIG_MD5_SIZE_VS_SPEED=2
+CONFIG_FEATURE_FAST_TOP=y
+# CONFIG_FEATURE_ETC_NETWORKS is not set
+CONFIG_FEATURE_EDITING=y
+CONFIG_FEATURE_EDITING_MAX_LEN=1024
+# CONFIG_FEATURE_EDITING_VI is not set
+CONFIG_FEATURE_EDITING_HISTORY=15
+# CONFIG_FEATURE_EDITING_SAVEHISTORY is not set
+CONFIG_FEATURE_TAB_COMPLETION=y
+# CONFIG_FEATURE_USERNAME_COMPLETION is not set
+# CONFIG_FEATURE_EDITING_FANCY_PROMPT is not set
+# CONFIG_FEATURE_VERBOSE_CP_MESSAGE is not set
+CONFIG_FEATURE_COPYBUF_KB=4
+# CONFIG_MONOTONIC_SYSCALL is not set
+CONFIG_IOCTL_HEX2STR_ERROR=y
+# CONFIG_FEATURE_HWIB is not set
+
+#
+# Applets
+#
+
+#
+# Archival Utilities
+#
+# CONFIG_FEATURE_SEAMLESS_LZMA is not set
+CONFIG_FEATURE_SEAMLESS_BZ2=y
+CONFIG_FEATURE_SEAMLESS_GZ=y
+# CONFIG_FEATURE_SEAMLESS_Z is not set
+# CONFIG_AR is not set
+# CONFIG_FEATURE_AR_LONG_FILENAMES is not set
+# CONFIG_BUNZIP2 is not set
+# CONFIG_BZIP2 is not set
+# CONFIG_CPIO is not set
+# CONFIG_FEATURE_CPIO_O is not set
+# CONFIG_FEATURE_CPIO_P is not set
+# CONFIG_DPKG is not set
+# CONFIG_DPKG_DEB is not set
+# CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY is not set
+CONFIG_GUNZIP=y
+CONFIG_GZIP=y
+# CONFIG_RPM2CPIO is not set
+# CONFIG_RPM is not set
+CONFIG_TAR=y
+CONFIG_FEATURE_TAR_CREATE=y
+# CONFIG_FEATURE_TAR_AUTODETECT is not set
+# CONFIG_FEATURE_TAR_FROM is not set
+# CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY is not set
+CONFIG_FEATURE_TAR_OLDSUN_COMPATIBILITY=y
+CONFIG_FEATURE_TAR_GNU_EXTENSIONS=y
+# CONFIG_FEATURE_TAR_LONG_OPTIONS is not set
+# CONFIG_FEATURE_TAR_UNAME_GNAME is not set
+# CONFIG_UNCOMPRESS is not set
+# CONFIG_UNLZMA is not set
+# CONFIG_FEATURE_LZMA_FAST is not set
+CONFIG_UNZIP=y
+
+#
+# Coreutils
+#
+# CONFIG_BASENAME is not set
+# CONFIG_CAL is not set
+CONFIG_CAT=y
+# CONFIG_CATV is not set
+# CONFIG_CHGRP is not set
+CONFIG_CHMOD=y
+# CONFIG_CHOWN is not set
+# CONFIG_CHROOT is not set
+# CONFIG_CKSUM is not set
+# CONFIG_COMM is not set
+CONFIG_CP=y
+CONFIG_CUT=y
+CONFIG_DATE=y
+CONFIG_FEATURE_DATE_ISOFMT=y
+CONFIG_DD=y
+CONFIG_FEATURE_DD_SIGNAL_HANDLING=y
+CONFIG_FEATURE_DD_IBS_OBS=y
+CONFIG_DF=y
+# CONFIG_FEATURE_DF_FANCY is not set
+# CONFIG_DIRNAME is not set
+# CONFIG_DOS2UNIX is not set
+# CONFIG_UNIX2DOS is not set
+CONFIG_DU=y
+CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K=y
+CONFIG_ECHO=y
+CONFIG_FEATURE_FANCY_ECHO=y
+CONFIG_ENV=y
+# CONFIG_FEATURE_ENV_LONG_OPTIONS is not set
+# CONFIG_EXPAND is not set
+# CONFIG_FEATURE_EXPAND_LONG_OPTIONS is not set
+CONFIG_EXPR=y
+CONFIG_EXPR_MATH_SUPPORT_64=y
+# CONFIG_FALSE is not set
+# CONFIG_FOLD is not set
+CONFIG_HEAD=y
+CONFIG_FEATURE_FANCY_HEAD=y
+# CONFIG_HOSTID is not set
+# CONFIG_ID is not set
+# CONFIG_INSTALL is not set
+# CONFIG_FEATURE_INSTALL_LONG_OPTIONS is not set
+# CONFIG_LENGTH is not set
+CONFIG_LN=y
+# CONFIG_LOGNAME is not set
+CONFIG_LS=y
+CONFIG_FEATURE_LS_FILETYPES=y
+CONFIG_FEATURE_LS_FOLLOWLINKS=y
+CONFIG_FEATURE_LS_RECURSIVE=y
+CONFIG_FEATURE_LS_SORTFILES=y
+CONFIG_FEATURE_LS_TIMESTAMPS=y
+CONFIG_FEATURE_LS_USERNAME=y
+CONFIG_FEATURE_LS_COLOR=y
+CONFIG_FEATURE_LS_COLOR_IS_DEFAULT=y
+CONFIG_MD5SUM=y
+CONFIG_MKDIR=y
+# CONFIG_FEATURE_MKDIR_LONG_OPTIONS is not set
+# CONFIG_MKFIFO is not set
+# CONFIG_MKNOD is not set
+CONFIG_MV=y
+# CONFIG_FEATURE_MV_LONG_OPTIONS is not set
+# CONFIG_NICE is not set
+CONFIG_NOHUP=y
+# CONFIG_OD is not set
+# CONFIG_PRINTENV is not set
+CONFIG_PRINTF=y
+CONFIG_PWD=y
+# CONFIG_READLINK is not set
+# CONFIG_FEATURE_READLINK_FOLLOW is not set
+# CONFIG_REALPATH is not set
+CONFIG_RM=y
+CONFIG_RMDIR=y
+# CONFIG_FEATURE_RMDIR_LONG_OPTIONS is not set
+# CONFIG_SEQ is not set
+# CONFIG_SHA1SUM is not set
+# CONFIG_SHA256SUM is not set
+# CONFIG_SHA512SUM is not set
+CONFIG_SLEEP=y
+CONFIG_FEATURE_FANCY_SLEEP=y
+# CONFIG_FEATURE_FLOAT_SLEEP is not set
+CONFIG_SORT=y
+CONFIG_FEATURE_SORT_BIG=y
+# CONFIG_SPLIT is not set
+# CONFIG_FEATURE_SPLIT_FANCY is not set
+# CONFIG_STAT is not set
+# CONFIG_FEATURE_STAT_FORMAT is not set
+# CONFIG_STTY is not set
+# CONFIG_SUM is not set
+CONFIG_SYNC=y
+# CONFIG_TAC is not set
+CONFIG_TAIL=y
+CONFIG_FEATURE_FANCY_TAIL=y
+# CONFIG_TEE is not set
+# CONFIG_FEATURE_TEE_USE_BLOCK_IO is not set
+CONFIG_TEST=y
+CONFIG_FEATURE_TEST_64=y
+CONFIG_TOUCH=y
+CONFIG_TR=y
+CONFIG_FEATURE_TR_CLASSES=y
+CONFIG_FEATURE_TR_EQUIV=y
+# CONFIG_TRUE is not set
+# CONFIG_TTY is not set
+CONFIG_UNAME=y
+# CONFIG_UNEXPAND is not set
+# CONFIG_FEATURE_UNEXPAND_LONG_OPTIONS is not set
+# CONFIG_UNIQ is not set
+CONFIG_USLEEP=y
+# CONFIG_UUDECODE is not set
+# CONFIG_UUENCODE is not set
+CONFIG_WC=y
+CONFIG_FEATURE_WC_LARGE=y
+# CONFIG_WHO is not set
+# CONFIG_WHOAMI is not set
+# CONFIG_YES is not set
+
+#
+# Common options for cp and mv
+#
+CONFIG_FEATURE_PRESERVE_HARDLINKS=y
+
+#
+# Common options for ls, more and telnet
+#
+CONFIG_FEATURE_AUTOWIDTH=y
+
+#
+# Common options for df, du, ls
+#
+CONFIG_FEATURE_HUMAN_READABLE=y
+
+#
+# Common options for md5sum, sha1sum
+#
+# CONFIG_FEATURE_MD5_SHA1_SUM_CHECK is not set
+
+#
+# Console Utilities
+#
+# CONFIG_CHVT is not set
+CONFIG_CLEAR=y
+# CONFIG_DEALLOCVT is not set
+# CONFIG_DUMPKMAP is not set
+# CONFIG_KBD_MODE is not set
+# CONFIG_LOADFONT is not set
+# CONFIG_LOADKMAP is not set
+# CONFIG_OPENVT is not set
+# CONFIG_RESET is not set
+# CONFIG_RESIZE is not set
+# CONFIG_FEATURE_RESIZE_PRINT is not set
+CONFIG_SETCONSOLE=y
+# CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS is not set
+# CONFIG_SETFONT is not set
+# CONFIG_FEATURE_SETFONT_TEXTUAL_MAP is not set
+CONFIG_DEFAULT_SETFONT_DIR=""
+# CONFIG_SETKEYCODES is not set
+# CONFIG_SETLOGCONS is not set
+# CONFIG_SHOWKEY is not set
+
+#
+# Debian Utilities
+#
+# CONFIG_MKTEMP is not set
+# CONFIG_PIPE_PROGRESS is not set
+# CONFIG_RUN_PARTS is not set
+# CONFIG_FEATURE_RUN_PARTS_LONG_OPTIONS is not set
+# CONFIG_FEATURE_RUN_PARTS_FANCY is not set
+# CONFIG_START_STOP_DAEMON is not set
+# CONFIG_FEATURE_START_STOP_DAEMON_FANCY is not set
+# CONFIG_FEATURE_START_STOP_DAEMON_LONG_OPTIONS is not set
+CONFIG_WHICH=y
+
+#
+# Editors
+#
+CONFIG_AWK=y
+CONFIG_FEATURE_AWK_LIBM=y
+CONFIG_CMP=y
+# CONFIG_DIFF is not set
+# CONFIG_FEATURE_DIFF_BINARY is not set
+# CONFIG_FEATURE_DIFF_DIR is not set
+# CONFIG_FEATURE_DIFF_MINIMAL is not set
+# CONFIG_ED is not set
+# CONFIG_PATCH is not set
+CONFIG_SED=y
+CONFIG_VI=y
+CONFIG_FEATURE_VI_MAX_LEN=4096
+# CONFIG_FEATURE_VI_8BIT is not set
+CONFIG_FEATURE_VI_COLON=y
+CONFIG_FEATURE_VI_YANKMARK=y
+CONFIG_FEATURE_VI_SEARCH=y
+CONFIG_FEATURE_VI_USE_SIGNALS=y
+CONFIG_FEATURE_VI_DOT_CMD=y
+CONFIG_FEATURE_VI_READONLY=y
+CONFIG_FEATURE_VI_SETOPTS=y
+CONFIG_FEATURE_VI_SET=y
+CONFIG_FEATURE_VI_WIN_RESIZE=y
+# CONFIG_FEATURE_VI_OPTIMIZE_CURSOR is not set
+# CONFIG_FEATURE_ALLOW_EXEC is not set
+
+#
+# Finding Utilities
+#
+CONFIG_FIND=y
+CONFIG_FEATURE_FIND_PRINT0=y
+# CONFIG_FEATURE_FIND_MTIME is not set
+# CONFIG_FEATURE_FIND_MMIN is not set
+# CONFIG_FEATURE_FIND_PERM is not set
+# CONFIG_FEATURE_FIND_TYPE is not set
+# CONFIG_FEATURE_FIND_XDEV is not set
+# CONFIG_FEATURE_FIND_MAXDEPTH is not set
+# CONFIG_FEATURE_FIND_NEWER is not set
+# CONFIG_FEATURE_FIND_INUM is not set
+CONFIG_FEATURE_FIND_EXEC=y
+# CONFIG_FEATURE_FIND_USER is not set
+# CONFIG_FEATURE_FIND_GROUP is not set
+CONFIG_FEATURE_FIND_NOT=y
+# CONFIG_FEATURE_FIND_DEPTH is not set
+# CONFIG_FEATURE_FIND_PAREN is not set
+# CONFIG_FEATURE_FIND_SIZE is not set
+# CONFIG_FEATURE_FIND_PRUNE is not set
+# CONFIG_FEATURE_FIND_DELETE is not set
+# CONFIG_FEATURE_FIND_PATH is not set
+# CONFIG_FEATURE_FIND_REGEX is not set
+# CONFIG_FEATURE_FIND_CONTEXT is not set
+CONFIG_GREP=y
+CONFIG_FEATURE_GREP_EGREP_ALIAS=y
+CONFIG_FEATURE_GREP_FGREP_ALIAS=y
+CONFIG_FEATURE_GREP_CONTEXT=y
+# CONFIG_XARGS is not set
+# CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION is not set
+# CONFIG_FEATURE_XARGS_SUPPORT_QUOTES is not set
+# CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT is not set
+# CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM is not set
+
+#
+# Init Utilities
+#
+# CONFIG_INIT is not set
+# CONFIG_FEATURE_USE_INITTAB is not set
+# CONFIG_FEATURE_KILL_REMOVED is not set
+CONFIG_FEATURE_KILL_DELAY=0
+# CONFIG_FEATURE_INIT_SCTTY is not set
+# CONFIG_FEATURE_INIT_SYSLOG is not set
+# CONFIG_FEATURE_EXTRA_QUIET is not set
+# CONFIG_FEATURE_INIT_COREDUMPS is not set
+# CONFIG_FEATURE_INITRD is not set
+# CONFIG_HALT is not set
+# CONFIG_MESG is not set
+
+#
+# Login/Password Management Utilities
+#
+CONFIG_FEATURE_SHADOWPASSWDS=y
+CONFIG_USE_BB_PWD_GRP=y
+CONFIG_USE_BB_SHADOW=y
+# CONFIG_USE_BB_CRYPT is not set
+# CONFIG_USE_BB_CRYPT_SHA is not set
+# CONFIG_ADDGROUP is not set
+# CONFIG_FEATURE_ADDUSER_TO_GROUP is not set
+# CONFIG_DELGROUP is not set
+# CONFIG_FEATURE_DEL_USER_FROM_GROUP is not set
+# CONFIG_FEATURE_CHECK_NAMES is not set
+# CONFIG_ADDUSER is not set
+# CONFIG_FEATURE_ADDUSER_LONG_OPTIONS is not set
+# CONFIG_DELUSER is not set
+# CONFIG_GETTY is not set
+# CONFIG_FEATURE_UTMP is not set
+# CONFIG_FEATURE_WTMP is not set
+CONFIG_LOGIN=y
+# CONFIG_PAM is not set
+# CONFIG_LOGIN_SCRIPTS is not set
+# CONFIG_FEATURE_NOLOGIN is not set
+# CONFIG_FEATURE_SECURETTY is not set
+# CONFIG_PASSWD is not set
+# CONFIG_FEATURE_PASSWD_WEAK_CHECK is not set
+# CONFIG_CRYPTPW is not set
+# CONFIG_CHPASSWD is not set
+# CONFIG_SU is not set
+# CONFIG_FEATURE_SU_SYSLOG is not set
+# CONFIG_FEATURE_SU_CHECKS_SHELLS is not set
+# CONFIG_SULOGIN is not set
+# CONFIG_VLOCK is not set
+
+#
+# Linux Ext2 FS Progs
+#
+# CONFIG_CHATTR is not set
+# CONFIG_FSCK is not set
+# CONFIG_LSATTR is not set
+
+#
+# Linux Module Utilities
+#
+# CONFIG_MODPROBE_SMALL is not set
+# CONFIG_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE is not set
+# CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED is not set
+CONFIG_INSMOD=y
+CONFIG_RMMOD=y
+CONFIG_LSMOD=y
+# CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT is not set
+CONFIG_MODPROBE=y
+# CONFIG_FEATURE_MODPROBE_BLACKLIST is not set
+# CONFIG_DEPMOD is not set
+
+#
+# Options common to multiple modutils
+#
+CONFIG_FEATURE_2_4_MODULES=y
+# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set
+# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set
+# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set
+# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set
+# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set
+# CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set
+# CONFIG_FEATURE_MODUTILS_ALIAS is not set
+# CONFIG_FEATURE_MODUTILS_SYMBOLS is not set
+CONFIG_DEFAULT_MODULES_DIR="/lib/modules"
+CONFIG_DEFAULT_DEPMOD_FILE="/lib/modules/2.4.20/modules.dep"
+
+#
+# Linux System Utilities
+#
+# CONFIG_ACPID is not set
+# CONFIG_FEATURE_ACPID_COMPAT is not set
+# CONFIG_BLKID is not set
+CONFIG_DMESG=y
+CONFIG_FEATURE_DMESG_PRETTY=y
+# CONFIG_FBSET is not set
+# CONFIG_FEATURE_FBSET_FANCY is not set
+# CONFIG_FEATURE_FBSET_READMODE is not set
+# CONFIG_FDFLUSH is not set
+# CONFIG_FDFORMAT is not set
+# CONFIG_FDISK is not set
+CONFIG_FDISK_SUPPORT_LARGE_DISKS=y
+# CONFIG_FEATURE_FDISK_WRITABLE is not set
+# CONFIG_FEATURE_AIX_LABEL is not set
+# CONFIG_FEATURE_SGI_LABEL is not set
+# CONFIG_FEATURE_SUN_LABEL is not set
+# CONFIG_FEATURE_OSF_LABEL is not set
+# CONFIG_FEATURE_FDISK_ADVANCED is not set
+# CONFIG_FINDFS is not set
+# CONFIG_FREERAMDISK is not set
+# CONFIG_FSCK_MINIX is not set
+# CONFIG_MKFS_MINIX is not set
+# CONFIG_FEATURE_MINIX2 is not set
+# CONFIG_MKFS_VFAT is not set
+# CONFIG_GETOPT is not set
+# CONFIG_HEXDUMP is not set
+# CONFIG_FEATURE_HEXDUMP_REVERSE is not set
+# CONFIG_HD is not set
+# CONFIG_HWCLOCK is not set
+# CONFIG_FEATURE_HWCLOCK_LONG_OPTIONS is not set
+# CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS is not set
+# CONFIG_IPCRM is not set
+# CONFIG_IPCS is not set
+# CONFIG_LOSETUP is not set
+# CONFIG_MDEV is not set
+# CONFIG_FEATURE_MDEV_CONF is not set
+# CONFIG_FEATURE_MDEV_RENAME is not set
+# CONFIG_FEATURE_MDEV_RENAME_REGEXP is not set
+# CONFIG_FEATURE_MDEV_EXEC is not set
+# CONFIG_FEATURE_MDEV_LOAD_FIRMWARE is not set
+# CONFIG_MKSWAP is not set
+# CONFIG_FEATURE_MKSWAP_V0 is not set
+CONFIG_MORE=y
+CONFIG_FEATURE_USE_TERMIOS=y
+# CONFIG_VOLUMEID is not set
+# CONFIG_FEATURE_VOLUMEID_EXT is not set
+# CONFIG_FEATURE_VOLUMEID_REISERFS is not set
+# CONFIG_FEATURE_VOLUMEID_FAT is not set
+# CONFIG_FEATURE_VOLUMEID_HFS is not set
+# CONFIG_FEATURE_VOLUMEID_JFS is not set
+# CONFIG_FEATURE_VOLUMEID_XFS is not set
+# CONFIG_FEATURE_VOLUMEID_NTFS is not set
+# CONFIG_FEATURE_VOLUMEID_ISO9660 is not set
+# CONFIG_FEATURE_VOLUMEID_UDF is not set
+# CONFIG_FEATURE_VOLUMEID_LUKS is not set
+# CONFIG_FEATURE_VOLUMEID_LINUXSWAP is not set
+# CONFIG_FEATURE_VOLUMEID_CRAMFS is not set
+# CONFIG_FEATURE_VOLUMEID_ROMFS is not set
+# CONFIG_FEATURE_VOLUMEID_SYSV is not set
+# CONFIG_FEATURE_VOLUMEID_OCFS2 is not set
+# CONFIG_FEATURE_VOLUMEID_LINUXRAID is not set
+CONFIG_MOUNT=y
+# CONFIG_FEATURE_MOUNT_FAKE is not set
+# CONFIG_FEATURE_MOUNT_VERBOSE is not set
+CONFIG_FEATURE_MOUNT_HELPERS=y
+# CONFIG_FEATURE_MOUNT_LABEL is not set
+# CONFIG_FEATURE_MOUNT_NFS is not set
+CONFIG_FEATURE_MOUNT_CIFS=y
+CONFIG_FEATURE_MOUNT_FLAGS=y
+# CONFIG_FEATURE_MOUNT_FSTAB is not set
+# CONFIG_PIVOT_ROOT is not set
+# CONFIG_RDATE is not set
+# CONFIG_RDEV is not set
+# CONFIG_READPROFILE is not set
+# CONFIG_RTCWAKE is not set
+# CONFIG_SCRIPT is not set
+# CONFIG_SETARCH is not set
+# CONFIG_SWAPONOFF is not set
+# CONFIG_FEATURE_SWAPON_PRI is not set
+# CONFIG_SWITCH_ROOT is not set
+CONFIG_UMOUNT=y
+# CONFIG_FEATURE_UMOUNT_ALL is not set
+
+#
+# Common options for mount/umount
+#
+# CONFIG_FEATURE_MOUNT_LOOP is not set
+# CONFIG_FEATURE_MTAB_SUPPORT is not set
+
+#
+# Miscellaneous Utilities
+#
+# CONFIG_ADJTIMEX is not set
+# CONFIG_BBCONFIG is not set
+# CONFIG_CHAT is not set
+# CONFIG_FEATURE_CHAT_NOFAIL is not set
+# CONFIG_FEATURE_CHAT_TTY_HIFI is not set
+# CONFIG_FEATURE_CHAT_IMPLICIT_CR is not set
+# CONFIG_FEATURE_CHAT_SWALLOW_OPTS is not set
+# CONFIG_FEATURE_CHAT_SEND_ESCAPES is not set
+# CONFIG_FEATURE_CHAT_VAR_ABORT_LEN is not set
+# CONFIG_FEATURE_CHAT_CLR_ABORT is not set
+# CONFIG_CHRT is not set
+CONFIG_CROND=y
+# CONFIG_FEATURE_CROND_D is not set
+# CONFIG_FEATURE_CROND_CALL_SENDMAIL is not set
+CONFIG_FEATURE_CROND_DIR="/var/spool/cron"
+# CONFIG_CRONTAB is not set
+# CONFIG_DC is not set
+# CONFIG_FEATURE_DC_LIBM is not set
+# CONFIG_DEVFSD is not set
+# CONFIG_DEVFSD_MODLOAD is not set
+# CONFIG_DEVFSD_FG_NP is not set
+# CONFIG_DEVFSD_VERBOSE is not set
+# CONFIG_FEATURE_DEVFS is not set
+# CONFIG_DEVMEM is not set
+# CONFIG_EJECT is not set
+# CONFIG_FEATURE_EJECT_SCSI is not set
+# CONFIG_FBSPLASH is not set
+# CONFIG_FLASH_ERASEALL is not set
+# CONFIG_IONICE is not set
+# CONFIG_INOTIFYD is not set
+# CONFIG_LAST is not set
+# CONFIG_FEATURE_LAST_SMALL is not set
+# CONFIG_FEATURE_LAST_FANCY is not set
+CONFIG_LESS=y
+CONFIG_FEATURE_LESS_MAXLINES=9999999
+# CONFIG_FEATURE_LESS_BRACKETS is not set
+# CONFIG_FEATURE_LESS_FLAGS is not set
+# CONFIG_FEATURE_LESS_MARKS is not set
+# CONFIG_FEATURE_LESS_REGEXP is not set
+# CONFIG_FEATURE_LESS_WINCH is not set
+# CONFIG_FEATURE_LESS_DASHCMD is not set
+# CONFIG_FEATURE_LESS_LINENUMS is not set
+# CONFIG_HDPARM is not set
+# CONFIG_FEATURE_HDPARM_GET_IDENTITY is not set
+# CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF is not set
+# CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF is not set
+# CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET is not set
+# CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF is not set
+# CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA is not set
+# CONFIG_MAKEDEVS is not set
+# CONFIG_FEATURE_MAKEDEVS_LEAF is not set
+# CONFIG_FEATURE_MAKEDEVS_TABLE is not set
+# CONFIG_MAN is not set
+# CONFIG_MICROCOM is not set
+# CONFIG_MOUNTPOINT is not set
+# CONFIG_MT is not set
+# CONFIG_RAIDAUTORUN is not set
+# CONFIG_READAHEAD is not set
+# CONFIG_RUNLEVEL is not set
+# CONFIG_RX is not set
+# CONFIG_SETSID is not set
+CONFIG_STRINGS=y
+# CONFIG_TASKSET is not set
+# CONFIG_FEATURE_TASKSET_FANCY is not set
+# CONFIG_TIME is not set
+# CONFIG_TIMEOUT is not set
+# CONFIG_TTYSIZE is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Networking Utilities
+#
+# CONFIG_FEATURE_IPV6 is not set
+# CONFIG_FEATURE_PREFER_IPV4_ADDRESS is not set
+# CONFIG_VERBOSE_RESOLUTION_ERRORS is not set
+CONFIG_ARP=y
+CONFIG_ARPING=y
+# CONFIG_BRCTL is not set
+# CONFIG_FEATURE_BRCTL_FANCY is not set
+# CONFIG_FEATURE_BRCTL_SHOW is not set
+# CONFIG_DNSD is not set
+CONFIG_ETHER_WAKE=y
+# CONFIG_FAKEIDENTD is not set
+# CONFIG_FTPD is not set
+# CONFIG_FEATURE_FTP_WRITE is not set
+CONFIG_FTPGET=y
+CONFIG_FTPPUT=y
+# CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS is not set
+# CONFIG_HOSTNAME is not set
+# CONFIG_HTTPD is not set
+# CONFIG_FEATURE_HTTPD_RANGES is not set
+# CONFIG_FEATURE_HTTPD_USE_SENDFILE is not set
+# CONFIG_FEATURE_HTTPD_SETUID is not set
+# CONFIG_FEATURE_HTTPD_BASIC_AUTH is not set
+# CONFIG_FEATURE_HTTPD_AUTH_MD5 is not set
+# CONFIG_FEATURE_HTTPD_CGI is not set
+# CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR is not set
+# CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV is not set
+# CONFIG_FEATURE_HTTPD_ENCODE_URL_STR is not set
+# CONFIG_FEATURE_HTTPD_ERROR_PAGES is not set
+# CONFIG_FEATURE_HTTPD_PROXY is not set
+CONFIG_IFCONFIG=y
+CONFIG_FEATURE_IFCONFIG_STATUS=y
+# CONFIG_FEATURE_IFCONFIG_SLIP is not set
+# CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ is not set
+CONFIG_FEATURE_IFCONFIG_HW=y
+CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS=y
+# CONFIG_IFENSLAVE is not set
+# CONFIG_IFUPDOWN is not set
+CONFIG_IFUPDOWN_IFSTATE_PATH=""
+# CONFIG_FEATURE_IFUPDOWN_IP is not set
+# CONFIG_FEATURE_IFUPDOWN_IP_BUILTIN is not set
+# CONFIG_FEATURE_IFUPDOWN_IFCONFIG_BUILTIN is not set
+# CONFIG_FEATURE_IFUPDOWN_IPV4 is not set
+# CONFIG_FEATURE_IFUPDOWN_IPV6 is not set
+# CONFIG_FEATURE_IFUPDOWN_MAPPING is not set
+# CONFIG_FEATURE_IFUPDOWN_EXTERNAL_DHCP is not set
+# CONFIG_INETD is not set
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO is not set
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD is not set
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME is not set
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME is not set
+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN is not set
+# CONFIG_FEATURE_INETD_RPC is not set
+# CONFIG_IP is not set
+# CONFIG_FEATURE_IP_ADDRESS is not set
+# CONFIG_FEATURE_IP_LINK is not set
+# CONFIG_FEATURE_IP_ROUTE is not set
+# CONFIG_FEATURE_IP_TUNNEL is not set
+# CONFIG_FEATURE_IP_RULE is not set
+# CONFIG_FEATURE_IP_SHORT_FORMS is not set
+# CONFIG_FEATURE_IP_RARE_PROTOCOLS is not set
+# CONFIG_IPADDR is not set
+# CONFIG_IPLINK is not set
+# CONFIG_IPROUTE is not set
+# CONFIG_IPTUNNEL is not set
+# CONFIG_IPRULE is not set
+# CONFIG_IPCALC is not set
+# CONFIG_FEATURE_IPCALC_FANCY is not set
+# CONFIG_FEATURE_IPCALC_LONG_OPTIONS is not set
+# CONFIG_NAMEIF is not set
+# CONFIG_FEATURE_NAMEIF_EXTENDED is not set
+CONFIG_NC=y
+# CONFIG_NC_SERVER is not set
+CONFIG_NC_EXTRA=y
+CONFIG_NETSTAT=y
+CONFIG_FEATURE_NETSTAT_WIDE=y
+# CONFIG_FEATURE_NETSTAT_PRG is not set
+CONFIG_NSLOOKUP=y
+CONFIG_PING=y
+# CONFIG_PING6 is not set
+CONFIG_FEATURE_FANCY_PING=y
+CONFIG_PSCAN=y
+CONFIG_ROUTE=y
+# CONFIG_SLATTACH is not set
+CONFIG_TELNET=y
+# CONFIG_FEATURE_TELNET_TTYPE is not set
+# CONFIG_FEATURE_TELNET_AUTOLOGIN is not set
+CONFIG_TELNETD=y
+CONFIG_FEATURE_TELNETD_STANDALONE=y
+# CONFIG_TFTP is not set
+# CONFIG_TFTPD is not set
+# CONFIG_FEATURE_TFTP_GET is not set
+# CONFIG_FEATURE_TFTP_PUT is not set
+# CONFIG_FEATURE_TFTP_BLOCKSIZE is not set
+# CONFIG_TFTP_DEBUG is not set
+CONFIG_TRACEROUTE=y
+CONFIG_FEATURE_TRACEROUTE_VERBOSE=y
+CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE=y
+CONFIG_FEATURE_TRACEROUTE_USE_ICMP=y
+# CONFIG_APP_UDHCPD is not set
+# CONFIG_APP_DHCPRELAY is not set
+# CONFIG_APP_DUMPLEASES is not set
+# CONFIG_FEATURE_UDHCPD_WRITE_LEASES_EARLY is not set
+CONFIG_DHCPD_LEASES_FILE=""
+CONFIG_APP_UDHCPC=y
+# CONFIG_FEATURE_UDHCPC_ARPING is not set
+# CONFIG_FEATURE_UDHCP_PORT is not set
+# CONFIG_UDHCP_DEBUG is not set
+# CONFIG_FEATURE_UDHCP_RFC3397 is not set
+CONFIG_UDHCPC_DEFAULT_SCRIPT="/usr/share/udhcpc/default.script"
+CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS=80
+CONFIG_IFUPDOWN_UDHCPC_CMD_OPTIONS=""
+# CONFIG_VCONFIG is not set
+CONFIG_WGET=y
+# CONFIG_FEATURE_WGET_STATUSBAR is not set
+CONFIG_FEATURE_WGET_AUTHENTICATION=y
+# CONFIG_FEATURE_WGET_LONG_OPTIONS is not set
+# CONFIG_ZCIP is not set
+# CONFIG_TCPSVD is not set
+# CONFIG_TUNCTL is not set
+# CONFIG_FEATURE_TUNCTL_UG is not set
+# CONFIG_UDPSVD is not set
+
+#
+# Print Utilities
+#
+# CONFIG_LPD is not set
+# CONFIG_LPR is not set
+# CONFIG_LPQ is not set
+
+#
+# Mail Utilities
+#
+# CONFIG_MAKEMIME is not set
+CONFIG_FEATURE_MIME_CHARSET=""
+# CONFIG_POPMAILDIR is not set
+# CONFIG_FEATURE_POPMAILDIR_DELIVERY is not set
+# CONFIG_REFORMIME is not set
+# CONFIG_FEATURE_REFORMIME_COMPAT is not set
+# CONFIG_SENDMAIL is not set
+
+#
+# Process Utilities
+#
+CONFIG_FREE=y
+# CONFIG_FUSER is not set
+CONFIG_KILL=y
+CONFIG_KILLALL=y
+# CONFIG_KILLALL5 is not set
+# CONFIG_NMETER is not set
+# CONFIG_PGREP is not set
+CONFIG_PIDOF=y
+# CONFIG_FEATURE_PIDOF_SINGLE is not set
+# CONFIG_FEATURE_PIDOF_OMIT is not set
+# CONFIG_PKILL is not set
+CONFIG_PS=y
+CONFIG_FEATURE_PS_WIDE=y
+# CONFIG_FEATURE_PS_TIME is not set
+# CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS is not set
+# CONFIG_RENICE is not set
+# CONFIG_BB_SYSCTL is not set
+CONFIG_TOP=y
+CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE=y
+CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS=y
+# CONFIG_FEATURE_TOP_SMP_CPU is not set
+# CONFIG_FEATURE_TOP_DECIMALS is not set
+# CONFIG_FEATURE_TOP_SMP_PROCESS is not set
+# CONFIG_FEATURE_TOPMEM is not set
+CONFIG_UPTIME=y
+CONFIG_WATCH=y
+
+#
+# Runit Utilities
+#
+# CONFIG_RUNSV is not set
+# CONFIG_RUNSVDIR is not set
+# CONFIG_FEATURE_RUNSVDIR_LOG is not set
+# CONFIG_SV is not set
+CONFIG_SV_DEFAULT_SERVICE_DIR=""
+# CONFIG_SVLOGD is not set
+# CONFIG_CHPST is not set
+# CONFIG_SETUIDGID is not set
+# CONFIG_ENVUIDGID is not set
+# CONFIG_ENVDIR is not set
+# CONFIG_SOFTLIMIT is not set
+# CONFIG_CHCON is not set
+# CONFIG_FEATURE_CHCON_LONG_OPTIONS is not set
+# CONFIG_GETENFORCE is not set
+# CONFIG_GETSEBOOL is not set
+# CONFIG_LOAD_POLICY is not set
+# CONFIG_MATCHPATHCON is not set
+# CONFIG_RESTORECON is not set
+# CONFIG_RUNCON is not set
+# CONFIG_FEATURE_RUNCON_LONG_OPTIONS is not set
+# CONFIG_SELINUXENABLED is not set
+# CONFIG_SETENFORCE is not set
+# CONFIG_SETFILES is not set
+# CONFIG_FEATURE_SETFILES_CHECK_OPTION is not set
+# CONFIG_SETSEBOOL is not set
+# CONFIG_SESTATUS is not set
+
+#
+# Shells
+#
+CONFIG_FEATURE_SH_IS_ASH=y
+# CONFIG_FEATURE_SH_IS_HUSH is not set
+# CONFIG_FEATURE_SH_IS_MSH is not set
+# CONFIG_FEATURE_SH_IS_NONE is not set
+CONFIG_ASH=y
+
+#
+# Ash Shell Options
+#
+CONFIG_ASH_BASH_COMPAT=y
+# CONFIG_ASH_JOB_CONTROL is not set
+# CONFIG_ASH_READ_NCHARS is not set
+# CONFIG_ASH_READ_TIMEOUT is not set
+CONFIG_ASH_ALIAS=y
+# CONFIG_ASH_GETOPTS is not set
+# CONFIG_ASH_BUILTIN_ECHO is not set
+# CONFIG_ASH_BUILTIN_PRINTF is not set
+# CONFIG_ASH_BUILTIN_TEST is not set
+# CONFIG_ASH_CMDCMD is not set
+# CONFIG_ASH_MAIL is not set
+CONFIG_ASH_OPTIMIZE_FOR_SIZE=y
+# CONFIG_ASH_RANDOM_SUPPORT is not set
+# CONFIG_ASH_EXPAND_PRMT is not set
+# CONFIG_HUSH is not set
+# CONFIG_HUSH_HELP is not set
+# CONFIG_HUSH_INTERACTIVE is not set
+# CONFIG_HUSH_JOB is not set
+# CONFIG_HUSH_TICK is not set
+# CONFIG_HUSH_IF is not set
+# CONFIG_HUSH_LOOPS is not set
+# CONFIG_HUSH_CASE is not set
+# CONFIG_HUSH_FUNCTIONS is not set
+# CONFIG_LASH is not set
+# CONFIG_MSH is not set
+
+#
+# Bourne Shell Options
+#
+CONFIG_SH_MATH_SUPPORT=y
+# CONFIG_SH_MATH_SUPPORT_64 is not set
+# CONFIG_FEATURE_SH_EXTRA_QUIET is not set
+# CONFIG_FEATURE_SH_STANDALONE is not set
+# CONFIG_FEATURE_SH_NOFORK is not set
+# CONFIG_CTTYHACK is not set
+
+#
+# System Logging Utilities
+#
+CONFIG_SYSLOGD=y
+CONFIG_FEATURE_ROTATE_LOGFILE=y
+CONFIG_FEATURE_REMOTE_LOG=y
+# CONFIG_FEATURE_SYSLOGD_DUP is not set
+# CONFIG_FEATURE_IPC_SYSLOG is not set
+CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE=0
+# CONFIG_LOGREAD is not set
+# CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING is not set
+CONFIG_KLOGD=y
+CONFIG_LOGGER=y
diff --git a/release/src/router/busybox/AUTHORS b/release/src/router/busybox/AUTHORS
index 9755ad9dda..378c33295f 100644
--- a/release/src/router/busybox/AUTHORS
+++ b/release/src/router/busybox/AUTHORS
@@ -166,7 +166,7 @@ Paul Fox
Roberto A. Foglietta
port: dnsd
-Bernhard Fischer
+Bernhard Reutner-Fischer
misc
Mike Frysinger
diff --git a/release/src/router/busybox/Config.in b/release/src/router/busybox/Config.in
index c2005c78a8..fff6d83d58 100644
--- a/release/src/router/busybox/Config.in
+++ b/release/src/router/busybox/Config.in
@@ -155,15 +155,17 @@ config FEATURE_SUID
default n
help
With this option you can install the busybox binary belonging
- to root with the suid bit set, and it'll and it'll automatically drop
+ to root with the suid bit set, and it will automatically drop
priviledges for applets that don't need root access.
- If you're really paranoid and don't want to do this, build two
+ If you are really paranoid and don't want to do this, build two
busybox binaries with different applets in them (and the appropriate
symlinks pointing to each binary), and only set the suid bit on the
one that needs it. The applets currently marked to need the suid bit
- are login, passwd, su, ping, traceroute, crontab, dnsd, ipcrm, ipcs,
- and vlock.
+ are:
+
+ crontab, dnsd, findfs, ipcrm, ipcs, login, passwd, ping, su,
+ traceroute, vlock.
config FEATURE_SUID_CONFIG
bool "Runtime SUID/SGID configuration via /etc/busybox.conf"
@@ -254,18 +256,18 @@ config BUSYBOX_EXEC_PATH
# These are auto-selected by other options
config FEATURE_SYSLOG
- bool "Support for logging to syslog"
+ bool #No description makes it a hidden option
default n
- help
- This option is auto-selected when you select any applet which may
- send its output to syslog. You do not need to select it manually.
+ #help
+ # This option is auto-selected when you select any applet which may
+ # send its output to syslog. You do not need to select it manually.
config FEATURE_HAVE_RPC
- bool "RPC support"
+ bool #No description makes it a hidden option
default n
- help
- This is automatically selected if any of enabled applets need it.
- You do not need to select it manually.
+ #help
+ # This is automatically selected if any of enabled applets need it.
+ # You do not need to select it manually.
endmenu
@@ -402,9 +404,18 @@ config CROSS_COMPILER_PREFIX
help
If you want to build BusyBox with a cross compiler, then you
will need to set this to the cross-compiler prefix, for example,
- "i386-uclibc-". Note that CROSS_COMPILE environment variable
- or "make CROSS_COMPILE=xxx ..." will override this selection.
- For native build leave it empty.
+ "i386-uclibc-".
+
+ Note that CROSS_COMPILE environment variable or
+ "make CROSS_COMPILE=xxx ..." will override this selection.
+
+ Native builds leave this empty.
+
+config EXTRA_CFLAGS
+ string "Additional CFLAGS"
+ default ""
+ help
+ Additional CFLAGS to pass to the compiler verbatim.
endmenu
@@ -491,8 +502,8 @@ config INCLUDE_SUSv2
will be supported in head, tail, and fold. (Note: should
affect renice too.)
-config PARSE
- bool "Uniform config file parser debugging applet: parse"
+### config PARSE
+### bool "Uniform config file parser debugging applet: parse"
endmenu
@@ -590,9 +601,10 @@ source modutils/Config.in
source util-linux/Config.in
source miscutils/Config.in
source networking/Config.in
+source printutils/Config.in
+source mailutils/Config.in
source procps/Config.in
-source shell/Config.in
-source sysklogd/Config.in
source runit/Config.in
source selinux/Config.in
-source printutils/Config.in
+source shell/Config.in
+source sysklogd/Config.in
diff --git a/release/src/router/busybox/Makefile b/release/src/router/busybox/Makefile
index 1bfb270829..0d6e17d04c 100644
--- a/release/src/router/busybox/Makefile
+++ b/release/src/router/busybox/Makefile
@@ -1,6 +1,6 @@
VERSION = 1
-PATCHLEVEL = 12
-SUBLEVEL = 3
+PATCHLEVEL = 14
+SUBLEVEL = 0
EXTRAVERSION =
NAME = Unnamed
@@ -168,6 +168,7 @@ ifeq ($(CROSS_COMPILE),)
CROSS_COMPILE := $(shell grep ^CONFIG_CROSS_COMPILER_PREFIX .config 2>/dev/null)
CROSS_COMPILE := $(subst CONFIG_CROSS_COMPILER_PREFIX=,,$(CROSS_COMPILE))
CROSS_COMPILE := $(subst ",,$(CROSS_COMPILE))
+#")
endif
# SUBARCH tells the usermode build what the underlying arch is. That is set
@@ -456,6 +457,7 @@ libs-y := \
libbb/ \
libpwdgrp/ \
loginutils/ \
+ mailutils/ \
miscutils/ \
modutils/ \
networking/ \
@@ -505,7 +507,7 @@ endif
# command line.
# This allow a user to issue only 'make' to build a kernel including modules
# Defaults busybox but it is usually overridden in the arch makefile
-all: busybox
+all: busybox doc
-include $(srctree)/arch/$(ARCH)/Makefile
@@ -966,6 +968,12 @@ clean: archclean $(clean-dirs)
-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \) \
-type f -print | xargs rm -f
+PHONY += doc-clean
+doc-clean: rm-files := docs/busybox.pod \
+ docs/BusyBox.html docs/BusyBox.1 docs/BusyBox.txt
+doc-clean:
+ $(call cmd,rmfiles)
+
# mrproper - Delete all generated files, including .config
#
mrproper: rm-dirs := $(wildcard $(MRPROPER_DIRS))
diff --git a/release/src/router/busybox/Makefile.custom b/release/src/router/busybox/Makefile.custom
index 58a979e112..d9a2367ab3 100644
--- a/release/src/router/busybox/Makefile.custom
+++ b/release/src/router/busybox/Makefile.custom
@@ -105,6 +105,12 @@ bigdata: busybox_unstripped
.PHONY: doc
doc: docs/busybox.pod docs/BusyBox.txt docs/BusyBox.1 docs/BusyBox.html
+# FIXME: Doesn't belong here
+ cmd_doc =
+ quiet_cmd_doc = $(Q)echo " DOC $(@F)"
+silent_cmd_doc =
+disp_doc = $($(quiet)cmd_doc)
+
docs/busybox.pod: $(srctree)/docs/busybox_header.pod \
$(srctree)/include/usage.h \
$(srctree)/docs/busybox_footer.pod \
diff --git a/release/src/router/busybox/Makefile.flags b/release/src/router/busybox/Makefile.flags
index e31480204e..2109fdf11c 100644
--- a/release/src/router/busybox/Makefile.flags
+++ b/release/src/router/busybox/Makefile.flags
@@ -23,6 +23,7 @@ CFLAGS += $(call cc-option,-Wwrite-strings,)
CFLAGS += $(call cc-option,-Wundef,)
CFLAGS += $(call cc-option,-Wstrict-prototypes,)
CFLAGS += $(call cc-option,-Wunused -Wunused-parameter,)
+CFLAGS += $(call cc-option,-Wunused-function -Wunused-value,)
CFLAGS += $(call cc-option,-Wmissing-prototypes -Wmissing-declarations,)
# warn about C99 declaration after statement
CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
@@ -81,6 +82,11 @@ CFLAGS_busybox += $(ARCH_PIE)
CFLAGS += $(ARCH_FPIE)
endif
+ifneq ($(CONFIG_EXTRA_CFLAGS),)
+CFLAGS += $(strip $(subst ",,$(CONFIG_EXTRA_CFLAGS)))
+#"))
+endif
+
LDLIBS += m crypt
ifeq ($(CONFIG_PAM),y)
@@ -99,12 +105,12 @@ ifeq ($(CONFIG_DMALLOC),y)
LDLIBS += dmalloc
endif
-# If a flat binary should be built, CFLAGS_busybox="-Wl,-elf2flt"
+# If a flat binary should be built, CFLAGS_busybox="-elf2flt"
# env var should be set for make invocation.
# Here we check whether CFLAGS_busybox indeed contains that flag.
# (For historical reasons, we also check LDFLAGS, which doesn't
-# seem to be entirely correct variable to put "-Wl,-elf2flt" into).
-W_ELF2FLT = -Wl,-elf2flt
+# seem to be entirely correct variable to put "-elf2flt" into).
+W_ELF2FLT = -elf2flt
ifneq (,$(findstring $(W_ELF2FLT),$(LDFLAGS) $(CFLAGS_busybox)))
SKIP_STRIP = y
endif
diff --git a/release/src/router/busybox/Makefile.help b/release/src/router/busybox/Makefile.help
index f957403652..999d0298e5 100644
--- a/release/src/router/busybox/Makefile.help
+++ b/release/src/router/busybox/Makefile.help
@@ -6,6 +6,7 @@ help:
@echo 'Cleaning:'
@echo ' clean - delete temporary files created by build'
@echo ' distclean - delete all non-source files (including .config)'
+ @echo ' doc-clean - delete all generated documentation'
@echo
@echo 'Build:'
@echo ' all - Executable and documentation'
diff --git a/release/src/router/busybox/README b/release/src/router/busybox/README
index 57407b5504..40490449e3 100644
--- a/release/src/router/busybox/README
+++ b/release/src/router/busybox/README
@@ -78,7 +78,7 @@ Downloading the current source code:
http://busybox.net/developer.html
The developers also have a bug and patch tracking system
- (http://bugs.busybox.net) although posting a bug/patch to the mailing list
+ (https://bugs.busybox.net) although posting a bug/patch to the mailing list
is generally a faster way of getting it fixed, and the complete archive of
what happened is the subversion changelog.
diff --git a/release/src/router/busybox/TODO b/release/src/router/busybox/TODO
index 133fd4bedc..d6a60d1dd2 100644
--- a/release/src/router/busybox/TODO
+++ b/release/src/router/busybox/TODO
@@ -23,7 +23,7 @@ Rob Landley suggested these:
lash is phased out. hush can be configured down to be nearly as small,
but less buggy :)
init
- General cleanup (should use ENABLE_FEATURE_INIT_SYSLOG and ENABLE_FEATURE_INIT_DEBUG).
+ General cleanup (should use ENABLE_FEATURE_INIT_SYSLOG).
Do a SUSv3 audit
Look at the full Single Unix Specification version 3 (available online at
"http://www.opengroup.org/onlinepubs/009695399/nfindex.html") and
@@ -99,15 +99,10 @@ Rob Landley suggested these:
This one's open to everybody, but I'll wind up doing it...
-Bernhard Fischer suggests to look at these:
+Bernhard Reutner-Fischer suggests to look at these:
New debug options:
-Wlarger-than-127
Cleanup any big users
- -Wunused-parameter
- Facilitate applet PROTOTYPES to provide means for having applets that
- do a) not take any arguments b) need only one of argc or argv c) need
- both argc and argv. All of these three options should go for the most
- feature complete denominator.
Collate BUFSIZ IOBUF_SIZE MY_BUF_SIZE PIPE_PROGRESS_SIZE BUFSIZE PIPESIZE
make bb_common_bufsiz1 configurable, size wise.
make pipesize configurable, size wise.
@@ -132,14 +127,6 @@ patch
And while we're at it, a new patch filename quoting format is apparently
coming soon: http://marc.theaimsgroup.com/?l=git&m=112927316408690&w=2
---
-man
- It would be nice to have a man command. Not one that handles troff or
- anything, just one that can handle preformatted ascii man pages, possibly
- compressed. This could probably be a script in the extras directory that
- calls cat/zcat/bzcat | less
-
- (How doclifter might work into this is anybody's guess.)
----
ar
Write support!
---
@@ -183,8 +170,7 @@ Unify archivers
---
Text buffer support.
Several existing applets (sort, vi, less...) read
- a whole file into memory and act on it. There might be an opportunity
- for shared code in there that could be moved into libbb...
+ a whole file into memory and act on it. Use open_read_close().
---
Memory Allocation
We have a CONFIG_BUFFER mechanism that lets us select whether to do memory
@@ -236,7 +222,7 @@ Switch CONFIG_SYMBOLS to ENABLE_SYMBOLS
FEATURE_CLEAN_UP
This is more an unresolved issue than a to-do item. More thought is needed.
- Normally we rely on exit() to free memory, close files, and unmap segments
+ Normally we rely on exit() to free memory, close files and unmap segments
for us. This makes most calls to free(), close(), and unmap() optional in
busybox applets that don't intend to run for very long, and optional stuff
can be omitted to save size.
@@ -287,6 +273,7 @@ Minor stuff:
---
in_ether duplicated in network/{interface,ifconfig}.c
---
+ unify progress_meter. wget, flash_eraseall, pipe_progress, fbsplash, setfiles.
Code cleanup:
diff --git a/release/src/router/busybox/TODO_config_nommu b/release/src/router/busybox/TODO_config_nommu
index 8e13e1fe5e..2061bfd1cd 100644
--- a/release/src/router/busybox/TODO_config_nommu
+++ b/release/src/router/busybox/TODO_config_nommu
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Busybox version: 1.12.0.svn
-# Wed Aug 20 00:24:07 2008
+# Busybox version: 1.13.0.svn
+# Sun Nov 9 17:09:13 2008
#
CONFIG_HAVE_DOT_CONFIG=y
@@ -13,8 +13,8 @@ CONFIG_HAVE_DOT_CONFIG=y
# General Configuration
#
CONFIG_DESKTOP=y
-# CONFIG_EXTRA_COMPAT is not set
-CONFIG_FEATURE_ASSUME_UNICODE=y
+CONFIG_EXTRA_COMPAT=y
+# CONFIG_FEATURE_ASSUME_UNICODE is not set
CONFIG_FEATURE_BUFFERS_USE_MALLOC=y
# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set
# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set
@@ -58,7 +58,6 @@ CONFIG_NO_DEBUG_LIB=y
# CONFIG_DMALLOC is not set
# CONFIG_EFENCE is not set
CONFIG_INCLUDE_SUSv2=y
-# CONFIG_PARSE is not set
#
# Installation Options
@@ -111,6 +110,7 @@ CONFIG_BUNZIP2=y
CONFIG_BZIP2=y
CONFIG_CPIO=y
CONFIG_FEATURE_CPIO_O=y
+CONFIG_FEATURE_CPIO_P=y
CONFIG_DPKG=y
CONFIG_DPKG_DEB=y
CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY=y
@@ -153,7 +153,7 @@ CONFIG_DD=y
CONFIG_FEATURE_DD_SIGNAL_HANDLING=y
CONFIG_FEATURE_DD_IBS_OBS=y
CONFIG_DF=y
-CONFIG_FEATURE_DF_INODE=y
+CONFIG_FEATURE_DF_FANCY=y
CONFIG_DIRNAME=y
CONFIG_DOS2UNIX=y
CONFIG_UNIX2DOS=y
@@ -283,6 +283,8 @@ CONFIG_FEATURE_RESIZE_PRINT=y
CONFIG_SETCONSOLE=y
CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS=y
CONFIG_SETFONT=y
+CONFIG_FEATURE_SETFONT_TEXTUAL_MAP=y
+CONFIG_DEFAULT_SETFONT_DIR=""
CONFIG_SETKEYCODES=y
CONFIG_SETLOGCONS=y
CONFIG_SHOWKEY=y
@@ -304,7 +306,7 @@ CONFIG_WHICH=y
# Editors
#
CONFIG_AWK=y
-CONFIG_FEATURE_AWK_MATH=y
+CONFIG_FEATURE_AWK_LIBM=y
CONFIG_CMP=y
CONFIG_DIFF=y
CONFIG_FEATURE_DIFF_BINARY=y
@@ -367,7 +369,6 @@ CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM=y
# Init Utilities
#
CONFIG_INIT=y
-# CONFIG_DEBUG_INIT is not set
CONFIG_FEATURE_USE_INITTAB=y
CONFIG_FEATURE_KILL_REMOVED=y
CONFIG_FEATURE_KILL_DELAY=1
@@ -422,35 +423,36 @@ CONFIG_LSATTR=y
#
# Linux Module Utilities
#
+CONFIG_DEFAULT_MODULES_DIR="/lib/modules"
+CONFIG_DEFAULT_DEPMOD_FILE="modules.dep"
CONFIG_MODPROBE_SMALL=y
CONFIG_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE=y
CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED=y
-# CONFIG_DEPMOD is not set
-# CONFIG_FEATURE_DEPMOD_PRUNE_FANCY is not set
-# CONFIG_FEATURE_DEPMOD_ALIAS is not set
# CONFIG_INSMOD is not set
-# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set
-# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set
-# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set
-# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set
-# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set
# CONFIG_RMMOD is not set
# CONFIG_LSMOD is not set
# CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT is not set
# CONFIG_MODPROBE is not set
-# CONFIG_FEATURE_MODPROBE_MULTIPLE_OPTIONS is not set
-# CONFIG_FEATURE_MODPROBE_FANCY_ALIAS is not set
# CONFIG_FEATURE_MODPROBE_BLACKLIST is not set
-# CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set
+# CONFIG_DEPMOD is not set
+
+#
+# Options common to multiple modutils
+#
# CONFIG_FEATURE_2_4_MODULES is not set
-# CONFIG_FEATURE_2_6_MODULES is not set
-CONFIG_DEFAULT_MODULES_DIR="/lib/modules"
-CONFIG_DEFAULT_DEPMOD_FILE="modules.dep"
-# CONFIG_FEATURE_QUERY_MODULE_INTERFACE is not set
+# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set
+# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set
+# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set
+# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set
+# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set
+# CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set
+# CONFIG_FEATURE_MODUTILS_ALIAS is not set
+# CONFIG_FEATURE_MODUTILS_SYMBOLS is not set
#
# Linux System Utilities
#
+CONFIG_BLKID=y
CONFIG_DMESG=y
CONFIG_FEATURE_DMESG_PRETTY=y
CONFIG_FBSET=y
@@ -555,15 +557,17 @@ CONFIG_FEATURE_CHAT_VAR_ABORT_LEN=y
CONFIG_FEATURE_CHAT_CLR_ABORT=y
CONFIG_CHRT=y
CONFIG_CROND=y
-CONFIG_DEBUG_CROND_OPTION=y
+CONFIG_FEATURE_CROND_D=y
CONFIG_FEATURE_CROND_CALL_SENDMAIL=y
CONFIG_CRONTAB=y
CONFIG_DC=y
+CONFIG_FEATURE_DC_LIBM=y
# CONFIG_DEVFSD is not set
# CONFIG_DEVFSD_MODLOAD is not set
# CONFIG_DEVFSD_FG_NP is not set
# CONFIG_DEVFSD_VERBOSE is not set
# CONFIG_FEATURE_DEVFS is not set
+CONFIG_DEVMEM=y
CONFIG_EJECT=y
CONFIG_FEATURE_EJECT_SCSI=y
CONFIG_FBSPLASH=y
@@ -575,9 +579,11 @@ CONFIG_LESS=y
CONFIG_FEATURE_LESS_MAXLINES=9999999
CONFIG_FEATURE_LESS_BRACKETS=y
CONFIG_FEATURE_LESS_FLAGS=y
-CONFIG_FEATURE_LESS_FLAGCS=y
+CONFIG_FEATURE_LESS_DASHCMD=y
CONFIG_FEATURE_LESS_MARKS=y
CONFIG_FEATURE_LESS_REGEXP=y
+CONFIG_FEATURE_LESS_LINENUMS=y
+CONFIG_FEATURE_LESS_WINCH=y
CONFIG_HDPARM=y
CONFIG_FEATURE_HDPARM_GET_IDENTITY=y
CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF=y
@@ -625,11 +631,9 @@ CONFIG_HOSTNAME=y
CONFIG_HTTPD=y
CONFIG_FEATURE_HTTPD_RANGES=y
CONFIG_FEATURE_HTTPD_USE_SENDFILE=y
-CONFIG_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP=y
CONFIG_FEATURE_HTTPD_SETUID=y
CONFIG_FEATURE_HTTPD_BASIC_AUTH=y
CONFIG_FEATURE_HTTPD_AUTH_MD5=y
-CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES=y
CONFIG_FEATURE_HTTPD_CGI=y
CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR=y
CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV=y
@@ -689,8 +693,6 @@ CONFIG_PING6=y
CONFIG_FEATURE_FANCY_PING=y
CONFIG_PSCAN=y
CONFIG_ROUTE=y
-CONFIG_SENDMAIL=y
-CONFIG_FETCHMAIL=y
CONFIG_SLATTACH=y
CONFIG_TELNET=y
CONFIG_FEATURE_TELNET_TTYPE=y
@@ -702,7 +704,7 @@ CONFIG_TFTPD=y
CONFIG_FEATURE_TFTP_GET=y
CONFIG_FEATURE_TFTP_PUT=y
CONFIG_FEATURE_TFTP_BLOCKSIZE=y
-CONFIG_DEBUG_TFTP=y
+CONFIG_TFTP_DEBUG=y
CONFIG_TRACEROUTE=y
CONFIG_FEATURE_TRACEROUTE_VERBOSE=y
CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE=y
@@ -715,9 +717,9 @@ CONFIG_DHCPD_LEASES_FILE="/var/lib/misc/udhcpd.leases"
CONFIG_APP_UDHCPC=y
CONFIG_FEATURE_UDHCPC_ARPING=y
CONFIG_FEATURE_UDHCP_PORT=y
-CONFIG_FEATURE_UDHCP_DEBUG=y
-CONFIG_FEATURE_RFC3397=y
-CONFIG_DHCPC_DEFAULT_SCRIPT="/usr/share/udhcpc/default.script"
+CONFIG_UDHCP_DEBUG=y
+CONFIG_FEATURE_UDHCP_RFC3397=y
+CONFIG_UDHCPC_DEFAULT_SCRIPT="/usr/share/udhcpc/default.script"
CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS=80
CONFIG_VCONFIG=y
CONFIG_WGET=y
@@ -729,6 +731,26 @@ CONFIG_TCPSVD=y
CONFIG_UDPSVD=y
#
+# Print Utilities
+#
+CONFIG_LPD=y
+CONFIG_LPR=y
+CONFIG_LPQ=y
+
+#
+# Mail Utilities
+#
+CONFIG_MAKEMIME=y
+CONFIG_FEATURE_MIME_CHARSET="us-ascii"
+CONFIG_POPMAILDIR=y
+CONFIG_FEATURE_POPMAILDIR_DELIVERY=y
+CONFIG_REFORMIME=y
+CONFIG_FEATURE_REFORMIME_COMPAT=y
+CONFIG_SENDMAIL=y
+CONFIG_FEATURE_SENDMAIL_MAILX=y
+CONFIG_FEATURE_SENDMAIL_MAILXX=y
+
+#
# Process Utilities
#
CONFIG_FREE=y
@@ -751,18 +773,54 @@ CONFIG_BB_SYSCTL=y
CONFIG_TOP=y
CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE=y
CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS=y
+CONFIG_FEATURE_TOP_SMP_CPU=y
CONFIG_FEATURE_TOP_DECIMALS=y
+CONFIG_FEATURE_TOP_SMP_PROCESS=y
CONFIG_FEATURE_TOPMEM=y
CONFIG_UPTIME=y
CONFIG_WATCH=y
#
+# Runit Utilities
+#
+CONFIG_RUNSV=y
+CONFIG_RUNSVDIR=y
+CONFIG_FEATURE_RUNSVDIR_LOG=y
+CONFIG_SV=y
+CONFIG_SV_DEFAULT_SERVICE_DIR="/var/service"
+CONFIG_SVLOGD=y
+CONFIG_CHPST=y
+CONFIG_SETUIDGID=y
+CONFIG_ENVUIDGID=y
+CONFIG_ENVDIR=y
+CONFIG_SOFTLIMIT=y
+
+#
+# SELinux Utilities
+#
+CONFIG_CHCON=y
+CONFIG_FEATURE_CHCON_LONG_OPTIONS=y
+CONFIG_GETENFORCE=y
+CONFIG_GETSEBOOL=y
+CONFIG_LOAD_POLICY=y
+CONFIG_MATCHPATHCON=y
+CONFIG_RESTORECON=y
+CONFIG_RUNCON=y
+CONFIG_FEATURE_RUNCON_LONG_OPTIONS=y
+CONFIG_SELINUXENABLED=y
+CONFIG_SETENFORCE=y
+CONFIG_SETFILES=y
+CONFIG_FEATURE_SETFILES_CHECK_OPTION=y
+CONFIG_SETSEBOOL=y
+CONFIG_SESTATUS=y
+
+#
# Shells
#
# CONFIG_FEATURE_SH_IS_ASH is not set
-# CONFIG_FEATURE_SH_IS_HUSH is not set
+CONFIG_FEATURE_SH_IS_HUSH=y
# CONFIG_FEATURE_SH_IS_MSH is not set
-CONFIG_FEATURE_SH_IS_NONE=y
+# CONFIG_FEATURE_SH_IS_NONE is not set
# CONFIG_ASH is not set
# CONFIG_ASH_BASH_COMPAT is not set
# CONFIG_ASH_JOB_CONTROL is not set
@@ -812,42 +870,3 @@ CONFIG_LOGREAD=y
CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING=y
CONFIG_KLOGD=y
CONFIG_LOGGER=y
-
-#
-# Runit Utilities
-#
-CONFIG_RUNSV=y
-CONFIG_RUNSVDIR=y
-CONFIG_SV=y
-CONFIG_SVLOGD=y
-CONFIG_CHPST=y
-CONFIG_SETUIDGID=y
-CONFIG_ENVUIDGID=y
-CONFIG_ENVDIR=y
-CONFIG_SOFTLIMIT=y
-
-#
-# Selinux Utilities
-#
-CONFIG_CHCON=y
-CONFIG_FEATURE_CHCON_LONG_OPTIONS=y
-CONFIG_GETENFORCE=y
-CONFIG_GETSEBOOL=y
-CONFIG_LOAD_POLICY=y
-CONFIG_MATCHPATHCON=y
-CONFIG_RESTORECON=y
-CONFIG_RUNCON=y
-CONFIG_FEATURE_RUNCON_LONG_OPTIONS=y
-CONFIG_SELINUXENABLED=y
-CONFIG_SETENFORCE=y
-CONFIG_SETFILES=y
-CONFIG_FEATURE_SETFILES_CHECK_OPTION=y
-CONFIG_SETSEBOOL=y
-CONFIG_SESTATUS=y
-
-#
-# Print Utilities
-#
-CONFIG_LPD=y
-CONFIG_LPR=y
-CONFIG_LPQ=y
diff --git a/release/src/router/busybox/applets/usage.c b/release/src/router/busybox/applets/usage.c
index a35817f9f7..1e038b3672 100644
--- a/release/src/router/busybox/applets/usage.c
+++ b/release/src/router/busybox/applets/usage.c
@@ -1,4 +1,9 @@
/* vi: set sw=4 ts=4: */
+/*
+ * Copyright (C) 2008 Denys Vlasenko.
+ *
+ * Licensed under GPLv2, see file LICENSE in this tarball for details.
+ */
#include
/* Just #include "autoconf.h" doesn't work for builds in separate
diff --git a/release/src/router/busybox/applets/usage_compressed b/release/src/router/busybox/applets/usage_compressed
index 05ceafd4a9..c30bcfa29b 100755
--- a/release/src/router/busybox/applets/usage_compressed
+++ b/release/src/router/busybox/applets/usage_compressed
@@ -17,7 +17,7 @@ echo 'static const char packed_usage[] ALIGN1 = {'
## Breaks on big-endian systems!
## # Extra effort to avoid using "od -t x1": -t is not available
## # in non-CONFIG_DESKTOPed busybox od
-##
+##
## "$loc/usage" | bzip2 -1 | od -v -x \
## | $SED -e 's/^[^ ]*//' \
## | $SED -e 's/ //g' \
diff --git a/release/src/router/busybox/archival/Config.in b/release/src/router/busybox/archival/Config.in
index 808757e28f..64b44c218c 100644
--- a/release/src/router/busybox/archival/Config.in
+++ b/release/src/router/busybox/archival/Config.in
@@ -110,9 +110,17 @@ config FEATURE_CPIO_O
This implementation of cpio can create cpio archives in the "newc"
format only.
+config FEATURE_CPIO_P
+ bool "Support for passthrough mode"
+ default n
+ depends on FEATURE_CPIO_O
+ help
+ Passthrough mode. Rarely used.
+
config DPKG
bool "dpkg"
default n
+ select FEATURE_SEAMLESS_GZ
help
dpkg is a medium-level tool to install, build, remove and manage
Debian packages.
@@ -123,9 +131,9 @@ config DPKG
config DPKG_DEB
bool "dpkg_deb"
default n
+ select FEATURE_SEAMLESS_GZ
help
- dpkg-deb packs, unpacks and provides information about Debian
- archives.
+ dpkg-deb unpacks and provides information about Debian archives.
This implementation of dpkg-deb cannot pack archives.
diff --git a/release/src/router/busybox/archival/bbunzip.c b/release/src/router/busybox/archival/bbunzip.c
index c7962058e2..75489f2a5a 100644
--- a/release/src/router/busybox/archival/bbunzip.c
+++ b/release/src/router/busybox/archival/bbunzip.c
@@ -30,13 +30,14 @@ int open_to_or_warn(int to_fd, const char *filename, int flags, int mode)
int FAST_FUNC bbunpack(char **argv,
char* (*make_new_name)(char *filename),
- USE_DESKTOP(long long) int (*unpacker)(void)
+ USE_DESKTOP(long long) int (*unpacker)(unpack_info_t *info)
)
{
struct stat stat_buf;
USE_DESKTOP(long long) int status;
char *filename, *new_name;
smallint exitcode = 0;
+ unpack_info_t info;
do {
/* NB: new_name is *maybe* malloc'ed! */
@@ -92,14 +93,29 @@ int FAST_FUNC bbunpack(char **argv,
"use -f to force it");
}
- status = unpacker();
+ /* memset(&info, 0, sizeof(info)); */
+ info.mtime = 0; /* so far it has one member only */
+ status = unpacker(&info);
if (status < 0)
exitcode = 1;
if (filename) {
char *del = new_name;
if (status >= 0) {
- /* TODO: restore user/group/times here? */
+ /* TODO: restore other things? */
+ if (info.mtime) {
+ struct utimbuf times;
+
+ times.actime = info.mtime;
+ times.modtime = info.mtime;
+ /* Close first.
+ * On some systems calling utime
+ * then closing resets the mtime. */
+ close(STDOUT_FILENO);
+ /* Ignoring errors */
+ utime(new_name, ×);
+ }
+
/* Delete _compressed_ file */
del = filename;
/* restore extension (unless tgz -> tar case) */
@@ -159,7 +175,7 @@ char* make_new_name_bunzip2(char *filename)
}
static
-USE_DESKTOP(long long) int unpack_bunzip2(void)
+USE_DESKTOP(long long) int unpack_bunzip2(unpack_info_t *info UNUSED_PARAM)
{
return unpack_bz2_stream_prime(STDIN_FILENO, STDOUT_FILENO);
}
@@ -235,7 +251,7 @@ char* make_new_name_gunzip(char *filename)
}
static
-USE_DESKTOP(long long) int unpack_gunzip(void)
+USE_DESKTOP(long long) int unpack_gunzip(unpack_info_t *info)
{
USE_DESKTOP(long long) int status = -1;
@@ -247,7 +263,7 @@ USE_DESKTOP(long long) int unpack_gunzip(void)
if (ENABLE_FEATURE_SEAMLESS_Z && magic2 == 0x9d) {
status = unpack_Z_stream(STDIN_FILENO, STDOUT_FILENO);
} else if (magic2 == 0x8b) {
- status = unpack_gz_stream(STDIN_FILENO, STDOUT_FILENO);
+ status = unpack_gz_stream_with_info(STDIN_FILENO, STDOUT_FILENO, info);
} else {
goto bad_magic;
}
@@ -309,7 +325,7 @@ char* make_new_name_unlzma(char *filename)
}
static
-USE_DESKTOP(long long) int unpack_unlzma(void)
+USE_DESKTOP(long long) int unpack_unlzma(unpack_info_t *info UNUSED_PARAM)
{
return unpack_lzma_stream(STDIN_FILENO, STDOUT_FILENO);
}
@@ -344,7 +360,7 @@ char* make_new_name_uncompress(char *filename)
}
static
-USE_DESKTOP(long long) int unpack_uncompress(void)
+USE_DESKTOP(long long) int unpack_uncompress(unpack_info_t *info UNUSED_PARAM)
{
USE_DESKTOP(long long) int status = -1;
diff --git a/release/src/router/busybox/archival/bzip2.c b/release/src/router/busybox/archival/bzip2.c
index 1149cad2a5..8eb5ca9aef 100644
--- a/release/src/router/busybox/archival/bzip2.c
+++ b/release/src/router/busybox/archival/bzip2.c
@@ -8,6 +8,7 @@
*/
#include "libbb.h"
+#include "unarchive.h"
#define CONFIG_BZIP2_FEATURE_SPEED 1
@@ -101,7 +102,7 @@ USE_DESKTOP(long long) int bz_write(bz_stream *strm, void* rbuf, ssize_t rlen, v
}
static
-USE_DESKTOP(long long) int compressStream(void)
+USE_DESKTOP(long long) int compressStream(unpack_info_t *info UNUSED_PARAM)
{
USE_DESKTOP(long long) int total;
ssize_t count;
diff --git a/release/src/router/busybox/archival/cpio.c b/release/src/router/busybox/archival/cpio.c
index 37b6b5ccea..11b22e4781 100644
--- a/release/src/router/busybox/archival/cpio.c
+++ b/release/src/router/busybox/archival/cpio.c
@@ -14,6 +14,87 @@
#include "libbb.h"
#include "unarchive.h"
+/* GNU cpio 2.9 --help (abridged):
+
+ Modes:
+ -t, --list List the archive
+ -i, --extract Extract files from an archive
+ -o, --create Create the archive
+ -p, --pass-through Copy-pass mode [was ist das?!]
+
+ Options valid in any mode:
+ --block-size=SIZE I/O block size = SIZE * 512 bytes
+ -B I/O block size = 5120 bytes
+ -c Use the old portable (ASCII) archive format
+ -C, --io-size=NUMBER I/O block size in bytes
+ -f, --nonmatching Only copy files that do not match given pattern
+ -F, --file=FILE Use FILE instead of standard input or output
+ -H, --format=FORMAT Use given archive FORMAT
+ -M, --message=STRING Print STRING when the end of a volume of the
+ backup media is reached
+ -n, --numeric-uid-gid If -v, show numeric UID and GID
+ --quiet Do not print the number of blocks copied
+ --rsh-command=COMMAND Use remote COMMAND instead of rsh
+ -v, --verbose Verbosely list the files processed
+ -V, --dot Print a "." for each file processed
+ -W, --warning=FLAG Control warning display: 'none','truncate','all';
+ multiple options accumulate
+
+ Options valid only in --extract mode:
+ -b, --swap Swap both halfwords of words and bytes of
+ halfwords in the data (equivalent to -sS)
+ -r, --rename Interactively rename files
+ -s, --swap-bytes Swap the bytes of each halfword in the files
+ -S, --swap-halfwords Swap the halfwords of each word (4 bytes)
+ --to-stdout Extract files to standard output
+ -E, --pattern-file=FILE Read additional patterns specifying filenames to
+ extract or list from FILE
+ --only-verify-crc Verify CRC's, don't actually extract the files
+
+ Options valid only in --create mode:
+ -A, --append Append to an existing archive
+ -O FILE File to use instead of standard output
+
+ Options valid only in --pass-through mode:
+ -l, --link Link files instead of copying them, when possible
+
+ Options valid in --extract and --create modes:
+ --absolute-filenames Do not strip file system prefix components from
+ the file names
+ --no-absolute-filenames Create all files relative to the current dir
+
+ Options valid in --create and --pass-through modes:
+ -0, --null A list of filenames is terminated by a NUL
+ -a, --reset-access-time Reset the access times of files after reading them
+ -I FILE File to use instead of standard input
+ -L, --dereference Dereference symbolic links (copy the files
+ that they point to instead of copying the links)
+ -R, --owner=[USER][:.][GROUP] Set owner of created files
+
+ Options valid in --extract and --pass-through modes:
+ -d, --make-directories Create leading directories where needed
+ -m, --preserve-modification-time Retain mtime when creating files
+ --no-preserve-owner Do not change the ownership of the files
+ --sparse Write files with blocks of zeros as sparse files
+ -u, --unconditional Replace all files unconditionally
+ */
+enum {
+ CPIO_OPT_EXTRACT = (1 << 0),
+ CPIO_OPT_TEST = (1 << 1),
+ CPIO_OPT_NUL_TERMINATED = (1 << 2),
+ CPIO_OPT_UNCONDITIONAL = (1 << 3),
+ CPIO_OPT_VERBOSE = (1 << 4),
+ CPIO_OPT_CREATE_LEADING_DIR = (1 << 5),
+ CPIO_OPT_PRESERVE_MTIME = (1 << 6),
+ CPIO_OPT_DEREF = (1 << 7),
+ CPIO_OPT_FILE = (1 << 8),
+ CPIO_OPT_CREATE = (1 << 9) * ENABLE_FEATURE_CPIO_O,
+ CPIO_OPT_FORMAT = (1 << 10) * ENABLE_FEATURE_CPIO_O,
+ CPIO_OPT_PASSTHROUGH = (1 << 11) * ENABLE_FEATURE_CPIO_P,
+};
+
+#define OPTION_STR "it0uvdmLF:"
+
#if ENABLE_FEATURE_CPIO_O
static off_t cpio_pad4(off_t size)
{
@@ -30,6 +111,7 @@ static off_t cpio_pad4(off_t size)
* It's ok to exit instead of return. */
static int cpio_o(void)
{
+ static const char trailer[] ALIGN1 = "TRAILER!!!";
struct name_s {
struct name_s *next;
char name[1];
@@ -48,7 +130,9 @@ static int cpio_o(void)
char *line;
struct stat st;
- line = xmalloc_fgetline(stdin);
+ line = (option_mask32 & CPIO_OPT_NUL_TERMINATED)
+ ? bb_get_chunk_from_file(stdin, NULL)
+ : xmalloc_fgetline(stdin);
if (line) {
/* Strip leading "./[./]..." from the filename */
@@ -61,7 +145,10 @@ static int cpio_o(void)
free(line);
continue;
}
- if (lstat(name, &st)) {
+ if ((option_mask32 & CPIO_OPT_DEREF)
+ ? stat(name, &st)
+ : lstat(name, &st)
+ ) {
abort_cpio_o:
bb_simple_perror_msg_and_die(name);
}
@@ -119,7 +206,7 @@ static int cpio_o(void)
} else {
/* If no (more) hardlinks to output,
* output "trailer" entry */
- name = "TRAILER!!!";
+ name = trailer;
/* st.st_size == 0 is a must, but for uniformity
* in the output, we zero out everything */
memset(&st, 0, sizeof(st));
@@ -167,7 +254,7 @@ static int cpio_o(void)
}
if (!line) {
- if (links)
+ if (name != trailer)
goto next_link;
/* TODO: GNU cpio pads trailer to 512 bytes, do we want that? */
return EXIT_SUCCESS;
@@ -178,71 +265,6 @@ static int cpio_o(void)
}
#endif
-/* GNU cpio 2.9 --help (abridged):
-
- Modes:
- -i, --extract Extract files from an archive
- -o, --create Create the archive
- -p, --pass-through Copy-pass mode [was ist das?!]
- -t, --list List the archive
-
- Options valid in any mode:
- --block-size=SIZE I/O block size = SIZE * 512 bytes
- -B I/O block size = 5120 bytes
- -c Use the old portable (ASCII) archive format
- -C, --io-size=NUMBER I/O block size in bytes
- -f, --nonmatching Only copy files that do not match given pattern
- -F, --file=FILE Use FILE instead of standard input or output
- -H, --format=FORMAT Use given archive FORMAT
- -M, --message=STRING Print STRING when the end of a volume of the
- backup media is reached
- -n, --numeric-uid-gid If -v, show numeric UID and GID
- --quiet Do not print the number of blocks copied
- --rsh-command=COMMAND Use remote COMMAND instead of rsh
- -v, --verbose Verbosely list the files processed
- -V, --dot Print a "." for each file processed
- -W, --warning=FLAG Control warning display: 'none','truncate','all';
- multiple options accumulate
-
- Options valid only in --extract mode:
- -b, --swap Swap both halfwords of words and bytes of
- halfwords in the data (equivalent to -sS)
- -r, --rename Interactively rename files
- -s, --swap-bytes Swap the bytes of each halfword in the files
- -S, --swap-halfwords Swap the halfwords of each word (4 bytes)
- --to-stdout Extract files to standard output
- -E, --pattern-file=FILE Read additional patterns specifying filenames to
- extract or list from FILE
- --only-verify-crc Verify CRC's, don't actually extract the files
-
- Options valid only in --create mode:
- -A, --append Append to an existing archive
- -O FILE File to use instead of standard output
-
- Options valid only in --pass-through mode:
- -l, --link Link files instead of copying them, when possible
-
- Options valid in --extract and --create modes:
- --absolute-filenames Do not strip file system prefix components from
- the file names
- --no-absolute-filenames Create all files relative to the current dir
-
- Options valid in --create and --pass-through modes:
- -0, --null A list of filenames is terminated by a NUL
- -a, --reset-access-time Reset the access times of files after reading them
- -I FILE File to use instead of standard input
- -L, --dereference Dereference symbolic links (copy the files
- that they point to instead of copying the links)
- -R, --owner=[USER][:.][GROUP] Set owner of created files
-
- Options valid in --extract and --pass-through modes:
- -d, --make-directories Create leading directories where needed
- -m, --preserve-modification-time Retain mtime when creating files
- --no-preserve-owner Do not change the ownership of the files
- --sparse Write files with blocks of zeros as sparse files
- -u, --unconditional Replace all files unconditionally
- */
-
int cpio_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int cpio_main(int argc UNUSED_PARAM, char **argv)
{
@@ -250,17 +272,6 @@ int cpio_main(int argc UNUSED_PARAM, char **argv)
char *cpio_filename;
USE_FEATURE_CPIO_O(const char *cpio_fmt = "";)
unsigned opt;
- enum {
- CPIO_OPT_EXTRACT = (1 << 0),
- CPIO_OPT_TEST = (1 << 1),
- CPIO_OPT_UNCONDITIONAL = (1 << 2),
- CPIO_OPT_VERBOSE = (1 << 3),
- CPIO_OPT_FILE = (1 << 4),
- CPIO_OPT_CREATE_LEADING_DIR = (1 << 5),
- CPIO_OPT_PRESERVE_MTIME = (1 << 6),
- CPIO_OPT_CREATE = (1 << 7),
- CPIO_OPT_FORMAT = (1 << 8),
- };
#if ENABLE_GETOPT_LONG
applet_long_options =
@@ -269,21 +280,67 @@ int cpio_main(int argc UNUSED_PARAM, char **argv)
#if ENABLE_FEATURE_CPIO_O
"create\0" No_argument "o"
"format\0" Required_argument "H"
+#if ENABLE_FEATURE_CPIO_P
+ "pass-through\0" No_argument "p"
+#endif
#endif
;
#endif
- /* Initialize */
- archive_handle = init_handle();
- archive_handle->src_fd = STDIN_FILENO;
- archive_handle->seek = seek_by_read;
- archive_handle->ah_flags = ARCHIVE_EXTRACT_NEWER;
+ /* As of now we do not enforce this: */
+ /* -i,-t,-o,-p are mutually exclusive */
+ /* -u,-d,-m make sense only with -i or -p */
+ /* -L makes sense only with -o or -p */
-#if ENABLE_FEATURE_CPIO_O
- opt = getopt32(argv, "ituvF:dmoH:", &cpio_filename, &cpio_fmt);
+#if !ENABLE_FEATURE_CPIO_O
+ opt = getopt32(argv, OPTION_STR, &cpio_filename);
+#else
+ opt = getopt32(argv, OPTION_STR "oH:" USE_FEATURE_CPIO_P("p"), &cpio_filename, &cpio_fmt);
+ if (opt & CPIO_OPT_PASSTHROUGH) {
+ pid_t pid;
+ struct fd_pair pp;
+ if (argv[optind] == NULL)
+ bb_show_usage();
+ if (opt & CPIO_OPT_CREATE_LEADING_DIR)
+ mkdir(argv[optind], 0777);
+ /* Crude existence check:
+ * close(xopen(argv[optind], O_RDONLY | O_DIRECTORY));
+ * We can also xopen, fstat, IS_DIR, later fchdir.
+ * This would check for existence earlier and cleaner.
+ * As it stands now, if we fail xchdir later,
+ * child dies on EPIPE, unless it caught
+ * a diffrerent problem earlier.
+ * This is good enough for now.
+ */
+#if !BB_MMU
+ pp.rd = 3;
+ pp.wr = 4;
+ if (!re_execed) {
+ close(3);
+ close(4);
+ xpiped_pair(pp);
+ }
+#else
+ xpiped_pair(pp);
+#endif
+ pid = fork_or_rexec(argv);
+ if (pid == 0) { /* child */
+ close(pp.rd);
+ xmove_fd(pp.wr, STDOUT_FILENO);
+ goto dump;
+ }
+ /* parent */
+ xchdir(argv[optind++]);
+ close(pp.wr);
+ xmove_fd(pp.rd, STDIN_FILENO);
+ opt &= ~CPIO_OPT_PASSTHROUGH;
+ opt |= CPIO_OPT_EXTRACT;
+ goto skip;
+ }
+ /* -o */
if (opt & CPIO_OPT_CREATE) {
- if (*cpio_fmt != 'n')
+ if (*cpio_fmt != 'n') /* we _require_ "-H newc" */
bb_show_usage();
if (opt & CPIO_OPT_FILE) {
fclose(stdout);
@@ -291,13 +348,18 @@ int cpio_main(int argc UNUSED_PARAM, char **argv)
/* Paranoia: I don't trust libc that much */
xdup2(fileno(stdout), STDOUT_FILENO);
}
+ dump:
return cpio_o();
}
-#else
- opt = getopt32(argv, "ituvF:dm", &cpio_filename);
+ skip:
#endif
argv += optind;
+ archive_handle = init_handle();
+ archive_handle->src_fd = STDIN_FILENO;
+ archive_handle->seek = seek_by_read;
+ archive_handle->ah_flags = ARCHIVE_EXTRACT_NEWER;
+
/* One of either extract or test options must be given */
if ((opt & (CPIO_OPT_TEST | CPIO_OPT_EXTRACT)) == 0) {
bb_show_usage();
@@ -305,9 +367,7 @@ int cpio_main(int argc UNUSED_PARAM, char **argv)
if (opt & CPIO_OPT_TEST) {
/* if both extract and test options are given, ignore extract option */
- if (opt & CPIO_OPT_EXTRACT) {
- opt &= ~CPIO_OPT_EXTRACT;
- }
+ opt &= ~CPIO_OPT_EXTRACT;
archive_handle->action_header = header_list;
}
if (opt & CPIO_OPT_EXTRACT) {
@@ -341,8 +401,13 @@ int cpio_main(int argc UNUSED_PARAM, char **argv)
argv++;
}
+ /* see get_header_cpio */
+ archive_handle->ah_priv[2] = (void*) ~(ptrdiff_t)0;
while (get_header_cpio(archive_handle) == EXIT_SUCCESS)
continue;
+ if (archive_handle->ah_priv[2] != (void*) ~(ptrdiff_t)0)
+ printf("%lu blocks\n", (unsigned long)(ptrdiff_t)(archive_handle->ah_priv[2]));
+
return EXIT_SUCCESS;
}
diff --git a/release/src/router/busybox/archival/dpkg.c b/release/src/router/busybox/archival/dpkg.c
index f31a7f0170..577b77fec6 100644
--- a/release/src/router/busybox/archival/dpkg.c
+++ b/release/src/router/busybox/archival/dpkg.c
@@ -6,6 +6,10 @@
* written by glenn mcgrath with the help of others
* copyright (c) 2001 by glenn mcgrath
*
+ * parts of the version comparison code is plucked from the real dpkg
+ * application which is licensed GPLv2 and
+ * copyright (c) 1995 Ian Jackson
+ *
* started life as a busybox implementation of udpkg
*
* licensed under gplv2 or later, see file license in this tarball for details.
@@ -25,6 +29,7 @@
*/
#include "libbb.h"
+#include
#include "unarchive.h"
/* note: if you vary hash_prime sizes be aware,
@@ -134,7 +139,7 @@ static void make_hash(const char *key, unsigned *start, unsigned *decrement, con
/* 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, don't want to shift data to where it has
- * no effect*/
+ * no effect */
hash_num += (key[i] + key[i-1]) << ((key[i] * i) % 24);
}
*start = (unsigned) hash_num % hash_prime;
@@ -182,60 +187,52 @@ static unsigned search_status_hashtable(const char *key)
return probe_address;
}
-/* Need to rethink version comparison, maybe the official dpkg has something i can use ? */
-static int version_compare_part(const char *version1, const char *version2)
+static int order(char x)
{
- 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;
-
- 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) {
- return tmp_int;
+ return (x == '~' ? -1
+ : x == '\0' ? 0
+ : isdigit(x) ? 0
+ : isalpha(x) ? x
+ : (unsigned char)x + 256
+ );
+}
+
+/* This code is taken from dpkg and modified slightly to work with busybox */
+static int version_compare_part(const char *val, const char *ref)
+{
+ if (!val) val = "";
+ if (!ref) ref = "";
+
+ while (*val || *ref) {
+ int first_diff;
+
+ while ((*val && !isdigit(*val)) || (*ref && !isdigit(*ref))) {
+ int vc = order(*val);
+ int rc = order(*ref);
+ if (vc != rc)
+ return vc - rc;
+ val++;
+ ref++;
}
- /* 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) {
- return -1;
+ while (*val == '0')
+ val++;
+ while (*ref == '0')
+ ref++;
+
+ first_diff = 0;
+ while (isdigit(*val) && isdigit(*ref)) {
+ if (first_diff == 0)
+ first_diff = *val - *ref;
+ val++;
+ ref++;
}
- if (ver_num1 > ver_num2) {
+ if (isdigit(*val))
return 1;
- }
+ if (isdigit(*ref))
+ return -1;
+ if (first_diff)
+ return first_diff;
}
return 0;
}
@@ -248,39 +245,34 @@ static int version_compare(const unsigned ver1, const unsigned ver2)
{
char *ch_ver1 = name_hashtable[ver1];
char *ch_ver2 = name_hashtable[ver2];
-
- char epoch1, epoch2;
+ unsigned long epoch1 = 0, epoch2 = 0;
+ char *colon;
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;
+ colon = strchr(ch_ver1, ':');
+ if (colon) {
+ epoch1 = atoi(ch_ver1);
+ ch_ver1 = colon + 1;
}
- if (ch_ver2[1] == ':') {
- epoch2 = ch_ver2[0];
- ver2_ptr = strchr(ch_ver2, ':') + 1;
- } else {
- epoch2 = '0';
- ver2_ptr = ch_ver2;
+ colon = strchr(ch_ver2, ':');
+ if (colon) {
+ epoch2 = atoi(ch_ver2);
+ ch_ver2 = colon + 1;
}
if (epoch1 < epoch2) {
return -1;
}
- else if (epoch1 > epoch2) {
+ if (epoch1 > epoch2) {
return 1;
}
/* Compare upstream version */
- upstream_ver1 = xstrdup(ver1_ptr);
- upstream_ver2 = xstrdup(ver2_ptr);
+ upstream_ver1 = xstrdup(ch_ver1);
+ upstream_ver2 = xstrdup(ch_ver2);
/* Chop off debian version, and store for later use */
deb_ver1 = strrchr(upstream_ver1, '-');
@@ -1293,7 +1285,7 @@ static void free_array(char **array)
* the status_hashtable to retrieve the info. This results in smaller code than
* scanning the status file. The resulting list, however, is unsorted.
*/
-static void list_packages(void)
+static void list_packages(const char *pattern)
{
int i;
@@ -1314,6 +1306,9 @@ static void list_packages(void)
name_str = name_hashtable[package_hashtable[status_hashtable[i]->package]->name];
vers_str = name_hashtable[package_hashtable[status_hashtable[i]->package]->version];
+ if (pattern && fnmatch(pattern, name_str, 0))
+ continue;
+
/* get abbreviation for status field 1 */
s1 = stat_str[0] == 'i' ? 'i' : 'r';
@@ -1626,7 +1621,7 @@ int dpkg_main(int argc UNUSED_PARAM, char **argv)
/* if the list action was given print the installed packages and exit */
if (opt & OPT_list_installed) {
- list_packages();
+ list_packages(argv[0]);
return EXIT_SUCCESS;
}
diff --git a/release/src/router/busybox/archival/gzip.c b/release/src/router/busybox/archival/gzip.c
index ee051356e5..43804b2e40 100644
--- a/release/src/router/busybox/archival/gzip.c
+++ b/release/src/router/busybox/archival/gzip.c
@@ -40,6 +40,7 @@ aa: 85.1% -- replaced with aa.gz
*/
#include "libbb.h"
+#include "unarchive.h"
/* ===========================================================================
@@ -2014,7 +2015,7 @@ char* make_new_name_gzip(char *filename)
}
static
-USE_DESKTOP(long long) int pack_gzip(void)
+USE_DESKTOP(long long) int pack_gzip(unpack_info_t *info UNUSED_PARAM)
{
struct stat s;
diff --git a/release/src/router/busybox/archival/libunarchive/data_extract_all.c b/release/src/router/busybox/archival/libunarchive/data_extract_all.c
index a67587d72e..8b1ee2a6ea 100644
--- a/release/src/router/busybox/archival/libunarchive/data_extract_all.c
+++ b/release/src/router/busybox/archival/libunarchive/data_extract_all.c
@@ -77,7 +77,9 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle)
}
case S_IFDIR:
res = mkdir(file_header->name, file_header->mode);
- if ((res == -1) && (errno != EISDIR)
+ if ((res == -1)
+ && (errno != EISDIR) /* btw, Linux doesn't return this */
+ && (errno != EEXIST)
&& !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)
) {
bb_perror_msg("cannot make dir %s", file_header->name);
diff --git a/release/src/router/busybox/archival/libunarchive/decompress_unzip.c b/release/src/router/busybox/archival/libunarchive/decompress_unzip.c
index f25808a1a4..86969251e0 100644
--- a/release/src/router/busybox/archival/libunarchive/decompress_unzip.c
+++ b/release/src/router/busybox/archival/libunarchive/decompress_unzip.c
@@ -1083,8 +1083,7 @@ static uint16_t buffer_read_le_u16(STATE_PARAM_ONLY)
{
uint16_t res;
#if BB_LITTLE_ENDIAN
- /* gcc 4.2.1 is very clever */
- memcpy(&res, &bytebuffer[bytebuffer_offset], 2);
+ move_from_unaligned16(res, &bytebuffer[bytebuffer_offset]);
#else
res = bytebuffer[bytebuffer_offset];
res |= bytebuffer[bytebuffer_offset + 1] << 8;
@@ -1097,7 +1096,7 @@ static uint32_t buffer_read_le_u32(STATE_PARAM_ONLY)
{
uint32_t res;
#if BB_LITTLE_ENDIAN
- memcpy(&res, &bytebuffer[bytebuffer_offset], 4);
+ move_from_unaligned32(res, &bytebuffer[bytebuffer_offset]);
#else
res = bytebuffer[bytebuffer_offset];
res |= bytebuffer[bytebuffer_offset + 1] << 8;
@@ -1108,18 +1107,21 @@ static uint32_t buffer_read_le_u32(STATE_PARAM_ONLY)
return res;
}
-static int check_header_gzip(STATE_PARAM_ONLY)
+static int check_header_gzip(STATE_PARAM unpack_info_t *info)
{
union {
unsigned char raw[8];
struct {
uint8_t gz_method;
uint8_t flags;
- //uint32_t mtime; - unused fields
- //uint8_t xtra_flags;
- //uint8_t os_flags;
- } formatted; /* packed */
+ uint32_t mtime;
+ uint8_t xtra_flags_UNUSED;
+ uint8_t os_flags_UNUSED;
+ } __attribute__((packed)) formatted;
} header;
+ struct BUG_header {
+ char BUG_header[sizeof(header) == 8 ? 1 : -1];
+ };
/*
* Rewind bytebuffer. We use the beginning because the header has 8
@@ -1167,6 +1169,9 @@ static int check_header_gzip(STATE_PARAM_ONLY)
}
}
+ if (info)
+ info->mtime = SWAP_LE32(header.formatted.mtime);
+
/* Read the header checksum */
if (header.formatted.flags & 0x02) {
if (!top_up(PASS_STATE 2))
@@ -1177,7 +1182,7 @@ static int check_header_gzip(STATE_PARAM_ONLY)
}
USE_DESKTOP(long long) int FAST_FUNC
-unpack_gz_stream(int in, int out)
+unpack_gz_stream_with_info(int in, int out, unpack_info_t *info)
{
uint32_t v32;
USE_DESKTOP(long long) int n;
@@ -1192,7 +1197,7 @@ unpack_gz_stream(int in, int out)
gunzip_src_fd = in;
again:
- if (!check_header_gzip(PASS_STATE_ONLY)) {
+ if (!check_header_gzip(PASS_STATE info)) {
bb_error_msg("corrupted data");
n = -1;
goto ret;
@@ -1239,3 +1244,9 @@ unpack_gz_stream(int in, int out)
DEALLOC_STATE;
return n;
}
+
+USE_DESKTOP(long long) int FAST_FUNC
+unpack_gz_stream(int in, int out)
+{
+ return unpack_gz_stream_with_info(in, out, NULL);
+}
diff --git a/release/src/router/busybox/archival/libunarchive/get_header_cpio.c b/release/src/router/busybox/archival/libunarchive/get_header_cpio.c
index 93f6c61aa0..302f122331 100644
--- a/release/src/router/busybox/archival/libunarchive/get_header_cpio.c
+++ b/release/src/router/busybox/archival/libunarchive/get_header_cpio.c
@@ -27,6 +27,7 @@ char FAST_FUNC get_header_cpio(archive_handle_t *archive_handle)
#define hardlinks_to_create (*(hardlinks_t **)(&archive_handle->ah_priv[0]))
#define created_hardlinks (*(hardlinks_t **)(&archive_handle->ah_priv[1]))
+#define block_count (archive_handle->ah_priv[2])
// if (!archive_handle->ah_priv_inited) {
// archive_handle->ah_priv_inited = 1;
// hardlinks_to_create = NULL;
@@ -76,7 +77,7 @@ char FAST_FUNC get_header_cpio(archive_handle_t *archive_handle)
if (strcmp(file_header->name, "TRAILER!!!") == 0) {
/* Always round up. ">> 9" divides by 512 */
- printf("%"OFF_FMT"u blocks\n", (archive_handle->offset + 511) >> 9);
+ block_count = (void*)(ptrdiff_t) ((archive_handle->offset + 511) >> 9);
goto create_hardlinks;
}
diff --git a/release/src/router/busybox/archival/libunarchive/get_header_tar.c b/release/src/router/busybox/archival/libunarchive/get_header_tar.c
index bf0f92b258..443052f7e0 100644
--- a/release/src/router/busybox/archival/libunarchive/get_header_tar.c
+++ b/release/src/router/busybox/archival/libunarchive/get_header_tar.c
@@ -14,6 +14,74 @@
#include "libbb.h"
#include "unarchive.h"
+/*
+ * GNU tar uses "base-256 encoding" for very large numbers (>8 billion).
+ * Encoding is binary, with highest bit always set as a marker
+ * and sign in next-highest bit:
+ * 80 00 .. 00 - zero
+ * bf ff .. ff - largest positive number
+ * ff ff .. ff - minus 1
+ * c0 00 .. 00 - smallest negative number
+ *
+ * We expect it only in size field, where negative numbers don't make sense.
+ */
+static off_t getBase256_len12(const char *str)
+{
+ off_t value;
+ int len;
+
+ /* if (*str & 0x40) error; - caller prevents this */
+
+ if (sizeof(off_t) >= 12) {
+ /* Probably 128-bit (16 byte) off_t. Can be optimized. */
+ len = 12;
+ value = *str++ & 0x3f;
+ while (--len)
+ value = (value << 8) + (unsigned char) *str++;
+ return value;
+ }
+
+#ifdef CHECK_FOR_OVERFLOW
+ /* Can be optimized to eat 32-bit chunks */
+ char c = *str++ & 0x3f;
+ len = 12;
+ while (1) {
+ if (c)
+ bb_error_msg_and_die("overflow in base-256 encoded file size");
+ if (--len == sizeof(off_t))
+ break;
+ c = *str++;
+ }
+#else
+ str += (12 - sizeof(off_t));
+#endif
+
+/* Now str points to sizeof(off_t) least significant bytes.
+ *
+ * Example of tar file with 8914993153 (0x213600001) byte file.
+ * Field starts at offset 7c:
+ * 00070 30 30 30 00 30 30 30 30 30 30 30 00 80 00 00 00 |000.0000000.....|
+ * 00080 00 00 00 02 13 60 00 01 31 31 31 32 30 33 33 36 |.....`..11120336|
+ *
+ * str is at offset 80 or 84 now (64-bit or 32-bit off_t).
+ * We (ab)use the fact that value happens to be aligned,
+ * and fetch it in one go:
+ */
+ if (sizeof(off_t) == 8) {
+ value = *(off_t*)str;
+ value = SWAP_BE64(value);
+ } else if (sizeof(off_t) == 4) {
+ value = *(off_t*)str;
+ value = SWAP_BE32(value);
+ } else {
+ value = 0;
+ len = sizeof(off_t);
+ while (--len)
+ value = (value << 8) + (unsigned char) *str++;
+ }
+ return value;
+}
+
/* NB: _DESTROYS_ str[len] character! */
static unsigned long long getOctal(char *str, int len)
{
@@ -91,7 +159,7 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
again_after_align:
-#if ENABLE_DESKTOP
+#if ENABLE_DESKTOP || ENABLE_FEATURE_TAR_AUTODETECT
/* to prevent misdetection of bz2 sig */
*(uint32_t*)(&tar) = 0;
i = full_read(archive_handle->src_fd, &tar, 512);
@@ -142,7 +210,7 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
#if ENABLE_FEATURE_TAR_AUTODETECT
char FAST_FUNC (*get_header_ptr)(archive_handle_t *);
- USE_DESKTOP(autodetect:)
+ autodetect:
/* tar gz/bz autodetect: check for gz/bz2 magic.
* If we see the magic, and it is the very first block,
* we can switch to get_header_tar_gz/bz2/lzma().
@@ -234,7 +302,10 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
file_header->gname = tar.gname[0] ? xstrndup(tar.gname, sizeof(tar.gname)) : NULL;
#endif
file_header->mtime = GET_OCTAL(tar.mtime);
- file_header->size = GET_OCTAL(tar.size);
+ /* Size field: handle GNU tar's "base256 encoding" */
+ file_header->size = (*tar.size & 0xc0) == 0x80 /* positive base256? */
+ ? getBase256_len12(tar.size)
+ : GET_OCTAL(tar.size);
file_header->gid = GET_OCTAL(tar.gid);
file_header->uid = GET_OCTAL(tar.uid);
/* Set bits 0-11 of the files mode */
diff --git a/release/src/router/busybox/archival/libunarchive/header_verbose_list.c b/release/src/router/busybox/archival/libunarchive/header_verbose_list.c
index f059dd9818..dc31003613 100644
--- a/release/src/router/busybox/archival/libunarchive/header_verbose_list.c
+++ b/release/src/router/busybox/archival/libunarchive/header_verbose_list.c
@@ -24,11 +24,11 @@ void FAST_FUNC header_verbose_list(const file_header_t *file_header)
snprintf(gid, sizeof(gid), "%u", (unsigned)file_header->gid);
group = gid;
}
- printf("%s %s/%s %9u %4u-%02u-%02u %02u:%02u:%02u %s",
+ printf("%s %s/%s %9"OFF_FMT"u %4u-%02u-%02u %02u:%02u:%02u %s",
bb_mode_string(file_header->mode),
user,
group,
- (unsigned int) file_header->size,
+ file_header->size,
1900 + mtime->tm_year,
1 + mtime->tm_mon,
mtime->tm_mday,
diff --git a/release/src/router/busybox/archival/rpm.c b/release/src/router/busybox/archival/rpm.c
index e1f3c89305..4c36067c4d 100644
--- a/release/src/router/busybox/archival/rpm.c
+++ b/release/src/router/busybox/archival/rpm.c
@@ -115,8 +115,8 @@ int rpm_main(int argc, char **argv)
}
}
argv += optind;
- argc -= optind;
- if (!argc) bb_show_usage();
+ //argc -= optind;
+ if (!argv[0]) bb_show_usage();
while (*argv) {
rpm_fd = xopen(*argv++, O_RDONLY);
@@ -202,7 +202,12 @@ static void extract_cpio_gz(int fd)
archive_handle->seek = seek_by_read;
//archive_handle->action_header = header_list;
archive_handle->action_data = data_extract_all;
- archive_handle->ah_flags = ARCHIVE_PRESERVE_DATE | ARCHIVE_CREATE_LEADING_DIRS;
+ archive_handle->ah_flags = ARCHIVE_PRESERVE_DATE | ARCHIVE_CREATE_LEADING_DIRS
+ /* compat: overwrite existing files.
+ * try "rpm -i foo.src.rpm" few times in a row -
+ * standard rpm will not complain.
+ * (TODO? real rpm creates "file;1234" and then renames it) */
+ | ARCHIVE_EXTRACT_UNCONDITIONAL;
archive_handle->src_fd = fd;
/*archive_handle->offset = 0; - init_handle() did it */
@@ -246,7 +251,7 @@ static void extract_cpio_gz(int fd)
static rpm_index **rpm_gettags(int fd, int *num_tags)
{
/* We should never need mode than 200, and realloc later */
- rpm_index **tags = xzalloc(200 * sizeof(struct rpmtag *));
+ rpm_index **tags = xzalloc(200 * sizeof(tags[0]));
int pass, tagindex = 0;
xlseek(fd, 96, SEEK_CUR); /* Seek past the unused lead */
@@ -260,6 +265,9 @@ static rpm_index **rpm_gettags(int fd, int *num_tags)
uint32_t entries; /* Number of entries in header (4 bytes) */
uint32_t size; /* Size of store (4 bytes) */
} header;
+ struct BUG_header {
+ char BUG_header[sizeof(header) == 16 ? 1 : -1];
+ };
rpm_index *tmpindex;
int storepos;
@@ -273,8 +281,8 @@ static rpm_index **rpm_gettags(int fd, int *num_tags)
storepos = xlseek(fd,0,SEEK_CUR) + header.entries * 16;
while (header.entries--) {
- tmpindex = tags[tagindex++] = xmalloc(sizeof(rpm_index));
- xread(fd, tmpindex, sizeof(rpm_index));
+ tmpindex = tags[tagindex++] = xmalloc(sizeof(*tmpindex));
+ xread(fd, tmpindex, sizeof(*tmpindex));
tmpindex->tag = ntohl(tmpindex->tag);
tmpindex->type = ntohl(tmpindex->type);
tmpindex->count = ntohl(tmpindex->count);
@@ -287,7 +295,7 @@ static rpm_index **rpm_gettags(int fd, int *num_tags)
if (pass == 0)
xlseek(fd, (8 - (xlseek(fd,0,SEEK_CUR) % 8)) % 8, SEEK_CUR);
}
- tags = xrealloc(tags, tagindex * sizeof(struct rpmtag *)); /* realloc tags to save space */
+ tags = xrealloc(tags, tagindex * sizeof(tags[0])); /* realloc tags to save space */
*num_tags = tagindex;
return tags; /* All done, leave the file at the start of the gzipped cpio archive */
}
@@ -378,9 +386,11 @@ static void fileaction_dobackup(char *filename, int fileref)
static void fileaction_setowngrp(char *filename, int fileref)
{
- int uid, gid;
- uid = xuname2uid(rpm_getstr(TAG_FILEUSERNAME, fileref));
- gid = xgroup2gid(rpm_getstr(TAG_FILEGROUPNAME, fileref));
+ /* real rpm warns: "user foo does not exist - using " */
+ struct passwd *pw = getpwnam(rpm_getstr(TAG_FILEUSERNAME, fileref));
+ int uid = pw ? pw->pw_uid : getuid(); /* or euid? */
+ struct group *gr = getgrnam(rpm_getstr(TAG_FILEGROUPNAME, fileref));
+ int gid = gr ? gr->gr_gid : getgid();
chown(filename, uid, gid);
}
diff --git a/release/src/router/busybox/archival/tar.c b/release/src/router/busybox/archival/tar.c
index 45701c9850..eeaf3586bf 100644
--- a/release/src/router/busybox/archival/tar.c
+++ b/release/src/router/busybox/archival/tar.c
@@ -357,7 +357,8 @@ static int writeTarHeader(struct TarBallInfo *tbInfo,
if (tbInfo->verboseFlag) {
FILE *vbFd = stdout;
- if (tbInfo->tarFd == STDOUT_FILENO) /* If the archive goes to stdout, verbose to stderr */
+ /* If archive goes to stdout, verbose goes to stderr */
+ if (tbInfo->tarFd == STDOUT_FILENO)
vbFd = stderr;
/* GNU "tar cvvf" prints "extended" listing a-la "ls -l" */
/* We don't have such excesses here: for us "v" == "vv" */
@@ -591,8 +592,6 @@ static NOINLINE int writeTarFile(int tar_fd, int verboseFlag,
struct TarBallInfo tbInfo;
tbInfo.hlInfoHead = NULL;
-
- fchmod(tar_fd, 0644);
tbInfo.tarFd = tar_fd;
tbInfo.verboseFlag = verboseFlag;
@@ -818,6 +817,10 @@ int tar_main(int argc UNUSED_PARAM, char **argv)
| ARCHIVE_PRESERVE_DATE
| ARCHIVE_EXTRACT_UNCONDITIONAL;
+ /* Apparently only root's tar preserves perms (see bug 3844) */
+ if (getuid() != 0)
+ tar_handle->ah_flags |= ARCHIVE_NOPRESERVE_PERM;
+
/* Prepend '-' to the first argument if required */
opt_complementary = "--:" // first arg is options
"tt:vv:" // count -t,-v
diff --git a/release/src/router/busybox/archival/unzip.c b/release/src/router/busybox/archival/unzip.c
index 1c9bc246c7..7b47a8ab8c 100644
--- a/release/src/router/busybox/archival/unzip.c
+++ b/release/src/router/busybox/archival/unzip.c
@@ -16,12 +16,7 @@
*/
/* TODO
- * Endian issues
* Zip64 + other methods
- * Improve handling of zip format, ie.
- * - deferred CRC, comp. & uncomp. lengths (zip header flags bit 3)
- * - unix file permissions, etc.
- * - central directory
*/
#include "libbb.h"
@@ -31,12 +26,12 @@ enum {
#if BB_BIG_ENDIAN
ZIP_FILEHEADER_MAGIC = 0x504b0304,
ZIP_CDS_MAGIC = 0x504b0102,
- ZIP_CDS_END_MAGIC = 0x504b0506,
+ ZIP_CDE_MAGIC = 0x504b0506,
ZIP_DD_MAGIC = 0x504b0708,
#else
ZIP_FILEHEADER_MAGIC = 0x04034b50,
ZIP_CDS_MAGIC = 0x02014b50,
- ZIP_CDS_END_MAGIC = 0x06054b50,
+ ZIP_CDE_MAGIC = 0x06054b50,
ZIP_DD_MAGIC = 0x08074b50,
#endif
};
@@ -46,16 +41,16 @@ enum {
typedef union {
uint8_t raw[ZIP_HEADER_LEN];
struct {
- uint16_t version; /* 0-1 */
- uint16_t flags; /* 2-3 */
- uint16_t method; /* 4-5 */
- uint16_t modtime; /* 6-7 */
- uint16_t moddate; /* 8-9 */
- uint32_t crc32 PACKED; /* 10-13 */
- uint32_t cmpsize PACKED; /* 14-17 */
- uint32_t ucmpsize PACKED; /* 18-21 */
- uint16_t filename_len; /* 22-23 */
- uint16_t extra_len; /* 24-25 */
+ uint16_t version; /* 0-1 */
+ uint16_t flags; /* 2-3 */
+ uint16_t method; /* 4-5 */
+ uint16_t modtime; /* 6-7 */
+ uint16_t moddate; /* 8-9 */
+ uint32_t crc32 PACKED; /* 10-13 */
+ uint32_t cmpsize PACKED; /* 14-17 */
+ uint32_t ucmpsize PACKED; /* 18-21 */
+ uint16_t filename_len; /* 22-23 */
+ uint16_t extra_len; /* 24-25 */
} formatted PACKED;
} zip_header_t; /* PACKED - gcc 4.2.1 doesn't like it (spews warning) */
@@ -65,11 +60,11 @@ typedef union {
*/
struct BUG_zip_header_must_be_26_bytes {
char BUG_zip_header_must_be_26_bytes[
- offsetof(zip_header_t, formatted.extra_len) + 2 ==
- ZIP_HEADER_LEN ? 1 : -1];
+ offsetof(zip_header_t, formatted.extra_len) + 2
+ == ZIP_HEADER_LEN ? 1 : -1];
};
-#define FIX_ENDIANNESS(zip_header) do { \
+#define FIX_ENDIANNESS_ZIP(zip_header) do { \
(zip_header).formatted.version = SWAP_LE16((zip_header).formatted.version ); \
(zip_header).formatted.flags = SWAP_LE16((zip_header).formatted.flags ); \
(zip_header).formatted.method = SWAP_LE16((zip_header).formatted.method ); \
@@ -82,9 +77,138 @@ struct BUG_zip_header_must_be_26_bytes {
(zip_header).formatted.extra_len = SWAP_LE16((zip_header).formatted.extra_len ); \
} while (0)
-static void unzip_skip(int fd, off_t skip)
+#define CDS_HEADER_LEN 42
+
+typedef union {
+ uint8_t raw[CDS_HEADER_LEN];
+ struct {
+ /* uint32_t signature; 50 4b 01 02 */
+ uint16_t version_made_by; /* 0-1 */
+ uint16_t version_needed; /* 2-3 */
+ uint16_t cds_flags; /* 4-5 */
+ uint16_t method; /* 6-7 */
+ uint16_t mtime; /* 8-9 */
+ uint16_t mdate; /* 10-11 */
+ uint32_t crc32; /* 12-15 */
+ uint32_t cmpsize; /* 16-19 */
+ uint32_t ucmpsize; /* 20-23 */
+ uint16_t file_name_length; /* 24-25 */
+ uint16_t extra_field_length; /* 26-27 */
+ uint16_t file_comment_length; /* 28-29 */
+ uint16_t disk_number_start; /* 30-31 */
+ uint16_t internal_file_attributes; /* 32-33 */
+ uint32_t external_file_attributes PACKED; /* 34-37 */
+ uint32_t relative_offset_of_local_header PACKED; /* 38-41 */
+ } formatted PACKED;
+} cds_header_t;
+
+struct BUG_cds_header_must_be_42_bytes {
+ char BUG_cds_header_must_be_42_bytes[
+ offsetof(cds_header_t, formatted.relative_offset_of_local_header) + 4
+ == CDS_HEADER_LEN ? 1 : -1];
+};
+
+#define FIX_ENDIANNESS_CDS(cds_header) do { \
+ (cds_header).formatted.crc32 = SWAP_LE32((cds_header).formatted.crc32 ); \
+ (cds_header).formatted.cmpsize = SWAP_LE32((cds_header).formatted.cmpsize ); \
+ (cds_header).formatted.ucmpsize = SWAP_LE32((cds_header).formatted.ucmpsize ); \
+ (cds_header).formatted.file_name_length = SWAP_LE16((cds_header).formatted.file_name_length); \
+ (cds_header).formatted.extra_field_length = SWAP_LE16((cds_header).formatted.extra_field_length); \
+ (cds_header).formatted.file_comment_length = SWAP_LE16((cds_header).formatted.file_comment_length); \
+} while (0)
+
+#define CDE_HEADER_LEN 16
+
+typedef union {
+ uint8_t raw[CDE_HEADER_LEN];
+ struct {
+ /* uint32_t signature; 50 4b 05 06 */
+ uint16_t this_disk_no;
+ uint16_t disk_with_cds_no;
+ uint16_t cds_entries_on_this_disk;
+ uint16_t cds_entries_total;
+ uint32_t cds_size;
+ uint32_t cds_offset;
+ /* uint16_t file_comment_length; */
+ /* .ZIP file comment (variable size) */
+ } formatted PACKED;
+} cde_header_t;
+
+struct BUG_cde_header_must_be_16_bytes {
+ char BUG_cde_header_must_be_16_bytes[
+ sizeof(cde_header_t) == CDE_HEADER_LEN ? 1 : -1];
+};
+
+#define FIX_ENDIANNESS_CDE(cde_header) do { \
+ (cde_header).formatted.cds_offset = SWAP_LE32((cde_header).formatted.cds_offset); \
+} while (0)
+
+enum { zip_fd = 3 };
+
+
+#if ENABLE_DESKTOP
+/* NB: does not preserve file position! */
+static uint32_t find_cds_offset(void)
+{
+ unsigned char buf[1024];
+ cde_header_t cde_header;
+ unsigned char *p;
+ off_t end;
+
+ end = xlseek(zip_fd, 0, SEEK_END);
+ if (end < 1024)
+ end = 1024;
+ end -= 1024;
+ xlseek(zip_fd, end, SEEK_SET);
+ full_read(zip_fd, buf, 1024);
+
+ p = buf;
+ while (p <= buf + 1024 - CDE_HEADER_LEN - 4) {
+ if (*p != 'P') {
+ p++;
+ continue;
+ }
+ if (*++p != 'K')
+ continue;
+ if (*++p != 5)
+ continue;
+ if (*++p != 6)
+ continue;
+ /* we found CDE! */
+ memcpy(cde_header.raw, p + 1, CDE_HEADER_LEN);
+ FIX_ENDIANNESS_CDE(cde_header);
+ return cde_header.formatted.cds_offset;
+ }
+ bb_error_msg_and_die("can't find file table");
+};
+
+static uint32_t read_next_cds(int count_m1, uint32_t cds_offset, cds_header_t *cds_ptr)
{
- bb_copyfd_exact_size(fd, -1, skip);
+ off_t org;
+
+ org = xlseek(zip_fd, 0, SEEK_CUR);
+
+ if (!cds_offset)
+ cds_offset = find_cds_offset();
+
+ while (count_m1-- >= 0) {
+ xlseek(zip_fd, cds_offset + 4, SEEK_SET);
+ xread(zip_fd, cds_ptr->raw, CDS_HEADER_LEN);
+ FIX_ENDIANNESS_CDS(*cds_ptr);
+ cds_offset += 4 + CDS_HEADER_LEN
+ + cds_ptr->formatted.file_name_length
+ + cds_ptr->formatted.extra_field_length
+ + cds_ptr->formatted.file_comment_length;
+ }
+
+ xlseek(zip_fd, org, SEEK_SET);
+ return cds_offset;
+};
+#endif
+
+static void unzip_skip(off_t skip)
+{
+ bb_copyfd_exact_size(zip_fd, -1, skip);
}
static void unzip_create_leading_dirs(const char *fn)
@@ -97,17 +221,17 @@ static void unzip_create_leading_dirs(const char *fn)
free(name);
}
-static void unzip_extract(zip_header_t *zip_header, int src_fd, int dst_fd)
+static void unzip_extract(zip_header_t *zip_header, int dst_fd)
{
if (zip_header->formatted.method == 0) {
/* Method 0 - stored (not compressed) */
off_t size = zip_header->formatted.ucmpsize;
if (size)
- bb_copyfd_exact_size(src_fd, dst_fd, size);
+ bb_copyfd_exact_size(zip_fd, dst_fd, size);
} else {
/* Method 8 - inflate */
inflate_unzip_result res;
- if (inflate_unzip(&res, zip_header->formatted.cmpsize, src_fd, dst_fd) < 0)
+ if (inflate_unzip(&res, zip_header->formatted.cmpsize, zip_fd, dst_fd) < 0)
bb_error_msg_and_die("inflate error");
/* Validate decompression - crc */
if (zip_header->formatted.crc32 != (res.crc ^ 0xffffffffL)) {
@@ -131,9 +255,12 @@ int unzip_main(int argc, char **argv)
smallint verbose = 1;
smallint listing = 0;
smallint overwrite = O_PROMPT;
+#if ENABLE_DESKTOP
+ uint32_t cds_offset;
+ unsigned cds_entries;
+#endif
unsigned total_size;
unsigned total_entries;
- int src_fd = -1;
int dst_fd = -1;
char *src_fn = NULL;
char *dst_fn = NULL;
@@ -221,13 +348,14 @@ int unzip_main(int argc, char **argv)
/* Open input file */
if (LONE_DASH(src_fn)) {
- src_fd = STDIN_FILENO;
+ xdup2(STDIN_FILENO, zip_fd);
/* Cannot use prompt mode since zip data is arriving on STDIN */
if (overwrite == O_PROMPT)
overwrite = O_NEVER;
} else {
static const char extn[][5] = {"", ".zip", ".ZIP"};
int orig_src_fn_len = strlen(src_fn);
+ int src_fd = -1;
for (i = 0; (i < 3) && (src_fd == -1); i++) {
strcpy(src_fn + orig_src_fn_len, extn[i]);
@@ -237,6 +365,7 @@ int unzip_main(int argc, char **argv)
src_fn[orig_src_fn_len] = '\0';
bb_error_msg_and_die("can't open %s, %s.zip, %s.ZIP", src_fn, src_fn, src_fn);
}
+ xmove_fd(src_fd, zip_fd);
}
/* Change dir if necessary */
@@ -253,37 +382,63 @@ int unzip_main(int argc, char **argv)
total_size = 0;
total_entries = 0;
+#if ENABLE_DESKTOP
+ cds_entries = 0;
+ cds_offset = 0;
+#endif
while (1) {
uint32_t magic;
/* Check magic number */
- xread(src_fd, &magic, 4);
+ xread(zip_fd, &magic, 4);
/* Central directory? It's at the end, so exit */
if (magic == ZIP_CDS_MAGIC)
break;
+#if ENABLE_DESKTOP
+ /* Data descriptor? It was a streaming file, go on */
+ if (magic == ZIP_DD_MAGIC) {
+ /* skip over duplicate crc32, cmpsize and ucmpsize */
+ unzip_skip(3 * 4);
+ continue;
+ }
+#endif
if (magic != ZIP_FILEHEADER_MAGIC)
bb_error_msg_and_die("invalid zip magic %08X", (int)magic);
/* Read the file header */
- xread(src_fd, zip_header.raw, ZIP_HEADER_LEN);
- FIX_ENDIANNESS(zip_header);
+ xread(zip_fd, zip_header.raw, ZIP_HEADER_LEN);
+ FIX_ENDIANNESS_ZIP(zip_header);
if ((zip_header.formatted.method != 0) && (zip_header.formatted.method != 8)) {
bb_error_msg_and_die("unsupported method %d", zip_header.formatted.method);
}
- if (zip_header.formatted.flags & (0x0008|0x0001)) {
+#if !ENABLE_DESKTOP
+ if (zip_header.formatted.flags & 0x0009) {
+ bb_error_msg_and_die("zip flags 1 and 8 are not supported");
+ }
+#else
+ if (zip_header.formatted.flags & 0x0001) {
/* 0x0001 - encrypted */
+ bb_error_msg_and_die("zip flag 1 (encryption) is not supported");
+ }
+ if (zip_header.formatted.flags & 0x0008) {
+ cds_header_t cds_header;
/* 0x0008 - streaming. [u]cmpsize can be reliably gotten
* only from Central Directory. See unzip_doc.txt */
- bb_error_msg_and_die("zip flags 8 and 1 are not supported");
+ cds_offset = read_next_cds(total_entries - cds_entries, cds_offset, &cds_header);
+ cds_entries = total_entries + 1;
+ zip_header.formatted.crc32 = cds_header.formatted.crc32;
+ zip_header.formatted.cmpsize = cds_header.formatted.cmpsize;
+ zip_header.formatted.ucmpsize = cds_header.formatted.ucmpsize;
}
+#endif
/* Read filename */
free(dst_fn);
dst_fn = xzalloc(zip_header.formatted.filename_len + 1);
- xread(src_fd, dst_fn, zip_header.formatted.filename_len);
+ xread(zip_fd, dst_fn, zip_header.formatted.filename_len);
/* Skip extra header bytes */
- unzip_skip(src_fd, zip_header.formatted.extra_len);
+ unzip_skip(zip_header.formatted.extra_len);
/* Filter zip entries */
if (find_list_entry(zreject, dst_fn)
@@ -304,7 +459,6 @@ int unzip_main(int argc, char **argv)
(dostime & 0x000007e0) >> 5,
dst_fn);
total_size += zip_header.formatted.ucmpsize;
- total_entries++;
} else {
/* short listing -- filenames only */
puts(dst_fn);
@@ -315,7 +469,7 @@ int unzip_main(int argc, char **argv)
} else if (last_char_is(dst_fn, '/')) { /* Extract directory */
if (stat(dst_fn, &stat_buf) == -1) {
if (errno != ENOENT) {
- bb_perror_msg_and_die("cannot stat '%s'", dst_fn);
+ bb_perror_msg_and_die("can't stat '%s'", dst_fn);
}
if (verbose) {
printf(" creating: %s\n", dst_fn);
@@ -335,7 +489,7 @@ int unzip_main(int argc, char **argv)
check_file:
if (stat(dst_fn, &stat_buf) == -1) { /* File does not exist */
if (errno != ENOENT) {
- bb_perror_msg_and_die("cannot stat '%s'", dst_fn);
+ bb_perror_msg_and_die("can't stat '%s'", dst_fn);
}
i = 'y';
} else { /* File already exists */
@@ -347,7 +501,7 @@ int unzip_main(int argc, char **argv)
} else {
printf("replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ", dst_fn);
if (!fgets(key_buf, sizeof(key_buf), stdin)) {
- bb_perror_msg_and_die("cannot read input");
+ bb_perror_msg_and_die("can't read input");
}
i = key_buf[0];
}
@@ -368,7 +522,7 @@ int unzip_main(int argc, char **argv)
if (verbose) {
printf(" inflating: %s\n", dst_fn);
}
- unzip_extract(&zip_header, src_fd, dst_fd);
+ unzip_extract(&zip_header, dst_fd);
if (dst_fd != STDOUT_FILENO) {
/* closing STDOUT is potentially bad for future business */
close(dst_fd);
@@ -379,14 +533,14 @@ int unzip_main(int argc, char **argv)
overwrite = O_NEVER;
case 'n':
/* Skip entry data */
- unzip_skip(src_fd, zip_header.formatted.cmpsize);
+ unzip_skip(zip_header.formatted.cmpsize);
break;
case 'r':
/* Prompt for new name */
printf("new name: ");
if (!fgets(key_buf, sizeof(key_buf), stdin)) {
- bb_perror_msg_and_die("cannot read input");
+ bb_perror_msg_and_die("can't read input");
}
free(dst_fn);
dst_fn = xstrdup(key_buf);
@@ -398,12 +552,7 @@ int unzip_main(int argc, char **argv)
goto check_file;
}
-// Looks like bug (data descriptor cannot be identified this way)
-// /* Data descriptor section */
-// if (zip_header.formatted.flags & 4) {
-// /* skip over duplicate crc, compressed size and uncompressed size */
-// unzip_skip(src_fd, 12);
-// }
+ total_entries++;
}
if (listing && verbose) {
diff --git a/release/src/router/busybox/config_g b/release/src/router/busybox/config_g
deleted file mode 100644
index 8fa45da7bb..0000000000
--- a/release/src/router/busybox/config_g
+++ /dev/null
@@ -1,853 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Busybox version: 1.12.2
-# Fri Nov 28 22:55:05 2008
-#
-CONFIG_HAVE_DOT_CONFIG=y
-
-#
-# Busybox Settings
-#
-
-#
-# General Configuration
-#
-# CONFIG_DESKTOP is not set
-# CONFIG_EXTRA_COMPAT is not set
-# CONFIG_FEATURE_ASSUME_UNICODE is not set
-CONFIG_FEATURE_BUFFERS_USE_MALLOC=y
-# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set
-# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set
-CONFIG_SHOW_USAGE=y
-CONFIG_FEATURE_VERBOSE_USAGE=y
-CONFIG_FEATURE_COMPRESS_USAGE=y
-# CONFIG_FEATURE_INSTALLER is not set
-# CONFIG_LOCALE_SUPPORT is not set
-CONFIG_GETOPT_LONG=y
-CONFIG_FEATURE_DEVPTS=y
-# CONFIG_FEATURE_CLEAN_UP is not set
-CONFIG_FEATURE_PIDFILE=y
-CONFIG_FEATURE_SUID=y
-# CONFIG_FEATURE_SUID_CONFIG is not set
-# CONFIG_FEATURE_SUID_CONFIG_QUIET is not set
-# CONFIG_SELINUX is not set
-# CONFIG_FEATURE_PREFER_APPLETS is not set
-CONFIG_BUSYBOX_EXEC_PATH="/proc/self/exe"
-CONFIG_FEATURE_SYSLOG=y
-CONFIG_FEATURE_HAVE_RPC=y
-
-#
-# Build Options
-#
-# CONFIG_STATIC is not set
-# CONFIG_PIE is not set
-# CONFIG_NOMMU is not set
-# CONFIG_BUILD_LIBBUSYBOX is not set
-# CONFIG_FEATURE_INDIVIDUAL is not set
-# CONFIG_FEATURE_SHARED_BUSYBOX is not set
-CONFIG_LFS=y
-CONFIG_CROSS_COMPILER_PREFIX="mipsel-uclibc-"
-
-#
-# Debugging Options
-#
-# CONFIG_DEBUG is not set
-# CONFIG_DEBUG_PESSIMIZE is not set
-# CONFIG_WERROR is not set
-CONFIG_NO_DEBUG_LIB=y
-# CONFIG_DMALLOC is not set
-# CONFIG_EFENCE is not set
-CONFIG_INCLUDE_SUSv2=y
-# CONFIG_PARSE is not set
-
-#
-# Installation Options
-#
-# CONFIG_INSTALL_NO_USR is not set
-CONFIG_INSTALL_APPLET_SYMLINKS=y
-# CONFIG_INSTALL_APPLET_HARDLINKS is not set
-# CONFIG_INSTALL_APPLET_SCRIPT_WRAPPERS is not set
-# CONFIG_INSTALL_APPLET_DONT is not set
-# CONFIG_INSTALL_SH_APPLET_SYMLINK is not set
-# CONFIG_INSTALL_SH_APPLET_HARDLINK is not set
-# CONFIG_INSTALL_SH_APPLET_SCRIPT_WRAPPER is not set
-CONFIG_PREFIX="./_install"
-
-#
-# Busybox Library Tuning
-#
-CONFIG_PASSWORD_MINLEN=6
-CONFIG_MD5_SIZE_VS_SPEED=2
-CONFIG_FEATURE_FAST_TOP=y
-# CONFIG_FEATURE_ETC_NETWORKS is not set
-CONFIG_FEATURE_EDITING=y
-CONFIG_FEATURE_EDITING_MAX_LEN=1024
-# CONFIG_FEATURE_EDITING_VI is not set
-CONFIG_FEATURE_EDITING_HISTORY=15
-# CONFIG_FEATURE_EDITING_SAVEHISTORY is not set
-CONFIG_FEATURE_TAB_COMPLETION=y
-# CONFIG_FEATURE_USERNAME_COMPLETION is not set
-# CONFIG_FEATURE_EDITING_FANCY_PROMPT is not set
-# CONFIG_FEATURE_VERBOSE_CP_MESSAGE is not set
-CONFIG_FEATURE_COPYBUF_KB=4
-# CONFIG_MONOTONIC_SYSCALL is not set
-CONFIG_IOCTL_HEX2STR_ERROR=y
-# CONFIG_FEATURE_HWIB is not set
-
-#
-# Applets
-#
-
-#
-# Archival Utilities
-#
-# CONFIG_FEATURE_SEAMLESS_LZMA is not set
-CONFIG_FEATURE_SEAMLESS_BZ2=y
-CONFIG_FEATURE_SEAMLESS_GZ=y
-# CONFIG_FEATURE_SEAMLESS_Z is not set
-# CONFIG_AR is not set
-# CONFIG_FEATURE_AR_LONG_FILENAMES is not set
-# CONFIG_BUNZIP2 is not set
-# CONFIG_BZIP2 is not set
-# CONFIG_CPIO is not set
-# CONFIG_FEATURE_CPIO_O is not set
-# CONFIG_DPKG is not set
-# CONFIG_DPKG_DEB is not set
-# CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY is not set
-CONFIG_GUNZIP=y
-CONFIG_GZIP=y
-# CONFIG_RPM2CPIO is not set
-# CONFIG_RPM is not set
-CONFIG_TAR=y
-CONFIG_FEATURE_TAR_CREATE=y
-# CONFIG_FEATURE_TAR_AUTODETECT is not set
-# CONFIG_FEATURE_TAR_FROM is not set
-# CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY is not set
-CONFIG_FEATURE_TAR_OLDSUN_COMPATIBILITY=y
-CONFIG_FEATURE_TAR_GNU_EXTENSIONS=y
-# CONFIG_FEATURE_TAR_LONG_OPTIONS is not set
-# CONFIG_FEATURE_TAR_UNAME_GNAME is not set
-# CONFIG_UNCOMPRESS is not set
-# CONFIG_UNLZMA is not set
-# CONFIG_FEATURE_LZMA_FAST is not set
-CONFIG_UNZIP=y
-
-#
-# Coreutils
-#
-# CONFIG_BASENAME is not set
-# CONFIG_CAL is not set
-CONFIG_CAT=y
-# CONFIG_CATV is not set
-# CONFIG_CHGRP is not set
-CONFIG_CHMOD=y
-# CONFIG_CHOWN is not set
-# CONFIG_CHROOT is not set
-# CONFIG_CKSUM is not set
-# CONFIG_COMM is not set
-CONFIG_CP=y
-CONFIG_CUT=y
-CONFIG_DATE=y
-CONFIG_FEATURE_DATE_ISOFMT=y
-CONFIG_DD=y
-CONFIG_FEATURE_DD_SIGNAL_HANDLING=y
-CONFIG_FEATURE_DD_IBS_OBS=y
-CONFIG_DF=y
-# CONFIG_FEATURE_DF_INODE is not set
-# CONFIG_DIRNAME is not set
-# CONFIG_DOS2UNIX is not set
-# CONFIG_UNIX2DOS is not set
-CONFIG_DU=y
-CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K=y
-CONFIG_ECHO=y
-CONFIG_FEATURE_FANCY_ECHO=y
-CONFIG_ENV=y
-# CONFIG_FEATURE_ENV_LONG_OPTIONS is not set
-# CONFIG_EXPAND is not set
-# CONFIG_FEATURE_EXPAND_LONG_OPTIONS is not set
-CONFIG_EXPR=y
-CONFIG_EXPR_MATH_SUPPORT_64=y
-# CONFIG_FALSE is not set
-# CONFIG_FOLD is not set
-CONFIG_HEAD=y
-CONFIG_FEATURE_FANCY_HEAD=y
-# CONFIG_HOSTID is not set
-# CONFIG_ID is not set
-# CONFIG_INSTALL is not set
-# CONFIG_FEATURE_INSTALL_LONG_OPTIONS is not set
-# CONFIG_LENGTH is not set
-CONFIG_LN=y
-# CONFIG_LOGNAME is not set
-CONFIG_LS=y
-CONFIG_FEATURE_LS_FILETYPES=y
-CONFIG_FEATURE_LS_FOLLOWLINKS=y
-CONFIG_FEATURE_LS_RECURSIVE=y
-CONFIG_FEATURE_LS_SORTFILES=y
-CONFIG_FEATURE_LS_TIMESTAMPS=y
-CONFIG_FEATURE_LS_USERNAME=y
-CONFIG_FEATURE_LS_COLOR=y
-CONFIG_FEATURE_LS_COLOR_IS_DEFAULT=y
-CONFIG_MD5SUM=y
-CONFIG_MKDIR=y
-# CONFIG_FEATURE_MKDIR_LONG_OPTIONS is not set
-# CONFIG_MKFIFO is not set
-# CONFIG_MKNOD is not set
-CONFIG_MV=y
-# CONFIG_FEATURE_MV_LONG_OPTIONS is not set
-# CONFIG_NICE is not set
-CONFIG_NOHUP=y
-# CONFIG_OD is not set
-# CONFIG_PRINTENV is not set
-CONFIG_PRINTF=y
-CONFIG_PWD=y
-# CONFIG_READLINK is not set
-# CONFIG_FEATURE_READLINK_FOLLOW is not set
-# CONFIG_REALPATH is not set
-CONFIG_RM=y
-CONFIG_RMDIR=y
-# CONFIG_FEATURE_RMDIR_LONG_OPTIONS is not set
-# CONFIG_SEQ is not set
-# CONFIG_SHA1SUM is not set
-CONFIG_SLEEP=y
-CONFIG_FEATURE_FANCY_SLEEP=y
-# CONFIG_FEATURE_FLOAT_SLEEP is not set
-CONFIG_SORT=y
-CONFIG_FEATURE_SORT_BIG=y
-# CONFIG_SPLIT is not set
-# CONFIG_FEATURE_SPLIT_FANCY is not set
-# CONFIG_STAT is not set
-# CONFIG_FEATURE_STAT_FORMAT is not set
-# CONFIG_STTY is not set
-# CONFIG_SUM is not set
-CONFIG_SYNC=y
-# CONFIG_TAC is not set
-CONFIG_TAIL=y
-CONFIG_FEATURE_FANCY_TAIL=y
-# CONFIG_TEE is not set
-# CONFIG_FEATURE_TEE_USE_BLOCK_IO is not set
-CONFIG_TEST=y
-CONFIG_FEATURE_TEST_64=y
-CONFIG_TOUCH=y
-CONFIG_TR=y
-CONFIG_FEATURE_TR_CLASSES=y
-CONFIG_FEATURE_TR_EQUIV=y
-# CONFIG_TRUE is not set
-# CONFIG_TTY is not set
-CONFIG_UNAME=y
-# CONFIG_UNEXPAND is not set
-# CONFIG_FEATURE_UNEXPAND_LONG_OPTIONS is not set
-# CONFIG_UNIQ is not set
-CONFIG_USLEEP=y
-# CONFIG_UUDECODE is not set
-# CONFIG_UUENCODE is not set
-CONFIG_WC=y
-CONFIG_FEATURE_WC_LARGE=y
-# CONFIG_WHO is not set
-# CONFIG_WHOAMI is not set
-# CONFIG_YES is not set
-
-#
-# Common options for cp and mv
-#
-CONFIG_FEATURE_PRESERVE_HARDLINKS=y
-
-#
-# Common options for ls, more and telnet
-#
-CONFIG_FEATURE_AUTOWIDTH=y
-
-#
-# Common options for df, du, ls
-#
-CONFIG_FEATURE_HUMAN_READABLE=y
-
-#
-# Common options for md5sum, sha1sum
-#
-# CONFIG_FEATURE_MD5_SHA1_SUM_CHECK is not set
-
-#
-# Console Utilities
-#
-# CONFIG_CHVT is not set
-CONFIG_CLEAR=y
-# CONFIG_DEALLOCVT is not set
-# CONFIG_DUMPKMAP is not set
-# CONFIG_KBD_MODE is not set
-# CONFIG_LOADFONT is not set
-# CONFIG_LOADKMAP is not set
-# CONFIG_OPENVT is not set
-# CONFIG_RESET is not set
-# CONFIG_RESIZE is not set
-# CONFIG_FEATURE_RESIZE_PRINT is not set
-CONFIG_SETCONSOLE=y
-# CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS is not set
-# CONFIG_SETFONT is not set
-# CONFIG_SETKEYCODES is not set
-# CONFIG_SETLOGCONS is not set
-# CONFIG_SHOWKEY is not set
-
-#
-# Debian Utilities
-#
-# CONFIG_MKTEMP is not set
-# CONFIG_PIPE_PROGRESS is not set
-# CONFIG_RUN_PARTS is not set
-# CONFIG_FEATURE_RUN_PARTS_LONG_OPTIONS is not set
-# CONFIG_FEATURE_RUN_PARTS_FANCY is not set
-# CONFIG_START_STOP_DAEMON is not set
-# CONFIG_FEATURE_START_STOP_DAEMON_FANCY is not set
-# CONFIG_FEATURE_START_STOP_DAEMON_LONG_OPTIONS is not set
-CONFIG_WHICH=y
-
-#
-# Editors
-#
-CONFIG_AWK=y
-CONFIG_FEATURE_AWK_MATH=y
-CONFIG_CMP=y
-# CONFIG_DIFF is not set
-# CONFIG_FEATURE_DIFF_BINARY is not set
-# CONFIG_FEATURE_DIFF_DIR is not set
-# CONFIG_FEATURE_DIFF_MINIMAL is not set
-# CONFIG_ED is not set
-# CONFIG_PATCH is not set
-CONFIG_SED=y
-CONFIG_VI=y
-CONFIG_FEATURE_VI_MAX_LEN=4096
-# CONFIG_FEATURE_VI_8BIT is not set
-CONFIG_FEATURE_VI_COLON=y
-CONFIG_FEATURE_VI_YANKMARK=y
-CONFIG_FEATURE_VI_SEARCH=y
-CONFIG_FEATURE_VI_USE_SIGNALS=y
-CONFIG_FEATURE_VI_DOT_CMD=y
-CONFIG_FEATURE_VI_READONLY=y
-CONFIG_FEATURE_VI_SETOPTS=y
-CONFIG_FEATURE_VI_SET=y
-CONFIG_FEATURE_VI_WIN_RESIZE=y
-# CONFIG_FEATURE_VI_OPTIMIZE_CURSOR is not set
-# CONFIG_FEATURE_ALLOW_EXEC is not set
-
-#
-# Finding Utilities
-#
-CONFIG_FIND=y
-CONFIG_FEATURE_FIND_PRINT0=y
-# CONFIG_FEATURE_FIND_MTIME is not set
-# CONFIG_FEATURE_FIND_MMIN is not set
-# CONFIG_FEATURE_FIND_PERM is not set
-# CONFIG_FEATURE_FIND_TYPE is not set
-# CONFIG_FEATURE_FIND_XDEV is not set
-# CONFIG_FEATURE_FIND_MAXDEPTH is not set
-# CONFIG_FEATURE_FIND_NEWER is not set
-# CONFIG_FEATURE_FIND_INUM is not set
-CONFIG_FEATURE_FIND_EXEC=y
-# CONFIG_FEATURE_FIND_USER is not set
-# CONFIG_FEATURE_FIND_GROUP is not set
-CONFIG_FEATURE_FIND_NOT=y
-# CONFIG_FEATURE_FIND_DEPTH is not set
-# CONFIG_FEATURE_FIND_PAREN is not set
-# CONFIG_FEATURE_FIND_SIZE is not set
-# CONFIG_FEATURE_FIND_PRUNE is not set
-# CONFIG_FEATURE_FIND_DELETE is not set
-# CONFIG_FEATURE_FIND_PATH is not set
-# CONFIG_FEATURE_FIND_REGEX is not set
-# CONFIG_FEATURE_FIND_CONTEXT is not set
-CONFIG_GREP=y
-CONFIG_FEATURE_GREP_EGREP_ALIAS=y
-CONFIG_FEATURE_GREP_FGREP_ALIAS=y
-CONFIG_FEATURE_GREP_CONTEXT=y
-# CONFIG_XARGS is not set
-# CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION is not set
-# CONFIG_FEATURE_XARGS_SUPPORT_QUOTES is not set
-# CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT is not set
-# CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM is not set
-
-#
-# Init Utilities
-#
-# CONFIG_INIT is not set
-# CONFIG_DEBUG_INIT is not set
-# CONFIG_FEATURE_USE_INITTAB is not set
-# CONFIG_FEATURE_KILL_REMOVED is not set
-CONFIG_FEATURE_KILL_DELAY=0
-# CONFIG_FEATURE_INIT_SCTTY is not set
-# CONFIG_FEATURE_INIT_SYSLOG is not set
-# CONFIG_FEATURE_EXTRA_QUIET is not set
-# CONFIG_FEATURE_INIT_COREDUMPS is not set
-# CONFIG_FEATURE_INITRD is not set
-# CONFIG_HALT is not set
-# CONFIG_MESG is not set
-
-#
-# Login/Password Management Utilities
-#
-CONFIG_FEATURE_SHADOWPASSWDS=y
-CONFIG_USE_BB_PWD_GRP=y
-CONFIG_USE_BB_SHADOW=y
-# CONFIG_USE_BB_CRYPT is not set
-# CONFIG_ADDGROUP is not set
-# CONFIG_FEATURE_ADDUSER_TO_GROUP is not set
-# CONFIG_DELGROUP is not set
-# CONFIG_FEATURE_DEL_USER_FROM_GROUP is not set
-# CONFIG_FEATURE_CHECK_NAMES is not set
-# CONFIG_ADDUSER is not set
-# CONFIG_FEATURE_ADDUSER_LONG_OPTIONS is not set
-# CONFIG_DELUSER is not set
-# CONFIG_GETTY is not set
-CONFIG_FEATURE_UTMP=y
-# CONFIG_FEATURE_WTMP is not set
-CONFIG_LOGIN=y
-# CONFIG_PAM is not set
-# CONFIG_LOGIN_SCRIPTS is not set
-# CONFIG_FEATURE_NOLOGIN is not set
-# CONFIG_FEATURE_SECURETTY is not set
-# CONFIG_PASSWD is not set
-# CONFIG_FEATURE_PASSWD_WEAK_CHECK is not set
-# CONFIG_CRYPTPW is not set
-# CONFIG_CHPASSWD is not set
-# CONFIG_SU is not set
-# CONFIG_FEATURE_SU_SYSLOG is not set
-# CONFIG_FEATURE_SU_CHECKS_SHELLS is not set
-# CONFIG_SULOGIN is not set
-# CONFIG_VLOCK is not set
-
-#
-# Linux Ext2 FS Progs
-#
-# CONFIG_CHATTR is not set
-# CONFIG_FSCK is not set
-# CONFIG_LSATTR is not set
-
-#
-# Linux Module Utilities
-#
-# CONFIG_MODPROBE_SMALL is not set
-# CONFIG_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE is not set
-# CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED is not set
-# CONFIG_DEPMOD is not set
-# CONFIG_FEATURE_DEPMOD_PRUNE_FANCY is not set
-# CONFIG_FEATURE_DEPMOD_ALIAS is not set
-CONFIG_INSMOD=y
-# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set
-# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set
-# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set
-# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set
-# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set
-CONFIG_RMMOD=y
-CONFIG_LSMOD=y
-# CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT is not set
-CONFIG_MODPROBE=y
-CONFIG_FEATURE_MODPROBE_MULTIPLE_OPTIONS=y
-# CONFIG_FEATURE_MODPROBE_FANCY_ALIAS is not set
-# CONFIG_FEATURE_MODPROBE_BLACKLIST is not set
-
-#
-# Options common to multiple modutils
-#
-CONFIG_FEATURE_CHECK_TAINTED_MODULE=y
-CONFIG_FEATURE_2_4_MODULES=y
-# CONFIG_FEATURE_2_6_MODULES is not set
-CONFIG_DEFAULT_MODULES_DIR="/lib/modules"
-CONFIG_DEFAULT_DEPMOD_FILE="modules.dep"
-CONFIG_FEATURE_QUERY_MODULE_INTERFACE=y
-
-#
-# Linux System Utilities
-#
-CONFIG_DMESG=y
-CONFIG_FEATURE_DMESG_PRETTY=y
-# CONFIG_FBSET is not set
-# CONFIG_FEATURE_FBSET_FANCY is not set
-# CONFIG_FEATURE_FBSET_READMODE is not set
-# CONFIG_FDFLUSH is not set
-# CONFIG_FDFORMAT is not set
-# CONFIG_FDISK is not set
-CONFIG_FDISK_SUPPORT_LARGE_DISKS=y
-# CONFIG_FEATURE_FDISK_WRITABLE is not set
-# CONFIG_FEATURE_AIX_LABEL is not set
-# CONFIG_FEATURE_SGI_LABEL is not set
-# CONFIG_FEATURE_SUN_LABEL is not set
-# CONFIG_FEATURE_OSF_LABEL is not set
-# CONFIG_FEATURE_FDISK_ADVANCED is not set
-# CONFIG_FINDFS is not set
-# CONFIG_FREERAMDISK is not set
-# CONFIG_FSCK_MINIX is not set
-# CONFIG_MKFS_MINIX is not set
-# CONFIG_FEATURE_MINIX2 is not set
-# CONFIG_GETOPT is not set
-# CONFIG_HEXDUMP is not set
-# CONFIG_FEATURE_HEXDUMP_REVERSE is not set
-# CONFIG_HD is not set
-# CONFIG_HWCLOCK is not set
-# CONFIG_FEATURE_HWCLOCK_LONG_OPTIONS is not set
-# CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS is not set
-# CONFIG_IPCRM is not set
-# CONFIG_IPCS is not set
-# CONFIG_LOSETUP is not set
-# CONFIG_MDEV is not set
-# CONFIG_FEATURE_MDEV_CONF is not set
-# CONFIG_FEATURE_MDEV_RENAME is not set
-# CONFIG_FEATURE_MDEV_RENAME_REGEXP is not set
-# CONFIG_FEATURE_MDEV_EXEC is not set
-# CONFIG_FEATURE_MDEV_LOAD_FIRMWARE is not set
-# CONFIG_MKSWAP is not set
-# CONFIG_FEATURE_MKSWAP_V0 is not set
-CONFIG_MORE=y
-CONFIG_FEATURE_USE_TERMIOS=y
-# CONFIG_VOLUMEID is not set
-# CONFIG_FEATURE_VOLUMEID_EXT is not set
-# CONFIG_FEATURE_VOLUMEID_REISERFS is not set
-# CONFIG_FEATURE_VOLUMEID_FAT is not set
-# CONFIG_FEATURE_VOLUMEID_HFS is not set
-# CONFIG_FEATURE_VOLUMEID_JFS is not set
-# CONFIG_FEATURE_VOLUMEID_XFS is not set
-# CONFIG_FEATURE_VOLUMEID_NTFS is not set
-# CONFIG_FEATURE_VOLUMEID_ISO9660 is not set
-# CONFIG_FEATURE_VOLUMEID_UDF is not set
-# CONFIG_FEATURE_VOLUMEID_LUKS is not set
-# CONFIG_FEATURE_VOLUMEID_LINUXSWAP is not set
-# CONFIG_FEATURE_VOLUMEID_CRAMFS is not set
-# CONFIG_FEATURE_VOLUMEID_ROMFS is not set
-# CONFIG_FEATURE_VOLUMEID_SYSV is not set
-# CONFIG_FEATURE_VOLUMEID_OCFS2 is not set
-# CONFIG_FEATURE_VOLUMEID_LINUXRAID is not set
-CONFIG_MOUNT=y
-# CONFIG_FEATURE_MOUNT_FAKE is not set
-# CONFIG_FEATURE_MOUNT_VERBOSE is not set
-CONFIG_FEATURE_MOUNT_HELPERS=y
-# CONFIG_FEATURE_MOUNT_LABEL is not set
-# CONFIG_FEATURE_MOUNT_NFS is not set
-CONFIG_FEATURE_MOUNT_CIFS=y
-CONFIG_FEATURE_MOUNT_FLAGS=y
-# CONFIG_FEATURE_MOUNT_FSTAB is not set
-# CONFIG_PIVOT_ROOT is not set
-# CONFIG_RDATE is not set
-# CONFIG_RDEV is not set
-# CONFIG_READPROFILE is not set
-# CONFIG_RTCWAKE is not set
-# CONFIG_SCRIPT is not set
-# CONFIG_SETARCH is not set
-# CONFIG_SWAPONOFF is not set
-# CONFIG_FEATURE_SWAPON_PRI is not set
-# CONFIG_SWITCH_ROOT is not set
-CONFIG_UMOUNT=y
-# CONFIG_FEATURE_UMOUNT_ALL is not set
-
-#
-# Common options for mount/umount
-#
-# CONFIG_FEATURE_MOUNT_LOOP is not set
-# CONFIG_FEATURE_MTAB_SUPPORT is not set
-
-#
-# Miscellaneous Utilities
-#
-# CONFIG_ADJTIMEX is not set
-# CONFIG_BBCONFIG is not set
-# CONFIG_CHAT is not set
-# CONFIG_FEATURE_CHAT_NOFAIL is not set
-# CONFIG_FEATURE_CHAT_TTY_HIFI is not set
-# CONFIG_FEATURE_CHAT_IMPLICIT_CR is not set
-# CONFIG_FEATURE_CHAT_SWALLOW_OPTS is not set
-# CONFIG_FEATURE_CHAT_SEND_ESCAPES is not set
-# CONFIG_FEATURE_CHAT_VAR_ABORT_LEN is not set
-# CONFIG_FEATURE_CHAT_CLR_ABORT is not set
-# CONFIG_CHRT is not set
-CONFIG_CROND=y
-# CONFIG_DEBUG_CROND_OPTION is not set
-# CONFIG_FEATURE_CROND_CALL_SENDMAIL is not set
-# CONFIG_CRONTAB is not set
-# CONFIG_DC is not set
-# CONFIG_DEVFSD is not set
-# CONFIG_DEVFSD_MODLOAD is not set
-# CONFIG_DEVFSD_FG_NP is not set
-# CONFIG_DEVFSD_VERBOSE is not set
-# CONFIG_FEATURE_DEVFS is not set
-# CONFIG_EJECT is not set
-# CONFIG_FEATURE_EJECT_SCSI is not set
-# CONFIG_FBSPLASH is not set
-# CONFIG_INOTIFYD is not set
-# CONFIG_LAST is not set
-# CONFIG_FEATURE_LAST_SMALL is not set
-# CONFIG_FEATURE_LAST_FANCY is not set
-CONFIG_LESS=y
-CONFIG_FEATURE_LESS_MAXLINES=9999999
-# CONFIG_FEATURE_LESS_BRACKETS is not set
-# CONFIG_FEATURE_LESS_FLAGS is not set
-# CONFIG_FEATURE_LESS_FLAGCS is not set
-# CONFIG_FEATURE_LESS_MARKS is not set
-# CONFIG_FEATURE_LESS_REGEXP is not set
-# CONFIG_HDPARM is not set
-# CONFIG_FEATURE_HDPARM_GET_IDENTITY is not set
-# CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF is not set
-# CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF is not set
-# CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET is not set
-# CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF is not set
-# CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA is not set
-# CONFIG_MAKEDEVS is not set
-# CONFIG_FEATURE_MAKEDEVS_LEAF is not set
-# CONFIG_FEATURE_MAKEDEVS_TABLE is not set
-# CONFIG_MAN is not set
-# CONFIG_MICROCOM is not set
-# CONFIG_MOUNTPOINT is not set
-# CONFIG_MT is not set
-# CONFIG_RAIDAUTORUN is not set
-# CONFIG_READAHEAD is not set
-# CONFIG_RUNLEVEL is not set
-# CONFIG_RX is not set
-# CONFIG_SETSID is not set
-CONFIG_STRINGS=y
-# CONFIG_TASKSET is not set
-# CONFIG_FEATURE_TASKSET_FANCY is not set
-# CONFIG_TIME is not set
-# CONFIG_TTYSIZE is not set
-# CONFIG_WATCHDOG is not set
-
-#
-# Networking Utilities
-#
-# CONFIG_FEATURE_IPV6 is not set
-# CONFIG_FEATURE_PREFER_IPV4_ADDRESS is not set
-# CONFIG_VERBOSE_RESOLUTION_ERRORS is not set
-CONFIG_ARP=y
-CONFIG_ARPING=y
-# CONFIG_BRCTL is not set
-# CONFIG_FEATURE_BRCTL_FANCY is not set
-# CONFIG_FEATURE_BRCTL_SHOW is not set
-# CONFIG_DNSD is not set
-CONFIG_ETHER_WAKE=y
-# CONFIG_FAKEIDENTD is not set
-CONFIG_FTPGET=y
-CONFIG_FTPPUT=y
-# CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS is not set
-# CONFIG_HOSTNAME is not set
-# CONFIG_HTTPD is not set
-# CONFIG_FEATURE_HTTPD_RANGES is not set
-# CONFIG_FEATURE_HTTPD_USE_SENDFILE is not set
-# CONFIG_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP is not set
-# CONFIG_FEATURE_HTTPD_SETUID is not set
-# CONFIG_FEATURE_HTTPD_BASIC_AUTH is not set
-# CONFIG_FEATURE_HTTPD_AUTH_MD5 is not set
-# CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES is not set
-# CONFIG_FEATURE_HTTPD_CGI is not set
-# CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR is not set
-# CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV is not set
-# CONFIG_FEATURE_HTTPD_ENCODE_URL_STR is not set
-# CONFIG_FEATURE_HTTPD_ERROR_PAGES is not set
-# CONFIG_FEATURE_HTTPD_PROXY is not set
-CONFIG_IFCONFIG=y
-CONFIG_FEATURE_IFCONFIG_STATUS=y
-# CONFIG_FEATURE_IFCONFIG_SLIP is not set
-# CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ is not set
-CONFIG_FEATURE_IFCONFIG_HW=y
-CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS=y
-# CONFIG_IFENSLAVE is not set
-# CONFIG_IFUPDOWN is not set
-CONFIG_IFUPDOWN_IFSTATE_PATH=""
-# CONFIG_FEATURE_IFUPDOWN_IP is not set
-# CONFIG_FEATURE_IFUPDOWN_IP_BUILTIN is not set
-# CONFIG_FEATURE_IFUPDOWN_IFCONFIG_BUILTIN is not set
-# CONFIG_FEATURE_IFUPDOWN_IPV4 is not set
-# CONFIG_FEATURE_IFUPDOWN_IPV6 is not set
-# CONFIG_FEATURE_IFUPDOWN_MAPPING is not set
-# CONFIG_FEATURE_IFUPDOWN_EXTERNAL_DHCP is not set
-# CONFIG_INETD is not set
-# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO is not set
-# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD is not set
-# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME is not set
-# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME is not set
-# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN is not set
-# CONFIG_FEATURE_INETD_RPC is not set
-# CONFIG_IP is not set
-# CONFIG_FEATURE_IP_ADDRESS is not set
-# CONFIG_FEATURE_IP_LINK is not set
-# CONFIG_FEATURE_IP_ROUTE is not set
-# CONFIG_FEATURE_IP_TUNNEL is not set
-# CONFIG_FEATURE_IP_RULE is not set
-# CONFIG_FEATURE_IP_SHORT_FORMS is not set
-# CONFIG_FEATURE_IP_RARE_PROTOCOLS is not set
-# CONFIG_IPADDR is not set
-# CONFIG_IPLINK is not set
-# CONFIG_IPROUTE is not set
-# CONFIG_IPTUNNEL is not set
-# CONFIG_IPRULE is not set
-# CONFIG_IPCALC is not set
-# CONFIG_FEATURE_IPCALC_FANCY is not set
-# CONFIG_FEATURE_IPCALC_LONG_OPTIONS is not set
-# CONFIG_NAMEIF is not set
-# CONFIG_FEATURE_NAMEIF_EXTENDED is not set
-CONFIG_NC=y
-# CONFIG_NC_SERVER is not set
-CONFIG_NC_EXTRA=y
-CONFIG_NETSTAT=y
-CONFIG_FEATURE_NETSTAT_WIDE=y
-# CONFIG_FEATURE_NETSTAT_PRG is not set
-CONFIG_NSLOOKUP=y
-CONFIG_PING=y
-# CONFIG_PING6 is not set
-CONFIG_FEATURE_FANCY_PING=y
-CONFIG_PSCAN=y
-CONFIG_ROUTE=y
-# CONFIG_SENDMAIL is not set
-# CONFIG_FETCHMAIL is not set
-# CONFIG_SLATTACH is not set
-CONFIG_TELNET=y
-# CONFIG_FEATURE_TELNET_TTYPE is not set
-# CONFIG_FEATURE_TELNET_AUTOLOGIN is not set
-CONFIG_TELNETD=y
-CONFIG_FEATURE_TELNETD_STANDALONE=y
-# CONFIG_TFTP is not set
-# CONFIG_TFTPD is not set
-# CONFIG_FEATURE_TFTP_GET is not set
-# CONFIG_FEATURE_TFTP_PUT is not set
-# CONFIG_FEATURE_TFTP_BLOCKSIZE is not set
-# CONFIG_DEBUG_TFTP is not set
-CONFIG_TRACEROUTE=y
-CONFIG_FEATURE_TRACEROUTE_VERBOSE=y
-CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE=y
-CONFIG_FEATURE_TRACEROUTE_USE_ICMP=y
-# CONFIG_APP_UDHCPD is not set
-# CONFIG_APP_DHCPRELAY is not set
-# CONFIG_APP_DUMPLEASES is not set
-# CONFIG_FEATURE_UDHCPD_WRITE_LEASES_EARLY is not set
-CONFIG_DHCPD_LEASES_FILE=""
-CONFIG_APP_UDHCPC=y
-CONFIG_FEATURE_UDHCPC_ARPING=y
-# CONFIG_FEATURE_UDHCP_PORT is not set
-# CONFIG_FEATURE_UDHCP_DEBUG is not set
-CONFIG_FEATURE_RFC3397=y
-CONFIG_DHCPC_DEFAULT_SCRIPT="/usr/share/udhcpc/default.script"
-CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS=80
-# CONFIG_VCONFIG is not set
-CONFIG_WGET=y
-# CONFIG_FEATURE_WGET_STATUSBAR is not set
-CONFIG_FEATURE_WGET_AUTHENTICATION=y
-# CONFIG_FEATURE_WGET_LONG_OPTIONS is not set
-# CONFIG_ZCIP is not set
-# CONFIG_TCPSVD is not set
-# CONFIG_UDPSVD is not set
-
-#
-# Process Utilities
-#
-CONFIG_FREE=y
-# CONFIG_FUSER is not set
-CONFIG_KILL=y
-CONFIG_KILLALL=y
-# CONFIG_KILLALL5 is not set
-# CONFIG_NMETER is not set
-# CONFIG_PGREP is not set
-CONFIG_PIDOF=y
-# CONFIG_FEATURE_PIDOF_SINGLE is not set
-# CONFIG_FEATURE_PIDOF_OMIT is not set
-# CONFIG_PKILL is not set
-CONFIG_PS=y
-CONFIG_FEATURE_PS_WIDE=y
-# CONFIG_FEATURE_PS_TIME is not set
-# CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS is not set
-# CONFIG_RENICE is not set
-# CONFIG_BB_SYSCTL is not set
-CONFIG_TOP=y
-CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE=y
-CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS=y
-# CONFIG_FEATURE_TOP_DECIMALS is not set
-# CONFIG_FEATURE_TOPMEM is not set
-CONFIG_UPTIME=y
-CONFIG_WATCH=y
-
-#
-# Shells
-#
-CONFIG_FEATURE_SH_IS_ASH=y
-# CONFIG_FEATURE_SH_IS_HUSH is not set
-# CONFIG_FEATURE_SH_IS_MSH is not set
-# CONFIG_FEATURE_SH_IS_NONE is not set
-CONFIG_ASH=y
-
-#
-# Ash Shell Options
-#
-CONFIG_ASH_BASH_COMPAT=y
-# CONFIG_ASH_JOB_CONTROL is not set
-# CONFIG_ASH_READ_NCHARS is not set
-# CONFIG_ASH_READ_TIMEOUT is not set
-CONFIG_ASH_ALIAS=y
-CONFIG_ASH_MATH_SUPPORT=y
-CONFIG_ASH_MATH_SUPPORT_64=y
-# CONFIG_ASH_GETOPTS is not set
-# CONFIG_ASH_BUILTIN_ECHO is not set
-# CONFIG_ASH_BUILTIN_PRINTF is not set
-# CONFIG_ASH_BUILTIN_TEST is not set
-# CONFIG_ASH_CMDCMD is not set
-# CONFIG_ASH_MAIL is not set
-CONFIG_ASH_OPTIMIZE_FOR_SIZE=y
-# CONFIG_ASH_RANDOM_SUPPORT is not set
-# CONFIG_ASH_EXPAND_PRMT is not set
-# CONFIG_HUSH is not set
-# CONFIG_HUSH_HELP is not set
-# CONFIG_HUSH_INTERACTIVE is not set
-# CONFIG_HUSH_JOB is not set
-# CONFIG_HUSH_TICK is not set
-# CONFIG_HUSH_IF is not set
-# CONFIG_HUSH_LOOPS is not set
-# CONFIG_HUSH_CASE is not set
-# CONFIG_LASH is not set
-# CONFIG_MSH is not set
-
-#
-# Bourne Shell Options
-#
-# CONFIG_FEATURE_SH_EXTRA_QUIET is not set
-# CONFIG_FEATURE_SH_STANDALONE is not set
-# CONFIG_FEATURE_SH_NOFORK is not set
-# CONFIG_CTTYHACK is not set
-
-#
-# System Logging Utilities
-#
-CONFIG_SYSLOGD=y
-CONFIG_FEATURE_ROTATE_LOGFILE=y
-CONFIG_FEATURE_REMOTE_LOG=y
-# CONFIG_FEATURE_SYSLOGD_DUP is not set
-# CONFIG_FEATURE_IPC_SYSLOG is not set
-CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE=
-# CONFIG_LOGREAD is not set
-# CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING is not set
-CONFIG_KLOGD=y
-CONFIG_LOGGER=y
-
-#
-# Runit Utilities
-#
-# CONFIG_RUNSV is not set
-# CONFIG_RUNSVDIR is not set
-# CONFIG_SV is not set
-# CONFIG_SVLOGD is not set
-# CONFIG_CHPST is not set
-# CONFIG_SETUIDGID is not set
-# CONFIG_ENVUIDGID is not set
-# CONFIG_ENVDIR is not set
-# CONFIG_SOFTLIMIT is not set
-# CONFIG_CHCON is not set
-# CONFIG_FEATURE_CHCON_LONG_OPTIONS is not set
-# CONFIG_GETENFORCE is not set
-# CONFIG_GETSEBOOL is not set
-# CONFIG_LOAD_POLICY is not set
-# CONFIG_MATCHPATHCON is not set
-# CONFIG_RESTORECON is not set
-# CONFIG_RUNCON is not set
-# CONFIG_FEATURE_RUNCON_LONG_OPTIONS is not set
-# CONFIG_SELINUXENABLED is not set
-# CONFIG_SETENFORCE is not set
-# CONFIG_SETFILES is not set
-# CONFIG_FEATURE_SETFILES_CHECK_OPTION is not set
-# CONFIG_SETSEBOOL is not set
-# CONFIG_SESTATUS is not set
-
-#
-# Print Utilities
-#
-# CONFIG_LPD is not set
-# CONFIG_LPR is not set
-# CONFIG_LPQ is not set
diff --git a/release/src/router/busybox/console-tools/Config.in b/release/src/router/busybox/console-tools/Config.in
index 254e2f7c85..994140b79c 100644
--- a/release/src/router/busybox/console-tools/Config.in
+++ b/release/src/router/busybox/console-tools/Config.in
@@ -101,6 +101,21 @@ config SETFONT
help
Allows to load console screen map. Useful for i18n.
+config FEATURE_SETFONT_TEXTUAL_MAP
+ bool "Support reading textual screen maps"
+ default n
+ depends on SETFONT
+ help
+ Support reading textual screen maps.
+
+config DEFAULT_SETFONT_DIR
+ string "Default directory for console-tools files"
+ default ""
+ depends on SETFONT
+ help
+ Directory to use if setfont's params are simple filenames
+ (not /path/to/file or ./file). Default is "" (no default directory).
+
config SETKEYCODES
bool "setkeycodes"
default n
diff --git a/release/src/router/busybox/console-tools/kbd_mode.c b/release/src/router/busybox/console-tools/kbd_mode.c
index cb97947ce6..544bbb7894 100644
--- a/release/src/router/busybox/console-tools/kbd_mode.c
+++ b/release/src/router/busybox/console-tools/kbd_mode.c
@@ -2,37 +2,37 @@
/*
* Mini kbd_mode implementation for busybox
*
- * Copyright (C) 2007 Loïc Grenié
+ * Copyright (C) 2007 Loic Grenie
* written using Andries Brouwer 's kbd_mode from
* console-utils v0.2.3, licensed under GNU GPLv2
*
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
- *
*/
-
#include "libbb.h"
#include
int kbd_mode_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int kbd_mode_main(int argc UNUSED_PARAM, char **argv)
{
- int fd;
- unsigned opt;
enum {
SCANCODE = (1 << 0),
ASCII = (1 << 1),
MEDIUMRAW = (1 << 2),
- UNICODE = (1 << 3)
+ UNICODE = (1 << 3),
};
- static const char KD_xxx[] ALIGN1 = "saku";
- opt = getopt32(argv, KD_xxx);
- fd = get_console_fd_or_die();
+ int fd;
+ unsigned opt;
+ const char *tty_name = CURRENT_TTY;
+
+ opt = getopt32(argv, "sakuC:", &tty_name);
+ fd = xopen(tty_name, O_NONBLOCK);
+ opt &= 0xf; /* clear -C bit, see (*) */
if (!opt) { /* print current setting */
const char *mode = "unknown";
int m;
- ioctl(fd, KDGKBMODE, &m);
+ xioctl(fd, KDGKBMODE, &m);
if (m == K_RAW)
mode = "raw (scancode)";
else if (m == K_XLATE)
@@ -43,6 +43,7 @@ int kbd_mode_main(int argc UNUSED_PARAM, char **argv)
mode = "Unicode (UTF-8)";
printf("The keyboard is in %s mode\n", mode);
} else {
+ /* here we depend on specific bits assigned to options (*) */
opt = opt & UNICODE ? 3 : opt >> 1;
/* double cast prevents warnings about widening conversion */
xioctl(fd, KDSKBMODE, (void*)(ptrdiff_t)opt);
diff --git a/release/src/router/busybox/console-tools/loadfont.c b/release/src/router/busybox/console-tools/loadfont.c
index 78700706f3..336418061a 100644
--- a/release/src/router/busybox/console-tools/loadfont.c
+++ b/release/src/router/busybox/console-tools/loadfont.c
@@ -6,10 +6,34 @@
*
* Loads the console font, and possibly the corresponding screen map(s).
* (Adapted for busybox by Matej Vela.)
+ *
+ * Licensed under GPLv2, see file LICENSE in this tarball for details.
*/
#include "libbb.h"
#include
+#ifndef KDFONTOP
+#define KDFONTOP 0x4B72
+struct console_font_op {
+ unsigned op; /* KD_FONT_OP_* */
+ unsigned flags; /* KD_FONT_FLAG_* */
+ unsigned width, height;
+ unsigned charcount;
+ unsigned char *data; /* font data with height fixed to 32 */
+};
+
+#define KD_FONT_OP_SET 0 /* Set font */
+#define KD_FONT_OP_GET 1 /* Get font */
+#define KD_FONT_OP_SET_DEFAULT 2 /* Set font to default,
+ data points to name / NULL */
+#define KD_FONT_OP_COPY 3 /* Copy from another console */
+
+#define KD_FONT_FLAG_OLD 0x80000000 /* Invoked via old interface */
+#define KD_FONT_FLAG_DONT_RECALC 1 /* Don't call adjust_height() */
+ /* (Used internally for PIO_FONT support) */
+#endif /* KDFONTOP */
+
+
enum {
PSF_MAGIC1 = 0x36,
PSF_MAGIC2 = 0x04,
@@ -17,7 +41,7 @@ enum {
PSF_MODE512 = 0x01,
PSF_MODEHASTAB = 0x02,
PSF_MAXMODE = 0x03,
- PSF_SEPARATOR = 0xFFFF
+ PSF_SEPARATOR = 0xffff
};
struct psf_header {
@@ -40,6 +64,28 @@ static void do_loadfont(int fd, unsigned char *inbuf, int unit, int fontsize)
for (i = 0; i < fontsize; i++)
memcpy(buf + (32 * i), inbuf + (unit * i), unit);
+ { /* KDFONTOP */
+ struct console_font_op cfo;
+
+ cfo.op = KD_FONT_OP_SET;
+ cfo.flags = 0;
+ cfo.width = 8;
+ cfo.height = unit;
+ cfo.charcount = fontsize;
+ cfo.data = (void*)buf;
+#if 0
+ if (!ioctl_or_perror(fd, KDFONTOP, &cfo, "KDFONTOP ioctl failed (will try PIO_FONTX)"))
+ goto ret; /* success */
+#else
+ xioctl(fd, KDFONTOP, &cfo);
+#endif
+ }
+
+#if 0
+/* These ones do not honour -C tty (they set font on current tty regardless)
+ * On x86, this distinction is visible on framebuffer consoles
+ * (regular character consoles may have only one shared font anyway)
+ */
#if defined(PIO_FONTX) && !defined(__sparc__)
{
struct consolefontdesc cfd;
@@ -49,11 +95,12 @@ static void do_loadfont(int fd, unsigned char *inbuf, int unit, int fontsize)
cfd.chardata = buf;
if (!ioctl_or_perror(fd, PIO_FONTX, &cfd, "PIO_FONTX ioctl failed (will try PIO_FONT)"))
- goto ret; /* success */
+ goto ret; /* success */
}
#endif
xioctl(fd, PIO_FONT, buf);
ret:
+#endif /* 0 */
free(buf);
}
@@ -155,7 +202,7 @@ int loadfont_main(int argc UNUSED_PARAM, char **argv)
* just read the entire file.
*/
len = 32*1024; // can't be larger
- psfhdr = (struct psf_header *) xmalloc_read(STDIN_FILENO, &len);
+ psfhdr = xmalloc_read(STDIN_FILENO, &len);
// xmalloc_open_zipped_read_close(filename, &len);
if (!psfhdr)
bb_perror_msg_and_die("error reading input font");
@@ -166,30 +213,159 @@ int loadfont_main(int argc UNUSED_PARAM, char **argv)
#endif
#if ENABLE_SETFONT
+
+/*
+kbd-1.12:
+
+setfont [-O font+umap.orig] [-o font.orig] [-om cmap.orig]
+[-ou umap.orig] [-N] [font.new ...] [-m cmap] [-u umap] [-C console]
+[-hNN] [-v] [-V]
+
+-h NN Override font height
+-o file
+ Save previous font in file
+-O file
+ Save previous font and Unicode map in file
+-om file
+ Store console map in file
+-ou file
+ Save previous Unicode map in file
+-m file
+ Load console map or Unicode console map from file
+-u file
+ Load Unicode table describing the font from file
+ Example:
+ # cp866
+ 0x00-0x7f idem
+ #
+ 0x80 U+0410 # CYRILLIC CAPITAL LETTER A
+ 0x81 U+0411 # CYRILLIC CAPITAL LETTER BE
+ 0x82 U+0412 # CYRILLIC CAPITAL LETTER VE
+-C console
+ Set the font for the indicated console
+-v Verbose
+-V Version
+*/
+
+#if ENABLE_FEATURE_SETFONT_TEXTUAL_MAP
+static int ctoi(char *s)
+{
+ if (s[0] == '\'' && s[1] != '\0' && s[2] == '\'' && s[3] == '\0')
+ return s[1];
+ // U+ means 0x
+ if (s[0] == 'U' && s[1] == '+') {
+ s[0] = '0';
+ s[1] = 'x';
+ }
+ if (!isdigit(s[0]))
+ return -1;
+ return xstrtoul(s, 0);
+}
+#endif
+
int setfont_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int setfont_main(int argc UNUSED_PARAM, char **argv)
{
size_t len;
+ unsigned opts;
+ int fd;
struct psf_header *psfhdr;
char *mapfilename;
- int fd;
+ const char *tty_name = CURRENT_TTY;
opt_complementary = "=1";
- getopt32(argv, "m:", &mapfilename);
+ opts = getopt32(argv, "m:C:", &mapfilename, &tty_name);
argv += optind;
+ fd = xopen(tty_name, O_NONBLOCK);
+
+ if (sizeof(CONFIG_DEFAULT_SETFONT_DIR) > 1) { // if not ""
+ if (*argv[0] != '/') {
+ // goto default fonts location. don't die if doesn't exist
+ chdir(CONFIG_DEFAULT_SETFONT_DIR "/consolefonts");
+ }
+ }
// load font
len = 32*1024; // can't be larger
- psfhdr = (struct psf_header *) xmalloc_open_zipped_read_close(*argv, &len);
- fd = get_console_fd_or_die();
+ psfhdr = xmalloc_open_zipped_read_close(*argv, &len);
+ if (!psfhdr)
+ bb_simple_perror_msg_and_die(*argv);
do_load(fd, psfhdr, len);
// load the screen map, if any
- if (option_mask32 & 1) { // -m
- void *map = xmalloc_open_zipped_read_close(mapfilename, &len);
+ if (opts & 1) { // -m
+ unsigned mode = PIO_SCRNMAP;
+ void *map;
+
+ if (sizeof(CONFIG_DEFAULT_SETFONT_DIR) > 1) { // if not ""
+ if (mapfilename[0] != '/') {
+ // goto default keymaps location
+ chdir(CONFIG_DEFAULT_SETFONT_DIR "/consoletrans");
+ }
+ }
+ // fetch keymap
+ map = xmalloc_open_zipped_read_close(mapfilename, &len);
+ if (!map)
+ bb_simple_perror_msg_and_die(mapfilename);
+ // file size is 256 or 512 bytes? -> assume binary map
if (len == E_TABSZ || len == 2*E_TABSZ) {
- xioctl(fd, (len == 2*E_TABSZ) ? PIO_UNISCRNMAP : PIO_SCRNMAP, map);
+ if (len == 2*E_TABSZ)
+ mode = PIO_UNISCRNMAP;
}
+#if ENABLE_FEATURE_SETFONT_TEXTUAL_MAP
+ // assume textual Unicode console maps:
+ // 0x00 U+0000 # NULL (NUL)
+ // 0x01 U+0001 # START OF HEADING (SOH)
+ // 0x02 U+0002 # START OF TEXT (STX)
+ // 0x03 U+0003 # END OF TEXT (ETX)
+ else {
+ int i;
+ char *token[2];
+ parser_t *parser;
+
+ if (ENABLE_FEATURE_CLEAN_UP)
+ free(map);
+ map = xmalloc(E_TABSZ * sizeof(unsigned short));
+
+#define unicodes ((unsigned short *)map)
+ // fill vanilla map
+ for (i = 0; i < E_TABSZ; i++)
+ unicodes[i] = 0xf000 + i;
+
+ parser = config_open(mapfilename);
+ while (config_read(parser, token, 2, 2, "# \t", PARSE_NORMAL | PARSE_MIN_DIE)) {
+ // parse code/value pair
+ int a = ctoi(token[0]);
+ int b = ctoi(token[1]);
+ if (a < 0 || a >= E_TABSZ
+ || b < 0 || b > 65535
+ ) {
+ bb_error_msg_and_die("map format");
+ }
+ // patch map
+ unicodes[a] = b;
+ // unicode character is met?
+ if (b > 255)
+ mode = PIO_UNISCRNMAP;
+ }
+ if (ENABLE_FEATURE_CLEAN_UP)
+ config_close(parser);
+
+ if (mode != PIO_UNISCRNMAP) {
+#define asciis ((unsigned char *)map)
+ for (i = 0; i < E_TABSZ; i++)
+ asciis[i] = unicodes[i];
+#undef asciis
+ }
+#undef unicodes
+ }
+#endif // ENABLE_FEATURE_SETFONT_TEXTUAL_MAP
+
+ // do set screen map
+ xioctl(fd, mode, map);
+
+ if (ENABLE_FEATURE_CLEAN_UP)
+ free(map);
}
return EXIT_SUCCESS;
diff --git a/release/src/router/busybox/console-tools/loadkmap.c b/release/src/router/busybox/console-tools/loadkmap.c
index 56948e0d05..ac2c0a6e00 100644
--- a/release/src/router/busybox/console-tools/loadkmap.c
+++ b/release/src/router/busybox/console-tools/loadkmap.c
@@ -5,9 +5,7 @@
* Copyright (C) 1998 Enrique Zanardi
*
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
- *
*/
-
#include "libbb.h"
#define BINARY_KEYMAP_MAGIC "bkeymap"
@@ -31,11 +29,15 @@ int loadkmap_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
struct kbentry ke;
int i, j, fd;
uint16_t ibuff[NR_KEYS];
+/* const char *tty_name = CURRENT_TTY; */
RESERVE_CONFIG_BUFFER(flags,MAX_NR_KEYMAPS);
-/* bb_warn_ignoring_args(argc>=2);*/
-
+/* bb_warn_ignoring_args(argc >= 2); */
fd = get_console_fd_or_die();
+/* or maybe:
+ opt = getopt32(argv, "C:", &tty_name);
+ fd = xopen(tty_name, O_NONBLOCK);
+*/
xread(STDIN_FILENO, flags, 7);
if (strncmp(flags, BINARY_KEYMAP_MAGIC, 7))
diff --git a/release/src/router/busybox/console-tools/resize.c b/release/src/router/busybox/console-tools/resize.c
index ea7fe5fcac..4504cc85d6 100644
--- a/release/src/router/busybox/console-tools/resize.c
+++ b/release/src/router/busybox/console-tools/resize.c
@@ -2,7 +2,7 @@
/*
* resize - set terminal width and height.
*
- * Copyright 2006 Bernhard Fischer
+ * Copyright 2006 Bernhard Reutner-Fischer
*
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
diff --git a/release/src/router/busybox/console-tools/setconsole.c b/release/src/router/busybox/console-tools/setconsole.c
index b685937ae1..8ad9948dd5 100644
--- a/release/src/router/busybox/console-tools/setconsole.c
+++ b/release/src/router/busybox/console-tools/setconsole.c
@@ -3,7 +3,7 @@
* setconsole.c - redirect system console output
*
* Copyright (C) 2004,2005 Enrik Berkhan
- * Copyright (C) 2008 Bernhard Fischer
+ * Copyright (C) 2008 Bernhard Reutner-Fischer
*
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
diff --git a/release/src/router/busybox/console-tools/showkey.c b/release/src/router/busybox/console-tools/showkey.c
index 95db6e16eb..681114df79 100644
--- a/release/src/router/busybox/console-tools/showkey.c
+++ b/release/src/router/busybox/console-tools/showkey.c
@@ -72,9 +72,9 @@ int showkey_main(int argc UNUSED_PARAM, char **argv)
// get keyboard settings
xioctl(STDIN_FILENO, KDGKBMODE, &kbmode);
printf("kb mode was %s\n\nPress any keys. Program terminates %s\n\n",
- kbmode == K_RAW ? "RAW" :
- (kbmode == K_XLATE ? "XLATE" :
- (kbmode == K_MEDIUMRAW ? "MEDIUMRAW" :
+ kbmode == K_RAW ? "RAW" :
+ (kbmode == K_XLATE ? "XLATE" :
+ (kbmode == K_MEDIUMRAW ? "MEDIUMRAW" :
(kbmode == K_UNICODE ? "UNICODE" : "?UNKNOWN?")))
, (option_mask32 & OPT_a) ? "when CTRL+D pressed" : "10s after last keypress"
);
diff --git a/release/src/router/busybox/coreutils/Config.in b/release/src/router/busybox/coreutils/Config.in
index 413839035a..b047ce5e29 100644
--- a/release/src/router/busybox/coreutils/Config.in
+++ b/release/src/router/busybox/coreutils/Config.in
@@ -136,12 +136,12 @@ config DF
df reports the amount of disk space used and available
on filesystems.
-config FEATURE_DF_INODE
- bool "Enable -i (inode information)"
+config FEATURE_DF_FANCY
+ bool "Enable -a, -i, -B"
default n
depends on DF
help
- This option enables support for df -i.
+ This option enables -a, -i and -B.
config DIRNAME
bool "dirname"
@@ -189,7 +189,7 @@ config ECHO
config FEATURE_FANCY_ECHO
bool "Enable echo options (-n and -e)"
default y
- depends on ECHO
+ depends on ECHO || ASH_BUILTIN_ECHO || HUSH
help
This adds options (-n and -e) to echo.
@@ -509,6 +509,18 @@ config SHA1SUM
help
Compute and check SHA1 message digest
+config SHA256SUM
+ bool "sha256sum"
+ default n
+ help
+ Compute and check SHA256 message digest
+
+config SHA512SUM
+ bool "sha512sum"
+ default n
+ help
+ Compute and check SHA512 message digest
+
config SLEEP
bool "sleep"
default n
@@ -649,7 +661,7 @@ config TEST
config FEATURE_TEST_64
bool "Extend test to 64 bit"
default n
- depends on TEST
+ depends on TEST || ASH_BUILTIN_TEST
help
Enable 64-bit support in test.
@@ -754,7 +766,7 @@ config FEATURE_WC_LARGE
default n
depends on WC
help
- Use "unsigned long long" in wc for count variables.
+ Use "unsigned long long" in wc for counter variables.
config WHO
bool "who"
diff --git a/release/src/router/busybox/coreutils/Kbuild b/release/src/router/busybox/coreutils/Kbuild
index a5a2d4c26f..57100a9cf0 100644
--- a/release/src/router/busybox/coreutils/Kbuild
+++ b/release/src/router/busybox/coreutils/Kbuild
@@ -44,6 +44,7 @@ lib-$(CONFIG_LENGTH) += length.o
lib-$(CONFIG_LN) += ln.o
lib-$(CONFIG_LOGNAME) += logname.o
lib-$(CONFIG_LS) += ls.o
+lib-$(CONFIG_FTPD) += ls.o
lib-$(CONFIG_MD5SUM) += md5_sha1_sum.o
lib-$(CONFIG_MKDIR) += mkdir.o
lib-$(CONFIG_MKFIFO) += mkfifo.o
@@ -62,6 +63,8 @@ lib-$(CONFIG_RM) += rm.o
lib-$(CONFIG_RMDIR) += rmdir.o
lib-$(CONFIG_SEQ) += seq.o
lib-$(CONFIG_SHA1SUM) += md5_sha1_sum.o
+lib-$(CONFIG_SHA256SUM) += md5_sha1_sum.o
+lib-$(CONFIG_SHA512SUM) += md5_sha1_sum.o
lib-$(CONFIG_SLEEP) += sleep.o
lib-$(CONFIG_SPLIT) += split.o
lib-$(CONFIG_SORT) += sort.o
diff --git a/release/src/router/busybox/coreutils/basename.c b/release/src/router/busybox/coreutils/basename.c
index 8a05e92e5f..8a5597e65d 100644
--- a/release/src/router/busybox/coreutils/basename.c
+++ b/release/src/router/busybox/coreutils/basename.c
@@ -48,5 +48,6 @@ int basename_main(int argc, char **argv)
/* puts(s) will do, but we can do without stdio this way: */
s[m++] = '\n';
+ /* NB: != is correct here: */
return full_write(STDOUT_FILENO, s, m) != (ssize_t)m;
}
diff --git a/release/src/router/busybox/coreutils/cksum.c b/release/src/router/busybox/coreutils/cksum.c
index 598718486a..3a77c753ac 100644
--- a/release/src/router/busybox/coreutils/cksum.c
+++ b/release/src/router/busybox/coreutils/cksum.c
@@ -13,8 +13,9 @@ int cksum_main(int argc UNUSED_PARAM, char **argv)
{
uint32_t *crc32_table = crc32_filltable(NULL, 1);
uint32_t crc;
- long length, filesize;
+ off_t length, filesize;
int bytes_read;
+ int exit_code = EXIT_SUCCESS;
uint8_t *cp;
#if ENABLE_DESKTOP
@@ -27,8 +28,10 @@ int cksum_main(int argc UNUSED_PARAM, char **argv)
do {
int fd = open_or_warn_stdin(*argv ? *argv : bb_msg_standard_input);
- if (fd < 0)
+ if (fd < 0) {
+ exit_code = EXIT_FAILURE;
continue;
+ }
crc = 0;
length = 0;
@@ -44,13 +47,21 @@ int cksum_main(int argc UNUSED_PARAM, char **argv)
filesize = length;
- for (; length; length >>= 8)
- crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ length) & 0xff];
- crc ^= 0xffffffffL;
+ while (length) {
+ crc = (crc << 8) ^ crc32_table[(uint8_t)(crc >> 24) ^ (uint8_t)length];
+ /* must ensure that shift is unsigned! */
+ if (sizeof(length) <= sizeof(unsigned))
+ length = (unsigned)length >> 8;
+ else if (sizeof(length) <= sizeof(unsigned long))
+ length = (unsigned long)length >> 8;
+ else
+ length = (unsigned long long)length >> 8;
+ }
+ crc = ~crc;
- printf((*argv ? "%" PRIu32 " %li %s\n" : "%" PRIu32 " %li\n"),
+ printf((*argv ? "%"PRIu32" %"OFF_FMT"i %s\n" : "%"PRIu32" %"OFF_FMT"i\n"),
crc, filesize, *argv);
} while (*argv && *++argv);
- fflush_stdout_and_exit(EXIT_SUCCESS);
+ fflush_stdout_and_exit(exit_code);
}
diff --git a/release/src/router/busybox/coreutils/cp.c b/release/src/router/busybox/coreutils/cp.c
index 40d3625b32..71a29396f8 100644
--- a/release/src/router/busybox/coreutils/cp.c
+++ b/release/src/router/busybox/coreutils/cp.c
@@ -46,7 +46,55 @@ int cp_main(int argc, char **argv)
// -R (and therefore -r) turns on -d (coreutils does this)
// -a = -pdR
opt_complementary = "-2:l--s:s--l:Pd:rRd:Rd:apdR:HL";
- flags = getopt32(argv, FILEUTILS_CP_OPTSTR "arPH");
+ // -v (--verbose) is ignored
+ flags = getopt32(argv, FILEUTILS_CP_OPTSTR "arPHv");
+ /* Options of cp from GNU coreutils 6.10:
+ * -a, --archive
+ * -f, --force
+ * -i, --interactive
+ * -l, --link
+ * -L, --dereference
+ * -P, --no-dereference
+ * -R, -r, --recursive
+ * -s, --symbolic-link
+ * -v, --verbose
+ * -H follow command-line symbolic links in SOURCE
+ * -d same as --no-dereference --preserve=links
+ * -p same as --preserve=mode,ownership,timestamps
+ * -c same as --preserve=context
+ * NOT SUPPORTED IN BBOX:
+ * long options are not supported (even those above).
+ * --backup[=CONTROL]
+ * make a backup of each existing destination file
+ * -b like --backup but does not accept an argument
+ * --copy-contents
+ * copy contents of special files when recursive
+ * --preserve[=ATTR_LIST]
+ * preserve attributes (default: mode,ownership,timestamps),
+ * if possible additional attributes: security context,links,all
+ * --no-preserve=ATTR_LIST
+ * --parents
+ * use full source file name under DIRECTORY
+ * --remove-destination
+ * remove each existing destination file before attempting to open
+ * --sparse=WHEN
+ * control creation of sparse files
+ * --strip-trailing-slashes
+ * remove any trailing slashes from each SOURCE argument
+ * -S, --suffix=SUFFIX
+ * override the usual backup suffix
+ * -t, --target-directory=DIRECTORY
+ * copy all SOURCE arguments into DIRECTORY
+ * -T, --no-target-directory
+ * treat DEST as a normal file
+ * -u, --update
+ * copy only when the SOURCE file is newer than the destination
+ * file or when the destination file is missing
+ * -x, --one-file-system
+ * stay on this file system
+ * -Z, --context=CONTEXT
+ * (SELinux) set SELinux security context of copy to CONTEXT
+ */
argc -= optind;
argv += optind;
flags ^= FILEUTILS_DEREFERENCE; /* the sense of this flag was reversed */
diff --git a/release/src/router/busybox/coreutils/cut.c b/release/src/router/busybox/coreutils/cut.c
index 3c9fdbda37..9cc22be16e 100644
--- a/release/src/router/busybox/coreutils/cut.c
+++ b/release/src/router/busybox/coreutils/cut.c
@@ -4,7 +4,7 @@
*
* Copyright (C) 1999,2000,2001 by Lineo, inc.
* Written by Mark Whitley
- * debloated by Bernhard Fischer
+ * debloated by Bernhard Reutner-Fischer
*
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
diff --git a/release/src/router/busybox/coreutils/date.c b/release/src/router/busybox/coreutils/date.c
index 8469190cf4..177b7d0757 100644
--- a/release/src/router/busybox/coreutils/date.c
+++ b/release/src/router/busybox/coreutils/date.c
@@ -5,7 +5,7 @@
* by Matthew Grant
*
* iso-format handling added by Robert Griebl
- * bugfixes and cleanup by Bernhard Fischer
+ * bugfixes and cleanup by Bernhard Reutner-Fischer
*
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
diff --git a/release/src/router/busybox/coreutils/dd.c b/release/src/router/busybox/coreutils/dd.c
index 8a40aa77f8..38dacc71db 100644
--- a/release/src/router/busybox/coreutils/dd.c
+++ b/release/src/router/busybox/coreutils/dd.c
@@ -8,7 +8,6 @@
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
-#include /* For FEATURE_DD_SIGNAL_HANDLING */
#include "libbb.h"
/* This is a NOEXEC applet. Be very careful! */
diff --git a/release/src/router/busybox/coreutils/df.c b/release/src/router/busybox/coreutils/df.c
index 9cb328aa31..dfd6e0b419 100644
--- a/release/src/router/busybox/coreutils/df.c
+++ b/release/src/router/busybox/coreutils/df.c
@@ -8,7 +8,7 @@
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
-/* BB_AUDIT SUSv3 _NOT_ compliant -- options -P and -t missing. Also blocksize. */
+/* BB_AUDIT SUSv3 _NOT_ compliant -- option -t missing. */
/* http://www.opengroup.org/onlinepubs/007904975/utilities/df.html */
/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
@@ -16,6 +16,10 @@
* Size reduction. Removed floating point dependency. Added error checking
* on output. Output stats on 0-sized filesystems if specifically listed on
* the command line. Properly round *-blocks, Used, and Available quantities.
+ *
+ * Aug 28, 2008 Bernhard Reutner-Fischer
+ *
+ * Implement -P and -B; better coreutils compat; cleanup
*/
#include
@@ -34,51 +38,72 @@ int df_main(int argc, char **argv)
{
unsigned long blocks_used;
unsigned blocks_percent_used;
-#if ENABLE_FEATURE_HUMAN_READABLE
- unsigned df_disp_hr = 1024;
-#endif
+ unsigned long df_disp_hr = 1024;
int status = EXIT_SUCCESS;
unsigned opt;
FILE *mount_table;
struct mntent *mount_entry;
struct statfs s;
- /* default display is kilobytes */
- const char *disp_units_hdr = "1k-blocks";
+ static const char ignored_mounts[] ALIGN1 = "rootfs\0";
enum {
- OPT_ALL = (1 << 0),
- OPT_INODE = (ENABLE_FEATURE_HUMAN_READABLE ? (1 << 4) : (1 << 2))
- * ENABLE_FEATURE_DF_INODE
+ OPT_KILO = (1 << 0),
+ OPT_POSIX = (1 << 1),
+ OPT_ALL = (1 << 2) * ENABLE_FEATURE_DF_FANCY,
+ OPT_INODE = (1 << 3) * ENABLE_FEATURE_DF_FANCY,
+ OPT_BSIZE = (1 << 4) * ENABLE_FEATURE_DF_FANCY,
+ OPT_HUMAN = (1 << (2 + 3*ENABLE_FEATURE_DF_FANCY)) * ENABLE_FEATURE_HUMAN_READABLE,
+ OPT_MEGA = (1 << (3 + 3*ENABLE_FEATURE_DF_FANCY)) * ENABLE_FEATURE_HUMAN_READABLE,
};
+ const char *disp_units_hdr = NULL;
+ char *chp;
-#if ENABLE_FEATURE_HUMAN_READABLE
- opt_complementary = "h-km:k-hm:m-hk";
- opt = getopt32(argv, "ahmk" USE_FEATURE_DF_INODE("i"));
- if (opt & (1 << 1)) { // -h
+#if ENABLE_FEATURE_HUMAN_READABLE && ENABLE_FEATURE_DF_FANCY
+ opt_complementary = "k-mB:m-Bk:B-km";
+#elif ENABLE_FEATURE_HUMAN_READABLE
+ opt_complementary = "k-m:m-k";
+#endif
+ opt = getopt32(argv, "kP"
+ USE_FEATURE_DF_FANCY("aiB:")
+ USE_FEATURE_HUMAN_READABLE("hm")
+ USE_FEATURE_DF_FANCY(, &chp));
+ if (opt & OPT_MEGA)
+ df_disp_hr = 1024*1024;
+
+ if (opt & OPT_BSIZE)
+ df_disp_hr = xatoul_range(chp, 1, ULONG_MAX); /* disallow 0 */
+
+ /* From the manpage of df from coreutils-6.10:
+ Disk space is shown in 1K blocks by default, unless the environment
+ variable POSIXLY_CORRECT is set, in which case 512-byte blocks are used.
+ */
+ if (getenv("POSIXLY_CORRECT")) /* TODO - a new libbb function? */
+ df_disp_hr = 512;
+
+ if (opt & OPT_HUMAN) {
df_disp_hr = 0;
disp_units_hdr = " Size";
}
- if (opt & (1 << 2)) { // -m
- df_disp_hr = 1024*1024;
- disp_units_hdr = "1M-blocks";
- }
- if (opt & OPT_INODE) {
+ if (opt & OPT_INODE)
disp_units_hdr = " Inodes";
- }
+
+ if (disp_units_hdr == NULL) {
+#if ENABLE_FEATURE_HUMAN_READABLE
+ disp_units_hdr = xasprintf("%s-blocks",
+ make_human_readable_str(df_disp_hr, 0, !!(opt & OPT_POSIX)));
#else
- opt = getopt32(argv, "ak" USE_FEATURE_DF_INODE("i"));
+ disp_units_hdr = xasprintf("%lu-blocks", df_disp_hr);
#endif
-
- printf("Filesystem %-15sUsed Available Use%% Mounted on\n",
- disp_units_hdr);
+ }
+ printf("Filesystem %-15sUsed Available %s Mounted on\n",
+ disp_units_hdr, (opt & OPT_POSIX) ? "Capacity" : "Use%");
mount_table = NULL;
argv += optind;
if (optind >= argc) {
mount_table = setmntent(bb_path_mtab_file, "r");
- if (!mount_table) {
+ if (!mount_table)
bb_perror_msg_and_die(bb_path_mtab_file);
- }
}
while (1) {
@@ -93,13 +118,12 @@ int df_main(int argc, char **argv)
}
} else {
mount_point = *argv++;
- if (!mount_point) {
+ if (!mount_point)
break;
- }
mount_entry = find_mount_point(mount_point, bb_path_mtab_file);
if (!mount_entry) {
bb_error_msg("%s: can't find mount point", mount_point);
- SET_ERROR:
+ set_error:
status = EXIT_FAILURE;
continue;
}
@@ -110,7 +134,7 @@ int df_main(int argc, char **argv)
if (statfs(mount_point, &s) != 0) {
bb_simple_perror_msg(mount_point);
- goto SET_ERROR;
+ goto set_error;
}
if ((s.f_blocks > 0) || !mount_table || (opt & OPT_ALL)) {
@@ -118,10 +142,9 @@ int df_main(int argc, char **argv)
s.f_blocks = s.f_files;
s.f_bavail = s.f_bfree = s.f_ffree;
s.f_bsize = 1;
-#if ENABLE_FEATURE_HUMAN_READABLE
+
if (df_disp_hr)
df_disp_hr = 1;
-#endif
}
blocks_used = s.f_blocks - s.f_bfree;
blocks_percent_used = 0;
@@ -131,11 +154,10 @@ int df_main(int argc, char **argv)
) / (blocks_used + s.f_bavail);
}
-#ifdef WHY_IT_SHOULD_BE_HIDDEN
- if (strcmp(device, "rootfs") == 0) {
+ /* GNU coreutils 6.10 skip certain mounts, try to be compatible. */
+ if (index_in_strings(device, ignored_mounts) != -1)
continue;
- }
-#endif
+
#ifdef WHY_WE_DO_IT_FOR_DEV_ROOT_ONLY
/* ... and also this is the only user of find_block_device */
if (strcmp(device, "/dev/root") == 0) {
@@ -143,7 +165,7 @@ int df_main(int argc, char **argv)
* or leaves device alone if it can't find it */
device = find_block_device("/");
if (!device) {
- goto SET_ERROR;
+ goto set_error;
}
}
#endif
@@ -164,12 +186,12 @@ int df_main(int argc, char **argv)
#else
printf(" %9lu %9lu %9lu %3u%% %s\n",
kscale(s.f_blocks, s.f_bsize),
- kscale(s.f_blocks-s.f_bfree, s.f_bsize),
+ kscale(s.f_blocks - s.f_bfree, s.f_bsize),
kscale(s.f_bavail, s.f_bsize),
blocks_percent_used, mount_point);
#endif
}
}
- fflush_stdout_and_exit(status);
+ return status;
}
diff --git a/release/src/router/busybox/coreutils/du.c b/release/src/router/busybox/coreutils/du.c
index efc9bb9fa0..16c7732435 100644
--- a/release/src/router/busybox/coreutils/du.c
+++ b/release/src/router/busybox/coreutils/du.c
@@ -25,19 +25,28 @@
#include "libbb.h"
+enum {
+ OPT_a_files_too = (1 << 0),
+ OPT_H_follow_links = (1 << 1),
+ OPT_k_kbytes = (1 << 2),
+ OPT_L_follow_links = (1 << 3),
+ OPT_s_total_norecurse = (1 << 4),
+ OPT_x_one_FS = (1 << 5),
+ OPT_d_maxdepth = (1 << 6),
+ OPT_l_hardlinks = (1 << 7),
+ OPT_c_total = (1 << 8),
+ OPT_h_for_humans = (1 << 9),
+ OPT_m_mbytes = (1 << 10),
+};
+
struct globals {
#if ENABLE_FEATURE_HUMAN_READABLE
unsigned long disp_hr;
#else
unsigned disp_k;
#endif
-
int max_print_depth;
- nlink_t count_hardlinks;
-
bool status;
- bool one_file_system;
- int print_files;
int slink_depth;
int du_depth;
dev_t dir_dev;
@@ -72,7 +81,7 @@ static unsigned long du(const char *filename)
return 0;
}
- if (G.one_file_system) {
+ if (option_mask32 & OPT_x_one_FS) {
if (G.du_depth == 0) {
G.dir_dev = statbuf.st_dev;
} else if (G.dir_dev != statbuf.st_dev) {
@@ -83,7 +92,7 @@ static unsigned long du(const char *filename)
sum = statbuf.st_blocks;
if (S_ISLNK(statbuf.st_mode)) {
- if (G.slink_depth > G.du_depth) { /* -H or -L */
+ if (G.slink_depth > G.du_depth) { /* -H or -L */
if (stat(filename, &statbuf) != 0) {
bb_simple_perror_msg(filename);
G.status = EXIT_FAILURE;
@@ -91,12 +100,15 @@ static unsigned long du(const char *filename)
}
sum = statbuf.st_blocks;
if (G.slink_depth == 1) {
- G.slink_depth = INT_MAX; /* Convert -H to -L. */
+ /* Convert -H to -L */
+ G.slink_depth = INT_MAX;
}
}
}
- if (statbuf.st_nlink > G.count_hardlinks) {
+ if (!(option_mask32 & OPT_l_hardlinks)
+ && statbuf.st_nlink > 1
+ ) {
/* Add files/directories with links only once */
if (is_in_ino_dev_hashtable(&statbuf)) {
return 0;
@@ -115,14 +127,8 @@ static unsigned long du(const char *filename)
return sum;
}
- newfile = last_char_is(filename, '/');
- if (newfile)
- *newfile = '\0';
-
while ((entry = readdir(dir))) {
- char *name = entry->d_name;
-
- newfile = concat_subpath_file(filename, name);
+ newfile = concat_subpath_file(filename, entry->d_name);
if (newfile == NULL)
continue;
++G.du_depth;
@@ -131,8 +137,9 @@ static unsigned long du(const char *filename)
free(newfile);
}
closedir(dir);
- } else if (G.du_depth > G.print_files) {
- return sum;
+ } else {
+ if (!(option_mask32 & OPT_a_files_too) && G.du_depth != 0)
+ return sum;
}
if (G.du_depth <= G.max_print_depth) {
print(sum, filename);
@@ -145,7 +152,6 @@ int du_main(int argc UNUSED_PARAM, char **argv)
{
unsigned long total;
int slink_depth_save;
- bool print_final_total;
unsigned opt;
#if ENABLE_FEATURE_HUMAN_READABLE
@@ -158,7 +164,6 @@ int du_main(int argc UNUSED_PARAM, char **argv)
/* SKIP_FEATURE_DU_DEFAULT_BLOCKSIZE_1K(G.disp_k = 0;) - G is pre-zeroed */
#endif
G.max_print_depth = INT_MAX;
- G.count_hardlinks = 1;
/* Note: SUSv3 specifies that -a and -s options cannot be used together
* in strictly conforming applications. However, it also says that some
@@ -170,16 +175,13 @@ int du_main(int argc UNUSED_PARAM, char **argv)
opt_complementary = "h-km:k-hm:m-hk:H-L:L-H:s-d:d-s:d+";
opt = getopt32(argv, "aHkLsx" "d:" "lc" "hm", &G.max_print_depth);
argv += optind;
- if (opt & (1 << 9)) {
- /* -h opt */
+ if (opt & OPT_h_for_humans) {
G.disp_hr = 0;
}
- if (opt & (1 << 10)) {
- /* -m opt */
+ if (opt & OPT_m_mbytes) {
G.disp_hr = 1024*1024;
}
- if (opt & (1 << 2)) {
- /* -k opt */
+ if (opt & OPT_k_kbytes) {
G.disp_hr = 1024;
}
#else
@@ -187,34 +189,20 @@ int du_main(int argc UNUSED_PARAM, char **argv)
opt = getopt32(argv, "aHkLsx" "d:" "lc", &G.max_print_depth);
argv += optind;
#if !ENABLE_FEATURE_DU_DEFAULT_BLOCKSIZE_1K
- if (opt & (1 << 2)) {
- /* -k opt */
+ if (opt & OPT_k_kbytes) {
G.disp_k = 1;
}
#endif
#endif
- if (opt & (1 << 0)) {
- /* -a opt */
- G.print_files = INT_MAX;
- }
- if (opt & (1 << 1)) {
- /* -H opt */
+ if (opt & OPT_H_follow_links) {
G.slink_depth = 1;
}
- if (opt & (1 << 3)) {
- /* -L opt */
+ if (opt & OPT_L_follow_links) {
G.slink_depth = INT_MAX;
}
- if (opt & (1 << 4)) {
- /* -s opt */
+ if (opt & OPT_s_total_norecurse) {
G.max_print_depth = 0;
}
- G.one_file_system = opt & (1 << 5); /* -x opt */
- if (opt & (1 << 7)) {
- /* -l opt */
- G.count_hardlinks = MAXINT(nlink_t);
- }
- print_final_total = opt & (1 << 8); /* -c opt */
/* go through remaining args (if any) */
if (!*argv) {
@@ -228,12 +216,12 @@ int du_main(int argc UNUSED_PARAM, char **argv)
total = 0;
do {
total += du(*argv);
+ /* otherwise du /dir /dir won't show /dir twice: */
+ reset_ino_dev_hashtable();
G.slink_depth = slink_depth_save;
} while (*++argv);
- if (ENABLE_FEATURE_CLEAN_UP)
- reset_ino_dev_hashtable();
- if (print_final_total)
+ if (opt & OPT_c_total)
print(total, "total");
fflush_stdout_and_exit(G.status);
diff --git a/release/src/router/busybox/coreutils/env.c b/release/src/router/busybox/coreutils/env.c
index 2f8c8b71d0..f50a03e8b6 100644
--- a/release/src/router/busybox/coreutils/env.c
+++ b/release/src/router/busybox/coreutils/env.c
@@ -43,8 +43,6 @@ static const char env_longopts[] ALIGN1 =
int env_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int env_main(int argc UNUSED_PARAM, char **argv)
{
- /* cleanenv was static - why? */
- char *cleanenv[1];
char **ep;
unsigned opt;
llist_t *unset_env = NULL;
@@ -60,12 +58,16 @@ int env_main(int argc UNUSED_PARAM, char **argv)
++argv;
}
if (opt & 1) {
- cleanenv[0] = NULL;
- environ = cleanenv;
- } else {
- while (unset_env) {
- unsetenv(llist_pop(&unset_env));
- }
+ clearenv();
+ }
+ while (unset_env) {
+ char *var = llist_pop(&unset_env);
+ /* This does not handle -uVAR=VAL
+ * (coreutils _sets_ the variable in that case): */
+ /*unsetenv(var);*/
+ /* This does, but uses somewhan undocumented feature that
+ * putenv("name_without_equal_sign") unsets the variable: */
+ putenv(var);
}
while (*argv && (strchr(*argv, '=') != NULL)) {
diff --git a/release/src/router/busybox/coreutils/expand.c b/release/src/router/busybox/coreutils/expand.c
index ee51c032fa..0967e25346 100644
--- a/release/src/router/busybox/coreutils/expand.c
+++ b/release/src/router/busybox/coreutils/expand.c
@@ -29,98 +29,78 @@ enum {
OPT_ALL = 1 << 2,
};
-static void xputchar(char c)
-{
- if (putchar(c) < 0)
- bb_error_msg_and_die(bb_msg_write_error);
-}
-
#if ENABLE_EXPAND
-static void expand(FILE *file, unsigned tab_size, unsigned opt)
+static void expand(FILE *file, int tab_size, unsigned opt)
{
char *line;
- char *ptr;
- int convert;
- unsigned pos;
- /* Increment tab_size by 1 locally.*/
- tab_size++;
+ tab_size = -tab_size;
while ((line = xmalloc_fgets(file)) != NULL) {
- convert = 1;
- pos = 0;
- ptr = line;
- while (*line) {
- pos++;
- if (*line == '\t' && convert) {
- for (; pos < tab_size; pos++) {
- xputchar(' ');
- }
- } else {
- if ((opt & OPT_INITIAL) && !isblank(*line)) {
- convert = 0;
- }
- xputchar(*line);
+ int pos;
+ unsigned char c;
+ char *ptr = line;
+
+ goto start;
+ while ((c = *ptr) != '\0') {
+ if ((opt & OPT_INITIAL) && !isblank(c)) {
+ fputs(ptr, stdout);
+ break;
}
- if (pos == tab_size) {
- pos = 0;
+ ptr++;
+ if (c == '\t') {
+ c = ' ';
+ while (++pos < 0)
+ bb_putchar(c);
+ }
+ bb_putchar(c);
+ if (++pos >= 0) {
+ start:
+ pos = tab_size;
}
- line++;
}
- free(ptr);
+ free(line);
}
}
#endif
#if ENABLE_UNEXPAND
-static void unexpand(FILE *file, unsigned int tab_size, unsigned opt)
+static void unexpand(FILE *file, unsigned tab_size, unsigned opt)
{
char *line;
- char *ptr;
- int convert;
- int pos;
- int i = 0;
- unsigned column = 0;
while ((line = xmalloc_fgets(file)) != NULL) {
- convert = 1;
- pos = 0;
- ptr = line;
- while (*line) {
- while ((*line == ' ' || *line == '\t') && convert) {
- pos += (*line == ' ') ? 1 : tab_size;
- line++;
+ char *ptr = line;
+ unsigned column = 0;
+
+ while (*ptr) {
+ unsigned n;
+
+ while (*ptr == ' ') {
column++;
- if ((opt & OPT_ALL) && column == tab_size) {
- column = 0;
- goto put_tab;
- }
+ ptr++;
+ }
+ if (*ptr == '\t') {
+ column += tab_size - (column % tab_size);
+ ptr++;
+ continue;
}
- if (pos) {
- i = pos / tab_size;
- if (i) {
- for (; i > 0; i--) {
- put_tab:
- xputchar('\t');
- }
- } else {
- for (i = pos % tab_size; i > 0; i--) {
- xputchar(' ');
- }
- }
- pos = 0;
- } else {
- if (opt & OPT_INITIAL) {
- convert = 0;
- }
- if (opt & OPT_ALL) {
- column++;
- }
- xputchar(*line);
- line++;
+
+ n = column / tab_size;
+ column = column % tab_size;
+ while (n--)
+ putchar('\t');
+
+ if ((opt & OPT_INITIAL) && ptr != line) {
+ printf("%*s%s", column, "", ptr);
+ break;
}
+ n = strcspn(ptr, "\t ");
+ printf("%*s%.*s", column, "", n, ptr);
+ ptr += n;
+ column = (column + n) % tab_size;
}
- free(ptr);
+ free(line);
}
}
#endif
diff --git a/release/src/router/busybox/coreutils/expr.c b/release/src/router/busybox/coreutils/expr.c
index 2f9c5c1e37..54c2ee1655 100644
--- a/release/src/router/busybox/coreutils/expr.c
+++ b/release/src/router/busybox/coreutils/expr.c
@@ -223,13 +223,13 @@ static VALUE *docolon(VALUE *sv, VALUE *pv)
tostring(pv);
if (pv->u.s[0] == '^') {
- bb_error_msg("\
-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);
+ bb_error_msg(
+"warning: '%s': using '^' as the first character\n"
+"of a basic regular expression is not portable; it is ignored", pv->u.s);
}
memset(&re_buffer, 0, sizeof(re_buffer));
- memset(re_regs, 0, sizeof(*re_regs));
+ memset(re_regs, 0, sizeof(re_regs));
xregcomp(&re_buffer, pv->u.s, 0);
/* expr uses an anchored pattern match, so check that there was a
@@ -238,7 +238,7 @@ of a basic regular expression is not portable; it is being ignored", pv->u.s);
&& re_regs[0].rm_so == 0
) {
/* Were \(...\) used? */
- if (re_buffer.re_nsub > 0) {
+ if (re_buffer.re_nsub > 0 && re_regs[1].rm_so >= 0) {
sv->u.s[re_regs[1].rm_eo] = '\0';
v = str_value(sv->u.s + re_regs[1].rm_so);
} else {
@@ -251,7 +251,7 @@ of a basic regular expression is not portable; it is being ignored", pv->u.s);
else
v = int_value(0);
}
-//FIXME: sounds like here is a bit missing: regfree(&re_buffer);
+ regfree(&re_buffer);
return v;
}
@@ -481,24 +481,21 @@ static VALUE *eval(void)
}
int expr_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int expr_main(int argc, char **argv)
+int expr_main(int argc UNUSED_PARAM, char **argv)
{
VALUE *v;
- if (argc == 1) {
+ xfunc_error_retval = 2; /* coreutils compat */
+ G.args = argv + 1;
+ if (*G.args == NULL) {
bb_error_msg_and_die("too few arguments");
}
-
- G.args = argv + 1;
-
v = eval();
if (*G.args)
bb_error_msg_and_die("syntax error");
-
if (v->type == INTEGER)
printf("%" PF_REZ "d\n", PF_REZ_TYPE v->u.i);
else
puts(v->u.s);
-
fflush_stdout_and_exit(null(v));
}
diff --git a/release/src/router/busybox/coreutils/head.c b/release/src/router/busybox/coreutils/head.c
index 570f140b1d..ac476d0919 100644
--- a/release/src/router/busybox/coreutils/head.c
+++ b/release/src/router/busybox/coreutils/head.c
@@ -40,7 +40,6 @@ int head_main(int argc, char **argv)
int count_bytes = 0;
int header_threshhold = 1;
#endif
-
FILE *fp;
const char *fmt;
char *p;
@@ -50,7 +49,7 @@ int head_main(int argc, char **argv)
#if ENABLE_INCLUDE_SUSv2 || ENABLE_FEATURE_FANCY_HEAD
/* Allow legacy syntax of an initial numeric option without -n. */
- if (argc > 1 && argv[1][0] == '-'
+ if (argv[1] && argv[1][0] == '-'
&& isdigit(argv[1][1])
) {
--argc;
@@ -79,7 +78,6 @@ int head_main(int argc, char **argv)
#if ENABLE_INCLUDE_SUSv2 || ENABLE_FEATURE_FANCY_HEAD
GET_COUNT:
#endif
-
#if !ENABLE_FEATURE_FANCY_HEAD
count = xatoul(p);
#else
@@ -128,10 +126,12 @@ int head_main(int argc, char **argv)
putchar(c);
}
if (fclose_if_not_stdin(fp)) {
- bb_simple_perror_msg(*argv); /* Avoid multibyte problems. */
+ bb_simple_perror_msg(*argv);
retval = EXIT_FAILURE;
}
die_if_ferror_stdout();
+ } else {
+ retval = EXIT_FAILURE;
}
fmt = header_fmt_str;
} while (*++argv);
diff --git a/release/src/router/busybox/coreutils/id.c b/release/src/router/busybox/coreutils/id.c
dissimilarity index 76%
index 0fadd98d3e..43f403fa37 100644
--- a/release/src/router/busybox/coreutils/id.c
+++ b/release/src/router/busybox/coreutils/id.c
@@ -1,126 +1,214 @@
-/* vi: set sw=4 ts=4: */
-/*
- * Mini id implementation for busybox
- *
- * Copyright (C) 2000 by Randolph Chung
- *
- * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
- */
-
-/* BB_AUDIT SUSv3 _NOT_ compliant -- option -G is not currently supported. */
-/* Hacked by Tito Ragusa (C) 2004 to handle usernames of whatever length and to
- * be more similar to GNU id.
- * -Z option support: by Yuichi Nakamura
- */
-
-#include "libbb.h"
-
-#define PRINT_REAL 1
-#define NAME_NOT_NUMBER 2
-#define JUST_USER 4
-#define JUST_GROUP 8
-#if ENABLE_SELINUX
-#define JUST_CONTEXT 16
-#endif
-
-static int printf_full(unsigned int id, const char *arg, const char prefix)
-{
- const char *fmt = "%cid=%u";
- int status = EXIT_FAILURE;
-
- if (arg) {
- fmt = "%cid=%u(%s)";
- status = EXIT_SUCCESS;
- }
- printf(fmt, prefix, id, arg);
- return status;
-}
-
-int id_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int id_main(int argc UNUSED_PARAM, char **argv)
-{
- struct passwd *p;
- uid_t uid;
- gid_t gid;
- unsigned long flags;
- short status;
-#if ENABLE_SELINUX
- security_context_t scontext;
-#endif
- /* Don't allow -n -r -nr -ug -rug -nug -rnug */
- /* Don't allow more than one username */
- opt_complementary = "?1:u--g:g--u:r?ug:n?ug" USE_SELINUX(":u--Z:Z--u:g--Z:Z--g");
- flags = getopt32(argv, "rnug" USE_SELINUX("Z"));
-
- /* This values could be overwritten later */
- uid = geteuid();
- gid = getegid();
- if (flags & PRINT_REAL) {
- uid = getuid();
- gid = getgid();
- }
-
- if (argv[optind]) {
- p = getpwnam(argv[optind]);
- /* xuname2uid is needed because it exits on failure */
- uid = xuname2uid(argv[optind]);
- gid = p->pw_gid;
- /* in this case PRINT_REAL is the same */
- }
-
- if (flags & (JUST_GROUP | JUST_USER USE_SELINUX(| JUST_CONTEXT))) {
- /* JUST_GROUP and JUST_USER are mutually exclusive */
- if (flags & NAME_NOT_NUMBER) {
- /* bb_getXXXid(-1) exit on failure, puts cannot segfault */
- puts((flags & JUST_USER) ? bb_getpwuid(NULL, -1, uid) : bb_getgrgid(NULL, -1, gid));
- } else {
- if (flags & JUST_USER) {
- printf("%u\n", uid);
- }
- if (flags & JUST_GROUP) {
- printf("%u\n", gid);
- }
- }
-
-#if ENABLE_SELINUX
- if (flags & JUST_CONTEXT) {
- selinux_or_die();
- if (argc - optind == 1) {
- bb_error_msg_and_die("user name can't be passed with -Z");
- }
-
- if (getcon(&scontext)) {
- bb_error_msg_and_die("can't get process context");
- }
- puts(scontext);
- }
-#endif
- /* exit */
- fflush_stdout_and_exit(EXIT_SUCCESS);
- }
-
- /* Print full info like GNU id */
- /* bb_getpwuid(0) doesn't exit on failure (returns NULL) */
- status = printf_full(uid, bb_getpwuid(NULL, 0, uid), 'u');
- bb_putchar(' ');
- status |= printf_full(gid, bb_getgrgid(NULL, 0, gid), 'g');
-
-#if ENABLE_SELINUX
- if (is_selinux_enabled()) {
- security_context_t mysid;
- const char *context;
-
- context = "unknown";
- getcon(&mysid);
- if (mysid) {
- context = alloca(strlen(mysid) + 1);
- strcpy((char*)context, mysid);
- freecon(mysid);
- }
- printf(" context=%s", context);
- }
-#endif
-
- bb_putchar('\n');
- fflush_stdout_and_exit(status);
-}
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini id implementation for busybox
+ *
+ * Copyright (C) 2000 by Randolph Chung
+ * Copyright (C) 2008 by Tito Ragusa
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+/* BB_AUDIT SUSv3 compliant. */
+/* Hacked by Tito Ragusa (C) 2004 to handle usernames of whatever
+ * length and to be more similar to GNU id.
+ * -Z option support: by Yuichi Nakamura
+ * Added -G option Tito Ragusa (C) 2008 for SUSv3.
+ */
+
+#include "libbb.h"
+
+#if !ENABLE_USE_BB_PWD_GRP
+#if defined(__UCLIBC_MAJOR__) && (__UCLIBC_MAJOR__ == 0)
+#if (__UCLIBC_MINOR__ < 9) || (__UCLIBC_MINOR__ == 9 && __UCLIBC_SUBLEVEL__ < 30)
+#error "Sorry, you need at least uClibc version 0.9.30 for id applet to build"
+#endif
+#endif
+#endif
+
+enum {
+ PRINT_REAL = (1 << 0),
+ NAME_NOT_NUMBER = (1 << 1),
+ JUST_USER = (1 << 2),
+ JUST_GROUP = (1 << 3),
+ JUST_ALL_GROUPS = (1 << 4),
+#if ENABLE_SELINUX
+ JUST_CONTEXT = (1 << 5),
+#endif
+};
+
+static int print_common(unsigned id, const char *name, const char *prefix)
+{
+ if (prefix) {
+ printf("%s", prefix);
+ }
+ if (!(option_mask32 & NAME_NOT_NUMBER) || !name) {
+ printf("%u", id);
+ }
+ if (!option_mask32 || (option_mask32 & NAME_NOT_NUMBER)) {
+ if (name) {
+ printf(option_mask32 ? "%s" : "(%s)", name);
+ } else {
+ /* Don't set error status flag in default mode */
+ if (option_mask32) {
+ if (ENABLE_DESKTOP)
+ bb_error_msg("unknown ID %u", id);
+ return EXIT_FAILURE;
+ }
+ }
+ }
+ return EXIT_SUCCESS;
+}
+
+static int print_group(gid_t id, const char *prefix)
+{
+ return print_common(id, gid2group(id), prefix);
+}
+
+static int print_user(uid_t id, const char *prefix)
+{
+ return print_common(id, uid2uname(id), prefix);
+}
+
+/* On error set *n < 0 and return >= 0
+ * If *n is too small, update it and return < 0
+ * (ok to trash groups[] in both cases)
+ * Otherwise fill in groups[] and return >= 0
+ */
+static int get_groups(const char *username, gid_t rgid, gid_t *groups, int *n)
+{
+ int m;
+
+ if (username) {
+ /* If the user is a member of more than
+ * *n groups, then -1 is returned. Otherwise >= 0.
+ * (and no defined way of detecting errors?!) */
+ m = getgrouplist(username, rgid, groups, n);
+ /* I guess *n < 0 might indicate error. Anyway,
+ * malloc'ing -1 bytes won't be good, so: */
+ //if (*n < 0)
+ // return 0;
+ //return m;
+ //commented out here, happens below anyway
+ } else {
+ /* On error -1 is returned, which ends up in *n */
+ int nn = getgroups(*n, groups);
+ /* 0: nn <= *n, groups[] was big enough; -1 otherwise */
+ m = - (nn > *n);
+ *n = nn;
+ }
+ if (*n < 0)
+ return 0; /* error, don't return < 0! */
+ return m;
+}
+
+int id_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int id_main(int argc UNUSED_PARAM, char **argv)
+{
+ uid_t ruid;
+ gid_t rgid;
+ uid_t euid;
+ gid_t egid;
+ unsigned opt;
+ int i;
+ int status = EXIT_SUCCESS;
+ const char *prefix;
+ const char *username;
+#if ENABLE_SELINUX
+ security_context_t scontext = NULL;
+#endif
+ /* Don't allow -n -r -nr -ug -rug -nug -rnug -uZ -gZ -GZ*/
+ /* Don't allow more than one username */
+ opt_complementary = "?1:u--g:g--u:G--u:u--G:g--G:G--g:r?ugG:n?ugG"
+ USE_SELINUX(":u--Z:Z--u:g--Z:Z--g:G--Z:Z--G");
+ opt = getopt32(argv, "rnugG" USE_SELINUX("Z"));
+
+ username = argv[optind];
+ if (username) {
+ struct passwd *p = xgetpwnam(username);
+ euid = ruid = p->pw_uid;
+ egid = rgid = p->pw_gid;
+ } else {
+ egid = getegid();
+ rgid = getgid();
+ euid = geteuid();
+ ruid = getuid();
+ }
+ /* JUST_ALL_GROUPS ignores -r PRINT_REAL flag even if man page for */
+ /* id says: print the real ID instead of the effective ID, with -ugG */
+ /* in fact in this case egid is always printed if egid != rgid */
+ if (!opt || (opt & JUST_ALL_GROUPS)) {
+ gid_t *groups;
+ int n;
+
+ if (!opt) {
+ /* Default Mode */
+ status |= print_user(ruid, "uid=");
+ status |= print_group(rgid, " gid=");
+ if (euid != ruid)
+ status |= print_user(euid, " euid=");
+ if (egid != rgid)
+ status |= print_group(egid, " egid=");
+ } else {
+ /* JUST_ALL_GROUPS */
+ status |= print_group(rgid, NULL);
+ if (egid != rgid)
+ status |= print_group(egid, " ");
+ }
+ /* We are supplying largish buffer, trying
+ * to not run get_groups() twice. That might be slow
+ * ("user database in remote SQL server" case) */
+ groups = xmalloc(64 * sizeof(gid_t));
+ n = 64;
+ if (get_groups(username, rgid, groups, &n) < 0) {
+ /* Need bigger buffer after all */
+ groups = xrealloc(groups, n * sizeof(gid_t));
+ get_groups(username, rgid, groups, &n);
+ }
+ if (n > 0) {
+ /* Print the list */
+ prefix = " groups=";
+ for (i = 0; i < n; i++) {
+ if (opt && (groups[i] == rgid || groups[i] == egid))
+ continue;
+ status |= print_group(groups[i], opt ? " " : prefix);
+ prefix = ",";
+ }
+ } else if (n < 0) { /* error in get_groups() */
+ if (!ENABLE_DESKTOP)
+ bb_error_msg_and_die("cannot get groups");
+ else
+ return EXIT_FAILURE;
+ }
+ if (ENABLE_FEATURE_CLEAN_UP)
+ free(groups);
+#if ENABLE_SELINUX
+ if (is_selinux_enabled()) {
+ if (getcon(&scontext) == 0)
+ printf(" context=%s", scontext);
+ }
+#endif
+ } else if (opt & PRINT_REAL) {
+ euid = ruid;
+ egid = rgid;
+ }
+
+ if (opt & JUST_USER)
+ status |= print_user(euid, NULL);
+ else if (opt & JUST_GROUP)
+ status |= print_group(egid, NULL);
+#if ENABLE_SELINUX
+ else if (opt & JUST_CONTEXT) {
+ selinux_or_die();
+ if (username || getcon(&scontext)) {
+ bb_error_msg_and_die("can't get process context%s",
+ username ? " for a different user" : "");
+ }
+ fputs(scontext, stdout);
+ }
+ /* freecon(NULL) seems to be harmless */
+ if (ENABLE_FEATURE_CLEAN_UP)
+ freecon(scontext);
+#endif
+ bb_putchar('\n');
+ fflush_stdout_and_exit(status);
+}
diff --git a/release/src/router/busybox/coreutils/id_test.sh b/release/src/router/busybox/coreutils/id_test.sh
new file mode 100644
index 0000000000..0d65f2ae31
--- /dev/null
+++ b/release/src/router/busybox/coreutils/id_test.sh
@@ -0,0 +1,244 @@
+#!/bin/bash
+# Test script for busybox id vs. coreutils id.
+# Needs root privileges for some tests.
+
+cp /usr/bin/id .
+BUSYBOX=./busybox
+ID=./id
+LIST=`awk -F: '{ printf "%s\n", $1 }' /etc/passwd`
+FLAG_USER_EXISTS="no"
+TEST_USER="f583ca884c1d93458fb61ed137ff44f6"
+
+echo "test 1: id [options] nousername"
+rm -f foo bar
+for OPTIONS in "" "-u" "-un" "-unr" "-g" "-gn" "-gnr" "-G" "-Gn" "-Gnr"
+do
+ #echo "$OPTIONS"
+ $BUSYBOX id $OPTIONS >foo 2>/dev/null
+ RET1=$?
+ $ID $OPTIONS >bar 2>/dev/null
+ RET2=$?
+ if test "$RET1" != "$RET2"; then
+ echo "Return Values differ ($RET1 != $RET2): options $OPTIONS"
+ fi
+ diff foo bar
+done
+
+echo "test 2: id [options] username"
+rm -f foo bar
+for OPTIONS in "" "-u" "-un" "-unr" "-g" "-gn" "-gnr" "-G" "-Gn" "-Gnr"
+do
+ #echo "$OPTIONS"
+ for i in $LIST ; do
+ if test "$i" = "$TEST_USER"; then
+ FLAG_USER_EXISTS="yes"
+ fi
+ $BUSYBOX id $OPTIONS $i >foo 2>/dev/null
+ RET1=$?
+ $ID $OPTIONS $i >bar 2>/dev/null
+ RET2=$?
+ if test "$RET1" != "$RET2"; then
+ echo "Return Values differ ($RET1 != $RET2): options $OPTIONS"
+ fi
+ diff foo bar
+ done
+done
+
+if test $FLAG_USER_EXISTS = "yes"; then
+ echo "test 3,4,5,6,7,8,9,10,11,12 skipped because test user $TEST_USER already exists"
+ rm -f foo bar
+ exit 1
+fi
+
+adduser -s /bin/true -g "" -H -D "$TEST_USER" || exit 1
+
+chown $TEST_USER.$TEST_USER $BUSYBOX
+chmod u+s $BUSYBOX 2>&1 /dev/null
+chown $TEST_USER.$TEST_USER $ID
+chmod u+s $ID 2>&1 /dev/null
+
+echo "test 3 setuid, existing user: id [options] no username"
+rm -f foo bar
+for OPTIONS in "" "-u" "-un" "-unr" "-g" "-gn" "-gnr" "-G" "-Gn" "-Gnr"
+do
+ #echo "$OPTIONS"
+ $BUSYBOX id $OPTIONS >foo 2>/dev/null
+ RET1=$?
+ $ID $OPTIONS >bar 2>/dev/null
+ RET2=$?
+ if test "$RET1" != "$RET2"; then
+ echo "Return Values differ ($RET1 != $RET2): options $OPTIONS"
+ fi
+ diff foo bar
+ #done
+done
+
+echo "test 4 setuid, existing user: id [options] username"
+rm -f foo bar
+for OPTIONS in "" "-u" "-un" "-unr" "-g" "-gn" "-gnr" "-G" "-Gn" "-Gnr"
+do
+ #echo "$OPTIONS"
+ for i in $LIST ; do
+ $BUSYBOX id $OPTIONS $i >foo 2>/dev/null
+ RET1=$?
+ $ID $OPTIONS $i >bar 2>/dev/null
+ RET2=$?
+ if test "$RET1" != "$RET2"; then
+ echo "Return Values differ ($RET1 != $RET2): options $OPTIONS"
+ fi
+ diff foo bar
+ done
+done
+
+chown $TEST_USER.$TEST_USER $BUSYBOX
+chmod g+s $BUSYBOX 2>&1 /dev/null
+chown $TEST_USER.$TEST_USER $ID
+chmod g+s $ID 2>&1 /dev/null
+
+echo "test 5 setgid, existing user: id [options] no username"
+rm -f foo bar
+for OPTIONS in "" "-u" "-un" "-unr" "-g" "-gn" "-gnr" "-G" "-Gn" "-Gnr"
+do
+ #echo "$OPTIONS"
+ $BUSYBOX id $OPTIONS >foo 2>/dev/null
+ RET1=$?
+ $ID $OPTIONS >bar 2>/dev/null
+ RET2=$?
+ if test "$RET1" != "$RET2"; then
+ echo "Return Values differ ($RET1 != $RET2): options $OPTIONS"
+ fi
+ diff foo bar
+ #done
+done
+
+echo "test 6 setgid, existing user: id [options] username"
+rm -f foo bar
+for OPTIONS in "" "-u" "-un" "-unr" "-g" "-gn" "-gnr" "-G" "-Gn" "-Gnr"
+do
+ #echo "$OPTIONS"
+ for i in $LIST ; do
+ $BUSYBOX id $OPTIONS $i >foo 2>/dev/null
+ RET1=$?
+ $ID $OPTIONS $i >bar 2>/dev/null
+ RET2=$?
+ if test "$RET1" != "$RET2"; then
+ echo "Return Values differ ($RET1 != $RET2): options $OPTIONS"
+ fi
+ diff foo bar
+ done
+done
+
+chown $TEST_USER.$TEST_USER $BUSYBOX
+chmod u+s,g+s $BUSYBOX 2>&1 /dev/null
+chown $TEST_USER.$TEST_USER $ID
+chmod u+s,g+s $ID 2>&1 /dev/null
+
+echo "test 7 setuid, setgid, existing user: id [options] no username"
+rm -f foo bar
+for OPTIONS in "" "-u" "-un" "-unr" "-g" "-gn" "-gnr" "-G" "-Gn" "-Gnr"
+do
+ #echo "$OPTIONS"
+ $BUSYBOX id $OPTIONS >foo 2>/dev/null
+ RET1=$?
+ $ID $OPTIONS >bar 2>/dev/null
+ RET2=$?
+ if test "$RET1" != "$RET2"; then
+ echo "Return Values differ ($RET1 != $RET2): options $OPTIONS"
+ fi
+ diff foo bar
+ #done
+done
+
+echo "test 8 setuid, setgid, existing user: id [options] username"
+rm -f foo bar
+for OPTIONS in "" "-u" "-un" "-unr" "-g" "-gn" "-gnr" "-G" "-Gn" "-Gnr"
+do
+ #echo "$OPTIONS"
+ for i in $LIST ; do
+ $BUSYBOX id $OPTIONS $i >foo 2>/dev/null
+ RET1=$?
+ $ID $OPTIONS $i >bar 2>/dev/null
+ RET2=$?
+ if test "$RET1" != "$RET2"; then
+ echo "Return Values differ ($RET1 != $RET2): options $OPTIONS"
+ fi
+ diff foo bar
+ done
+done
+
+deluser $TEST_USER || exit 1
+
+echo "test 9 setuid, setgid, not existing user: id [options] no username"
+rm -f foo bar
+for OPTIONS in "" "-u" "-un" "-unr" "-g" "-gn" "-gnr" "-G" "-Gn" "-Gnr"
+do
+ #echo "$OPTIONS"
+ $BUSYBOX id $OPTIONS >foo 2>/dev/null
+ RET1=$?
+ $ID $OPTIONS >bar 2>/dev/null
+ RET2=$?
+ if test "$RET1" != "$RET2"; then
+ echo "Return Values differ ($RET1 != $RET2): options $OPTIONS"
+ fi
+ diff foo bar
+done
+
+echo "test 10 setuid, setgid, not existing user: id [options] username"
+rm -f foo bar
+for OPTIONS in "" "-u" "-un" "-unr" "-g" "-gn" "-gnr" "-G" "-Gn" "-Gnr"
+do
+ #echo "$OPTIONS"
+ for i in $LIST ; do
+ $BUSYBOX id $OPTIONS $i >foo 2>/dev/null
+ RET1=$?
+ $ID $OPTIONS $i >bar 2>/dev/null
+ RET2=$?
+ if test "$RET1" != "$RET2"; then
+ echo "Return Values differ ($RET1 != $RET2): options $OPTIONS"
+ fi
+ diff foo bar
+ done
+done
+
+chown .root $BUSYBOX 2>&1 /dev/null
+chown .root $ID 2>&1 /dev/null
+chmod g+s $BUSYBOX 2>&1 /dev/null
+chmod g+s $ID 2>&1 /dev/null
+
+echo "test 11 setgid, not existing group: id [options] no username"
+rm -f foo bar
+for OPTIONS in "" "-u" "-un" "-unr" "-g" "-gn" "-gnr" "-G" "-Gn" "-Gnr"
+do
+ #echo "$OPTIONS"
+ $BUSYBOX id $OPTIONS >foo 2>/dev/null
+ RET1=$?
+ $ID $OPTIONS >bar 2>/dev/null
+ RET2=$?
+ if test "$RET1" != "$RET2"; then
+ echo "Return Values differ ($RET1 != $RET2): options $OPTIONS"
+ fi
+ diff foo bar
+ #done
+done
+
+echo "test 12 setgid, not existing group: id [options] username"
+rm -f foo bar
+for OPTIONS in "" "-u" "-un" "-unr" "-g" "-gn" "-gnr" "-G" "-Gn" "-Gnr"
+do
+ #echo "$OPTIONS"
+ for i in $LIST ; do
+ $BUSYBOX id $OPTIONS $i >foo 2>/dev/null
+ RET1=$?
+ $ID $OPTIONS $i >bar 2>/dev/null
+ RET2=$?
+ if test "$RET1" != "$RET2"; then
+ echo "Return Values differ ($RET1 != $RET2): options $OPTIONS"
+ fi
+ diff foo bar
+ done
+done
+
+chown root.root $BUSYBOX 2>&1 /dev/null
+chown root.root $ID 2>&1 /dev/null
+rm -f $ID
+rm -f foo bar
diff --git a/release/src/router/busybox/coreutils/install.c b/release/src/router/busybox/coreutils/install.c
index e99f1a3bd6..2b796e2a17 100644
--- a/release/src/router/busybox/coreutils/install.c
+++ b/release/src/router/busybox/coreutils/install.c
@@ -4,9 +4,6 @@
* SELinux support: by Yuichi Nakamura
*
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
- *
- * TODO: -d option, need a way of recursively making directories and changing
- * owner/group, will probably modify bb_make_directory(...)
*/
#include "libbb.h"
@@ -53,7 +50,8 @@ static void setdefaultfilecon(const char *path)
if (lsetfilecon(path, scontext) < 0) {
if (errno != ENOTSUP) {
- bb_perror_msg("warning: failed to change context of %s to %s", path, scontext);
+ bb_perror_msg("warning: failed to change context"
+ " of %s to %s", path, scontext);
}
}
@@ -75,7 +73,7 @@ int install_main(int argc, char **argv)
const char *uid_str;
const char *mode_str;
int copy_flags = FILEUTILS_DEREFERENCE | FILEUTILS_FORCE;
- int flags;
+ int opts;
int min_args = 1;
int ret = EXIT_SUCCESS;
int isdir = 0;
@@ -87,15 +85,16 @@ int install_main(int argc, char **argv)
OPT_c = 1 << 0,
OPT_v = 1 << 1,
OPT_b = 1 << 2,
- OPT_DIRECTORY = 1 << 3,
- OPT_PRESERVE_TIME = 1 << 4,
- OPT_STRIP = 1 << 5,
- OPT_GROUP = 1 << 6,
- OPT_MODE = 1 << 7,
- OPT_OWNER = 1 << 8,
+ OPT_MKDIR_LEADING = 1 << 3,
+ OPT_DIRECTORY = 1 << 4,
+ OPT_PRESERVE_TIME = 1 << 5,
+ OPT_STRIP = 1 << 6,
+ OPT_GROUP = 1 << 7,
+ OPT_MODE = 1 << 8,
+ OPT_OWNER = 1 << 9,
#if ENABLE_SELINUX
- OPT_SET_SECURITY_CONTEXT = 1 << 9,
- OPT_PRESERVE_SECURITY_CONTEXT = 1 << 10,
+ OPT_SET_SECURITY_CONTEXT = 1 << 10,
+ OPT_PRESERVE_SECURITY_CONTEXT = 1 << 11,
#endif
};
@@ -106,37 +105,38 @@ int install_main(int argc, char **argv)
/* -c exists for backwards compatibility, it's needed */
/* -v is ignored ("print name of each created directory") */
/* -b is ignored ("make a backup of each existing destination file") */
- flags = getopt32(argv, "cvb" "dpsg:m:o:" USE_SELINUX("Z:"),
+ opts = getopt32(argv, "cvb" "Ddpsg:m:o:" USE_SELINUX("Z:"),
&gid_str, &mode_str, &uid_str USE_SELINUX(, &scontext));
argc -= optind;
argv += optind;
#if ENABLE_SELINUX
- if (flags & (OPT_PRESERVE_SECURITY_CONTEXT|OPT_SET_SECURITY_CONTEXT)) {
+ if (opts & (OPT_PRESERVE_SECURITY_CONTEXT|OPT_SET_SECURITY_CONTEXT)) {
selinux_or_die();
use_default_selinux_context = 0;
- if (flags & OPT_PRESERVE_SECURITY_CONTEXT) {
+ if (opts & OPT_PRESERVE_SECURITY_CONTEXT) {
copy_flags |= FILEUTILS_PRESERVE_SECURITY_CONTEXT;
}
- if (flags & OPT_SET_SECURITY_CONTEXT) {
+ if (opts & OPT_SET_SECURITY_CONTEXT) {
setfscreatecon_or_die(scontext);
copy_flags |= FILEUTILS_SET_SECURITY_CONTEXT;
}
}
#endif
- /* preserve access and modification time, this is GNU behaviour, BSD only preserves modification time */
- if (flags & OPT_PRESERVE_TIME) {
+ /* preserve access and modification time, this is GNU behaviour,
+ * BSD only preserves modification time */
+ if (opts & OPT_PRESERVE_TIME) {
copy_flags |= FILEUTILS_PRESERVE_STATUS;
}
mode = 0666;
- if (flags & OPT_MODE)
+ if (opts & OPT_MODE)
bb_parse_mode(mode_str, &mode);
- uid = (flags & OPT_OWNER) ? get_ug_id(uid_str, xuname2uid) : getuid();
- gid = (flags & OPT_GROUP) ? get_ug_id(gid_str, xgroup2gid) : getgid();
+ uid = (opts & OPT_OWNER) ? get_ug_id(uid_str, xuname2uid) : getuid();
+ gid = (opts & OPT_GROUP) ? get_ug_id(gid_str, xgroup2gid) : getgid();
last = argv[argc - 1];
- if (!(flags & OPT_DIRECTORY)) {
+ if (!(opts & OPT_DIRECTORY)) {
argv[argc - 1] = NULL;
min_args++;
@@ -149,7 +149,7 @@ int install_main(int argc, char **argv)
while ((arg = *argv++) != NULL) {
char *dest = last;
- if (flags & OPT_DIRECTORY) {
+ if (opts & OPT_DIRECTORY) {
dest = arg;
/* GNU coreutils 6.9 does not set uid:gid
* on intermediate created directories
@@ -159,6 +159,13 @@ int install_main(int argc, char **argv)
goto next;
}
} else {
+ if (opts & OPT_MKDIR_LEADING) {
+ char *ddir = xstrdup(dest);
+ bb_make_directory(dirname(ddir), 0755, FILEUTILS_RECUR);
+ /* errors are not checked. copy_file
+ * will fail if dir is not created. */
+ free(ddir);
+ }
if (isdir)
dest = concat_path_file(last, basename(arg));
if (copy_file(arg, dest, copy_flags)) {
@@ -169,7 +176,7 @@ int install_main(int argc, char **argv)
}
/* Set the file mode */
- if ((flags & OPT_MODE) && chmod(dest, mode) == -1) {
+ if ((opts & OPT_MODE) && chmod(dest, mode) == -1) {
bb_perror_msg("can't change %s of %s", "permissions", dest);
ret = EXIT_FAILURE;
}
@@ -178,13 +185,13 @@ int install_main(int argc, char **argv)
setdefaultfilecon(dest);
#endif
/* Set the user and group id */
- if ((flags & (OPT_OWNER|OPT_GROUP))
+ if ((opts & (OPT_OWNER|OPT_GROUP))
&& lchown(dest, uid, gid) == -1
) {
bb_perror_msg("can't change %s of %s", "ownership", dest);
ret = EXIT_FAILURE;
}
- if (flags & OPT_STRIP) {
+ if (opts & OPT_STRIP) {
char *args[3];
args[0] = (char*)"strip";
args[1] = dest;
diff --git a/release/src/router/busybox/coreutils/length.c b/release/src/router/busybox/coreutils/length.c
index c7523a02a1..43a0f59880 100644
--- a/release/src/router/busybox/coreutils/length.c
+++ b/release/src/router/busybox/coreutils/length.c
@@ -1,4 +1,7 @@
/* vi: set sw=4 ts=4: */
+/*
+ * Licensed under GPLv2, see file LICENSE in this tarball for details.
+ */
/* BB_AUDIT SUSv3 N/A -- Apparently a busybox (obsolete?) extension. */
diff --git a/release/src/router/busybox/coreutils/libcoreutils/coreutils.h b/release/src/router/busybox/coreutils/libcoreutils/coreutils.h
index 89cd9532f2..99b67b14d6 100644
--- a/release/src/router/busybox/coreutils/libcoreutils/coreutils.h
+++ b/release/src/router/busybox/coreutils/libcoreutils/coreutils.h
@@ -4,11 +4,9 @@
*/
#ifndef COREUTILS_H
-#define COREUTILS_H 1
+#define COREUTILS_H 1
-#if __GNUC_PREREQ(4,1)
-# pragma GCC visibility push(hidden)
-#endif
+PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
typedef int (*stat_func)(const char *fn, struct stat *ps);
@@ -17,8 +15,6 @@ int cp_mv_stat(const char *fn, struct stat *fn_stat) FAST_FUNC;
mode_t getopt_mk_fifo_nod(char **argv) FAST_FUNC;
-#if __GNUC_PREREQ(4,1)
-# pragma GCC visibility pop
-#endif
+POP_SAVED_FUNCTION_VISIBILITY
#endif
diff --git a/release/src/router/busybox/coreutils/ls.c b/release/src/router/busybox/coreutils/ls.c
index f4e71bc6a4..61baa9a110 100644
--- a/release/src/router/busybox/coreutils/ls.c
+++ b/release/src/router/busybox/coreutils/ls.c
@@ -6,7 +6,7 @@
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
-/*
+/* [date unknown. Perhaps before year 2000]
* 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
@@ -18,8 +18,7 @@
*
* 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
+ * 2. hidden files can make column width too large
*
* NON-OPTIMAL BEHAVIOUR:
* 1. autowidth reads directories twice
@@ -27,6 +26,9 @@
* appended, there's no need to stat each one
* PORTABILITY:
* 1. requires lstat (BSD) - how do you do it without?
+ *
+ * [2009-03]
+ * ls sorts listing now, and supports almost all options.
*/
#include "libbb.h"
@@ -38,6 +40,21 @@
/* This is a NOEXEC applet. Be very careful! */
+#if ENABLE_FTPD
+/* ftpd uses ls, and without timestamps Mozilla won't understand
+ * ftpd's LIST output.
+ */
+# undef CONFIG_FEATURE_LS_TIMESTAMPS
+# undef ENABLE_FEATURE_LS_TIMESTAMPS
+# undef USE_FEATURE_LS_TIMESTAMPS
+# undef SKIP_FEATURE_LS_TIMESTAMPS
+# define CONFIG_FEATURE_LS_TIMESTAMPS 1
+# define ENABLE_FEATURE_LS_TIMESTAMPS 1
+# define USE_FEATURE_LS_TIMESTAMPS(...) __VA_ARGS__
+# define SKIP_FEATURE_LS_TIMESTAMPS(...)
+#endif
+
+
enum {
TERMINAL_WIDTH = 80, /* use 79 if terminal has linefold bug */
@@ -59,7 +76,7 @@ LIST_ID_NAME = 1 << 4,
LIST_ID_NUMERIC = 1 << 5,
LIST_CONTEXT = 1 << 6,
LIST_SIZE = 1 << 7,
-LIST_DEV = 1 << 8,
+//LIST_DEV = 1 << 8, - unused, synonym to LIST_SIZE
LIST_DATE_TIME = 1 << 9,
LIST_FULLTIME = 1 << 10,
LIST_FILENAME = 1 << 11,
@@ -110,13 +127,102 @@ SPLIT_SUBDIR = 2,
};
-#define TYPEINDEX(mode) (((mode) >> 12) & 0x0f)
-#define TYPECHAR(mode) ("0pcCd?bB-?l?s???" [TYPEINDEX(mode)])
-#define APPCHAR(mode) ("\0|\0\0/\0\0\0\0\0@\0=\0\0\0" [TYPEINDEX(mode)])
-#define COLOR(mode) ("\000\043\043\043\042\000\043\043"\
- "\000\000\044\000\043\000\000\040" [TYPEINDEX(mode)])
-#define ATTR(mode) ("\00\00\01\00\01\00\01\00"\
- "\00\00\01\00\01\00\00\01" [TYPEINDEX(mode)])
+/* "[-]Cadil1", POSIX mandated options, busybox always supports */
+/* "[-]gnsx", POSIX non-mandated options, busybox always supports */
+/* "[-]Q" GNU option? busybox always supports */
+/* "[-]Ak" GNU options, busybox always supports */
+/* "[-]FLRctur", POSIX mandated options, busybox optionally supports */
+/* "[-]p", POSIX non-mandated options, busybox optionally supports */
+/* "[-]SXvThw", GNU options, busybox optionally supports */
+/* "[-]K", SELinux mandated options, busybox optionally supports */
+/* "[-]e", I think we made this one up */
+static const char ls_options[] ALIGN1 =
+ "Cadil1gnsxQAk" /* 13 opts, total 13 */
+ USE_FEATURE_LS_TIMESTAMPS("cetu") /* 4, 17 */
+ USE_FEATURE_LS_SORTFILES("SXrv") /* 4, 21 */
+ USE_FEATURE_LS_FILETYPES("Fp") /* 2, 23 */
+ USE_FEATURE_LS_FOLLOWLINKS("L") /* 1, 24 */
+ USE_FEATURE_LS_RECURSIVE("R") /* 1, 25 */
+ USE_FEATURE_HUMAN_READABLE("h") /* 1, 26 */
+ USE_SELINUX("K") /* 1, 27 */
+ USE_SELINUX("Z") /* 1, 28 */
+ USE_FEATURE_AUTOWIDTH("T:w:") /* 2, 30 */
+ ;
+enum {
+ //OPT_C = (1 << 0),
+ //OPT_a = (1 << 1),
+ //OPT_d = (1 << 2),
+ //OPT_i = (1 << 3),
+ //OPT_l = (1 << 4),
+ //OPT_1 = (1 << 5),
+ OPT_g = (1 << 6),
+ //OPT_n = (1 << 7),
+ //OPT_s = (1 << 8),
+ //OPT_x = (1 << 9),
+ OPT_Q = (1 << 10),
+ //OPT_A = (1 << 11),
+ //OPT_k = (1 << 12),
+};
+
+enum {
+ LIST_MASK_TRIGGER = 0,
+ STYLE_MASK_TRIGGER = STYLE_MASK,
+ DISP_MASK_TRIGGER = DISP_ROWS,
+ SORT_MASK_TRIGGER = SORT_MASK,
+};
+
+/* TODO: simple toggles may be stored as OPT_xxx bits instead */
+static const unsigned opt_flags[] = {
+ LIST_SHORT | STYLE_COLUMNS, /* C */
+ DISP_HIDDEN | DISP_DOT, /* a */
+ DISP_NOLIST, /* d */
+ LIST_INO, /* i */
+ LIST_LONG | STYLE_LONG, /* l - remember LS_DISP_HR in mask! */
+ LIST_SHORT | STYLE_SINGLE, /* 1 */
+ 0, /* g (don't show group) - handled via OPT_g */
+ LIST_ID_NUMERIC, /* n */
+ LIST_BLOCKS, /* s */
+ DISP_ROWS, /* x */
+ 0, /* Q (quote filename) - handled via OPT_Q */
+ DISP_HIDDEN, /* A */
+ ENABLE_SELINUX * LIST_CONTEXT, /* k (ignored if !SELINUX) */
+#if ENABLE_FEATURE_LS_TIMESTAMPS
+ TIME_CHANGE | (ENABLE_FEATURE_LS_SORTFILES * SORT_CTIME), /* c */
+ LIST_FULLTIME, /* e */
+ ENABLE_FEATURE_LS_SORTFILES * SORT_MTIME, /* t */
+ TIME_ACCESS | (ENABLE_FEATURE_LS_SORTFILES * SORT_ATIME), /* u */
+#endif
+#if ENABLE_FEATURE_LS_SORTFILES
+ SORT_SIZE, /* S */
+ SORT_EXT, /* X */
+ SORT_REVERSE, /* r */
+ SORT_VERSION, /* v */
+#endif
+#if ENABLE_FEATURE_LS_FILETYPES
+ LIST_FILETYPE | LIST_EXEC, /* F */
+ LIST_FILETYPE, /* p */
+#endif
+#if ENABLE_FEATURE_LS_FOLLOWLINKS
+ FOLLOW_LINKS, /* L */
+#endif
+#if ENABLE_FEATURE_LS_RECURSIVE
+ DISP_RECURSIVE, /* R */
+#endif
+#if ENABLE_FEATURE_HUMAN_READABLE
+ LS_DISP_HR, /* h */
+#endif
+#if ENABLE_SELINUX
+ LIST_MODEBITS|LIST_NLINKS|LIST_CONTEXT|LIST_SIZE|LIST_DATE_TIME, /* K */
+#endif
+#if ENABLE_SELINUX
+ LIST_MODEBITS|LIST_ID_NAME|LIST_CONTEXT, /* Z */
+#endif
+ (1U<<31)
+ /* options after Z are not processed through opt_flags:
+ * T, w - ignored
+ */
+};
+
/*
* a directory entry and its stat info are stored here
@@ -230,18 +336,46 @@ static struct dnode *my_stat(const char *fullname, const char *name, int force_f
return cur;
}
+
+/* FYI type values: 1:fifo 2:char 4:dir 6:blk 8:file 10:link 12:socket
+ * (various wacky OSes: 13:Sun door 14:BSD whiteout 5:XENIX named file
+ * 3/7:multiplexed char/block device)
+ * and we use 0 for unknown and 15 for executables (see below) */
+#define TYPEINDEX(mode) (((mode) >> 12) & 0x0f)
+#define TYPECHAR(mode) ("0pcCd?bB-?l?s???" [TYPEINDEX(mode)])
+#define APPCHAR(mode) ("\0|\0\0/\0\0\0\0\0@\0=\0\0\0" [TYPEINDEX(mode)])
+/* 036 black foreground 050 black background
+ 037 red foreground 051 red background
+ 040 green foreground 052 green background
+ 041 brown foreground 053 brown background
+ 042 blue foreground 054 blue background
+ 043 magenta (purple) foreground 055 magenta background
+ 044 cyan (light blue) foreground 056 cyan background
+ 045 gray foreground 057 white background
+*/
+#define COLOR(mode) ( \
+ /*un fi chr dir blk file link sock exe */ \
+ "\037\043\043\045\042\045\043\043\000\045\044\045\043\045\045\040" \
+ [TYPEINDEX(mode)])
+/* Select normal (0) [actually "reset all"] or bold (1)
+ * (other attributes are 2:dim 4:underline 5:blink 7:reverse,
+ * let's use 7 for "impossible" types, just for fun)
+ * Note: coreutils 6.9 uses inverted red for setuid binaries.
+ */
+#define ATTR(mode) ( \
+ /*un fi chr dir blk file link sock exe */ \
+ "\01\00\01\07\01\07\01\07\00\07\01\07\01\07\07\01" \
+ [TYPEINDEX(mode)])
+
#if ENABLE_FEATURE_LS_COLOR
+/* mode of zero is interpreted as "unknown" (stat failed) */
static char fgcolor(mode_t mode)
{
- /* Check wheter the file is existing (if so, color it red!) */
- if (errno == ENOENT)
- return '\037';
if (S_ISREG(mode) && (mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
return COLOR(0xF000); /* File is executable ... */
return COLOR(mode);
}
-
-static char bgcolor(mode_t mode)
+static char bold(mode_t mode)
{
if (S_ISREG(mode) && (mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
return ATTR(0xF000); /* File is executable ... */
@@ -264,6 +398,7 @@ static char append_char(mode_t mode)
}
#endif
+
#define countdirs(A, B) count_dirs((A), (B), 1)
#define countsubdirs(A, B) count_dirs((A), (B), 0)
static int count_dirs(struct dnode **dn, int nfiles, int notsubdirs)
@@ -573,10 +708,41 @@ static struct dnode **list_dir(const char *path)
}
-static int list_single(const struct dnode *dn)
+static int print_name(const char *name)
{
- int i, column = 0;
+ if (option_mask32 & OPT_Q) {
+#if ENABLE_FEATURE_ASSUME_UNICODE
+ int len = 2 + mbstrlen(name);
+#else
+ int len = 2;
+#endif
+ putchar('"');
+ while (*name) {
+ if (*name == '"') {
+ putchar('\\');
+ len++;
+ }
+ putchar(*name++);
+ if (!ENABLE_FEATURE_ASSUME_UNICODE)
+ len++;
+ }
+ putchar('"');
+ return len;
+ }
+ /* No -Q: */
+#if ENABLE_FEATURE_ASSUME_UNICODE
+ fputs(name, stdout);
+ return mbstrlen(name);
+#else
+ return printf("%s", name);
+#endif
+}
+
+static int list_single(const struct dnode *dn)
+{
+ int column = 0;
+ char *lpath = lpath; /* for compiler */
#if ENABLE_FEATURE_LS_TIMESTAMPS
char *filetime;
time_t ttime, age;
@@ -601,219 +767,128 @@ static int list_single(const struct dnode *dn)
append = append_char(dn->dstat.st_mode);
#endif
- for (i = 0; i <= 31; i++) {
- switch (all_fmt & (1 << i)) {
- case LIST_INO:
- column += printf("%7ld ", (long) dn->dstat.st_ino);
- break;
- case LIST_BLOCKS:
- column += printf("%4"OFF_FMT"d ", (off_t) dn->dstat.st_blocks >> 1);
- break;
- case LIST_MODEBITS:
- column += printf("%-10s ", (char *) bb_mode_string(dn->dstat.st_mode));
- break;
- case LIST_NLINKS:
- column += printf("%4ld ", (long) dn->dstat.st_nlink);
- break;
- case LIST_ID_NAME:
+ /* Do readlink early, so that if it fails, error message
+ * does not appear *inside* of the "ls -l" line */
+ if (all_fmt & LIST_SYMLINK)
+ if (S_ISLNK(dn->dstat.st_mode))
+ lpath = xmalloc_readlink_or_warn(dn->fullname);
+
+ if (all_fmt & LIST_INO)
+ column += printf("%7lu ", (long) dn->dstat.st_ino);
+ if (all_fmt & LIST_BLOCKS)
+ column += printf("%4"OFF_FMT"u ", (off_t) dn->dstat.st_blocks >> 1);
+ if (all_fmt & LIST_MODEBITS)
+ column += printf("%-10s ", (char *) bb_mode_string(dn->dstat.st_mode));
+ if (all_fmt & LIST_NLINKS)
+ column += printf("%4lu ", (long) dn->dstat.st_nlink);
#if ENABLE_FEATURE_LS_USERNAME
- printf("%-8.8s %-8.8s",
+ if (all_fmt & LIST_ID_NAME) {
+ if (option_mask32 & OPT_g) {
+ column += printf("%-8.8s",
+ get_cached_username(dn->dstat.st_uid));
+ } else {
+ column += printf("%-8.8s %-8.8s",
get_cached_username(dn->dstat.st_uid),
get_cached_groupname(dn->dstat.st_gid));
- column += 17;
- break;
-#endif
- case LIST_ID_NUMERIC:
- column += printf("%-8d %-8d", dn->dstat.st_uid, dn->dstat.st_gid);
- break;
- case LIST_SIZE:
- case LIST_DEV:
- if (S_ISBLK(dn->dstat.st_mode) || S_ISCHR(dn->dstat.st_mode)) {
- column += printf("%4d, %3d ", (int) major(dn->dstat.st_rdev),
- (int) minor(dn->dstat.st_rdev));
+ }
+ }
+#endif
+ if (all_fmt & LIST_ID_NUMERIC) {
+ if (option_mask32 & OPT_g)
+ column += printf("%-8u", (int) dn->dstat.st_uid);
+ else
+ column += printf("%-8u %-8u",
+ (int) dn->dstat.st_uid,
+ (int) dn->dstat.st_gid);
+ }
+ if (all_fmt & (LIST_SIZE /*|LIST_DEV*/ )) {
+ if (S_ISBLK(dn->dstat.st_mode) || S_ISCHR(dn->dstat.st_mode)) {
+ column += printf("%4u, %3u ",
+ (int) major(dn->dstat.st_rdev),
+ (int) minor(dn->dstat.st_rdev));
+ } else {
+ if (all_fmt & LS_DISP_HR) {
+ column += printf("%9s ",
+ make_human_readable_str(dn->dstat.st_size, 1, 0));
} else {
- if (all_fmt & LS_DISP_HR) {
- column += printf("%9s ",
- make_human_readable_str(dn->dstat.st_size, 1, 0));
- } else {
- column += printf("%9"OFF_FMT"d ", (off_t) dn->dstat.st_size);
- }
+ column += printf("%9"OFF_FMT"u ", (off_t) dn->dstat.st_size);
}
- break;
+ }
+ }
#if ENABLE_FEATURE_LS_TIMESTAMPS
- case LIST_FULLTIME:
- printf("%24.24s ", filetime);
- column += 25;
- break;
- case LIST_DATE_TIME:
- if ((all_fmt & LIST_FULLTIME) == 0) {
- /* current_time_t ~== time(NULL) */
- age = current_time_t - 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;
+ if (all_fmt & LIST_FULLTIME)
+ column += printf("%24.24s ", filetime);
+ if (all_fmt & LIST_DATE_TIME)
+ if ((all_fmt & LIST_FULLTIME) == 0) {
+ /* current_time_t ~== time(NULL) */
+ age = current_time_t - 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);
}
- break;
+ column += 13;
+ }
#endif
#if ENABLE_SELINUX
- case LIST_CONTEXT:
- {
- char context[80];
- int len = 0;
-
- if (dn->sid) {
- /* I assume sid initilized with NULL */
- len = strlen(dn->sid) + 1;
- safe_strncpy(context, dn->sid, len);
- freecon(dn->sid);
- } else {
- safe_strncpy(context, "unknown", 8);
- }
- printf("%-32s ", context);
- column += MAX(33, len);
- }
- break;
+ if (all_fmt & LIST_CONTEXT) {
+ column += printf("%-32s ", dn->sid ? dn->sid : "unknown");
+ freecon(dn->sid);
+ }
#endif
- case LIST_FILENAME:
- errno = 0;
+ if (all_fmt & LIST_FILENAME) {
#if ENABLE_FEATURE_LS_COLOR
- if (show_color && !lstat(dn->fullname, &info)) {
- printf("\033[%d;%dm", bgcolor(info.st_mode),
- fgcolor(info.st_mode));
- }
+ if (show_color) {
+ info.st_mode = 0; /* for fgcolor() */
+ lstat(dn->fullname, &info);
+ printf("\033[%u;%um", bold(info.st_mode),
+ fgcolor(info.st_mode));
+ }
#endif
-#if ENABLE_FEATURE_ASSUME_UNICODE
- printf("%s", dn->name);
- column += mbstrlen(dn->name);
-#else
- column += printf("%s", dn->name);
+ column += print_name(dn->name);
+ if (show_color) {
+ printf("\033[0m");
+ }
+ }
+ if (all_fmt & LIST_SYMLINK) {
+ if (S_ISLNK(dn->dstat.st_mode) && lpath) {
+ printf(" -> ");
+#if ENABLE_FEATURE_LS_FILETYPES || ENABLE_FEATURE_LS_COLOR
+#if ENABLE_FEATURE_LS_COLOR
+ info.st_mode = 0; /* for fgcolor() */
#endif
- if (show_color) {
- printf("\033[0m");
+ if (stat(dn->fullname, &info) == 0) {
+ append = append_char(info.st_mode);
}
- break;
- case LIST_SYMLINK:
- if (S_ISLNK(dn->dstat.st_mode)) {
- char *lpath = xmalloc_readlink_or_warn(dn->fullname);
- if (!lpath) break;
- printf(" -> ");
-#if ENABLE_FEATURE_LS_FILETYPES || ENABLE_FEATURE_LS_COLOR
- if (!stat(dn->fullname, &info)) {
- append = append_char(info.st_mode);
- }
#endif
#if ENABLE_FEATURE_LS_COLOR
- if (show_color) {
- errno = 0;
- printf("\033[%d;%dm", bgcolor(info.st_mode),
- fgcolor(info.st_mode));
- }
+ if (show_color) {
+ printf("\033[%u;%um", bold(info.st_mode),
+ fgcolor(info.st_mode));
+ }
#endif
- column += printf("%s", lpath) + 4;
- if (show_color) {
- printf("\033[0m");
- }
- free(lpath);
+ column += print_name(lpath) + 4;
+ if (show_color) {
+ printf("\033[0m");
}
- break;
+ free(lpath);
+ }
+ }
#if ENABLE_FEATURE_LS_FILETYPES
- case LIST_FILETYPE:
- if (append) {
- putchar(append);
- column++;
- }
- break;
-#endif
+ if (all_fmt & LIST_FILETYPE) {
+ if (append) {
+ putchar(append);
+ column++;
}
}
+#endif
return column;
}
-/* "[-]Cadil1", POSIX mandated options, busybox always supports */
-/* "[-]gnsx", POSIX non-mandated options, busybox always supports */
-/* "[-]Ak" GNU options, busybox always supports */
-/* "[-]FLRctur", POSIX mandated options, busybox optionally supports */
-/* "[-]p", POSIX non-mandated options, busybox optionally supports */
-/* "[-]SXvThw", GNU options, busybox optionally supports */
-/* "[-]K", SELinux mandated options, busybox optionally supports */
-/* "[-]e", I think we made this one up */
-static const char ls_options[] ALIGN1 =
- "Cadil1gnsxAk"
- USE_FEATURE_LS_TIMESTAMPS("cetu")
- USE_FEATURE_LS_SORTFILES("SXrv")
- USE_FEATURE_LS_FILETYPES("Fp")
- USE_FEATURE_LS_FOLLOWLINKS("L")
- USE_FEATURE_LS_RECURSIVE("R")
- USE_FEATURE_HUMAN_READABLE("h")
- USE_SELINUX("K")
- USE_FEATURE_AUTOWIDTH("T:w:")
- USE_SELINUX("Z");
-
-enum {
- LIST_MASK_TRIGGER = 0,
- STYLE_MASK_TRIGGER = STYLE_MASK,
- DISP_MASK_TRIGGER = DISP_ROWS,
- SORT_MASK_TRIGGER = SORT_MASK,
-};
-
-static const unsigned opt_flags[] = {
- LIST_SHORT | STYLE_COLUMNS, /* C */
- DISP_HIDDEN | DISP_DOT, /* a */
- DISP_NOLIST, /* d */
- LIST_INO, /* i */
- LIST_LONG | STYLE_LONG, /* l - remember LS_DISP_HR in mask! */
- LIST_SHORT | STYLE_SINGLE, /* 1 */
- 0, /* g - ingored */
- LIST_ID_NUMERIC, /* n */
- LIST_BLOCKS, /* s */
- DISP_ROWS, /* x */
- DISP_HIDDEN, /* A */
- ENABLE_SELINUX * LIST_CONTEXT, /* k (ignored if !SELINUX) */
-#if ENABLE_FEATURE_LS_TIMESTAMPS
- TIME_CHANGE | (ENABLE_FEATURE_LS_SORTFILES * SORT_CTIME), /* c */
- LIST_FULLTIME, /* e */
- ENABLE_FEATURE_LS_SORTFILES * SORT_MTIME, /* t */
- TIME_ACCESS | (ENABLE_FEATURE_LS_SORTFILES * SORT_ATIME), /* u */
-#endif
-#if ENABLE_FEATURE_LS_SORTFILES
- SORT_SIZE, /* S */
- SORT_EXT, /* X */
- SORT_REVERSE, /* r */
- SORT_VERSION, /* v */
-#endif
-#if ENABLE_FEATURE_LS_FILETYPES
- LIST_FILETYPE | LIST_EXEC, /* F */
- LIST_FILETYPE, /* p */
-#endif
-#if ENABLE_FEATURE_LS_FOLLOWLINKS
- FOLLOW_LINKS, /* L */
-#endif
-#if ENABLE_FEATURE_LS_RECURSIVE
- DISP_RECURSIVE, /* R */
-#endif
-#if ENABLE_FEATURE_HUMAN_READABLE
- LS_DISP_HR, /* h */
-#endif
-#if ENABLE_SELINUX
- LIST_MODEBITS|LIST_NLINKS|LIST_CONTEXT|LIST_SIZE|LIST_DATE_TIME, /* K */
-#endif
-#if ENABLE_FEATURE_AUTOWIDTH
- 0, 0, /* T, w - ignored */
-#endif
-#if ENABLE_SELINUX
- LIST_MODEBITS|LIST_ID_NAME|LIST_CONTEXT, /* Z */
-#endif
- (1U<<31)
-};
-
-
/* colored LS support by JaWi, janwillem.janssen@lxtreme.nl */
#if ENABLE_FEATURE_LS_COLOR
/* long option entry used only for --color, which has no short option
@@ -824,7 +899,6 @@ static const char ls_color_opt[] ALIGN1 =
#endif
-int ls_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int ls_main(int argc UNUSED_PARAM, char **argv)
{
struct dnode **dnd;
@@ -932,8 +1006,8 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
dn = NULL;
nfiles = 0;
do {
- /* ls w/o -l follows links on command line */
- cur = my_stat(*argv, *argv, !(all_fmt & STYLE_LONG));
+ /* NB: follow links on command line unless -l or -s */
+ cur = my_stat(*argv, *argv, !(all_fmt & (STYLE_LONG|LIST_BLOCKS)));
argv++;
if (!cur)
continue;
diff --git a/release/src/router/busybox/coreutils/md5_sha1_sum.c b/release/src/router/busybox/coreutils/md5_sha1_sum.c
index a5681589bd..a988b9cbfd 100644
--- a/release/src/router/busybox/coreutils/md5_sha1_sum.c
+++ b/release/src/router/busybox/coreutils/md5_sha1_sum.c
@@ -8,7 +8,13 @@
#include "libbb.h"
-typedef enum { HASH_SHA1, HASH_MD5 } hash_algo_t;
+typedef enum {
+ /* 4th letter of applet_name is... */
+ HASH_MD5 = 's', /* "md5>s
- * Copyright 2006 Bernhard Fischer
+ * Copyright 2006 Bernhard Reutner-Fischer
*
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
diff --git a/release/src/router/busybox/coreutils/printenv.c b/release/src/router/busybox/coreutils/printenv.c
index 6971f7258e..2430f3a1ae 100644
--- a/release/src/router/busybox/coreutils/printenv.c
+++ b/release/src/router/busybox/coreutils/printenv.c
@@ -13,6 +13,8 @@
int printenv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int printenv_main(int argc UNUSED_PARAM, char **argv)
{
+ int exit_code = EXIT_SUCCESS;
+
/* no variables specified, show whole env */
if (!argv[1]) {
int e = 0;
@@ -26,8 +28,10 @@ int printenv_main(int argc UNUSED_PARAM, char **argv)
env = getenv(arg);
if (env)
puts(env);
+ else
+ exit_code = EXIT_FAILURE;
}
}
- fflush_stdout_and_exit(EXIT_SUCCESS);
+ fflush_stdout_and_exit(exit_code);
}
diff --git a/release/src/router/busybox/coreutils/printf.c b/release/src/router/busybox/coreutils/printf.c
index 76524f7064..0b004eaeb1 100644
--- a/release/src/router/busybox/coreutils/printf.c
+++ b/release/src/router/busybox/coreutils/printf.c
@@ -75,13 +75,13 @@ static int multiconvert(const char *arg, void *result, converter convert)
return 0;
}
-static void FAST_FUNC conv_strtoul(const char *arg, void *result)
+static void FAST_FUNC conv_strtoull(const char *arg, void *result)
{
- *(unsigned long*)result = bb_strtoul(arg, NULL, 0);
+ *(unsigned long long*)result = bb_strtoull(arg, NULL, 0);
}
-static void FAST_FUNC conv_strtol(const char *arg, void *result)
+static void FAST_FUNC conv_strtoll(const char *arg, void *result)
{
- *(long*)result = bb_strtol(arg, NULL, 0);
+ *(long long*)result = bb_strtoll(arg, NULL, 0);
}
static void FAST_FUNC conv_strtod(const char *arg, void *result)
{
@@ -96,17 +96,17 @@ static void FAST_FUNC conv_strtod(const char *arg, void *result)
}
/* Callers should check errno to detect errors */
-static unsigned long my_xstrtoul(const char *arg)
+static unsigned long long my_xstrtoull(const char *arg)
{
- unsigned long result;
- if (multiconvert(arg, &result, conv_strtoul))
+ unsigned long long result;
+ if (multiconvert(arg, &result, conv_strtoull))
result = 0;
return result;
}
-static long my_xstrtol(const char *arg)
+static long long my_xstrtoll(const char *arg)
{
- long result;
- if (multiconvert(arg, &result, conv_strtol))
+ long long result;
+ if (multiconvert(arg, &result, conv_strtoll))
result = 0;
return result;
}
@@ -134,61 +134,63 @@ static void print_direc(char *format, unsigned fmt_length,
int field_width, int precision,
const char *argument)
{
- long lv;
+ long long llv;
double dv;
char saved;
char *have_prec, *have_width;
+ saved = format[fmt_length];
+ format[fmt_length] = '\0';
+
have_prec = strstr(format, ".*");
have_width = strchr(format, '*');
if (have_width - 1 == have_prec)
have_width = NULL;
- saved = format[fmt_length];
- format[fmt_length] = '\0';
-
switch (format[fmt_length - 1]) {
case 'c':
printf(format, *argument);
break;
case 'd':
case 'i':
- lv = my_xstrtol(argument);
+ llv = my_xstrtoll(argument);
print_long:
/* if (errno) return; - see comment at the top */
if (!have_width) {
if (!have_prec)
- printf(format, lv);
+ printf(format, llv);
else
- printf(format, precision, lv);
+ printf(format, precision, llv);
} else {
if (!have_prec)
- printf(format, field_width, lv);
+ printf(format, field_width, llv);
else
- printf(format, field_width, precision, lv);
+ printf(format, field_width, precision, llv);
}
break;
case 'o':
case 'u':
case 'x':
case 'X':
- lv = my_xstrtoul(argument);
+ llv = my_xstrtoull(argument);
/* cheat: unsigned long and long have same width, so... */
goto print_long;
case 's':
- /* Are char* and long the same? (true for most arches) */
- if (sizeof(argument) == sizeof(lv)) {
- lv = (long)(ptrdiff_t)argument;
+ /* Are char* and long long the same? */
+ if (sizeof(argument) == sizeof(llv)) {
+ llv = (long long)(ptrdiff_t)argument;
goto print_long;
- } else { /* Hope compiler will optimize it out */
+ } else {
+ /* Hope compiler will optimize it out by moving call
+ * instruction after the ifs... */
if (!have_width) {
if (!have_prec)
- printf(format, argument);
+ printf(format, argument, /*unused:*/ argument, argument);
else
- printf(format, precision, argument);
+ printf(format, precision, argument, /*unused:*/ argument);
} else {
if (!have_prec)
- printf(format, field_width, argument);
+ printf(format, field_width, argument, /*unused:*/ argument);
else
printf(format, field_width, precision, argument);
}
@@ -286,38 +288,48 @@ static char **print_formatted(char *f, char **argv)
}
}
}
- /* Remove size modifiers - "%Ld" would try to printf
- * long long, we pass long, and it spews garbage */
- if ((*f | 0x20) == 'l' || *f == 'h' || *f == 'z') {
+
+ /* Remove "lLhz" size modifiers, repeatedly.
+ * bash does not like "%lld", but coreutils
+ * would happily take even "%Llllhhzhhzd"!
+ * We will be permissive like coreutils */
+ while ((*f | 0x20) == 'l' || *f == 'h' || *f == 'z') {
overlapping_strcpy(f, f + 1);
}
-//FIXME: actually, the same happens with bare "%d":
-//it printfs an int, but we pass long!
-//What saves us is that on most arches stack slot
-//is pointer-sized -> long-sized -> ints are promoted to longs
-// for variadic functions -> printf("%d", int_v) is in reality
-// indistinqushable from printf("%d", long_v) ->
-// since printf("%d", int_v) works, printf("%d", long_v) has to work.
-//But "clean" solution would be to add "l" to d,i,o,x,X.
-//Probably makes sense to go all the way to "ll" then.
-//Coreutils support long long-sized arguments.
-
- /* needed - try "printf %" without it */
- if (!strchr("diouxXfeEgGcs", *f)) {
- bb_error_msg("%s: invalid format", direc_start);
- /* causes main() to exit with error */
- return saved_argv - 1;
- }
- ++direc_length;
- if (*argv) {
- print_direc(direc_start, direc_length, field_width,
- precision, *argv);
- ++argv;
- } else {
- print_direc(direc_start, direc_length, field_width,
- precision, "");
+ /* Add "ll" if integer modifier, then print */
+ {
+ static const char format_chars[] ALIGN1 = "diouxXfeEgGcs";
+ char *p = strchr(format_chars, *f);
+ /* needed - try "printf %" without it */
+ if (p == NULL) {
+ bb_error_msg("%s: invalid format", direc_start);
+ /* causes main() to exit with error */
+ return saved_argv - 1;
+ }
+ ++direc_length;
+ if (p - format_chars <= 5) {
+ /* it is one of "diouxX" */
+ p = xmalloc(direc_length + 3);
+ memcpy(p, direc_start, direc_length);
+ p[direc_length + 1] = p[direc_length - 1];
+ p[direc_length - 1] = 'l';
+ p[direc_length] = 'l';
+ //bb_error_msg("<%s>", p);
+ direc_length += 2;
+ direc_start = p;
+ } else {
+ p = NULL;
+ }
+ if (*argv) {
+ print_direc(direc_start, direc_length, field_width,
+ precision, *argv);
+ ++argv;
+ } else {
+ print_direc(direc_start, direc_length, field_width,
+ precision, "");
+ }
+ free(p);
}
- /* if (errno) return saved_argv - 1; */
break;
case '\\':
if (*++f == 'c') {
@@ -359,8 +371,15 @@ int printf_main(int argc UNUSED_PARAM, char **argv)
* We will mimic coreutils. */
if (argv[1] && argv[1][0] == '-' && argv[1][1] == '-' && !argv[1][2])
argv++;
- if (!argv[1])
+ if (!argv[1]) {
+ if (ENABLE_ASH_BUILTIN_PRINTF
+ && applet_name[0] != 'p'
+ ) {
+ bb_error_msg("usage: printf FORMAT [ARGUMENT...]");
+ return 2; /* bash compat */
+ }
bb_show_usage();
+ }
format = argv[1];
argv2 = argv + 2;
diff --git a/release/src/router/busybox/coreutils/rm.c b/release/src/router/busybox/coreutils/rm.c
index 975f2267b1..6b3fbcf253 100644
--- a/release/src/router/busybox/coreutils/rm.c
+++ b/release/src/router/busybox/coreutils/rm.c
@@ -27,13 +27,14 @@ int rm_main(int argc UNUSED_PARAM, char **argv)
unsigned opt;
opt_complementary = "f-i:i-f";
- opt = getopt32(argv, "fiRr");
+ /* -v (verbose) is ignored */
+ opt = getopt32(argv, "fiRrv");
argv += optind;
if (opt & 1)
flags |= FILEUTILS_FORCE;
if (opt & 2)
flags |= FILEUTILS_INTERACTIVE;
- if (opt & 12)
+ if (opt & (8|4))
flags |= FILEUTILS_RECUR;
if (*argv != NULL) {
diff --git a/release/src/router/busybox/coreutils/seq.c b/release/src/router/busybox/coreutils/seq.c
index 01d71f256b..4b853c6986 100644
--- a/release/src/router/busybox/coreutils/seq.c
+++ b/release/src/router/busybox/coreutils/seq.c
@@ -15,26 +15,39 @@
int seq_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int seq_main(int argc, char **argv)
{
+ enum {
+ OPT_w = (1 << 0),
+ OPT_s = (1 << 1),
+ };
double last, increment, i;
+ const char *sep, *opt_s = "\n";
+ unsigned opt = getopt32(argv, "+ws:", &opt_s);
+ unsigned width = 0;
+ argc -= optind;
+ argv += optind;
i = increment = 1;
switch (argc) {
- case 4:
- increment = atof(argv[2]);
case 3:
- i = atof(argv[1]);
+ increment = atof(argv[1]);
case 2:
+ i = atof(*argv);
+ case 1:
last = atof(argv[argc-1]);
break;
default:
bb_show_usage();
}
+ if (opt & OPT_w) /* Pad to length of start or last */
+ width = MAX(strlen(*argv), strlen(argv[argc-1]));
/* You should note that this is pos-5.0.91 semantics, -- FK. */
+ sep = "";
while ((increment > 0 && i <= last) || (increment < 0 && i >= last)) {
- printf("%g\n", i);
+ printf("%s%0*g", sep, width, i);
+ sep = opt_s;
i += increment;
}
-
+ bb_putchar('\n');
return fflush(stdout);
}
diff --git a/release/src/router/busybox/coreutils/split.c b/release/src/router/busybox/coreutils/split.c
index 77cb66d536..f1ec64be02 100644
--- a/release/src/router/busybox/coreutils/split.c
+++ b/release/src/router/busybox/coreutils/split.c
@@ -1,7 +1,7 @@
/* vi: set sw=4 ts=4: */
/*
* split - split a file into pieces
- * Copyright (c) 2007 Bernhard Fischer
+ * Copyright (c) 2007 Bernhard Reutner-Fischer
*
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
diff --git a/release/src/router/busybox/coreutils/stat.c b/release/src/router/busybox/coreutils/stat.c
index c34c06acba..32e8b42f38 100644
--- a/release/src/router/busybox/coreutils/stat.c
+++ b/release/src/router/busybox/coreutils/stat.c
@@ -125,6 +125,20 @@ static const char *human_fstype(uint32_t f_type)
return humantypes[i].fs;
}
+/* "man statfs" says that statfsbuf->f_fsid is a mess */
+/* coreutils treats it as an array of ints, most significant first */
+static unsigned long long get_f_fsid(const struct statfs *statfsbuf)
+{
+ const unsigned *p = (const void*) &statfsbuf->f_fsid;
+ unsigned sz = sizeof(statfsbuf->f_fsid) / sizeof(unsigned);
+ unsigned long long r = 0;
+
+ do
+ r = (r << (sizeof(unsigned)*8)) | *p++;
+ while (--sz > 0);
+ return r;
+}
+
#if ENABLE_FEATURE_STAT_FORMAT
static void strcatc(char *str, char c)
{
@@ -148,11 +162,11 @@ static void print_statfs(char *pformat, const char m,
if (m == 'n') {
printfs(pformat, filename);
} else if (m == 'i') {
- strcat(pformat, "Lx");
- printf(pformat, statfsbuf->f_fsid);
+ strcat(pformat, "llx");
+ printf(pformat, get_f_fsid(statfsbuf));
} else if (m == 'l') {
strcat(pformat, "lu");
- printf(pformat, statfsbuf->f_namelen);
+ printf(pformat, (unsigned long) (statfsbuf->f_namelen));
} else if (m == 't') {
strcat(pformat, "lx");
printf(pformat, (unsigned long) (statfsbuf->f_type)); /* no equiv */
@@ -349,10 +363,11 @@ static void print_it(const char *masterformat, const char *filename,
#endif
static bool do_statfs(const char *filename, const char *format)
{
+ struct statfs statfsbuf;
+
#if !ENABLE_FEATURE_STAT_FORMAT
const char *format;
#endif
- struct statfs statfsbuf;
#if ENABLE_SELINUX
security_context_t scontext = NULL;
@@ -406,10 +421,10 @@ static bool do_statfs(const char *filename, const char *format)
format = (option_mask32 & OPT_TERSE
? "%s %llx %lu "
: " File: \"%s\"\n"
- " ID: %-8Lx Namelen: %-7lu ");
+ " ID: %-8llx Namelen: %-7lu ");
printf(format,
filename,
- statfsbuf.f_fsid,
+ get_f_fsid(&statfsbuf),
statfsbuf.f_namelen);
if (option_mask32 & OPT_TERSE)
diff --git a/release/src/router/busybox/coreutils/tail.c b/release/src/router/busybox/coreutils/tail.c
index 2505fc3a60..5dae2d35b1 100644
--- a/release/src/router/busybox/coreutils/tail.c
+++ b/release/src/router/busybox/coreutils/tail.c
@@ -104,7 +104,7 @@ int tail_main(int argc, char **argv)
if (argv[1] && (argv[1][0] == '+' || argv[1][0] == '-')
&& isdigit(argv[1][1])
) {
- count = eat_num(&argv[1][1]);
+ count = eat_num(argv[1]);
argv++;
argc--;
}
diff --git a/release/src/router/busybox/coreutils/tee.c b/release/src/router/busybox/coreutils/tee.c
index dc947c9358..0f24246708 100644
--- a/release/src/router/busybox/coreutils/tee.c
+++ b/release/src/router/busybox/coreutils/tee.c
@@ -11,7 +11,6 @@
/* http://www.opengroup.org/onlinepubs/007904975/utilities/tee.html */
#include "libbb.h"
-#include
int tee_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int tee_main(int argc, char **argv)
diff --git a/release/src/router/busybox/coreutils/test.c b/release/src/router/busybox/coreutils/test.c
index dbfe4af693..ae40192a21 100644
--- a/release/src/router/busybox/coreutils/test.c
+++ b/release/src/router/busybox/coreutils/test.c
@@ -12,7 +12,7 @@
* modified by Herbert Xu to be used as built-in in ash.
* modified by Erik Andersen to be used
* in busybox.
- * modified by Bernhard Fischer to be useable (i.e. a bit less bloaty).
+ * modified by Bernhard Reutner-Fischer to be useable (i.e. a bit less bloaty).
*
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*
diff --git a/release/src/router/busybox/coreutils/touch.c b/release/src/router/busybox/coreutils/touch.c
index 92f20235cd..20191546cd 100644
--- a/release/src/router/busybox/coreutils/touch.c
+++ b/release/src/router/busybox/coreutils/touch.c
@@ -41,6 +41,13 @@ int touch_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int touch_main(int argc UNUSED_PARAM, char **argv)
{
#if ENABLE_DESKTOP
+#if ENABLE_GETOPT_LONG
+ static const char longopts[] ALIGN1 =
+ /* name, has_arg, val */
+ "no-create\0" No_argument "c"
+ "reference\0" Required_argument "r"
+ ;
+#endif
struct utimbuf timebuf;
char *reference_file = NULL;
#else
@@ -49,11 +56,18 @@ int touch_main(int argc UNUSED_PARAM, char **argv)
#endif
int fd;
int status = EXIT_SUCCESS;
- int flags = getopt32(argv, "c" USE_DESKTOP("r:")
+ int opts;
+
+#if ENABLE_DESKTOP
+#if ENABLE_GETOPT_LONG
+ applet_long_options = longopts;
+#endif
+#endif
+ opts = getopt32(argv, "c" USE_DESKTOP("r:")
/*ignored:*/ "fma"
USE_DESKTOP(, &reference_file));
- flags &= 1; /* only -c bit is left */
+ opts &= 1; /* only -c bit is left */
argv += optind;
if (!*argv) {
bb_show_usage();
@@ -69,7 +83,7 @@ int touch_main(int argc UNUSED_PARAM, char **argv)
do {
if (utime(*argv, reference_file ? &timebuf : NULL)) {
if (errno == ENOENT) { /* no such file */
- if (flags) { /* creation is disabled, so ignore */
+ if (opts) { /* creation is disabled, so ignore */
continue;
}
/* Try to create the file. */
diff --git a/release/src/router/busybox/coreutils/tr.c b/release/src/router/busybox/coreutils/tr.c
index c736c716b2..d89b80bec1 100644
--- a/release/src/router/busybox/coreutils/tr.c
+++ b/release/src/router/busybox/coreutils/tr.c
@@ -16,235 +16,284 @@
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
/* http://www.opengroup.org/onlinepubs/009695399/utilities/tr.html
- * TODO: xdigit, graph, print
+ * TODO: graph, print
*/
#include "libbb.h"
-#define ASCII 0377
+enum {
+ ASCII = 256,
+ /* string buffer needs to be at least as big as the whole "alphabet".
+ * BUFSIZ == ASCII is ok, but we will realloc in expand
+ * even for smallest patterns, let's avoid that by using *2:
+ */
+ TR_BUFSIZ = (BUFSIZ > ASCII*2) ? BUFSIZ : ASCII*2,
+};
static void map(char *pvector,
- unsigned char *string1, unsigned int string1_len,
- unsigned char *string2, unsigned int string2_len)
+ char *string1, unsigned string1_len,
+ char *string2, unsigned string2_len)
{
char last = '0';
- unsigned int i, j;
+ unsigned i, j;
for (j = 0, i = 0; i < string1_len; i++) {
if (string2_len <= j)
- pvector[string1[i]] = last;
+ pvector[(unsigned char)(string1[i])] = last;
else
- pvector[string1[i]] = last = string2[j++];
+ pvector[(unsigned char)(string1[i])] = last = string2[j++];
}
}
/* supported constructs:
* Ranges, e.g., 0-9 ==> 0123456789
- * Ranges, e.g., [0-9] ==> 0123456789
* Escapes, e.g., \a ==> Control-G
* Character classes, e.g. [:upper:] ==> A...Z
* Equiv classess, e.g. [=A=] ==> A (hmmmmmmm?)
+ * not supported:
+ * \ooo-\ooo - octal ranges
+ * [x*N] - repeat char x N times
+ * [x*] - repeat char x until it fills STRING2:
+ * # echo qwe123 | /usr/bin/tr 123456789 '[d]'
+ * qwe[d]
+ * # echo qwe123 | /usr/bin/tr 123456789 '[d*]'
+ * qweddd
*/
-static unsigned int expand(const char *arg, char *buffer)
+static unsigned expand(const char *arg, char **buffer_p)
{
- char *buffer_start = buffer;
+ char *buffer = *buffer_p;
+ unsigned pos = 0;
+ unsigned size = TR_BUFSIZ;
unsigned i; /* can't be unsigned char: must be able to hold 256 */
unsigned char ac;
while (*arg) {
+ if (pos + ASCII > size) {
+ size += ASCII;
+ *buffer_p = buffer = xrealloc(buffer, size);
+ }
if (*arg == '\\') {
arg++;
- *buffer++ = bb_process_escape_sequence(&arg);
+ buffer[pos++] = bb_process_escape_sequence(&arg);
continue;
}
if (arg[1] == '-') { /* "0-9..." */
ac = arg[2];
if (ac == '\0') { /* "0-": copy verbatim */
- *buffer++ = *arg++; /* copy '0' */
+ buffer[pos++] = *arg++; /* copy '0' */
continue; /* next iter will copy '-' and stop */
}
- i = *arg;
+ i = (unsigned char) *arg;
while (i <= ac) /* ok: i is unsigned _int_ */
- *buffer++ = i++;
+ buffer[pos++] = i++;
arg += 3; /* skip 0-9 */
continue;
}
- if (*arg == '[') { /* "[xyz..." */
+ if ((ENABLE_FEATURE_TR_CLASSES || ENABLE_FEATURE_TR_EQUIV)
+ && *arg == '['
+ ) {
arg++;
- i = *arg++;
- /* "[xyz...", i=x, arg points to y */
- if (ENABLE_FEATURE_TR_CLASSES && i == ':') {
+ i = (unsigned char) *arg++;
+ /* "[xyz...". i=x, arg points to y */
+ if (ENABLE_FEATURE_TR_CLASSES && i == ':') { /* [:class:] */
#define CLO ":]\0"
static const char classes[] ALIGN1 =
"alpha"CLO "alnum"CLO "digit"CLO
"lower"CLO "upper"CLO "space"CLO
- "blank"CLO "punct"CLO "cntrl"CLO;
-#define CLASS_invalid 0 /* we increment the retval */
-#define CLASS_alpha 1
-#define CLASS_alnum 2
-#define CLASS_digit 3
-#define CLASS_lower 4
-#define CLASS_upper 5
-#define CLASS_space 6
-#define CLASS_blank 7
-#define CLASS_punct 8
-#define CLASS_cntrl 9
-//#define CLASS_xdigit 10
-//#define CLASS_graph 11
-//#define CLASS_print 12
+ "blank"CLO "punct"CLO "cntrl"CLO
+ "xdigit"CLO;
+ enum {
+ CLASS_invalid = 0, /* we increment the retval */
+ CLASS_alpha = 1,
+ CLASS_alnum = 2,
+ CLASS_digit = 3,
+ CLASS_lower = 4,
+ CLASS_upper = 5,
+ CLASS_space = 6,
+ CLASS_blank = 7,
+ CLASS_punct = 8,
+ CLASS_cntrl = 9,
+ CLASS_xdigit = 10,
+ //CLASS_graph = 11,
+ //CLASS_print = 12,
+ };
smalluint j;
- { /* not really pretty.. */
- char *tmp = xstrndup(arg, 7); // warning: xdigit would need 8, not 7
- j = index_in_strings(classes, tmp) + 1;
- free(tmp);
- }
- if (j == CLASS_alnum || j == CLASS_digit) {
+ char *tmp;
+
+ /* xdigit needs 8, not 7 */
+ i = 7 + (arg[0] == 'x');
+ tmp = xstrndup(arg, i);
+ j = index_in_strings(classes, tmp) + 1;
+ free(tmp);
+
+ if (j == CLASS_invalid)
+ goto skip_bracket;
+
+ arg += i;
+ if (j == CLASS_alnum || j == CLASS_digit || j == CLASS_xdigit) {
for (i = '0'; i <= '9'; i++)
- *buffer++ = i;
+ buffer[pos++] = i;
}
if (j == CLASS_alpha || j == CLASS_alnum || j == CLASS_upper) {
for (i = 'A'; i <= 'Z'; i++)
- *buffer++ = i;
+ buffer[pos++] = i;
}
if (j == CLASS_alpha || j == CLASS_alnum || j == CLASS_lower) {
for (i = 'a'; i <= 'z'; i++)
- *buffer++ = i;
+ buffer[pos++] = i;
}
if (j == CLASS_space || j == CLASS_blank) {
- *buffer++ = '\t';
+ buffer[pos++] = '\t';
if (j == CLASS_space) {
- *buffer++ = '\n';
- *buffer++ = '\v';
- *buffer++ = '\f';
- *buffer++ = '\r';
+ buffer[pos++] = '\n';
+ buffer[pos++] = '\v';
+ buffer[pos++] = '\f';
+ buffer[pos++] = '\r';
}
- *buffer++ = ' ';
+ buffer[pos++] = ' ';
}
if (j == CLASS_punct || j == CLASS_cntrl) {
- for (i = '\0'; i <= ASCII; i++)
+ for (i = '\0'; i < ASCII; i++) {
if ((j == CLASS_punct && isprint(i) && !isalnum(i) && !isspace(i))
- || (j == CLASS_cntrl && iscntrl(i)))
- *buffer++ = i;
+ || (j == CLASS_cntrl && iscntrl(i))
+ ) {
+ buffer[pos++] = i;
+ }
+ }
}
- if (j == CLASS_invalid) {
- *buffer++ = '[';
- *buffer++ = ':';
- continue;
+ if (j == CLASS_xdigit) {
+ for (i = 'A'; i <= 'F'; i++) {
+ buffer[pos + 6] = i | 0x20;
+ buffer[pos++] = i;
+ }
+ pos += 6;
}
- break;
+ continue;
}
/* "[xyz...", i=x, arg points to y */
if (ENABLE_FEATURE_TR_EQUIV && i == '=') { /* [=CHAR=] */
- *buffer++ = *arg; /* copy CHAR */
- if (!*arg || arg[1] != '=' || arg[2] != ']')
+ buffer[pos++] = *arg; /* copy CHAR */
+ if (!arg[0] || arg[1] != '=' || arg[2] != ']')
bb_show_usage();
arg += 3; /* skip CHAR=] */
continue;
}
- if (i == '\0' || *arg != '-') { /* not [x-...] - copy verbatim */
- *buffer++ = '[';
- arg--; /* points to x */
- continue; /* copy all, including eventual ']' */
- }
- /* [x-z] */
- arg++; /* skip - */
- if (arg[0] == '\0' || arg[1] != ']')
- bb_show_usage();
- ac = *arg++;
- while (i <= ac)
- *buffer++ = i++;
- arg++; /* skip ] */
- continue;
+ /* The rest of "[xyz..." cases is treated as normal
+ * string, "[" has no special meaning here:
+ * tr "[a-z]" "[A-Z]" can be written as tr "a-z" "A-Z",
+ * also try tr "[a-z]" "_A-Z+" and you'll see that
+ * [] is not special here.
+ */
+ skip_bracket:
+ arg -= 2; /* points to "[" in "[xyz..." */
}
- *buffer++ = *arg++;
+ buffer[pos++] = *arg++;
}
- return (buffer - buffer_start);
+ return pos;
}
+/* NB: buffer is guaranteed to be at least TR_BUFSIZE
+ * (which is >= ASCII) big.
+ */
static int complement(char *buffer, int buffer_len)
{
- int i, j, ix;
- char conv[ASCII + 2];
+ int len;
+ char conv[ASCII];
+ unsigned char ch;
- 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;
+ len = 0;
+ ch = '\0';
+ while (1) {
+ if (memchr(buffer, ch, buffer_len) == NULL)
+ conv[len++] = ch;
+ if (++ch == '\0')
+ break;
}
- memcpy(buffer, conv, ix);
- return ix;
+ memcpy(buffer, conv, len);
+ return len;
}
int tr_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int tr_main(int argc UNUSED_PARAM, char **argv)
{
- int output_length = 0, input_length;
int i;
- smalluint flags;
- ssize_t read_chars = 0;
- size_t in_index = 0, out_index = 0;
+ smalluint opts;
+ ssize_t read_chars;
+ size_t in_index, out_index;
unsigned last = UCHAR_MAX + 1; /* not equal to any char */
unsigned char coded, c;
- unsigned char *output = xmalloc(BUFSIZ);
- char *vector = xzalloc((ASCII+1) * 3);
- char *invec = vector + (ASCII+1);
- char *outvec = vector + (ASCII+1) * 2;
-
-#define TR_OPT_complement (1 << 0)
-#define TR_OPT_delete (1 << 1)
-#define TR_OPT_squeeze_reps (1 << 2)
+ char *str1 = xmalloc(TR_BUFSIZ);
+ char *str2 = xmalloc(TR_BUFSIZ);
+ int str2_length;
+ int str1_length;
+ char *vector = xzalloc(ASCII * 3);
+ char *invec = vector + ASCII;
+ char *outvec = vector + ASCII * 2;
- flags = getopt32(argv, "+cds"); /* '+': stop at first non-option */
- argv += optind;
+#define TR_OPT_complement (3 << 0)
+#define TR_OPT_delete (1 << 2)
+#define TR_OPT_squeeze_reps (1 << 3)
- for (i = 0; i <= ASCII; i++) {
+ for (i = 0; i < ASCII; i++) {
vector[i] = i;
/*invec[i] = outvec[i] = FALSE; - done by xzalloc */
}
-#define tr_buf bb_common_bufsiz1
- if (*argv != NULL) {
- input_length = expand(*argv++, tr_buf);
- if (flags & TR_OPT_complement)
- input_length = complement(tr_buf, input_length);
- if (*argv) {
- if (argv[0][0] == '\0')
- bb_error_msg_and_die("STRING2 cannot be empty");
- output_length = expand(*argv, (char *)output);
- map(vector, (unsigned char *)tr_buf, input_length, output, output_length);
- }
- for (i = 0; i < input_length; i++)
- invec[(unsigned char)tr_buf[i]] = TRUE;
- for (i = 0; i < output_length; i++)
- outvec[output[i]] = TRUE;
+ /* -C/-c difference is that -C complements "characters",
+ * and -c complements "values" (binary bytes I guess).
+ * In POSIX locale, these are the same.
+ */
+
+ opt_complementary = "-1";
+ opts = getopt32(argv, "+Ccds"); /* '+': stop at first non-option */
+ argv += optind;
+
+ str1_length = expand(*argv++, &str1);
+ str2_length = 0;
+ if (opts & TR_OPT_complement)
+ str1_length = complement(str1, str1_length);
+ if (*argv) {
+ if (argv[0][0] == '\0')
+ bb_error_msg_and_die("STRING2 cannot be empty");
+ str2_length = expand(*argv, &str2);
+ map(vector, str1, str1_length,
+ str2, str2_length);
}
+ for (i = 0; i < str1_length; i++)
+ invec[(unsigned char)(str1[i])] = TRUE;
+ for (i = 0; i < str2_length; i++)
+ outvec[(unsigned char)(str2[i])] = TRUE;
+ goto start_from;
+
+ /* In this loop, str1 space is reused as input buffer,
+ * str2 - as output one. */
for (;;) {
/* If we're out of input, flush output and read more input. */
if ((ssize_t)in_index == read_chars) {
if (out_index) {
- xwrite(STDOUT_FILENO, (char *)output, out_index);
+ xwrite(STDOUT_FILENO, str2, out_index);
+ start_from:
out_index = 0;
}
- read_chars = safe_read(STDIN_FILENO, tr_buf, BUFSIZ);
+ read_chars = safe_read(STDIN_FILENO, str1, TR_BUFSIZ);
if (read_chars <= 0) {
if (read_chars < 0)
bb_perror_msg_and_die(bb_msg_read_error);
- exit(EXIT_SUCCESS);
+ break;
}
in_index = 0;
}
- c = tr_buf[in_index++];
- coded = vector[c];
- if ((flags & TR_OPT_delete) && invec[c])
+ c = str1[in_index++];
+ if ((opts & TR_OPT_delete) && invec[c])
continue;
- if ((flags & TR_OPT_squeeze_reps) && last == coded
- && (invec[c] || outvec[coded]))
+ coded = vector[c];
+ if ((opts & TR_OPT_squeeze_reps) && last == coded
+ && (invec[c] || outvec[coded])
+ ) {
continue;
- output[out_index++] = last = coded;
+ }
+ str2[out_index++] = last = coded;
}
- /* NOTREACHED */
+
return EXIT_SUCCESS;
}
diff --git a/release/src/router/busybox/coreutils/tty.c b/release/src/router/busybox/coreutils/tty.c
index e83289440b..d49fb50b6e 100644
--- a/release/src/router/busybox/coreutils/tty.c
+++ b/release/src/router/busybox/coreutils/tty.c
@@ -30,7 +30,7 @@ int tty_main(int argc, char **argv SKIP_INCLUDE_SUSv2(UNUSED_PARAM))
retval = 0;
- s = ttyname(0);
+ s = xmalloc_ttyname(0);
if (s == NULL) {
/* According to SUSv3, ttyname can fail with EBADF or ENOTTY.
* We know the file descriptor is good, so failure means not a tty. */
diff --git a/release/src/router/busybox/coreutils/uname.c b/release/src/router/busybox/coreutils/uname.c
index e28285c441..33d026f186 100644
--- a/release/src/router/busybox/coreutils/uname.c
+++ b/release/src/router/busybox/coreutils/uname.c
@@ -9,25 +9,43 @@
/* http://www.opengroup.org/onlinepubs/007904975/utilities/uname.html */
/* 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
+ *
+ * GNU coreutils 6.10:
+ * Option: struct Example(s):
+ * utsname
+ * field:
+ * -s, --kernel-name sysname Linux
+ * -n, --nodename nodename localhost.localdomain
+ * -r, --kernel-release release 2.6.29
+ * -v, --kernel-version version #1 SMP Sun Jan 11 20:52:37 EST 2009
+ * -m, --machine machine x86_64 i686
+ * -p, --processor (none) x86_64 i686
+ * -i, --hardware-platform (none) x86_64 i386
+ * NB: vanilla coreutils reports "unknown" -p and -i,
+ * x86_64 and i686/i386 shown above are Fedora's inventions.
+ * -o, --operating-system (none) GNU/Linux
+ * -a, --all: all of the above, in the order shown.
+ * If -p or -i is not known, don't show them
+ */
- -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 */
-
-/* Busyboxed by Erik Andersen */
-
-/* Further size reductions by Glenn McGrath and Manuel Novoa III. */
-
-/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
+/* Busyboxed by Erik Andersen
*
- * Now does proper error checking on i/o. Plus some further space savings.
+ * Before 2003: Glenn McGrath and Manuel Novoa III
+ * Further size reductions.
+ * Mar 16, 2003: Manuel Novoa III (mjn3@codepoet.org)
+ * Now does proper error checking on i/o. Plus some further space savings.
+ * Jan 2009:
+ * Fix handling of -a to not print "unknown", add -o and -i support.
*/
#include
@@ -35,37 +53,60 @@
typedef struct {
struct utsname name;
- char processor[8]; /* for "unknown" */
+ char processor[sizeof(((struct utsname*)NULL)->machine)];
+ char platform[sizeof(((struct utsname*)NULL)->machine)];
+ char os[sizeof("GNU/Linux")];
} uname_info_t;
-static const char options[] ALIGN1 = "snrvmpa";
+static const char options[] ALIGN1 = "snrvmpioa";
static const unsigned short utsname_offset[] = {
- offsetof(uname_info_t, name.sysname),
- offsetof(uname_info_t, name.nodename),
- offsetof(uname_info_t, name.release),
- offsetof(uname_info_t, name.version),
- offsetof(uname_info_t, name.machine),
- offsetof(uname_info_t, processor)
+ offsetof(uname_info_t, name.sysname), /* -s */
+ offsetof(uname_info_t, name.nodename), /* -n */
+ offsetof(uname_info_t, name.release), /* -r */
+ offsetof(uname_info_t, name.version), /* -v */
+ offsetof(uname_info_t, name.machine), /* -m */
+ offsetof(uname_info_t, processor), /* -p */
+ offsetof(uname_info_t, platform), /* -i */
+ offsetof(uname_info_t, os), /* -o */
};
int uname_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int uname_main(int argc UNUSED_PARAM, char **argv)
{
+#if ENABLE_GETOPT_LONG
+ static const char longopts[] ALIGN1 =
+ /* name, has_arg, val */
+ "all\0" No_argument "a"
+ "kernel-name\0" No_argument "s"
+ "nodename\0" No_argument "n"
+ "kernel-release\0" No_argument "r"
+ "release\0" No_argument "r"
+ "kernel-version\0" No_argument "v"
+ "machine\0" No_argument "m"
+ "processor\0" No_argument "p"
+ "hardware-platform\0" No_argument "i"
+ "operating-system\0" No_argument "o"
+ ;
+#endif
uname_info_t uname_info;
#if defined(__sparc__) && defined(__linux__)
char *fake_sparc = getenv("FAKE_SPARC");
#endif
+ const char *unknown_str = "unknown";
+ const char *fmt;
const unsigned short *delta;
- char toprint;
+ unsigned toprint;
+ USE_GETOPT_LONG(applet_long_options = longopts);
toprint = getopt32(argv, options);
if (argv[optind]) { /* coreutils-6.9 compat */
bb_show_usage();
}
- if (toprint & (1 << 6)) { /* -a => all opts on */
- toprint = 0x3f;
+ if (toprint & (1 << 8)) { /* -a => all opts on */
+ toprint = (1 << 8) - 1;
+ unknown_str = ""; /* -a does not print unknown fields */
}
if (toprint == 0) { /* no opts => -s (sysname) */
@@ -79,16 +120,30 @@ int uname_main(int argc UNUSED_PARAM, char **argv)
strcpy(uname_info.name.machine, "sparc");
}
#endif
-
- strcpy(uname_info.processor, "unknown");
+ strcpy(uname_info.processor, unknown_str);
+ strcpy(uname_info.platform, unknown_str);
+ strcpy(uname_info.os, "GNU/Linux");
+#if 0
+ /* Fedora does something like this */
+ strcpy(uname_info.processor, uname_info.name.machine);
+ strcpy(uname_info.platform, uname_info.name.machine);
+ if (uname_info.platform[0] == 'i'
+ && uname_info.platform[1]
+ && uname_info.platform[2] == '8'
+ && uname_info.platform[3] == '6'
+ ) {
+ uname_info.platform[1] = '3';
+ }
+#endif
delta = utsname_offset;
+ fmt = " %s" + 1;
do {
if (toprint & 1) {
- /* printf would not be safe here */
- fputs((char *)(&uname_info) + *delta, stdout);
- if (toprint > 1) {
- bb_putchar(' ');
+ const char *p = (char *)(&uname_info) + *delta;
+ if (p[0]) {
+ printf(fmt, p);
+ fmt = " %s";
}
}
++delta;
diff --git a/release/src/router/busybox/coreutils/uniq.c b/release/src/router/busybox/coreutils/uniq.c
index 0918621186..126eaeef99 100644
--- a/release/src/router/busybox/coreutils/uniq.c
+++ b/release/src/router/busybox/coreutils/uniq.c
@@ -45,7 +45,7 @@ int uniq_main(int argc UNUSED_PARAM, char **argv)
};
skip_fields = skip_chars = 0;
- max_chars = -1;
+ max_chars = INT_MAX;
opt_complementary = "f+:s+:w+";
opt = getopt32(argv, "cduf:s:w:", &skip_fields, &skip_chars, &max_chars);
diff --git a/release/src/router/busybox/coreutils/who.c b/release/src/router/busybox/coreutils/who.c
index baf526b01e..85a0025c33 100644
--- a/release/src/router/busybox/coreutils/who.c
+++ b/release/src/router/busybox/coreutils/who.c
@@ -20,7 +20,6 @@
#include "libbb.h"
#include
-#include
static void idle_string(char *str6, time_t t)
{
diff --git a/release/src/router/busybox/coreutils/whoami.c b/release/src/router/busybox/coreutils/whoami.c
index 6756d4ba9f..0dbcba9553 100644
--- a/release/src/router/busybox/coreutils/whoami.c
+++ b/release/src/router/busybox/coreutils/whoami.c
@@ -20,7 +20,7 @@ int whoami_main(int argc, char **argv UNUSED_PARAM)
bb_show_usage();
/* Will complain and die if username not found */
- puts(bb_getpwuid(NULL, -1, geteuid()));
+ puts(xuid2uname(geteuid()));
return fflush(stdout);
}
diff --git a/release/src/router/busybox/debianutils/Config.in b/release/src/router/busybox/debianutils/Config.in
index 4ed00ddfa0..8deb38f373 100644
--- a/release/src/router/busybox/debianutils/Config.in
+++ b/release/src/router/busybox/debianutils/Config.in
@@ -64,6 +64,7 @@ config FEATURE_START_STOP_DAEMON_FANCY
Support additional arguments.
-o|--oknodo ignored since we exit with 0 anyway
-v|--verbose
+ -N|--nicelevel N
config FEATURE_START_STOP_DAEMON_LONG_OPTIONS
bool "Enable long options"
diff --git a/release/src/router/busybox/debianutils/run_parts.c b/release/src/router/busybox/debianutils/run_parts.c
index a58fab3a55..7c38fa11f9 100644
--- a/release/src/router/busybox/debianutils/run_parts.c
+++ b/release/src/router/busybox/debianutils/run_parts.c
@@ -2,7 +2,7 @@
/*
* Mini run-parts implementation for busybox
*
- * Copyright (C) 2007 Bernhard Fischer
+ * Copyright (C) 2007 Bernhard Reutner-Fischer
*
* Based on a older version that was in busybox which was 1k big..
* Copyright (C) 2001 by Emanuele Aina
diff --git a/release/src/router/busybox/debianutils/start_stop_daemon.c b/release/src/router/busybox/debianutils/start_stop_daemon.c
index 875eca511e..ab607bde0b 100644
--- a/release/src/router/busybox/debianutils/start_stop_daemon.c
+++ b/release/src/router/busybox/debianutils/start_stop_daemon.c
@@ -349,11 +349,11 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv)
opt_complementary = "K:S:K--S:S--K:m?p:K?xpun:S?xa"
USE_FEATURE_START_STOP_DAEMON_FANCY("q-v");
opt = getopt32(argv, "KSbqtma:n:s:u:c:x:p:"
- USE_FEATURE_START_STOP_DAEMON_FANCY("ovN:"),
-// USE_FEATURE_START_STOP_DAEMON_FANCY("ovN:R:"),
+ USE_FEATURE_START_STOP_DAEMON_FANCY("ovN:R:"),
&startas, &cmdname, &signame, &userspec, &chuid, &execname, &pidfile
USE_FEATURE_START_STOP_DAEMON_FANCY(,&opt_N)
-// USE_FEATURE_START_STOP_DAEMON_FANCY(,&retry_arg)
+ /* We accept and ignore -R / --retry */
+ USE_FEATURE_START_STOP_DAEMON_FANCY(,NULL)
);
if (opt & OPT_s) {
@@ -428,7 +428,7 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv)
write_pidfile(pidfile);
}
if (opt & OPT_c) {
- struct bb_uidgid_t ugid;
+ struct bb_uidgid_t ugid = { -1, -1 };
parse_chown_usergroup_or_die(&ugid, chuid);
if (ugid.gid != (gid_t) -1) xsetgid(ugid.gid);
if (ugid.uid != (uid_t) -1) xsetuid(ugid.uid);
diff --git a/release/src/router/busybox/docs/Serial-Programming-HOWTO.txt b/release/src/router/busybox/docs/Serial-Programming-HOWTO.txt
new file mode 100644
index 0000000000..0dfc8aa31b
--- /dev/null
+++ b/release/src/router/busybox/docs/Serial-Programming-HOWTO.txt
@@ -0,0 +1,424 @@
+Downloaded from http://www.lafn.org/~dave/linux/Serial-Programming-HOWTO.txt
+Seems to be somewhat old, but contains useful bits for getty.c hacking
+============================================================================
+
+ The Linux Serial Programming HOWTO, Part 1 of 2
+ By Vernon C. Hoxie
+ v2.0 10 September 1999
+
+ This document describes how to program communications with devices
+ over a serial port on a Linux box.
+ ______________________________________________________________________
+
+ Table of Contents
+
+ 1. Copyright
+
+ 2. Introduction
+
+ 3. Opening
+
+ 4. Commands
+
+ 5. Changing Baud Rates
+
+ 6. Additional Control Calls
+
+ 6.1 Sending a "break".
+ 6.2 Hardware flow control.
+ 6.3 Flushing I/O buffers.
+
+ 7. Modem control
+
+ 8. Process Groups
+
+ 8.1 Sessions
+ 8.2 Process Groups
+ 8.3 Controlling Terminal
+ 8.3.1 Get the foreground group process id.
+ 8.3.2 Set the foreground process group id of a terminal.
+ 8.3.3 Get process group id.
+
+ 9. Lockfiles
+
+ 10. Additional Information
+
+ 11. Feedback
+
+ ______________________________________________________________________
+
+ 1. Copyright
+
+ The Linux Serial-Programming-HOWTO is copyright (C) 1997 by Vernon
+ Hoxie. Linux HOWTO documents may be reproduced and distributed in
+ whole or in part, in any medium physical or electronic, as long as
+ this copyright notice is retained on all copies. Commercial
+ redistribution is allowed and encouraged; however, the author would
+ like to be notified of any such distributions.
+
+ All translations, derivative works, or aggregate works incorporating
+ this Linux HOWTO document must be covered under this copyright notice.
+ That is, you may not produce a derivative work from this HOWTO and
+ impose additional restrictions on its distribution.
+
+ This version is a complete rewrite of the previous Serial-Programming-
+ HOWTO by Peter H. Baumann,
+
+ 2. Introduction
+
+ This HOWTO will attempt to give hints about how to write a program
+ which needs to access a serial port. Its principal focus will be on
+ the Linux implementation and what the meaning of the various library
+ functions available.
+
+ Someone asked about which of several sequences of operations was
+ right. There is no absolute right way to accomplish an outcome. The
+ options available are too numerous. If your sequences produces the
+ desired results, then that is the right way for you. Another
+ programmer may select another set of options and get the same results.
+ His method is right for him.
+
+ Neither of these methods may operate properly with some other
+ implementation of UNIX. It is strange that many of the concepts which
+ were implemented in the SYSV version have been dumped. Because UNIX
+ was developed by AT&T and much code has been generated on those
+ concepts, the AT&T version should be the standard to which others
+ should emulate.
+
+ Now the standard is POSIX.
+
+ It was once stated that the popularity of UNIX and C was that they
+ were created by programmers for programmers. Not by scholars who
+ insist on purity of style in deference to results and simplicity of
+ use. Not by committees with people who have diverse personal or
+ proprietary agenda. Now ANSI and POSIX have strayed from those
+ original clear and simply concepts.
+
+ 3. Opening
+
+ The various serial devices are opened just as any other file.
+ Although, the fopen(3) command may be used, the plain open(2) is
+ preferred. This call returns the file descriptor which is required
+ for the various commands that configure the interface.
+
+ Open(2) has the format:
+
+ #include
+ int open(char *path, int flags, [int mode]);
+
+ In addition to the obvious O_RDWR, O_WRONLY and O_RDONLY, two
+ additional flags are available. These are O_NONBLOCK and O_NOCTTY.
+ Other flags listed in the open(2) manual page are not applicable to
+ serial devices.
+
+ Normally, a serial device opens in "blocking" mode. This means that
+ the open() will not return until the Carrier Detect line from the port
+ is active, e.g. modem, is active. When opened with the O_NONBLOCK
+ flag set, the open() will return immediately regardless of the status
+ of the DCD line. The "blocking" mode also affects the read() call.
+
+ The fcntl(2) command can be used to change the O_NONBLOCK flag anytime
+ after the device has been opened.
+
+ The device driver and the data passing through it are controlled
+ according to settings in the struct termios. This structure is
+ defined in "/usr/include/termios.h". In the Linux tree, further
+ reference is made to "/usr/include/asm/termbits.h".
+ In blocking mode, a read(2) will block until data is available or a
+ signal is received. It is still subject to state of the ICANON flag.
+
+ When the termios.c_lflag ICANON bit is set, input data is collected
+ into strings until a NL, EOF or EOL character is received. You can
+ define these in the termios.c_cc[] array. Also, ERASE and KILL
+ characters will operate on the incoming data before it is delivered to
+ the user.
+
+ In non-canonical mode, incoming data is quanitified by use of the
+ c_cc[VMIN and c_cc[VTIME] values in termios.c_cc[].
+
+ Some programmers use the select() call to detect the completion of a
+ read(). This is not the best way of checking for incoming data.
+ Select() is part of the SOCKETS scheme and too complex for most
+ applications.
+
+ A full explanation of the fields of the termios structure is contained
+ in termios(7) of the Users Manual. A version is included in Part 2 of
+ this HOWTO document.
+
+ 4. Commands
+
+ Changes to the struct termios are made by retrieving the current
+ settings, making the desired changes and transmitting the modified
+ structure back to the kernel.
+
+ The historic means of communicating with the kernel was by use of the
+ ioctl(fd, COMMAND, arg) system call. Then the purists in the
+ computer industry decided that this was not genetically consistent.
+ Their argument was that the argument changed its stripes. Sometimes
+ it was an int, sometimes it was a pointer to int and other times it
+ was a pointer to struct termios. Then there were those times it was
+ empty or NULL. These variations are dependent upon the COMMAND.
+
+ As a alternative, the tc* series of functions were concocted.
+
+ These are:
+
+ int tcgetattr(int filedes, struct termios *termios_p);
+ int tcsetattr(int filedes, int optional_actions,
+ const struct termios *termios_p);
+
+ instead of:
+
+ int ioctl(int filedes, int command,
+ struct termios *termios_p);
+
+ where command is TCGETS or one of TCSETS, TCSETSW or TCSETSF.
+
+ The TCSETS command is comparable to the TCSANOW optional_action for
+ the tc* version. These direct the kernel to adopt the changes
+ immediately. Other pairs are:
+
+ command optional_action Meaning
+ TCSETSW TCSADRAIN Change after all output has drained.
+ TCSETSF TCSAFLUSH Change after all output has drained
+ then discard any input characters
+ not read.
+
+ Since the return code from either the ioctl(2) or the tcsetattr(2)
+ commands only indicate that the command was processed by the kernel.
+ These do not indicate whether or not the changes were actually
+ accomplished. Either of these commands should be followed by a call
+ to:
+
+ ioctl(fd, TCGETS, &new_termios);
+
+ or:
+
+ tcgetattr(fd, &new_termios);
+
+ A user function which makes changes to the termios structure should
+ define two struct termios variables. One of these variables should
+ contain the desired configuration. The other should contain a copy of
+ the kernels version. Then after the desired configuration has been
+ sent to the kernel, another call should be made to retrieve the
+ kernels version. Then the two compared.
+
+ Here is an example of how to add RTS/CTS flow control:
+
+ struct termios my_termios;
+ struct termios new_termios;
+
+ tcgetattr(fd, &my_termios);
+ my_termios.c_flag |= CRTSCTS;
+ tcsetattr(fd, TCSANOW, &my_termios);
+ tcgetattr(fd, &new_termios);
+ if (memcmp(my_termios, new_termios,
+ sizeof(my_termios)) != 0) {
+ /* do some error handling */
+ }
+
+ 5. Changing Baud Rates
+
+ With Linux, the baud rate can be changed using a technique similar to
+ add/delete RTS/CTS.
+
+ struct termios my_termios;
+ struct termios new_termios;
+
+ tcgetattr(fd, &my_termios);
+ my_termios.c_flag &= ~CBAUD;
+ my_termios.c_flag |= B19200;
+ tcsetattr(fd, TCSANOW, &my_termios);
+ tcgetattr(fd, &new_termios);
+ if (memcmp(my_termios, new_termios,
+ sizeof(my_termios)) != 0) {
+ /* do some error handling */
+ }
+
+ POSIX adds another method. They define:
+
+ speed_t cfgetispeed(const struct termios *termios_p);
+ speed_t cfgetospeed(const struct termios *termios_p);
+
+ library calls to extract the current input or output speed from the
+ struct termios pointed to with *termio_p. This is a variable defined
+ in the calling process. In practice, the data contained in this
+ termios, should be obtained by the tcgetattr() call or an ioctl() call
+ using the TCGETS command.
+
+ The companion library calls are:
+
+ int cfsetispeed(struct termios *termios_p, speed_t speed);
+ int cfsetospeed(struct termios *termios_p, speed_t speed);
+
+ which are used to change the value of the baud rate in the locally
+ defined *termios_p. Following either of these calls, either a call to
+ tcsetattr() or ioctl() with one of TCSETS, TCSETSW or TCSETSF as the
+ command to transmit the change to the kernel.
+
+ The cf* commands are preferred for portability. Some weird Unices use
+ a considerably different format of termios.
+
+ Most implementations of Linux use only the input speed for both input
+ and output. These functions are defined in the application program by
+ reference to . In reality, they are in
+ /usr/include/asm/termbits.h.
+
+ 6. Additional Control Calls
+
+ 6.1. Sending a "break".
+
+ int ioctl(fd, TCSBRK, int arg);
+ int tcsendbreak(fd, int arg);
+
+ Send a break: Here the action differs between the conventional
+ ioctl() call and the POSIX call. For the conventional call, an arg of
+ '0' sets the break control line of the UART for 0.25 seconds. For the
+ POSIX command, the break line is set for arg times 0.1 seconds.
+
+ 6.2. Hardware flow control.
+
+ int ioctl(fd, TCXONC, int action);
+ int tcflow(fd, int action);
+
+ The action flags are:
+
+ o TCOOFF 0 suspend output
+
+ o TCOON 1 restart output
+
+ o TCIOFF 2 transmit STOP character to suspend input
+
+ o TCION 3 transmit START character to restart input
+
+ 6.3. Flushing I/O buffers.
+
+ int ioctl(fd, TCFLSH, queue_selector);
+ int tcflush(fd, queue_selector);
+
+ The queue_selector flags are:
+
+ o TCIFLUSH 0 flush any data not yet read from the input buffer
+
+ o TCOFLUSH 1 flush any data written to the output buffer but not
+ yet transmitted
+
+ o TCIOFLUSH 2 flush both buffers
+
+ 7. Modem control
+
+ The hardware modem control lines can be monitored or modified by the
+ ioctl(2) system call. A set of comparable tc* calls apparently do not
+ exist. The form of this call is:
+
+ int ioctl(fd, COMMAND, (int *)flags);
+
+ The COMMANDS and their action are:
+
+ o TIOCMBIS turn on control lines depending upon which bits are set
+ in flags.
+
+ o TIOCMBIC turn off control lines depending upon which bits are
+ unset in flags.
+ o TIOCMGET the appropriate bits are set in flags according to the
+ current status
+
+ o TIOCMSET the state of the UART is changed according to which bits
+ are set/unset in 'flags'
+
+ The bit pattern of flags refer to the following control lines:
+
+ o TIOCM_LE Line enable
+
+ o TIOCM_DTR Data Terminal Ready
+
+ o TIOCM_RTS Request to send
+
+ o TIOCM_ST Secondary transmit
+
+ o TIOCM_SR Secondary receive
+
+ o TIOCM_CTS Clear to send
+
+ o TIOCM_CAR Carrier detect
+
+ o TIOCM_RNG Ring
+
+ o TIOCM_DSR Data set ready
+
+ It should be noted that some of these bits are controlled by the modem
+ and the UART cannot change them but their status can be sensed by
+ TIOCMGET. Also, most Personal Computers do not provide hardware for
+ secondary transmit and receive.
+
+ There are also a pair of ioctl() to monitor these lines. They are
+ undocumented as far as I have learned. The commands are TIOCMIWAIT
+ and TCIOGICOUNT. They also differ between versions of the Linux
+ kernel.
+
+ See the lines.c file in my "serial_suite" for an example of how these
+ can be used see
+
+ 8. Process Groups
+
+ 8.1. Sessions
+
+ 8.2. Process Groups
+
+ Any newly created process inherits the Process Group of its creator.
+ The Process Group leader has the same PID as PGID.
+
+ 8.3. Controlling Terminal
+
+ There are a series of ioctl(2) and tc*(2) calls which can be used to
+ monitor or to change the process group to which the device is
+ attached.
+
+ 8.3.1. Get the foreground group process id.
+
+ If there is no foreground group, a number not representing an existing
+ process group is returned. On error, a -1 is returned and errno is
+ set.
+
+ int ioctl(fd, TIOCGPGRP, (pid_t *)pid);
+ int tcgetpgrp(fd, (pid_t *)pid);
+
+ 8.3.2. Set the foreground process group id of a terminal.
+
+ The fd must be the controlling terminal and be associated with the
+ session of the calling process.
+
+ int ioctl(fd, TIOCSPGRP, (pid_t *)pid);
+ int tcsetpgrp(fd, (pid_t *)pid);
+
+ 8.3.3. Get process group id.
+
+ int ioctl(fd, TIOCGPGRP, &(pid_t)pid);
+ int tcgetpgrp(fd, &(pid_t)pid);
+
+ 9. Lockfiles
+
+ Any process which accesses a serial device should first check for the
+ existence of lock file for the desired device. If such a lock lock
+ file exists, this means that the device may be in use by another
+ process.
+
+ Check my "libdevlocks-x.x.tgz" at
+ for an example of how these lock
+ files should be utilized.
+
+ 10. Additional Information
+
+ Check out my "serial_suite.tgz" for more information about programming
+ the serial ports at . There some
+ examples and some blurbs about setting up modems and comments about
+ some general considerations.
+
+ 11. Feedback
+
+ Please send me any corrections, questions, comments, suggestions, or
+ additional material. I would like to improve this HOWTO! Tell me
+ exactly what you don't understand, or what could be clearer. You can
+ reach me at via email. Please
+ include the version number of the Serial-Programming-HOWTO when
+ writing.
diff --git a/release/src/router/busybox/docs/autodocifier.pl b/release/src/router/busybox/docs/autodocifier.pl
index 68b6f3c058..576e31281c 100755
--- a/release/src/router/busybox/docs/autodocifier.pl
+++ b/release/src/router/busybox/docs/autodocifier.pl
@@ -1,4 +1,5 @@
#!/usr/bin/perl -w
+# vi: set sw=4 ts=4:
use strict;
use Getopt::Long;
@@ -36,6 +37,7 @@ sub beautify {
s/"\s*$//;
s/%/%%/g;
s/\$/\\\$/g;
+ s/\@/\\\@/g;
eval qq[ sprintf(qq{$_}) ]
} @line
);
@@ -48,11 +50,13 @@ sub pod_for_usage {
my $usage = shift;
# Sigh. Fixup the known odd-name applets.
+# Perhaps we can use some of APPLET_ODDNAME from include/applets.h ?
$name =~ s/dpkg_deb/dpkg-deb/g;
$name =~ s/fsck_minix/fsck.minix/g;
$name =~ s/mkfs_minix/mkfs.minix/g;
$name =~ s/run_parts/run-parts/g;
$name =~ s/start_stop_daemon/start-stop-daemon/g;
+ $name =~ s/ether_wake/ether-wake/g;
# make options bold
my $trivial = $usage->{trivial};
diff --git a/release/src/router/busybox/docs/busybox.net/FAQ.html b/release/src/router/busybox/docs/busybox.net/FAQ.html
index e0a7597813..7ed1394ce3 100644
--- a/release/src/router/busybox/docs/busybox.net/FAQ.html
+++ b/release/src/router/busybox/docs/busybox.net/FAQ.html
@@ -16,7 +16,7 @@ have additions to this FAQ document, we would love to add them,
Which architectures does BusyBox run on?
Which C libraries are supported?
Can I include BusyBox as part of the software on my device?
-Where can I find other small utilities since busybox does not include the features I want?
+Where can I find other small utilities since busybox does not include the features I want?
I demand that you to add <favorite feature> right now! How come you don't answer all my questions on the mailing list instantly? I demand that you help me with all of my problems Right Now !
I need help with BusyBox! What should I do?
I need you to add <favorite feature>! Are the BusyBox developers willing to be paid in order to fix bugs or add in <favorite feature>? Are you willing to provide support contracts?
@@ -40,25 +40,26 @@ have additions to this FAQ document, we would love to add them,
What are the goals of busybox?
What is the design of busybox?
- How is the source code organized?
-
+
I want to make busybox even smaller, how do I go about it?
Adding an applet to busybox
What standards does busybox adhere to?
Portability.
- Tips and tricks.
-
+
+
+ Who are the BusyBox developers?
@@ -179,12 +180,19 @@ within each applet. More build coverage testing.
during compilation. Only gcc and related binutils executables
are prefixed with $(CROSS_COMPILE) in the makefiles.
CROSS_COMPILE can be set on the command line:
+
make CROSS_COMPILE=arm-linux-uclibcgnueabi-
+
Alternatively CROSS_COMPILE can be set in the environment.
Default value for CROSS_COMPILE is not to prefix executables.
+
+ To store the cross-compiler in your .config, set the variable
+ CONFIG_CROSS_COMPILER_PREFIX accordingly in menuconfig or by
+ editing the .config file.
+
@@ -207,7 +215,7 @@ within each applet. More build coverage testing.
To learn how to build a working Linux system entirely from source code,
- the place to go is the Linux
+ the place to go is the Linux
From Scratch project. They have an entire book of step-by-step
instructions you can
read online
@@ -222,7 +230,7 @@ within each applet. More build coverage testing.
If you want an automated yet customizable system builder which produces
a BusyBox and uClibc based system, try
- buildroot , which is
+ buildroot , which is
another project by the maintainer of the uClibc (Erik Andersen).
Download the tarball, extract it, unset CC, make.
For more instructions, see the website.
@@ -308,9 +316,10 @@ within each applet. More build coverage testing.
BusyBox mailing list at busybox@busybox.net.
In addition to the mailing list, Erik Andersen (andersee), Manuel Nova
- (mjn3), Rob Landley (landley), Mike Frysinger (SpanKY), Bernhard Fischer
- (blindvt), and other long-time BusyBox developers are known to hang out
- on the uClibc IRC channel: #uclibc on irc.freenode.net. There is a
+ (mjn3), Rob Landley (landley), Mike Frysinger (SpanKY),
+ Bernhard Reutner-Fischer (blindvt), and other long-time BusyBox developers
+ are known to hang out on the uClibc IRC channel: #uclibc on
+ irc.freenode.net. There is a
web archive of
daily logs of the #uclibc IRC channel going back to 2002.
@@ -339,16 +348,6 @@ within each applet. More build coverage testing.
maintainer and ask them to recommend someone.
- If you prefer to deal with an organization rather than an individual, Rob
- Landley (the current BusyBox maintainer) works for
- TimeSys , and Eric Andersen (the previous
- busybox maintainer and current uClibc maintainer) owns
- CodePoet Consulting . Both
- companies offer support contracts and handle new development, and there
- are plenty of other companies that do the same.
-
-
-
Troubleshooting
@@ -358,7 +357,7 @@ within each applet. More build coverage testing.
If you simply need help with using or configuring BusyBox, please submit a
detailed description of your problem to the BusyBox mailing list at busybox@busybox.net .
+ href="mailto:busybox@busybox.net">busybox@busybox.net.
Please do not send email to individual developers asking
for private help unless you are planning on paying for consulting services.
When we answer questions on the BusyBox mailing list, it helps everyone,
@@ -371,7 +370,7 @@ within each applet. More build coverage testing.
only so much they can keep in their brains at a time. You can post a
polite reminder after 2-3 days without offending anybody. If that doesn't
result in a solution, please use the
- BusyBox Bug
+ BusyBox Bug
and Patch Tracking System to submit a detailed explanation and we'll
get to it as soon as we can.
@@ -386,7 +385,7 @@ within each applet. More build coverage testing.
-
+
Variants of this one get asked a lot.
@@ -395,7 +394,7 @@ and we're happy to respond to our users' needs. But if you're coming to the
list for free tech support we're going to ask you to upgrade to a current
version before we try to diagnose your problem.
-If you're building BusyBox 0.50 with uClibc 0.9.19 and gcc 0.9.26 there's a
+
If you're building BusyBox 0.50 with uClibc 0.9.19 and gcc 1.27 there's a
fairly large chance that whatever problem you're seeing has already been fixed.
To get that fix, all you have to do is upgrade to a newer version. If you
don't at least _try_ that, you're wasting our time.
@@ -509,7 +508,7 @@ int main(int argc, char *argv)
Busybox has nothing to do with the timezone. Please consult your libc
-documentation. (http://google.com/search?q=uclibc+glibc+timezone ).
+documentation. (http://google.com/search?q=uclibc+glibc+timezone ).
Development
@@ -785,9 +784,9 @@ successor to ibcs2: the 86open
project . That project disbanded in 1999 with the endorsement of an
existing standard: Linux ELF binaries. Since then, the major players at the
time (such as AIX , Solaris , and
-FreeBSD )
+href="http://www-03.ibm.com/servers/aix/products/aixos/linux/index.html">AIX, Solaris , and
+FreeBSD )
have all either grown Linux support or folded.
The major exceptions are newcomer MacOS X, some embedded environments
@@ -810,7 +809,7 @@ file is at least worth a look. Special-case code in the body of an applet is
something we're trying to avoid.
- Programming tips and tricks.
+
Various things busybox uses that aren't particularly well documented
elsewhere.
@@ -1048,7 +1047,8 @@ to measure).
Including kernel headers
-The "linux" or "asm" directories of /usr/include contain Linux kernel
+
The "linux" or "asm" directories of /usr/include
+contain Linux kernel
headers, so that the C library can talk directly to the Linux kernel. In
a perfect world, applications shouldn't include these headers directly, but
we don't live in a perfect world.
@@ -1058,7 +1058,7 @@ we don't live in a perfect world.
Attempts to cut and paste the information into a local busybox header file
proved incredibly painful, because portions of the loop_info structure vary by
architecture, namely the type __kernel_dev_t has different sizes on alpha,
-arm, x86, and so on. Meaning we either #include or
+arm, x86, and so on. Meaning we either #include <linux/posix_types.h> or
we hardwire #ifdefs to check what platform we're building on and define this
type appropriately for every single hardware architecture supported by
Linux, which is simply unworkable.
@@ -1066,7 +1066,8 @@ Linux, which is simply unworkable.
This is aside from the fact that the relevant type defined in
posix_types.h was renamed to __kernel_old_dev_t during the 2.5 series, so
to cut and paste the structure into our header we have to #include
- to figure out which name to use. (What we actually do is
+<linux/version.h> to figure out which name to use. (What we actually
+do is
check if we're building on 2.6, and if so just use the new 64 bit structure
instead to avoid the rename entirely.) But we still need the version
check, since 2.4 didn't have the 64 bit structure.
@@ -1075,8 +1076,9 @@ check, since 2.4 didn't have the 64 bit structure.
out a clean way to do all this. There isn't one. The losetup in the
util-linux package from kernel.org isn't doing it cleanly either, they just
hide the ugliness by nesting #include files. Their mount/loop.h
-#includes "my_dev_t.h", which #includes and
- just like we do. There simply is no alternative.
+#includes "my_dev_t.h", which #includes <linux/posix_types.h>
+and <linux/version.h> just like we do. There simply is no alternative.
+
Just because directly #including kernel headers is sometimes
unavoidable doesn't me we should include them when there's a better
@@ -1087,18 +1089,18 @@ is not a better way.
The following login accounts currently exist on busybox.net. (I.E. these
-people can commit patches
+people can commit patches
into subversion for the BusyBox, uClibc, and buildroot projects.)
-aldot :Bernhard Fischer
+aldot :Bernhard Reutner-Fischer
andersen :Erik Andersen - uClibc and BuildRoot maintainer.
bug1 :Glenn McGrath
davidm :David McCullough
gkajmowi :Garrett Kajmowicz - uClibc++ maintainer
jbglaw :Jan-Benedict Glaw
jocke :Joakim Tjernlund
-landley :Rob Landley - BusyBox maintainer
+landley :Rob Landley
lethal :Paul Mundt
mjn3 :Manuel Novoa III
osuadmin :osuadmin
@@ -1113,11 +1115,12 @@ solar :Ned Ludd
timr :Tim Riker
tobiasa :Tobias Anderberg
vapier :Mike Frysinger
+vda :Denys Vlasenko - BusyBox maintainer
The following accounts used to exist on busybox.net, but don't anymore so
-I can't ask /etc/passwd for their names. Rob Wentworth
-asked Google and recovered the names:
+I can't ask /etc/passwd for their names. Rob Wentworth
+<robwen at gmail.com> asked Google and recovered the names:
aaronl :Aaron Lehmann
diff --git a/release/src/router/busybox/docs/busybox.net/about.html b/release/src/router/busybox/docs/busybox.net/about.html
index 7b79afce9f..35809c3154 100644
--- a/release/src/router/busybox/docs/busybox.net/about.html
+++ b/release/src/router/busybox/docs/busybox.net/about.html
@@ -18,7 +18,7 @@ nodes in /dev, a few configuration files in /etc, and a Linux kernel.
BusyBox is maintained by
Denys Vlasenko ,
-and licensed under the GNU GENERAL PUBLIC LICENSE
+and licensed under the GNU GENERAL PUBLIC LICENSE
version 2.
diff --git a/release/src/router/busybox/docs/busybox.net/download.html b/release/src/router/busybox/docs/busybox.net/download.html
index b0bd6e3715..34195b6f16 100644
--- a/release/src/router/busybox/docs/busybox.net/download.html
+++ b/release/src/router/busybox/docs/busybox.net/download.html
@@ -14,29 +14,29 @@ Also there are patches on top of latest bug fix release.
Latest releases and patch directories for each branch:
-1.10.1 ,
-patches ,
+1.10.1 ,
+patches ,
-1.9.2 ,
-patches ,
+1.9.2 ,
+patches ,
-1.8.3 ,
-patches ,
+1.8.3 ,
+patches ,
-1.7.5 ,
-patches ,
+1.7.5 ,
+patches ,
-1.6.2 ,
-patches ,
+1.6.2 ,
+patches ,
-1.5.2 ,
-patches ,
+1.5.2 ,
+patches ,
-1.4.2 ,
-patches ,
+1.4.2 ,
+patches ,
-1.3.2 ,
-patches .
+1.3.2 ,
+patches .
You can also obtain Daily Snapshots of
@@ -44,7 +44,7 @@ the latest development source tree for those wishing to follow BusyBox developme
but cannot or do not wish to use Subversion (svn).
- Click here to browse the source tree .
+ Click here to browse the source tree .
Anonymous Subversion access is available.
diff --git a/release/src/router/busybox/docs/busybox.net/fix.html b/release/src/router/busybox/docs/busybox.net/fix.html
index 45621cde7f..7bd7fe0f47 100644
--- a/release/src/router/busybox/docs/busybox.net/fix.html
+++ b/release/src/router/busybox/docs/busybox.net/fix.html
@@ -5,7 +5,7 @@
If you found a regression or severe bug in busybox, and you have a patch
for it, and you want to see it added to "hot fixes", please rediff your
patch against corresponding unmodified busybox source and send it to
- the mailing list .
+ the mailing list .
diff --git a/release/src/router/busybox/docs/busybox.net/footer.html b/release/src/router/busybox/docs/busybox.net/footer.html
index 7f39ccb01a..0667092370 100644
--- a/release/src/router/busybox/docs/busybox.net/footer.html
+++ b/release/src/router/busybox/docs/busybox.net/footer.html
@@ -11,35 +11,39 @@
-
-
-
-
+
-
+
-
+
About
Development
Links
Developer Pages
-
-
-
-
-
+
diff --git a/release/src/router/busybox/docs/busybox.net/license.html b/release/src/router/busybox/docs/busybox.net/license.html
index 76358bc65b..2a4c51d103 100644
--- a/release/src/router/busybox/docs/busybox.net/license.html
+++ b/release/src/router/busybox/docs/busybox.net/license.html
@@ -1,7 +1,7 @@
-
BusyBox is licensed under the GNU General Public License, version 2
+
BusyBox is licensed under the
GNU General Public License version 2, which is often abbreviated as GPLv2.
@@ -11,7 +11,7 @@ familiar with it by now.)
A complete copy of the license text is included in the file LICENSE in
the BusyBox source code.
-Anyone thinking of shipping BusyBox as part of a
+Anyone thinking of shipping BusyBox as part of a
product should be familiar with the licensing terms under which they are
allowed to use and distribute BusyBox. Read the full test of the GPL (either
through the above link, or in the file LICENSE in the busybox tarball), and
@@ -25,17 +25,18 @@ you violate the license terms, and thus infringe on the copyrights of BusyBox.
(This requirement applies whether or not you modified BusyBox; either way the
license terms still apply to you.) Read the license text for the details.
-A note on GPL versions
+
Version 2 of the GPL is the only version of the GPL which current versions
of BusyBox may be distributed under. New code added to the tree is licensed
GPL version 2, and the project's license is GPL version 2.
Older versions of BusyBox (versions 1.2.2 and earlier, up through about svn
-16112) included variants of the recommended "GPL version 2 or (at your option)
-later versions" boilerplate permission grant. Ancient versions of BusyBox
+16112) included variants of the recommended
+"GPL version 2 or (at your option) later versions" boilerplate
+permission grant. Ancient versions of BusyBox
(before svn 49) did not specify any version at all, and section 9 of GPLv2
-(the most recent version at the time) says those old versions may be
+(the most recent version at that time) says those old versions may be
redistributed under any version of GPL (including the obsolete V1). This was
conceptually similar to a dual license, except that the different licenses were
different versions of the GPL.
@@ -43,7 +44,8 @@ different versions of the GPL.
However, BusyBox has apparently always contained chunks of code that were
licensed under GPL version 2 only. Examples include applets written by Linus
Torvalds (util-linux/mkfs_minix.c and util_linux/mkswap.c) which stated they
-"may be redistributed as per the Linux copyright" (which Linus clarified in the
+"may be redistributed as per the Linux copyright" (which Linus
+clarified in the
2.4.0-pre8 release announcement in 2000 was GPLv2 only), and Linux kernel code
copied into libbb/loop.c (after Linus's announcement). There are probably
more, because all we used to check was that the code was GPL, not which
@@ -59,18 +61,18 @@ versions such as release 1.2.2 or SVN 16112, and do your own homework to
identify and remove any code that can't be licensed under the GPL version you
want to use. New development is all GPLv2.
-License enforcement
+
BusyBox's copyrights are enforced by the Software Freedom Law Center
+href="http://www.softwarefreedom.org/">Software Freedom Law Center
(you can contact them at gpl@busybox.net), which
-"accepts primary responsibility for enforcement of US copyrights on the
+"accepts primary responsibility for enforcement of US copyrights on the
software... and coordinates international copyright enforcement efforts for
-such works as necessary." If you distribute BusyBox in a way that doesn't
+such works as necessary." If you distribute BusyBox in a way that doesn't
comply with the terms of the license BusyBox is distributed under, expect to
hear from these guys. Their entire reason for existing is to do pro-bono
legal work for free/open source software projects. (We used to list people who
-violate the BusyBox license in The Hall of Shame ,
+violate the BusyBox license in The Hall of Shame ,
but these days we find it much more effective to hand them over to the
lawyers.)
@@ -82,13 +84,13 @@ don't want monetary awards, injunctions, or to generate bad PR for a company,
unless that's the only way to get somebody that repeatedly ignores us to comply
with the license on our code.
-A Good Example
+
These days, Linksys is
doing a good job at complying with the GPL, they get to be an
example of how to do things right. Please take a moment and
check out what they do with
-
+
distributing the firmware for their WRT54G Router.
Following their example would be a fine way to ensure that you
have also fulfilled your licensing obligations.
diff --git a/release/src/router/busybox/docs/busybox.net/links.html b/release/src/router/busybox/docs/busybox.net/links.html
index 9cdbd7c8ce..14ad8d12ab 100644
--- a/release/src/router/busybox/docs/busybox.net/links.html
+++ b/release/src/router/busybox/docs/busybox.net/links.html
@@ -4,12 +4,12 @@
uClibc.org
uClibc++
-udhcp
+
buildroot
Scratchbox
OpenEmbedded
uCdot
-LinuxDevices
+LinuxDevices
Slashdot
Freshmeat
Linux Today
diff --git a/release/src/router/busybox/docs/busybox.net/lists.html b/release/src/router/busybox/docs/busybox.net/lists.html
index 3a28cc07e7..29c2f7472d 100644
--- a/release/src/router/busybox/docs/busybox.net/lists.html
+++ b/release/src/router/busybox/docs/busybox.net/lists.html
@@ -6,7 +6,7 @@
Mailing List Information
BusyBox has a mailing list for discussion and
development. You can subscribe by visiting
-this page .
+this page .
Only subscribers to the BusyBox mailing list are allowed to post
to this list.
@@ -14,7 +14,7 @@ to this list.
There is also a mailing list for active developers
wishing to read the complete diff of each and every change to busybox -- not for the
faint of heart. Active developers can subscribe by visiting
-this page .
+this page .
The Subversion server is the only one permtted to post to this list. And yes,
this list name uses the word 'cvs' even though we don't use that anymore...
diff --git a/release/src/router/busybox/docs/busybox.net/news.html b/release/src/router/busybox/docs/busybox.net/news.html
dissimilarity index 93%
index 74b0eb3381..8f756f088e 100644
--- a/release/src/router/busybox/docs/busybox.net/news.html
+++ b/release/src/router/busybox/docs/busybox.net/news.html
@@ -1,303 +1,517 @@
-
-
-
- 12 July 2008 -- BusyBox 1.11.1 (stable)
- BusyBox 1.11.1 .
- (svn ,
- patches ,
- how to add a patch )
-
- Bugfix-only release for 1.11.x branch. It contains fixes for awk,
- bunzip2, cpio, ifupdown, ip, man, start-stop-daemon, uname and vi.
-
-
- 11 July 2008 -- HOWTO is updated
-
-
- "How to build static busybox for i486-linux-uclibc" is updated
- and tested on a fresh Fedora 9 install. Please report if it doesn't
- work for you.
-
-
- 25 June 2008 -- BusyBox 1.11.0 (unstable), BusyBox 1.10.4 (stable)
- BusyBox 1.11.0 .
- (svn ,
- patches ,
- how to add a patch )
- BusyBox 1.10.4 .
- (svn ,
- patches ,
- how to add a patch )
- Sizes of busybox-1.10.4 and busybox-1.11.0 (with equivalent config, static uclibc build):
- text data bss dec hex filename
- 800675 636 7080 808391 c55c7 busybox-1.10.4
- 798392 611 6900 805903 c4c0f busybox-1.11.0
-
-
- New applets: inotify (Vladimir Dronnikov), man (Ivana Varekova),
- fbsplash (Michele Sanges), depmod (Bernhard Fischer)
-
-
Changes since previous release:
-
- build system: reinstate CONFIG_CROSS_COMPILE_PREFIX
- ash: optional bash compatibility features added; other fixes
- hush: lots and lots of fixes
- msh: fix the case where the file has exec bit but can't be run directly (runs "$SHELL file" instead)
- msh: fix exit codes when command is not found or can't be execed
- udhcpc: added workaround for buggy kernels
- mount: fix mishandling of proto=tcp/udp
- diff: make it work on non-seekable streams
- openvt: made more compatible with "standard" one
- mdev: fix block/char device detection
- ping: add -w, -W support (James Simmons)
- crond: add handling of "MAILTO=user" lines
- start-stop-daemon: make --exec follow symlinks (Joakim Tjernlund)
- date: make it accept ISO date format
- echo: fix echo -e -n "msg\n\0" (David Pinedo)
- httpd: fix several bugs triggered by relative path in -h DIR
- printf: fix printf -%s- foo, printf -- -%s- foo
- syslogd: do not error out on missing files to rotate
- ls: support Unicode in names
- ip: support for the LOWER_UP flag (Natanael Copa)
- mktemp: make argument optional (coreutil 6.12 compat)
- libiproute: fix option parsing, so that "ip -o link" works again
- other fixes and code size reductions in many applets
-
-
- The email address gpl@busybox.net is the recommended way to contact
- the Software Freedom Law Center to report BusyBox license violations.
-
-
- 12 June 2008 -- Sponsors!
- We want to thank the following companies which are providing support
- for BusyBox project:
-
-
-
- 5 June 2008 -- BusyBox 1.10.3 (stable)
- BusyBox 1.10.3 .
- (svn ,
- patches ,
- how to add a patch )
-
- Bugfix-only release for 1.10.x branch. It contains fixes for dnsd, fuser, hush,
- ip, mdev and syslogd.
-
-
- 8 May 2008 -- BusyBox 1.10.2 (stable)
- BusyBox 1.10.2 .
- (svn ,
- patches ,
- how to add a patch )
-
- Bugfix-only release for 1.10.x branch. It contains fixes for echo, httpd, pidof,
- start-stop-daemon, tar, taskset, tab completion in shells, build system.
-
Please note that mdev was backported from current svn trunk. Please
- report if you encounter any problems with it.
-
-
- 19 April 2008 -- BusyBox 1.10.1 (stable)
- BusyBox 1.10.1 .
- (svn ,
- patches ,
- how to add a patch )
-
- Bugfix-only release for 1.10.x branch. It contains fixes for
- fuser, init, less, nameif, tail, taskset, tcpudp, top, udhcp.
-
-
21 March 2008 -- BusyBox 1.10.0 (unstable)
- BusyBox 1.10.0 .
- (svn ,
- patches ,
- how to add a patch )
-
- Sizes of busybox-1.9.2 and busybox-1.10.0 (with almost full config, static uclibc build):
- text data bss dec hex filename
- 781405 679 7500 789584 c0c50 busybox-1.9.2
- 773551 640 7372 781563 becfb busybox-1.10.0
-
- Top 10 stack users:
-busybox-1.9.2: busybox-1.10.0:
-echo_dg 4116 bb_full_fd_action 4112
-bb_full_fd_action 4112 find_list_entry2 4096
-discard_dg 4108 readlink_main 4096
-discard_dg 4096 ipaddr_list_or_flush 3900
-echo_stream 4096 iproute_list_or_flush 3680
-discard_stream 4096 insmod_main 3152
-find_list_entry2 4096 fallbackSort 2952
-readlink_main 4096 do_iproute 2492
-ipaddr_list_or_flush 3900 cal_main 2464
-iproute_list_or_flush 3680 readhere 2308
-
-
- New applets: brctl, chat (by Vladimir Dronnikov <dronnikov AT gmail.com>),
- findfs, ifenslave (closes bug 115), lpd (by Vladimir Dronnikov <dronnikov AT gmail.com>),
- lpr+lpq (by Walter Harms), script (by Pascal Bellard <pascal.bellard AT ads-lu.com>),
- sendmail (Vladimir Dronnikov <dronnikov AT gmail.com>), tac, tftpd.
-
-
Made NOMMU-compatible: crond, crontab, ifupdown, inetd, init, runsv, svlogd, tcpsvd, udpsvd.
-
-
Changes since previous release:
-
- globally: add -Wunused-parameter
- globally: add optimization barrier to all "G trick" locations
- adduser/addgroup: check username for invalid chars (by Tito <farmatito AT tiscali.it>)
- adduser: optional support for long options. Closes bug 2134
- ash: handle "A=1 A=2 B=$A; echo $B". Closes bug 947
- ash: make ash -c "if set -o barfoo 2>/dev/null; then echo foo; else echo bar; fi" work. Closes bug 1142
- build system: don't use "gcc -o /dev/null", old gcc can delete /dev/null in this case
- build system: fixes for cross-compiling on an OS X host
- build system: make it do without "od -t"
- build system: pass CFLAGS to link stage too. Closes bug 1376
- build system: add CONFIG_NOMMU
- cp: add ENABLE_FEATURE_VERBOSE_CP_MESSAGE. Closes bug 1470
- crontab: almost complete rewrite
- dnsd: properly set _src_ IP:port on outgoing UDP packets
- dpkg: fix bug where existence check was reversed
- eject: add -s for SCSI- and USB-devices (Nico Erfurth)
- fdisk: fix a case where break was reached only for DOS labels
- fsck: don't kill pid -1! (Roy Marples <roy at marples.name>)
- fsck_minix: fix bug in map_block2: s/(blknr >= 256 * 256)/(blknr < 256 * 256)/
- fuser: substantial rewrite
- getopt: add support for "a+" specifier for nonnegative int parameters. By Vladimir Dronnikov <dronnikov at gmail.com>
- getty: don't try to detect parity on local lines (Joakim Tjernlund <Joakim.Tjernlund at transmode.se>)
- halt: write wtmp entry if wtmp support is enabled
- httpd: "HEAD" support. Closes bug 1530
- httpd: fix bug 2004: wrong argv when interpreter is invoked
- httpd: fix bug where we did chdir("") if CGI path had only one "/"
- httpd: fix for POST upload
- httpd: support for "I:index.xml" syntax (Peter Korsgaard <jacmet AT uclibc.org>)
- hush: fix a case where none of pipe members could be started because of fork failure
- hush: more correct handling of piping
- hush: reinstate `cmd` handling for NOMMU
- hush: report [v]fork failures
- hush: set CLOEXEC on script file being executed
- hush: try to add a bit more of vfork-friendliness
- inetd: make "udp nowait" work
- inetd: make inetd IPv6-capable
- init: add FEATURE_KILL_REMOVED (Eugene Bordenkircher <eugebo AT gmail.com>)
- init: allow last line of config file to be not terminated by "\n"
- init: do not die if "/dev/null" is missing
- init: fix bug 1111: restart actions were not splitting words
- init: wait for orphaned children too while waiting for sysinit-like processes (harald-tuxbox AT arcor.de)
- ip route: "ip route" was misbehaving (extra argv+1 ate 1st env var)
- last: do not go into endless loop on read error
- less,klogd,syslogd,nc,tcpudp: exit on signal by killing itself, not exit(1)
- less: "examine" command will not bomb out on bad file name now
- less: fix bug where backspace wasn't actually deleting chars
- less: make it a bit more resistant against status line corruption
- less: improve search when data is not supplied fast enough by stdin - now will try reading for 1-2 seconds before declaring that there is no match. This fixes a very common annoyance with long manpages
- less: update line input so that it doesn't interfere with screen update. Makes "man bash", [enter], [/], <enter search pattern>, [enter] more usable - manpage now draws even as you enter the pattern!
- libbb: filename completion matches dangling symlinks too
- libbb: fix getopt state corruption for NOFORK applets
- libbb: full_read/write now will report partial data counts prior to error
- libbb: intrduce and use safe_gethostname. By Tito <farmatito AT tiscali.it>
- libbb: introduce and use nonblock_safe_read(). Yay! Our shells are immune from this nasty O_NONBLOCK now!
- login,su: avoid clearing environment with some options, as was intended
- microcom: read more than 1 byte from device, if possible
- microcom: split -d (delay) option away from -t
- mktemp: support -p DIR (Timo Teras <timo.teras at iki.fi>)
- mount: #ifdef out MOUNT_LABEL code parts if it is not selected
- mount: add another mount helper call method
- mount: allow and ignore _netdev option
- mount: make -f work even without mtab support (Cristian Ionescu-Idbohrn <cristian.ionescu-idbohrn at axis.com>)
- mount: optional support for -vv verbosity
- mount: plug a hole where FEATURE_MOUNT_HELPERS could allow execution of arbitrary command
- mount: recognize "dirsync" (closes bug 835)
- mount: sanitize environment if called by non-root
- mount: support for mount by label. Closes bug 1143
- mount: with -vv -f, say what mount() calls we were going to make
- msh: create testsuite (based on hush one)
- msh: don't use floating point in "times" builtin
- msh: fix Ctrl-C handling with line editing
- msh: fix for bug 846 ("break" didn't work second time)
- msh: glob0/glob1/glob2/glob3 were just a sorting routine, removed
- msh: instead of fixing "ls | cd", "cd | ls" etc disallow builtins in pipes. They make no sense there anyway
- msh: stop trying to parse variables in "msh SCRIPT VAR=val param". They are passed as ordinary parameters
- netstat: print control chars as "^C" etc
- nmeter: fix bug where %[mf] behaves as %[mt]
- nohup: compat patch by Christoph Gysin <mailinglist.cache at gmail.com>
- od: handle /proc files (which have filesize 0) correctly
- patch: don't trash permissions of patched file
- ps: add conditional support for -o [e]time
- ps: fix COMMAND column adjustment; overflow in USER and VSZ columns
- reset: call "stty sane". Closes bug 1414
- rmdir: optional long options support for Debian users. By Roberto Gordo Saez <roberto.gordo AT gmail.com>
- run-parts: add --reverse
- script: correctly handle buffered "tail" of output
- sed: "n" command must reset "we had successful subst" flag. Closes bug 1214
- sort: -z outputs NUL terminated lines. Closes bug 1591
- stty: fix mishandling of control keywords (Ralf Friedl <Ralf.Friedl AT online.de>)
- switch_root: stop at first non-option. Closes bug 1425
- syslogd: avoid excessive time() system calls
- syslogd: don't die if remote host's IP cannot be resolved. Retry resolutions every two minutes instead
- syslogd: fix shmat error check
- syslogd: optional support for dropping dups. Closes bug 436
- syslogd: send "\n"-terminated messages over the network. Fully closes bug 1574
- syslogd: tighten up hostname handling
- tail: fix "tail -c 20 /dev/huge_disk" (was taking ages)
- tar: compat: handle tarballs with only one zero block at the end
- tar: autodetection of gz/bz2 compressed tarballs. Closes bug 992
- tar: real support for -p. By Natanael Copa <natanael.copa at gmail.com>
- tcpudp: narrow down time window where we have no wildcard socket
- telnetd: use login always, not "sometimes login, sometimes shell"
- test: fix mishandling of "test ! arg1 op arg2 more args"
- trylink: instead of build error, disable --gc-sections if GLIBC and STATIC are selected
- udhcp: make file paths configurable
- udhcp: optional support for non-standard DHCP ports
- udhcp: set correct op byte in the packet for DHCPDECLINE
- udhcpc: filter unwanted packets in kernel (Cristian Ionescu-Idbohrn <cristian.ionescu-idbohrn AT axis.com>)
- udhcpc: fix wrong options in decline and release packets (Jonas Danielsson <jonas.danielsson AT axis.com>)
- umount: do not complain several times about the same mountpoint
- umount: do not try to free loop device or erase mtab if remounted ro
- umount: instead of non-standard -D, use -d with opposite meaning. Closes bug 1604
- unlzma: shrink by Pascal Bellard <pascal.bellard AT ads-lu.com>
- unzip: do not try to read entire compressed stream at once (it can be huge)
- unzip: handle short reads correctly
- vi: many fixes
- zcip: don't chdir to root
- zcip: open ARP socket before openlog (else we can trash syslog socket)
-
-
-
- 21 March 2008 -- BusyBox old stable releases
-
- Bugfix-only releases for four past branches. Links to locations
- for future hot patches are in parentheses.
-
- 1.9.2
- (patches ),
- 1.8.3
- (patches ),
- 1.7.5
- (patches ),
- 1.5.2
- (patches ).
-
- How to add a patch.
-
-
- Old News
- Click here to read older news
-
-
-
-
-
-
-
-
+
+
+
+
+
+ We want to thank the following companies which are providing support for the BusyBox project:
+
+
+
+
+ 15 April 2009 -- BusyBox 1.14.0 (unstable), BusyBox 1.13.4 (stable)
+ BusyBox 1.14.0 .
+ (svn ,
+ patches ,
+ how to add a patch )
+ BusyBox 1.13.4 .
+ (svn ,
+ patches ,
+ how to add a patch )
+
+ Sizes of busybox-1.13.4 and busybox-1.14.0 (with equivalent config, static uclibc build):
+ text data bss dec hex filename
+ 785501 483 7036 793020 c19bc busybox.1.13.4/busybox
+ 788380 467 6960 795807 c249f busybox.1.14.0/busybox
+ 15361 0 0 15361 3c01 busybox.1.13.4/shell/hush.o
+ 20724 0 0 20724 50f4 busybox.1.14.0/shell/hush.o
+
+ Most of growth is in hush. The rest shrank a bit.
+
+
New applets:
+
+ flash_eraseall: by Sebastian Andrzej Siewior (bigeasy AT linutronix.de)
+ acpid,mkdosfs (aka mkfs.vfat),tunctl: by Vladimir
+ ftpd: by Adam Tkac
+ timeout: by Roberto Foglietta
+ ionice: adapted from Linux kernel' example by Walter Harms
+ mkpasswd: synonym to cryptpw. mkpasswd is in Debian, OTOH cryptpw was added to busybox earlier. Trying to make both camps happy by making those two applets just aliases. They are command-line compatible
+
+
+ Changes since previous release:
+
+
lash and msh are deprecated, please migrate to hush.
+
+
hush had many, many fixes and features added: here documents, arithmetic evaluation, function support, and all this works on NOMMU too, safely: 100kb-sized `command` and heredocs. Here document support, arithmetic evaluation, improved ${var} ops, other fixes are by Mike Frysinger (vapier AT gentoo.org).
+
+
Other changes:
+
+ libbb: unify concurrent-safe update of /etc/{passwd,group,[g]shadow}. By Tito (farmatito AT tiscali.it)
+ libbb/sha1/256/512: major code shrink
+ libbb/lineedit: make history saving/loading concurrent-safe
+ libbb: shrink linked list ops. By xmaks AT email.cz
+ libbb: str2sockaddr shuld accept [IPv6] addr without port - wget 'ftp://[::1]/file' needs that to work
+ libbb: make bb_info_msg do atomic, unbuffered writes
+ adduser: allow adding to group 0; don't _create_ /etc/shadow, only append data if it exists
+ ash: fix mishandled ^C
+ ash: fix "ash -c 'exec 1>&0'" complaining that fd 0 is busy
+ ash: fix $IFS handling in read. Closes bug 235
+ ash: fix a case where we close wrong descriptor
+ ash: fix bad interaction between ash -c '....&' and bash compat
+ ash: fix miscalculation of memory needed for eval tree. Found by Timo Teras (timo.teras AT iki.fi)
+ ash: in dotrap(), do not clear gotsig[] for SIGINT if there is no handler for it, otherwise raise interrupt gets confused later
+ ash: make dot command search current directory first, as bash does
+ ash: make evaltree save/restore int suppression depth. Hopefully this fixes bug 189
+ ash: printf builtin with no arguments should not exit
+ awk: fix long field separators case. By Ian Wienand (ianw AT vmware.com)
+ awk: in BEGIN section $0 should be "", not "0"
+ awk: make "struct global" hack more robust wrt alignment. Closes bug 131
+ brctl: fix compilation on 2.4.x kernels
+ chat: treat timeout more correctly
+ chat: recognize RECORD directive
+ cksum, printenv: report errors via exitcode
+ cpio: add -p, -0 and -L options
+ crond,crontab: make cron directory location configurable
+ crond: correct more of logfile to 0666 (as usual, umask allows user to remove unwanted bits)
+ crond: put tasks in separate process groups
+ dc: fix the "base 2" patch omission of base not being set
+ depmod: accept and ignore -r. Linux kernel build needs this
+ depmod: fix -b option. By timo.teras AT iki.fi
+ udhcpd,dumpleases: write and use 64-bit current time in lease file. without it, determination of remaining lease time is unreliable
+ udhcpd: remember and record hostnames
+ dhcprelay: fix usage text. Simplify and make code more readable
+ dumpleases: fix -a option; show hostnames
+ udhcpc: fix a problem where we don't open listening socket fast enough
+ udhcpc: stop filtering environment passed to the script
+ udhcpd: add code which rejects lease files with suspicious or old timestamp
+ udhcpd: disable opton to have absolute lease times in lease file (that does not work with dumpleases)
+ dnsd: fix a number of bugs. Ideas by Ming-Ching Tiew (mctiew AT yahoo.com)
+ dpkg: better and shorter code to compare versions. Taken from "official" dpkg by Eugene T. Bordenkircher (eugebo AT gmail.com)
+ du: fix "du /dir /dir" case
+ env: support -uVAR=VAL
+ expand: fix incorrect expansion exactly on tab boundary; shrink the code
+ expr: a bit more robust handling of regexps with groups. Closes bug 87
+ find: support --mindepth
+ getty: fix handling of speed 0; stop using non-portable way of setting speeds
+ grep: support -z
+ gzip: fix gzip -dc bug caused by using stale getopt state
+ head: report file open errors with exitcode 1 (was happily returning 0)
+ httpd: set $HOST to Host: header value. By Tobias Poschwatta (tp AT fonz.de)
+ ifupdown: allow options to udhcpc to be configurable from .config
+ init: do not eat last char in messages; do not print duplicate "init:" prefix to syslog
+ init: fix a bug where on reload order of entries might be wrong
+ init: major improvement in documentation and signal handling. Lots of nasty, but hard to trip, races are fixed
+ init: reinstate proper handling of !ENABLE_FEATURE_USE_INITTAB
+ init: remove wait loop on restart, it may be dangerous
+ init: test for vt terminal with VT_OPENQRY, assume that anything else is TERM=vt102, not TERM=linux. Closes bug 195
+ inotifyd: add x, o, and u events
+ inotifyd: fix buffer overflow and "unreaped zombies" problem
+ inotifyd: exit if x event happened for all files
+ inotifyd: conserve resourses by closing unused inotify descriptors
+ insmod/modprobe: do not pass NULL to kernel as module parameter
+ ip: in "ip rule add from all table 1", "all" is taken as 0.0.0.0/32, whereas "any" and "default" would be 0.0.0.0/0. They must be all 0.0.0.0/0. Closes bug 57
+ iproute: fix ipXXX utilities trying to parse their applet name as their 1st parameter
+ klogctl: fix a problem where we don't terminate read data with '\0' and then misinterpret it
+ ls: do not follow links with -s. Closes bug 33
+ ls: implement -Q and -g (-g was accepted but ignored)
+ ls: make readlink error to not disrupt output (try ls -l /proc/self/fd)
+ man: better check for duplicated MANPATH
+ mdev: add support for - ("dont stop here") char
+ mdev: if /sys/class/block exists, don't scan /sys/block
+ mdev: ignore events with "$SUBSYSTEM" == "firmware" && "$ACTION" == "remove"
+ mdev: provide $SUBSYSTEM. By Vladimir
+ modprobe/insmod for 2.4: support compressed modules. By Guenter (lists AT gknw.net)
+ modprobe: emit "can't open 'modules.dep': (errno)" instead of "module not found"
+ modprobe: rework/speedup by Timo Teras (timo.teras AT iki.fi)
+ modutils-24: fix bad interaction of xzalloc with xrealloc_vector
+ mount: support "-O option"
+ mount: stop trying to mount swap partitions
+ mount: fix CIFS support
+ mountpoint: add -n option. By Vladimir
+ nslookup: allow usage of IPv6 addresses or hostnames for DNS server name; allow for port specification. Tested to work: "nslookup google.com [::1]:5353". glibc + IPv6 address of DNS server still does not work
+ popmaildir: fix several grave bugs with using memory past end of malloc block
+ printf: fix 1.12.0 breakage (from %*d fix), it was misinterpreting "*"
+ printf: make integer format strings print long long-sized values
+ rmmod: fix bug 263 "modutils/rmmod can't remove modules with dash in name on 2.4 kernels"
+ sendmail: document and fix usage of fd #4, fix check for helper failure
+ sendmail: update by Vladimir
+ seq: add -w support. By Natanael Copa
+ seq: add support for "-s separator"
+ stat: make stat -f show filesystem "ID:" as coreutils does
+ sysctl: fix another corner case with "dots and slashes"
+ sysctl: fix broken -p [file]. Closes bug 231
+ sysctl: support recursing if name is a directory: "sysctl net.ipv4.conf". Patch by xmaks AT email.cz
+ syslogd: comment out file locking; make signal handling syncronous
+ syslogd: create logfile with 0666 (affected by umask as usual), not 0600
+ tail: fix tail +N syntax not working. Closes bug 221
+ tar: do not change new tarfile's mode, GNU tar doesn't do it
+ tar: support GNU tar's "base256" encoding
+ telnetd: correctly output 0xff char
+ telnetd: do not advertise TELNET_LFLOW, we do not support it properly
+ tftp: when we infer local name from remote (-r [/]path/path/file), strip path. This mimics wget and is generally more intuitive
+ timeout: fix parsing of -t NUM on MMU
+ top: make it work again on 2.4 kernels. Closes bug 125
+ tr: fix overflow in expand and complement, fix stop after [:class:]
+ tr: support -C as synonym to -c
+ tr: support [:xdigit:], fix handling of ranges and [x]'s
+ traceroute: rewrite. Do not emit raw IP packets, instead send UDP or ICMP packets and rely on the kernel to form IP headers, select source IP and interface
+ uname: add support for -i and -o, fix printing of unknown -p value with -a option
+ uname: support long options
+ unexpand: fix incorrect expansion
+ unzip: fix thinko with le/be conv and size. Closes bug 129
+ vi: fix several instances of major goof: when text grows, text[] might get reallocated! We were keeping around pointers to old place
+ vi: speedup and code shrink. By Walter Harms
+ volume_id: abort early on read failures. Should help with probing missing fdd's
+ volumeid: fix bug 249 "findfs finds the wrong partition"
+ wget: --post-data support. By Harald Kuthe (harald-tuxbox AT arcor.de)
+ wget: fix --header handling
+ wget: more robust EINTR detection
+
+
+
+ 8 March 2009 -- BusyBox 1.13.3 (stable)
+ BusyBox 1.13.3 .
+ (svn ,
+ patches ,
+ how to add a patch )
+
+ 1.13.3 is a bug fix release. It has fixes for awk, depmod, init, killall, mdev,
+ modprobe, printf, syslogd, tar, top, unzip, wget.
+
+
+
+ 31 December 2008 -- BusyBox 1.13.2 (stable), BusyBox 1.12.4 (stable)
+ BusyBox 1.13.2 .
+ (svn ,
+ patches ,
+ how to add a patch )
+ BusyBox 1.12.4 .
+ (svn ,
+ patches ,
+ how to add a patch )
+
+ Bug fix releases. 1.13.2 has fixes for crond, dc, init, ip, printf.
+ 1.12.4 has fixes for ip and printf.
+
+
+
+ 29 November 2008 -- BusyBox 1.13.1 (stable), BusyBox 1.12.3 (stable)
+ BusyBox 1.13.1 .
+ (svn ,
+ patches ,
+ how to add a patch )
+ BusyBox 1.12.3 .
+ (svn ,
+ patches ,
+ how to add a patch )
+
+ Bug fix releases. 1.13.1 has fixes for ash, option parsing, id, init,
+ inotifyd, klogd, line editing and modprobe. 1.12.3 has fixes
+ for option parsing and line editing.
+
+
+
+ 10 November 2008 -- BusyBox 1.13.0 (unstable), BusyBox 1.12.2 (stable)
+ BusyBox 1.13.0 .
+ (svn ,
+ patches ,
+ how to add a patch )
+ BusyBox 1.12.2 .
+ (svn ,
+ patches ,
+ how to add a patch )
+
+ Sizes of busybox-1.12.2 and busybox-1.13.0 (with equivalent config, static uclibc build):
+ text data bss dec hex filename
+ 778291 551 7856 786698 c010a busybox-1.12.2/busybox
+ 778981 551 7852 787384 c03b8 busybox-1.13.0/busybox
+
+
+ New applets: blkid, devmem
+
+
Changes since previous release:
+
+ mail applets: total overhaul. Vladimir as usual
+ ash: fix "while kill -0 $child; do true; done" looping forever
+ ash: fix NOEXEC mode - we were forgetting to pass environment
+ ash: fix a bug in standalone mode (corrupted getopt state)
+ ash: optionally support ">&file" and "&>file" redirections
+ awk: bitwise ops cast oprands and results to unsigned long, not signed. closes bug 4774
+ awk: fix typo in atan2 code. closes bug 5594
+ awk: improve handling of negative numbers in bitwise ops; fix handling of octal costants
+ awk: support hex constants
+ basename: fix error code (again)
+ cpio: emit TRAILER even when hard links were found. By Pascal Bellard (pascal.bellard AT ads-lu.com)
+ crontab: do not destroy STDIN_FILENO, editor may need it (crontab -e)
+ dc: support for bases 2 and 8, by Nate Case (ncase AT xes-inc.com)
+ dhcpc: treat "discover...select...discover..." loop the same way as "discover...discover...discover..."
+ dpkg: add dpkg -l PACKAGE_PATTERN. By Peter Korsgaard
+ fbset: fix mode matching code: original code may trigger false positive.
+ findfs: fix LUKS and FAT detection routines; do not exit if corrupted FAT fs makes us try to seek past the end
+ grep: fix 'echo aaa | grep -o a' + ENABLE_EXTRA_COMPAT case. By Natanael Copa
+ grep: fix EXTRA_COMPAT grep to honor -E and -i
+ gunzip: restore mtime
+ halt: reinstate -w even if !FEATURE_WTMP
+ hexdump: fix SEGV in hexdump -e ""
+ httpd: pass "Accept:" and "Accept-Language:" header to CGI scripts (Alina Friedrichsen)
+ hush: fix environment and memory leaks
+ hush: fix trashing of environment by local env vars: a=a; a=b cmd; - a was unset
+ id: improve compatibility with coreutils. By Tito Ragusa
+ inetd: fix a case when we have zero services
+ inetd: use config parser. by Vladimir
+ init: set stderr to NONBLOCK
+ insmod: fix detection of open failure
+ install: support -D
+ ip: fix ip route rejecting dotted quads as prefix
+ ip: route metric support (Natanael Copa)
+ iplink: accept shorthands for "address" keyword: "ip link set address 00:11:22:33:44:55"
+ kbd_mode: support -C TTY
+ kill[all[5]]: accept -s SIG too. By Steve Bennett (steveb AT workware.net.au)
+ klogd: handle many lines at once. By Steve Bennett (steveb AT workware.net.au)
+ less: support -I to be able to search case-insensitively
+ less: add optional line number toggle and resizing on window resize
+ libbb: do not reject floating point strings like ".15"
+ lineedit: fix bug 5824 "since rev 23530 fdisk and ed don't work any more"
+ lineedit: fix problems with empty commands in history
+ login: fix /etc/nologin handling
+ man: fix inconsistencies in handling $MANPATH
+ mdev: support match by major,minor. See bug 4714
+ modprobe-small: make insmod command line compatible
+ modprobe-small: support "blacklist" keyword in /etc/modules/MODULE_NAME
+ modprobe: fix a segfault when modprobe is called with no arguments at all
+ modutils/*: rewrite by Timo Teras (timo.teras AT iki.fi)
+ mount: fix "-o parm1 -o parm2" not accumulating
+ nmeter: 4k buffers are too small for /proc files, make them dynamically sized with 16k upper limit
+ ping: SO_RCVBUF must be bigger than packet size, otherwise large ping packets might fail to be received
+ route: fix for 64-bit BE machines by Seonghun Lim (wariua AT gmail.com)
+ rpm: fix incompatibilities which prevented rpm -i foo.src.rpm
+ runsvdir: support runsvdir-as-init
+ setarch: do not try to use non-existent data in argv[]
+ setfont: support -m and -C, support -m TEXTUAL_MAP (by Vladimir)
+ setup_environment: cd $HOME regardless of clear_env value
+ slattach: preserve speed in non-raw mode. By Matthieu Castet (matthieu.castet AT parrot.com)
+ start_stop_daemon: accept (and ignore) -R PARAM
+ sv: make default service dir configurable (Vladimir wants it)
+ sysctl: fix bug 3894 (by Kryzhanovskyy Maksym)
+ tar: fix bug 3844: non-root tar does not preserve perms
+ telnetd: handle emacs M-DEL and IAC-NOP. by Jim Cathey (jcathey AT ciena.com)
+ top: fix "top -d 1" (bug 5144)
+ top: optional SMP support by Vineet Gupta (vineetg76 AT gmail.com)
+ trylink: make messages less confusing
+ unzip: handle "central directory". needed for OpenOffice, gmail attachment .zips etc
+ vi: Rob's algorithm of reading and matching ESC sequences (nice work btw!)
+ vi: deal with EOF/error on stdin and with input NULs
+ vi: fix uninitialized last_search_pattern (bug 5794)
+ vi: handle chars 0x80, 0x81 etc correctly
+ volume identification: abolish /proc/partitions and /proc/cdroms scanning. It does not catch volume managers and such. Simply scan /dev/* for any block devices
+ watchdog: WDIOC_SETTIMEOUT accepts seconds, not milliseconds
+ watchdog: add -T option
+
+
+ The email address gpl@busybox.net is the recommended way to contact
+ the Software Freedom Law Center to report BusyBox license violations.
+
+
+
+ 28 September 2008 -- BusyBox 1.12.1 (stable), BusyBox 1.11.3 (stable)
+ BusyBox 1.12.1 .
+ (svn ,
+ patches ,
+ how to add a patch )
+ BusyBox 1.11.3 .
+ (svn ,
+ patches ,
+ how to add a patch )
+
+ Bugfix-only releases for 1.11.x and 1.12.x branches.
+
+
+
+ 21 August 2008 -- BusyBox 1.12.0 (unstable), BusyBox 1.11.2 (stable)
+ BusyBox 1.12.0 .
+ (svn ,
+ patches ,
+ how to add a patch )
+ BusyBox 1.11.2 .
+ (svn ,
+ patches ,
+ how to add a patch )
+
+ Sizes of busybox-1.11.2 and busybox-1.12.0 (with equivalent config, static uclibc build):
+ text data bss dec hex filename
+ 829687 617 7052 837356 cc6ec busybox-1.11.2/busybox
+ 822961 594 6832 830387 cabb3 busybox-1.12.0/busybox
+
+
+ New applets: rdev (Grant Erickson), setfont, showkey (both by Vladimir)
+
+
Most significant changes since previous release (please report any regression):
+
+ ash: bash compat: "shift $BIGNUM" is equivalent to "shift 1"
+ ash: dont allow e.g. exec <&10 to attach to script's fd!
+ ash: fix a bug where redirection fds were not closed afterwards. optimize close+fcntl(DUPFD) into dup2
+ ash: fix segfault in "command -v"
+ ash: fix very weak $RANDOM generator
+ ash: prevent exec NN>&- from closing fd used for script reading
+ ash: teach ash about 123>file. It could take only 0..9 before
+ hush: fix a case where "$@" must expand to no word at all
+ hush: fix mishandling of a'b'c=fff as assignments. They are not
+ hush: fix non-detection of builtins and applets in "v=break; ...; $v; ..." case
+ hush: fix "while false; ..." exitcode; add testsuites
+ hush: support "case...esac" statements (~350 bytes of code)
+ hush: support "break [N]" and "continue [N]" statements
+ hush: support "for if in do done then; do echo $if; done" case
+ hush: support "for v; do ... done" syntax (implied 'in "$@"')
+ hush: support $_NUMBERS variable names
+ libbb: unified config parser (by Vladimir). This change affected many applets
+
+
+ Other changes:
+
+ libbb: dump: do not use uninitialized memory (closes bug 4364)
+ libbb: fix bb_strtol[l]'s check for "-" (closes bug 4174)
+ libbb: fix --help to not affect "test --help"
+ libbb: fix mishandling of "all argv are opts" in getopt32()
+ libbb: getopt32() should not ever touch argv[0] (even read)
+ libbb: introduce and use xrealloc_vector
+ libbb: [x]fopen_for_{read,write} introduced and used (by Vladimir)
+ lineedit: fix use-after-free
+ libunarchive: refactor handling of archived files. "tar f file.tar.lzma" now works too
+ bb_strtoXXX: close bug 4174 (potential use of buf[-1])
+ open_transformer: don't leak file descriptor
+ open_transformer: fix bug of calling exit instead of _exit
+ arp: without -H type, assume "ether" (closes bug 4564)
+ ar: reuse existing ar unpacking code
+ awk: fix a case with multiple -f options. Simplify -f file reading.
+ build system: introduce and use FAST_FUNC: regparm on i386, otherwise no-op
+ bunzip2: fix an uncompression error (by Rob Landley rob AT landley.net)
+ b[un]zip2, g[un]zip: unlink destination if -f is given (closes bug 3854)
+ comm: almost total rewrite
+ cpio: fix -m to actually work as expected (by Pascal Bellard)
+ cpio: internalize archive_xread_all_eof, add a few paranoia checks for corrupted cpio files
+ cpio: make long opts depend only on ENABLE_GETOPT_LONG
+ cpio: on unpack, limit filename length to 8k
+ cpio: support some long options
+ crond: use execlp instead of execl
+ cut: fix buffer overflow (closes bug 4544)
+ envdir: fix "envdir" (no params at all) and "envdir dir" cases
+ findfs: make it use setuid-ness of busybox binary
+ fsck: use getmntent_r instead of open-coded parsing (by Vladimir)
+ fuser: a bit of safety in scanf
+ grep: option to use GNU regex matching instead of POSIX one. This fixes problems with NULs in files being scanned, but costs +800 bytes
+ halt: signal init regardless of ENABLE_INIT
+ httpd: add homedir directive specially for (and by) Walter Harms wharms AT bfs.de
+ ifupdown: /etc/network/interfaces can have comments with leading blanks
+ ifupdown: fixes for custom MAC address (by Wade Berrier wberrier AT gmail.com)
+ ifupdown: fixes for shutdown of DHCP-managed interfaces (by Wade Berrier wberrier AT gmail.com)
+ inetd: do not trash errno in signal handlers; in CHLD handler, stop looping through services when pid is found
+ insmod: users report that "|| defined(__powerpc__)" is missing
+ install: do not chown intermediate directories with install -d (by Natanael Copa)
+ install: fix long option not taking params (closes bug 4584)
+ lpd,lpr: send/receive ACKs after filenames, not only after file bodies
+ ls: fix a bug where we may use uninintialized variable
+ man: add handling of "man links", by Ivana Varekova varekova AT redhat.com
+ man: fix a case when a full pathname to manpage is given
+ man: fix inverted cat/man bool variable
+ man: fix missed NULL termination of an array
+ man: mimic "no manual entry for 'bogus'" message and exitcode
+ man: support cat pages too (by Jason Curl jcurlnews AT arcor.de)
+ man: teach it to use .lzma if requested by .config
+ mdev: check for "/block/" substring for block dev detection
+ mdev: do not complain if mdev.conf does not exist
+ mdev: if device was moved at creation, at removal correctly remove it from moved location and also remove symlinks to it
+ mdev: support for serializing hotplug
+ mdev, init: use shared code for fd sanitization
+ mkdir: fix "uname 0222; mkdir -p foo/bar" case (by Doug Graham dgraham AT nortel.com)
+ modprobe: support for /etc/modprobe.d (by Timo Teras)
+ modprobe: use buffering line reads (fgets()) instead of reads()
+ modutils: optional modprobe-small (by Vladimir), 15kb smaller than standard one
+ mount: support for "-o mand" and "[no]relatime"
+ mount: support nfs mount option "nordiplus" (by Octavian Purdila opurdila AT ixiacom.com)
+ mount: support "relatime" / "norelatime"
+ mount: testsuite for "-o mand"
+ msh: fix "while... continue; ..." (closes bug 3884)
+ mv: fix a case when we move dangling symlink across mountpoints
+ netstat: optional -p support (by L. Gabriel Somlo somlo AT cmu.edu)
+ nmeter: fix read past the end of a buffer (closes bug 4594)
+ od, hexdump: fix bug where xrealloc may move pointer, leaving other pointers dangling (closes bug 4104)
+ pidof/killall: allow find_pid_by_name to find running processes started as scripts_with_name_longer_than_15_bytes.sh (closes bug 4054)
+ printf: do not print garbage on "%Ld" (closes bug 4214)
+ printf: fix %b, fix several bugs in %*.*, fix compat issues with aborting too early, support %zd; expand testsuite
+ printf: protect against bogus format specifiers (closes bug 4184)
+ sendmail: updates from Vladimir:
+ sendmail: do not discard all headers
+ sendmail: do not ignore CC; accept to: and cc: case-insensitively. +20 bytes
+ sendmail: fixed mail recipient address
+ sendmail: fixed SEGV if sender address is missed
+ sendmail: use HOSTNAME instead of HOST when no server is explicitly specified
+ sleep: if FANCY && DESKTOP, support fractional seconds, minutes, hours and so on (coreutils compat)
+ ssd: CLOSE_EXTRA_FDS in MMU case too
+ ssd: do not stat -x EXECUTABLE, it is not needed anymore
+ ssd: fix -a without -x case
+ ssd: use $PATH
+ tar: fix handling of tarballs with symlinks with size field != 0
+ tar: handle autodetection for tiny .tar.gz files too, simplify autodetection
+ taskset: fix some careless code in both fancy and non-fancy cases. -5 bytes for fancy, +5 for non-fancy
+ tee: fix infinite looping on open error (echo asd | tee "")
+ tee: "-" is a name for stdout, handle it that way
+ telnetd: fix issue file printing
+ test: fix parser to prefer binop over unop, as coreutils does
+ testsuite: uniformly use $ECHO with -n -e
+ time: don't segfault with no arguments
+ touch: support -r REF_FILE if ENABLE_DESKTOP (needed for blackfin compile)
+ tr: fix "access past the end of a string" bug 4354
+ tr: fix "tr [=" case (closes bug 4374)
+ tr: fix yet another access past the end of a string (closes bug 4374)
+ unlzma: fix memory leak (by Pascal Bellard)
+ vi: fix reversed checks for underflow
+ vi: using array data after it fell out of scope is stupid
+ xargs: fix -e default to match newer GNU xargs, add SUS mandated -E (closes bug 4414)
+ other fixes and code size reductions in many applets
+
+
+
+ 12 July 2008 -- BusyBox 1.11.1 (stable)
+ BusyBox 1.11.1 .
+ (svn ,
+ patches ,
+ how to add a patch )
+
+ Bugfix-only release for 1.11.x branch. It contains fixes for awk,
+ bunzip2, cpio, ifupdown, ip, man, start-stop-daemon, uname and vi.
+
+
+
+ 11 July 2008 -- HOWTO is updated
+
+
+ "How to build static busybox for i486-linux-uclibc" is updated
+ and tested on a fresh Fedora 9 install. Please report if it doesn't
+ work for you.
+
+
+
+
+
+ Old News
+ Click here to read older news
+
+
+
+
+
+
+
diff --git a/release/src/router/busybox/docs/busybox.net/oldnews.html b/release/src/router/busybox/docs/busybox.net/oldnews.html
index d6bd581f71..444af74a44 100644
--- a/release/src/router/busybox/docs/busybox.net/oldnews.html
+++ b/release/src/router/busybox/docs/busybox.net/oldnews.html
@@ -1,12 +1,293 @@
+News archive
+
+ 25 June 2008 -- BusyBox 1.11.0 (unstable), BusyBox 1.10.4 (stable)
+ BusyBox 1.11.0 .
+ (svn ,
+ patches ,
+ how to add a patch )
+ BusyBox 1.10.4 .
+ (svn ,
+ patches ,
+ how to add a patch )
+ Sizes of busybox-1.10.4 and busybox-1.11.0 (with equivalent config, static uclibc build):
+ text data bss dec hex filename
+ 800675 636 7080 808391 c55c7 busybox-1.10.4
+ 798392 611 6900 805903 c4c0f busybox-1.11.0
+
+
+ New applets: inotify (Vladimir Dronnikov), man (Ivana Varekova),
+ fbsplash (Michele Sanges), depmod (Bernhard Reutner-Fischer)
+
+
Changes since previous release:
+
+ build system: reinstate CONFIG_CROSS_COMPILE_PREFIX
+ ash: optional bash compatibility features added; other fixes
+ hush: lots and lots of fixes
+ msh: fix the case where the file has exec bit but can't be run directly (runs "$SHELL file" instead)
+ msh: fix exit codes when command is not found or can't be execed
+ udhcpc: added workaround for buggy kernels
+ mount: fix mishandling of proto=tcp/udp
+ diff: make it work on non-seekable streams
+ openvt: made more compatible with "standard" one
+ mdev: fix block/char device detection
+ ping: add -w, -W support (James Simmons)
+ crond: add handling of "MAILTO=user" lines
+ start-stop-daemon: make --exec follow symlinks (Joakim Tjernlund)
+ date: make it accept ISO date format
+ echo: fix echo -e -n "msg\n\0" (David Pinedo)
+ httpd: fix several bugs triggered by relative path in -h DIR
+ printf: fix printf -%s- foo, printf -- -%s- foo
+ syslogd: do not error out on missing files to rotate
+ ls: support Unicode in names
+ ip: support for the LOWER_UP flag (Natanael Copa)
+ mktemp: make argument optional (coreutil 6.12 compat)
+ libiproute: fix option parsing, so that "ip -o link" works again
+ other fixes and code size reductions in many applets
+
+
+ The email address gpl@busybox.net is the recommended way to contact
+ the Software Freedom Law Center to report BusyBox license violations.
+
+
+
+ 12 June 2008 -- Sponsors!
+ We want to thank the following companies which are providing support
+ for the BusyBox project:
+
+
+
+
+ 5 June 2008 -- BusyBox 1.10.3 (stable)
+ BusyBox 1.10.3 .
+ (svn ,
+ patches ,
+ how to add a patch )
+
+ Bugfix-only release for 1.10.x branch. It contains fixes for dnsd, fuser, hush,
+ ip, mdev and syslogd.
+
+
+
+ 8 May 2008 -- BusyBox 1.10.2 (stable)
+ BusyBox 1.10.2 .
+ (svn ,
+ patches ,
+ how to add a patch )
+
+ Bugfix-only release for 1.10.x branch. It contains fixes for echo, httpd, pidof,
+ start-stop-daemon, tar, taskset, tab completion in shells, build system.
+
Please note that mdev was backported from current svn trunk. Please
+ report if you encounter any problems with it.
+
+
+
+ 19 April 2008 -- BusyBox 1.10.1 (stable)
+ BusyBox 1.10.1 .
+ (svn ,
+ patches ,
+ how to add a patch )
+
+ Bugfix-only release for 1.10.x branch. It contains fixes for
+ fuser, init, less, nameif, tail, taskset, tcpudp, top, udhcp.
+
+
+ 21 March 2008 -- BusyBox 1.10.0 (unstable)
+ BusyBox 1.10.0 .
+ (svn ,
+ patches ,
+ how to add a patch )
+
+ Sizes of busybox-1.9.2 and busybox-1.10.0 (with almost full config, static uclibc build):
+ text data bss dec hex filename
+ 781405 679 7500 789584 c0c50 busybox-1.9.2
+ 773551 640 7372 781563 becfb busybox-1.10.0
+
+ Top 10 stack users:
+busybox-1.9.2: busybox-1.10.0:
+echo_dg 4116 bb_full_fd_action 4112
+bb_full_fd_action 4112 find_list_entry2 4096
+discard_dg 4108 readlink_main 4096
+discard_dg 4096 ipaddr_list_or_flush 3900
+echo_stream 4096 iproute_list_or_flush 3680
+discard_stream 4096 insmod_main 3152
+find_list_entry2 4096 fallbackSort 2952
+readlink_main 4096 do_iproute 2492
+ipaddr_list_or_flush 3900 cal_main 2464
+iproute_list_or_flush 3680 readhere 2308
+
+
+ New applets: brctl, chat (by Vladimir Dronnikov <dronnikov AT gmail.com>),
+ findfs, ifenslave (closes bug 115), lpd (by Vladimir Dronnikov <dronnikov AT gmail.com>),
+ lpr+lpq (by Walter Harms), script (by Pascal Bellard <pascal.bellard AT ads-lu.com>),
+ sendmail (Vladimir Dronnikov <dronnikov AT gmail.com>), tac, tftpd.
+
+ Made NOMMU-compatible: crond, crontab, ifupdown, inetd, init, runsv, svlogd, tcpsvd, udpsvd.
+
+ Changes since previous release:
+
+
+ globally: add -Wunused-parameter
+ globally: add optimization barrier to all "G trick" locations
+ adduser/addgroup: check username for invalid chars (by Tito <farmatito AT tiscali.it>)
+ adduser: optional support for long options. Closes bug 2134
+ ash: handle "A=1 A=2 B=$A; echo $B". Closes bug 947
+ ash: make ash -c "if set -o barfoo 2>/dev/null; then echo foo; else echo bar; fi" work. Closes bug 1142
+ build system: don't use "gcc -o /dev/null", old gcc can delete /dev/null in this case
+ build system: fixes for cross-compiling on an OS X host
+ build system: make it do without "od -t"
+ build system: pass CFLAGS to link stage too. Closes bug 1376
+ build system: add CONFIG_NOMMU
+ cp: add ENABLE_FEATURE_VERBOSE_CP_MESSAGE. Closes bug 1470
+ crontab: almost complete rewrite
+ dnsd: properly set _src_ IP:port on outgoing UDP packets
+ dpkg: fix bug where existence check was reversed
+ eject: add -s for SCSI- and USB-devices (Nico Erfurth)
+ fdisk: fix a case where break was reached only for DOS labels
+ fsck: don't kill pid -1! (Roy Marples <roy at marples.name>)
+ fsck_minix: fix bug in map_block2: s/(blknr >= 256 * 256)/(blknr < 256 * 256)/
+ fuser: substantial rewrite
+ getopt: add support for "a+" specifier for nonnegative int parameters. By Vladimir Dronnikov <dronnikov at gmail.com>
+ getty: don't try to detect parity on local lines (Joakim Tjernlund <Joakim.Tjernlund at transmode.se>)
+ halt: write wtmp entry if wtmp support is enabled
+ httpd: "HEAD" support. Closes bug 1530
+ httpd: fix bug 2004: wrong argv when interpreter is invoked
+ httpd: fix bug where we did chdir("") if CGI path had only one "/"
+ httpd: fix for POST upload
+ httpd: support for "I:index.xml" syntax (Peter Korsgaard <jacmet AT uclibc.org>)
+ hush: fix a case where none of pipe members could be started because of fork failure
+ hush: more correct handling of piping
+ hush: reinstate `cmd` handling for NOMMU
+ hush: report [v]fork failures
+ hush: set CLOEXEC on script file being executed
+ hush: try to add a bit more of vfork-friendliness
+ inetd: make "udp nowait" work
+ inetd: make inetd IPv6-capable
+ init: add FEATURE_KILL_REMOVED (Eugene Bordenkircher <eugebo AT gmail.com>)
+ init: allow last line of config file to be not terminated by "\n"
+ init: do not die if "/dev/null" is missing
+ init: fix bug 1111: restart actions were not splitting words
+ init: wait for orphaned children too while waiting for sysinit-like processes (harald-tuxbox AT arcor.de)
+ ip route: "ip route" was misbehaving (extra argv+1 ate 1st env var)
+ last: do not go into endless loop on read error
+ less,klogd,syslogd,nc,tcpudp: exit on signal by killing itself, not exit(1)
+ less: "examine" command will not bomb out on bad file name now
+ less: fix bug where backspace wasn't actually deleting chars
+ less: make it a bit more resistant against status line corruption
+ less: improve search when data is not supplied fast enough by stdin - now will try reading for 1-2 seconds before declaring that there is no match. This fixes a very common annoyance with long manpages
+ less: update line input so that it doesn't interfere with screen update. Makes "man bash", [enter], [/], <enter search pattern>, [enter] more usable - manpage now draws even as you enter the pattern!
+ libbb: filename completion matches dangling symlinks too
+ libbb: fix getopt state corruption for NOFORK applets
+ libbb: full_read/write now will report partial data counts prior to error
+ libbb: intrduce and use safe_gethostname. By Tito <farmatito AT tiscali.it>
+ libbb: introduce and use nonblock_safe_read(). Yay! Our shells are immune from this nasty O_NONBLOCK now!
+ login,su: avoid clearing environment with some options, as was intended
+ microcom: read more than 1 byte from device, if possible
+ microcom: split -d (delay) option away from -t
+ mktemp: support -p DIR (Timo Teras <timo.teras at iki.fi>)
+ mount: #ifdef out MOUNT_LABEL code parts if it is not selected
+ mount: add another mount helper call method
+ mount: allow and ignore _netdev option
+ mount: make -f work even without mtab support (Cristian Ionescu-Idbohrn <cristian.ionescu-idbohrn at axis.com>)
+ mount: optional support for -vv verbosity
+ mount: plug a hole where FEATURE_MOUNT_HELPERS could allow execution of arbitrary command
+ mount: recognize "dirsync" (closes bug 835)
+ mount: sanitize environment if called by non-root
+ mount: support for mount by label. Closes bug 1143
+ mount: with -vv -f, say what mount() calls we were going to make
+ msh: create testsuite (based on hush one)
+ msh: don't use floating point in "times" builtin
+ msh: fix Ctrl-C handling with line editing
+ msh: fix for bug 846 ("break" didn't work second time)
+ msh: glob0/glob1/glob2/glob3 were just a sorting routine, removed
+ msh: instead of fixing "ls | cd", "cd | ls" etc disallow builtins in pipes. They make no sense there anyway
+ msh: stop trying to parse variables in "msh SCRIPT VAR=val param". They are passed as ordinary parameters
+ netstat: print control chars as "^C" etc
+ nmeter: fix bug where %[mf] behaves as %[mt]
+ nohup: compat patch by Christoph Gysin <mailinglist.cache at gmail.com>
+ od: handle /proc files (which have filesize 0) correctly
+ patch: don't trash permissions of patched file
+ ps: add conditional support for -o [e]time
+ ps: fix COMMAND column adjustment; overflow in USER and VSZ columns
+ reset: call "stty sane". Closes bug 1414
+ rmdir: optional long options support for Debian users. By Roberto Gordo Saez <roberto.gordo AT gmail.com>
+ run-parts: add --reverse
+ script: correctly handle buffered "tail" of output
+ sed: "n" command must reset "we had successful subst" flag. Closes bug 1214
+ sort: -z outputs NUL terminated lines. Closes bug 1591
+ stty: fix mishandling of control keywords (Ralf Friedl <Ralf.Friedl AT online.de>)
+ switch_root: stop at first non-option. Closes bug 1425
+ syslogd: avoid excessive time() system calls
+ syslogd: don't die if remote host's IP cannot be resolved. Retry resolutions every two minutes instead
+ syslogd: fix shmat error check
+ syslogd: optional support for dropping dups. Closes bug 436
+ syslogd: send "\n"-terminated messages over the network. Fully closes bug 1574
+ syslogd: tighten up hostname handling
+ tail: fix "tail -c 20 /dev/huge_disk" (was taking ages)
+ tar: compat: handle tarballs with only one zero block at the end
+ tar: autodetection of gz/bz2 compressed tarballs. Closes bug 992
+ tar: real support for -p. By Natanael Copa <natanael.copa at gmail.com>
+ tcpudp: narrow down time window where we have no wildcard socket
+ telnetd: use login always, not "sometimes login, sometimes shell"
+ test: fix mishandling of "test ! arg1 op arg2 more args"
+ trylink: instead of build error, disable --gc-sections if GLIBC and STATIC are selected
+ udhcp: make file paths configurable
+ udhcp: optional support for non-standard DHCP ports
+ udhcp: set correct op byte in the packet for DHCPDECLINE
+ udhcpc: filter unwanted packets in kernel (Cristian Ionescu-Idbohrn <cristian.ionescu-idbohrn AT axis.com>)
+ udhcpc: fix wrong options in decline and release packets (Jonas Danielsson <jonas.danielsson AT axis.com>)
+ umount: do not complain several times about the same mountpoint
+ umount: do not try to free loop device or erase mtab if remounted ro
+ umount: instead of non-standard -D, use -d with opposite meaning. Closes bug 1604
+ unlzma: shrink by Pascal Bellard <pascal.bellard AT ads-lu.com>
+ unzip: do not try to read entire compressed stream at once (it can be huge)
+ unzip: handle short reads correctly
+ vi: many fixes
+ zcip: don't chdir to root
+ zcip: open ARP socket before openlog (else we can trash syslog socket)
+
+
+
+ 21 March 2008 -- BusyBox old stable releases
+
+ Bugfix-only releases for four past branches. Links to locations
+ for future hot patches are in parentheses.
+
+ 1.9.2
+ (patches ),
+ 1.8.3
+ (patches ),
+ 1.7.5
+ (patches ),
+ 1.5.2
+ (patches ).
+
+ How to add a patch.
+
+
+
12 February 2008 -- BusyBox 1.9.1 (stable)
- BusyBox 1.9.1 .
- (svn ,
- patches ,
- how to add a patch )
+ BusyBox 1.9.1 .
+ (svn ,
+ patches ,
+ how to add a patch )
This is a bugfix-only release, with fixes to fsck,
iproute, mdev, mkswap, msh, nameif, stty, test, zcip.
@@ -16,10 +297,10 @@
24 December 2007 -- BusyBox 1.9.0 (unstable)
- BusyBox 1.9.0 .
- (svn ,
- patches ,
- how to add a patch )
+ BusyBox 1.9.0 .
+ (svn ,
+ patches ,
+ how to add a patch )
Sizes of busybox-1.8.2 and busybox-1.9.0 (with almost full config, static uclibc build):
text data bss dec hex filename
@@ -81,17 +362,17 @@ parse_prompt 4132 insmod_main 3152
df: -i option (show inode info) (Pascal Bellard <pascal.bellard at ads-lu.com>)
hexdump: -R option (Pascal Bellard <pascal.bellard at ads-lu.com>)
-
+
23 November 2007 -- BusyBox 1.8.2 (stable), BusyBox 1.7.4 (stable)
- BusyBox 1.8.2 .
- (svn ,
- patches ,
- how to add a patch )
- BusyBox 1.7.4 .
- (svn ,
- patches ,
- how to add a patch )
+ BusyBox 1.8.2 .
+ (svn ,
+ patches ,
+ how to add a patch )
+ BusyBox 1.7.4 .
+ (svn ,
+ patches ,
+ how to add a patch )
These are bugfix-only releases.
1.8.2 contains fixes for inetd, lash, tar, tr, and build system.
@@ -99,19 +380,19 @@ parse_prompt 4132 insmod_main 3152
9 November 2007 -- BusyBox 1.8.1 (stable)
- BusyBox 1.8.1 .
- (svn ,
- patches ,
- how to add a patch )
+ BusyBox 1.8.1 .
+ (svn ,
+ patches ,
+ how to add a patch )
This is a bugfix-only release, with fixes to login (PAM), modprobe, syslogd, telnetd, unzip.
4 November 2007 -- BusyBox 1.8.0 (unstable)
- BusyBox 1.8.0 .
- (svn ,
- patches ,
- how to add a patch )
+ BusyBox 1.8.0 .
+ (svn ,
+ patches ,
+ how to add a patch )
Note: this is probably the very last release with lash. It will be dropped. Please migrate to hush.
@@ -212,42 +493,40 @@ Equivalent .config, i386 uclibc static builds:
watchdog: allow millisecond spec (-t 250ms)
zcip: fix unaligned trap on ARM
-
-
4 November 2007 -- BusyBox 1.7.3 (stable)
- BusyBox 1.7.3 .
- (svn ,
- patches ,
- how to add a patch )
+ BusyBox 1.7.3 .
+ (svn ,
+ patches ,
+ how to add a patch )
This is a bugfix-only release, with fixes to ash, httpd, inetd, iptun, logger, login, tail.
30 September 2007 -- BusyBox 1.7.2 (stable)
- BusyBox 1.7.2 .
- (svn ,
- patches ,
- how to add a patch )
+ BusyBox 1.7.2 .
+ (svn ,
+ patches ,
+ how to add a patch )
This is a bugfix-only release, with fixes to install, find, login, httpd, runsvdir, chcon, setfiles, fdisk and line editing.
16 September 2007 -- BusyBox 1.7.1 (stable)
- BusyBox 1.7.1 .
- (svn ,
- patches ,
- how to add a patch )
+ BusyBox 1.7.1 .
+ (svn ,
+ patches ,
+ how to add a patch )
This is a bugfix-only release, with fixes to cp, runsv, tar, busybox --install and build system.
24 August 2007 -- BusyBox 1.7.0 (unstable)
- BusyBox 1.7.0 .
- (svn ,
- patches ,
- how to add a patch )
+ BusyBox 1.7.0 .
+ (svn ,
+ patches ,
+ how to add a patch )
Applets which had many changes since 1.6.x:
httpd:
@@ -388,23 +667,22 @@ Same .config built against static uclibc:
wget: lift 256 chars limitation on terminal width
wget, zcip: use monotonic_sec instead of gettimeofday
-
30 June 2007 -- BusyBox 1.6.1 (stable)
- BusyBox 1.6.1 .
- (svn ,
- patches ,
- how to add a patch )
+ BusyBox 1.6.1 .
+ (svn ,
+ patches ,
+ how to add a patch )
This is a bugfix-only release, with fixes to echo, hush, and wget.
1 June 2007 -- BusyBox 1.6.0 (unstable)
- BusyBox 1.6.0 .
- (svn ,
- patches ,
- how to add a patch )
+ BusyBox 1.6.0 .
+ (svn ,
+ patches ,
+ how to add a patch )
Since this is a x.x.0 release, it probably does not deserve "stable"
label. Please help making 1.6.1 stable by testing 1.6.0.
@@ -413,7 +691,7 @@ Same .config built against static uclibc:
report any such cases.
lash users please note: lash is going to be deprecated in busybox 1.7.0
and removed in the more distant future. Please migrate to hush.
- Memory usage has decreased, but we can do better still
+ Memory usage has decreased, but we can do better still
Other changes since previous release:
NOFORK: audit small applets and mark some of them as NOFORK. Put big scary warnings in relevant places
@@ -511,22 +789,21 @@ Same .config built against static uclibc:
xargs: shrink code, ~80 bytes; simplify word list management
zcip: make it work on NOMMU (+ improve NOMMU support machinery)
-
20 May 2007 -- BusyBox 1.5.1 (stable)
- BusyBox 1.5.1 .
- (patches ,
- how to add a patch )
+ BusyBox 1.5.1 .
+ (patches ,
+ how to add a patch )
This is a bugfix-only release, with fixes to hdparm, hush, ifupdown, ps
and sed.
23 March 2007 -- BusyBox 1.5.0 (unstable)
- BusyBox 1.5.0 .
- (patches ,
- how to add a patch )
+ BusyBox 1.5.0 .
+ (patches ,
+ how to add a patch )
Since this is a x.x.0 release, it probably does not deserve "stable"
label. Please help making 1.5.1 stable by testing 1.5.0.
@@ -560,11 +837,10 @@ Same .config built against static uclibc:
Applets with code cleaned up: telnet, fdisk, fsck_minix, mkfs_minix,
syslogd, swapon, runsv, svlogd, klogd
-
18 March 2007 -- BusyBox 1.4.2 (stable)
- BusyBox 1.4.2 .
+
BusyBox 1.4.2 .
This release includes only trivial fixes accumulated since 1.4.1.
@@ -572,16 +848,16 @@ Same .config built against static uclibc:
25 January 2007 -- BusyBox 1.4.1 (stable)
- BusyBox 1.4.1 .
- (patches )
+ BusyBox 1.4.1 .
+ (patches )
This release includes only trivial fixes accumulated since 1.4.0.
20 January 2007 -- BusyBox 1.4.0 (stable)
- BusyBox 1.4.0 .
- (patches )
+ BusyBox 1.4.0 .
+ (patches )
Since this is a x.x.0 release, it probably is a bit less "stable"
than usual.
@@ -611,27 +887,26 @@ Same .config built against static uclibc:
minor bugfixes to: passwd, date, tftp, start_stop_daemon, tar,
ps, ifupdown, time, su, stty, awk, ping[6], sort,...
-
20 January 2007 -- BusyBox 1.3.2 (stable)
- BusyBox 1.3.2 .
+ BusyBox 1.3.2 .
This release includes only one trivial fix accumulated since 1.3.1
27 December 2006 -- BusyBox 1.3.1 (stable)
- BusyBox 1.3.1 .
- (patches )
+ BusyBox 1.3.1 .
+ (patches )
Closing 2006 with new release. It includes only trivial fixes accumulated since 1.3.0
14 December 2006 -- BusyBox 1.3.0 (stable)
- BusyBox 1.3.0 .
- (patches )
+ BusyBox 1.3.0 .
+ (patches )
This release has CONFIG_DESKTOP option which enables features
needed for busybox usage on desktop machine. For example, find, chmod
@@ -666,7 +941,7 @@ Same .config built against static uclibc:
29 October 2006 -- BusyBox 1.2.2.1 (fix)
- BusyBox 1.2.2.1 .
+ BusyBox 1.2.2.1 .
Added compile-time warning that static linking against glibc
produces buggy executables.
@@ -674,7 +949,7 @@ Same .config built against static uclibc:
24 October 2006 -- BusyBox 1.2.2 (stable)
It's a bit overdue, but
- here is
+ here is
BusyBox 1.2.2 .
This release has dozens of fixes backported from the ongoing development
@@ -693,9 +968,9 @@ Same .config built against static uclibc:
gzip to save memory, fix sulogin -tNNN, a help text tweak, several warning
fixes and build fixes, fixup dnsd a bit, and a partridge in a pear tree.
- As Linux Weekly News noted ,
+
As Linux Weekly News noted ,
this is my (Rob's) last release of BusyBox. The new maintainer is Denis
- Vlasenko, I'm off to do other things .
+ Vlasenko, I'm off to do other things .
@@ -811,7 +1086,7 @@ Same .config built against static uclibc:
several existing applets. This prerelease should be noticeably more
standards
compliant than earlier versions of busybox, although we're
- still working out the bugs .
+ still working out the bugs .
16 August 2005 -- 1.01 is out
@@ -827,7 +1102,7 @@ Same .config built against static uclibc:
in their brains at a time. In my case, I'm lucky if I can remember my own
name, much less a bug report posted last week... To prevent your bug report
from getting lost, if you find a bug in BusyBox, please use the
- shiny new Bug and Patch Tracking System
+ shiny new Bug and Patch Tracking System
to post all the gory details.
@@ -1058,7 +1333,7 @@ Same .config built against static uclibc:
- People who rely on the daily BusyBox snapshots
+ People who rely on the daily BusyBox snapshots
should be aware that snapshots of the old busybox 0.60.x
series are no longer available. Daily snapshots are now
only available for the BusyBox 1.0.0 series and now use
@@ -1260,7 +1535,7 @@ Same .config built against static uclibc:
If you have submitted patches, and they are not in this release
and I have not emailed you explaining why your patch was
rejected, it is safe to say that I have lost your patch. That
- happens sometimes. Please do NOT send all your patches,
+ happens sometimes. Please do NOT send all your patches,
support questions, etc, directly to Erik. I get hundreds of
emails every day (which is why I end up losing patches
sometimes in the flood)... The busybox mailing list is the
@@ -1348,12 +1623,12 @@ Same .config built against static uclibc:
6 March 2002 -- busybox.net now has mirrors!
Busybox.net is now much more available, thanks to
- the fine folks at http://i-netinnovations.com/
+ the fine folks at http://i-netinnovations.com/
who are providing hosting for busybox.net and
uclibc.org. In addition, we now have two mirrors:
- http://busybox.linuxmagic.com/
+ http://busybox.linuxmagic.com/
in Canada and
- http://busybox.csservers.de/
+ http://busybox.csservers.de/
in Germany. I hope this makes things much more
accessible for everyone!
@@ -1461,7 +1736,7 @@ Click here to help buy busybox.net!
-
+
@@ -1595,7 +1870,7 @@ would be wonderful!
The illustrious Larry Doolittle has made a PostScript chart of the growth
of the Busybox tarball size over time. It is available for downloading /
-viewing right here .
+viewing right here .
(Note that while the number of applets in Busybox has increased, you
can still configure Busybox to be as small as you want by selectively
@@ -1641,7 +1916,7 @@ image. Here's how you use it:
-
+
Download the image
dd it onto a floppy like so: dd if=busybox.floppy.img
@@ -1767,7 +2042,7 @@ image . Here's how you use it:
Also, some exciting infrastructure news! Busybox now has its own
mailing list ,
publically browsable
- CVS tree ,
+ CVS tree ,
anonymous
CVS access , and
for those that are actively contributing there is even
diff --git a/release/src/router/busybox/docs/busybox.net/products.html b/release/src/router/busybox/docs/busybox.net/products.html
dissimilarity index 72%
index a727d9f9a1..7bb07f71d8 100644
--- a/release/src/router/busybox/docs/busybox.net/products.html
+++ b/release/src/router/busybox/docs/busybox.net/products.html
@@ -1,170 +1,165 @@
-
-
-
-Products/Projects Using BusyBox
-
-Do you use BusyBox? I'd love to know about it and
-I'd be happy to link to you.
-
-
-I know of the following products and/or projects that use BusyBox --
-listed in the order I happen to add them to the web page:
-
-
-
-buildroot A configurable
-means for building your own busybox/uClibc based system systems, maintained
-by the uClibc developers.
-
-OpenWrt a Linux distribution for embedded
-devices, based on buildroot.
-
-PTXdist another
-configurable means for building your own busybox based system systems.
-
-
-Debian installer (boot floppies) project
-
-Red Hat installer
-
-
-Slackware Installer
-
-Gentoo Linux install/boot CDs
-The Mandriva installer
-
-Linux Embedded Appliance Firewall The sucessor of the Linux Router Project, supporting all sorts of embedded Linux gateways, routers, wireless routers, and firewalls.
-
-tomsrtbt
-
-Stormix
-Installer
-
-EMAC Linux
-2.0 SBC
-
-Trinux
-
-ODDAS
-project
-
-Build Your
-Linux Disk
-
-Zdisk
-
-AdTran -
-VPN/firewall VPN Linux Distribution
-
-mkCDrec - make
-CD-ROM recovery
-
-Linux on
-nanoEngine
-
-Floppyfw
-
-Linux Terminal
-Server Project
-
-Devil-Linux
-
-DutNux
-
-Mindi
-
-ttylinux
-
-Coyote Linux
-
-Partition
-Image
-
-fli4l the on(e)-disk-router
-
-Tinfoil
-Hat Linux
-
-gp32linux
-Familiar Linux A linux distribution for handheld computers
-Timo's Rescue CD Set
-Netstation
-GNU/Fiwix Operating System
-Generations Linux
-SystemImager / System Installation Suite
-GENDIST distribution generator
-DIET-PC embedded Linux thin client distribution
-BYZantine Gnu/Linux
-Darik's Boot and Nuke
-TimeSys real-time Linux
-MoviX Boots from CD and automatically plays every video file on the CD
-katamaran Linux, X11, xfce windowmanager, based on BusyBox
-Prometheus SimplyGNUstep
-lowlife A documentation project on how to make your own uClibc-based systems and floppy.
-Metadistros a project to allow you easily make Live-CD distributions.
-Salvare More Linux than tomsrtbt but less than Knoppix, aims to provide a useful workstation as well as a rescue disk.
-stresslinux minimal linux distribution running from a bootable cdrom or via PXE.
-thinstation convert standard PCs into full-featured diskless thinclients.
-UHU-Linux Hungary
-Deep-Water Linux
-Freesco router
-Sentry Firewall CD
-
-
-
-Tuxscreen Linux Phone
-The Kerbango Internet Radio
-LinuxMagic VPN Firewall
-I-Silver Linux appliance servers
-Sharp Zaurus PDA
-Cyclades-TS and other Cyclades products
-Linksys WRT54G - Wireless-G Broadband Router
-Dell TrueMobile 1184
-Actiontec Dual PC Modem
-Kiss DP Series DVD players
-NetGear WG602 wireless router
- with sources here
-TRENDnet TEW-411BRP 802.11g Wireless AP/Router/Switch
- Source for busybox and udhcp here though no kernel source is provided.
-Buffalo WBR-G54 wireless router
- ASUS WL-300g Wireless LAN Access Point
- with sourcehere
- Belkin 54g Wireless DSL/Cable Gateway Router
- with sourcehere
- Acronis PartitionExpert 2003
- includes a heavily modified BusyBox v0.60.5 with built in
- cardmgr, device detection, gpm, lspci, etc. Also includes udhcp,
- uClibc 0.9.26, a heavily patched up linux kernel, etc. Source
- can only be obtained here
-
-U.S. Robotics Sureconnect 4-port ADSL router
- with source here
-
- ActionTec GT701-WG Wireless Gateway/DSL Modem
- with source here
-S.M.A.R.T. Linux
-DLink - Model GSL-G604T, DSL-300T, and possibly other models
- with source here,
- with source and here,
- and quite possibly other places as well. You may need to dig down a bit
- to find the source, but it does seem to be there.
-Siemens SE515 DSL router
- with source here, I think...
- with some details here.
-Free Remote Windows Terminal
-
-ZyXEL Routers
-
-
-
-
-
-
-
+
+
+
+Products/Projects Using BusyBox
+
+Do you use BusyBox? I'd love to know about it and
+I'd be happy to link to you.
+
+
+I know of the following projects that use BusyBox --
+listed in the order I happen to add them to the web page:
+
+
+
+buildroot A configurable
+means for building your own busybox/uClibc based system systems, maintained
+by the uClibc developers.
+
+OpenWrt a Linux distribution for embedded
+devices, based on buildroot.
+
+PTXdist
+ another configurable means for building your own busybox based systems.
+
+
+Debian installer (boot floppies) project
+
+Red Hat installer
+
+
+Slackware Installer
+
+Gentoo Linux install/boot CDs
+The Mandriva installer
+
+Linux Embedded Appliance Firewall
+ The sucessor of the Linux Router Project, supporting all sorts
+ of embedded Linux gateways, routers, wireless routers, and firewalls.
+
+tomsrtbt
+
+Stormix Installer
+
+EMAC Linux 2.0 SBC
+
+Trinux
+
+ODDAS project
+
+Build Your Linux Disk
+
+Zdisk
+
+AdTran -
+VPN/firewall VPN Linux Distribution
+
+mkCDrec - make CD-ROM recovery
+
+Linux on nanoEngine
+
+Floppyfw
+
+Linux Terminal Server Project
+
+Devil-Linux
+
+DutNux
+
+Mindi
+
+ttylinux
+
+Coyote Linux
+
+Partition Image
+
+fli4l the on(e)-disk-router
+
+Tinfoil Hat Linux
+
+gp32linux
+Familiar Linux A linux distribution for handheld computers
+Timo's Rescue CD Set
+Netstation
+GNU/Fiwix Operating System
+Generations Linux
+SystemImager / System Installation Suite
+GENDIST distribution generator
+DIET-PC embedded Linux thin client distribution
+BYZantine Gnu/Linux
+Darik's Boot and Nuke
+TimeSys real-time Linux
+MoviX Boots from CD and automatically plays every video file on the CD
+katamaran Linux, X11, xfce windowmanager, based on BusyBox
+Prometheus SimplyGNUstep
+lowlife A documentation project on how to make your own uClibc-based systems and floppy.
+Metadistros a project to allow you easily make Live-CD distributions.
+Salvare More Linux than tomsrtbt but less than Knoppix, aims to provide a useful workstation as well as a rescue disk.
+stresslinux minimal linux distribution running from a bootable cdrom or via PXE.
+thinstation convert standard PCs into full-featured diskless thinclients.
+UHU-Linux Hungary
+Deep-Water Linux
+Freesco router
+Sentry Firewall CD
+
+
+
+
+And here are products that use BusyBox --
+
+
+
+Dreambox (Linux based PVR)
+RD129 embedded board from ELPA
+EMTEC MovieCube R700 uses Busybox 1.1.3.
+ Tuxscreen Linux Phone
+The Kerbango Internet Radio
+LinuxMagic VPN Firewall
+I-Silver Linux appliance servers
+Sharp Zaurus PDA
+Cyclades-TS and other Cyclades products
+Linksys WRT54G - Wireless-G Broadband Router
+Dell TrueMobile 1184
+Actiontec Dual PC Modem
+Kiss DP Series DVD players
+NetGear WG602 wireless router
+ with sources here
+TRENDnet TEW-411BRP 802.11g Wireless AP/Router/Switch
+ Source for busybox and udhcp here though no kernel source is provided.
+Buffalo WBR-G54 wireless router
+ ASUS WL-300g Wireless LAN Access Point
+ with sourcehere
+ Belkin 54g Wireless DSL/Cable Gateway Router
+ with sourcehere
+ Acronis PartitionExpert 2003
+ includes a heavily modified BusyBox v0.60.5 with built in
+ cardmgr, device detection, gpm, lspci, etc. Also includes udhcp,
+ uClibc 0.9.26, a heavily patched up linux kernel, etc. Source
+ can only be obtained here
+
+U.S. Robotics Sureconnect 4-port ADSL router
+ with source here
+
+ ActionTec GT701-WG Wireless Gateway/DSL Modem
+ with source here
+S.M.A.R.T. Linux
+DLink - Model GSL-G604T, DSL-300T, and possibly other models
+ with source here,
+ with source and here,
+ and quite possibly other places as well. You may need to dig down a bit
+ to find the source, but it does seem to be there.
+Siemens SE515 DSL router
+ with source here, I think...
+ with some details here.
+Free Remote Windows Terminal
+
+ZyXEL Routers
+
+
+
+
diff --git a/release/src/router/busybox/docs/busybox.net/sponsors.html b/release/src/router/busybox/docs/busybox.net/sponsors.html
index efbfd45d62..e52adfc8ed 100644
--- a/release/src/router/busybox/docs/busybox.net/sponsors.html
+++ b/release/src/router/busybox/docs/busybox.net/sponsors.html
@@ -12,35 +12,35 @@ project, consider these fine companies!
OSU OSL kindly provides hosting for BusyBox and uClibc.
- Codepoet Consulting
+ Codepoet Consulting
Custom Linux, embedded Linux, BusyBox, and uClibc development.
- Laptop Computers contributes
+ Laptop Computers contributes
financially.
- AOE media, a
+ AOE media, a
TYPO3 development agency contributes financially.
- Analog Devices, Inc. provided
- a
+ Analog Devices, Inc. provided
+ a
Blackfin development board free of charge.
- Blackfin
+ Blackfin
is a NOMMU processor, and its availability for testing is invaluable.
If you are an embedded device developer,
please note that Analog Devices has entire Linux distribution available
for download for this board. Visit
- http://blackfin.uclinux.org/
+ http://blackfin.uclinux.org/
for more information.
- TimeSys
+ TimeSys
Embedded Linux development, cross-compilers, real-time, KGDB, tsrpm and cygwin.
- Penguru Consulting
+ Penguru Consulting
Custom development for embedded Linux systems and multimedia platforms.
diff --git a/release/src/router/busybox/docs/busybox.net/subversion.html b/release/src/router/busybox/docs/busybox.net/subversion.html
index 561a5b80b7..2c4517a35f 100644
--- a/release/src/router/busybox/docs/busybox.net/subversion.html
+++ b/release/src/router/busybox/docs/busybox.net/subversion.html
@@ -6,7 +6,7 @@
Patches
-You can download fixes for particular releases
+
You can download fixes for particular releases
of busybox, e.g. downloads/fixes-major -minor -patch /
Anonymous Subversion Access
@@ -18,9 +18,9 @@ grab a copy of the latest version of BusyBox using anonymous svn access:
svn co svn://busybox.net/trunk/busybox
-The current stable branch can be obtained with
+The stable branches can be obtained with
-svn co svn://busybox.net/branches/busybox_1_9_stable
+svn co svn://busybox.net/branches/busybox_1_NN_stable
diff --git a/release/src/router/busybox/docs/busybox.net/svnindex.css b/release/src/router/busybox/docs/busybox.net/svnindex.css
new file mode 100644
index 0000000000..b1ca24a054
--- /dev/null
+++ b/release/src/router/busybox/docs/busybox.net/svnindex.css
@@ -0,0 +1,92 @@
+/* A sample style sheet for displaying the Subversion directory listing
+ that is generated by mod_dav_svn and "svnindex.xsl". */
+
+body{
+ margin: 0;
+ padding: 0;
+}
+
+a {
+ color: navy;
+}
+
+.header {
+ padding-top: 5px;
+ text-align: center;
+}
+
+.footer {
+ margin-top: 8em;
+ padding: 0.5em 1em 0.5em;
+ border: 1px solid;
+ border-width: 1px 0;
+ clear: both;
+ border-color: rgb(30%,30%,50%) navy rgb(75%,80%,85%) navy;
+ background: rgb(88%,90%,92%);
+ font-size: 80%;
+}
+
+.svn {
+ margin: 3em;
+}
+
+.rev {
+ margin-right: 3px;
+ padding-left: 3px;
+ text-align: left;
+ font-size: 120%;
+}
+
+.dir a {
+ text-decoration: none;
+ color: black;
+}
+
+.file a {
+ text-decoration: none;
+ color: black;
+}
+
+.path {
+ margin: 3px;
+ padding: 3px;
+ background: #FFCC66;
+ font-size: 120%;
+}
+
+.updir {
+ margin: 3px;
+ padding: 3px;
+ margin-left: 3em;
+ background: #FFEEAA;
+}
+
+.file {
+ margin: 3px;
+ padding: 3px;
+ margin-left: 3em;
+ background: rgb(95%,95%,95%);
+}
+
+.file:hover {
+ margin: 3px;
+ padding: 3px;
+ margin-left: 3em;
+ background: rgb(100%,100%,90%);
+/* border: 1px black solid; */
+}
+
+.dir {
+ margin: 3px;
+ padding: 3px;
+ margin-left: 3em;
+ background: rgb(90%,90%,90%);
+}
+
+.dir:hover {
+ margin: 3px;
+ padding: 3px;
+ margin-left: 3em;
+ background: rgb(100%,100%,80%);
+/* border: 1px black solid; */
+}
diff --git a/release/src/router/busybox/docs/busybox.net/svnindex.xsl b/release/src/router/busybox/docs/busybox.net/svnindex.xsl
new file mode 100644
index 0000000000..2d3297c4c9
--- /dev/null
+++ b/release/src/router/busybox/docs/busybox.net/svnindex.xsl
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ :
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ :
+
+
+
+
+
+ —
+
+ Revision
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [
+
+ ..
+ Parent Directory
+
+ ]
+
+
+
+
+
+
+
+
+
+
+ /
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/release/src/router/busybox/docs/busybox.net/tinyutils.html b/release/src/router/busybox/docs/busybox.net/tinyutils.html
index 9122d6e352..18313460ce 100644
--- a/release/src/router/busybox/docs/busybox.net/tinyutils.html
+++ b/release/src/router/busybox/docs/busybox.net/tinyutils.html
@@ -9,7 +9,7 @@ dev mailing list.
-
+
Feature
Utilities
@@ -44,42 +44,42 @@ version of links.
SCRIPTING LANGUAGES
Although busybox has built-in support for shell scripts, plenty of other
small scripting languages are available on the net. A few examples:
-
+
-
-
+language
+description
- microperl
+ microperl
A small standalone perl interpreter that can be built from the perl source
s via "make -f Makefile.micro". If you really feel the need for perl on an embe
dded system, this is where to start.
-Lua
-If you just want a small embedded scripting language to write new
+Lua
+If you just want a small embedded scripting language to write new
code in, this Brazilian import is lightweight, fairly popular, and has
a complete book about it online.
-rc
+rc
The PLAN9 shell. Not compatible with conventional bourne shell syntax,
but fairly lightweight and small.
-forth
+forth
A well known language for fast and small programs, decades old but still
in use for everything from OpenBIOS to computer controlled engine timing.
For more information, you probably want to look at
-buildroot and
-TinyGentoo , which
+buildroot and
+TinyGentoo , which
build and use tiny utilities for all sorts of things.
diff --git a/release/src/router/busybox/docs/busybox_header.pod b/release/src/router/busybox/docs/busybox_header.pod
index 804b839703..9f2ffc48dc 100644
--- a/release/src/router/busybox/docs/busybox_header.pod
+++ b/release/src/router/busybox/docs/busybox_header.pod
@@ -6,9 +6,9 @@ BusyBox - The Swiss Army Knife of Embedded Linux
=head1 SYNTAX
- BusyBox [arguments...] # or
+ busybox [arguments...] # or
- [arguments...] # if symlinked
+ [arguments...] # if symlinked
=head1 DESCRIPTION
@@ -45,7 +45,8 @@ BusyBox is a multi-call binary. A multi-call binary is an executable program
that performs the same job as more than one utility program. That means there
is just a single BusyBox binary, but that single binary acts like a large
number of utilities. This allows BusyBox to be smaller since all the built-in
-utility programs (we call them applets) can share code for many common operations.
+utility programs (we call them applets) can share code for many common
+operations.
You can also invoke BusyBox by issuing a command as an argument on the
command line. For example, entering
@@ -72,11 +73,11 @@ applets that have been compiled into your BusyBox binary.
=head1 COMMON OPTIONS
-Most BusyBox commands support the B<--help> argument to provide a terse runtime
+Most BusyBox applets support the B<--help> argument to provide a terse runtime
description of their behavior. If the CONFIG_FEATURE_VERBOSE_USAGE option has
been enabled, more detailed usage information will also be available.
=head1 COMMANDS
-Currently defined functions include:
+Currently available applets include:
diff --git a/release/src/router/busybox/docs/logging_and_backgrounding.txt b/release/src/router/busybox/docs/logging_and_backgrounding.txt
new file mode 100644
index 0000000000..62a6d15503
--- /dev/null
+++ b/release/src/router/busybox/docs/logging_and_backgrounding.txt
@@ -0,0 +1,96 @@
+ Logging and backgrounding
+
+By default, bb_[p]error_msg[_and_die] messages go to stderr,
+and of course, usually applets do not auto-background. :)
+
+Historically, daemons and inetd services are different.
+
+Busybox is trying to provide compatible behavior, thus if an applet
+is emulating an existing utility, it should mimic it. If utility
+auto-backgrounds itself, busybox applet should do the same.
+If utility normally logs to syslog, busybox applet should do
+the same too.
+
+However, busybox should not needlessly restrict the freedom
+of the users. And users have different needs and different preferences.
+Some might like logging everything from daemons to syslog.
+Others prefer running stuff under runsv/svlogd and thus would like
+logging to stderr and no daemonization.
+
+To help with that, busybox applets should have options to override
+default behavior, whatever that is for a given applet.
+
+
+Current sutiation is a bit of a mess:
+
+acpid - auto-backgrounds unless -d
+crond - auto-backgrounds unless -f, logs to syslog unless -d or -L.
+ option -d logs to stderr, -L FILE logs to FILE
+devfsd - (obsolete)
+dnsd - option -d makes it background and log to syslog
+fakeidentd - inetd service. Auto-backgrounds and logs to syslog
+ if no -f and no -i and no -w (-i is "inetd service" flag,
+ -w is "inetd-wait service" flag)
+ftpd - inetd service. Logs to syslog with -S, with -v logs to strerr too
+httpd - auto-backgrounds unless -f or -i (-i is "inetd service" flag)
+inetd - auto-backgrounds unless -f, logs to syslog unless -e
+klogd - auto-backgrounds unless -n
+syslogd - auto-backgrounds unless -n
+telnetd - auto-backgrounds unless -f or -i (-i is "inetd service" flag)
+udhcpc - auto-backgrounds unless -f after lease is obtained,
+ option -b makes it background sooner (when lease attempt
+ fails and retries start),
+ after backgrounding it stops logging to stderr;
+ logs to stderr, but option -S makes it log *also* to syslog
+udhcpd - auto-backgrounds and do not log to stderr unless -f,
+ otherwise logs to stderr, but option -S makes it log *also* to syslog
+zcip - auto-backgrounds and logs *also* to syslog unless -f
+
+Total: 13 applets (+1 obsolete),
+ 4 log to syslog by default (crond fakeidentd inetd zcip),
+ 5 never log to syslog (acpid httpd telnetd klogd syslogd, last two
+ - for obviously correct reasons),
+ there are no daemons which always log to syslog,
+ 12 auto-background if not run as inetd servies (all except dnsd.
+ Note that there is no "standard" dnsd AFAIKS). But see below
+ for daemons (tcpsvd etc) which don't auto-background.
+
+miscutils/crond.c: logmode = LOGMODE_SYSLOG;
+networking/dnsd.c: logmode = LOGMODE_SYSLOG;
+networking/ftpd.c: logmode = LOGMODE_NONE;
+networking/ftpd.c: logmode |= LOGMODE_SYSLOG;
+networking/inetd.c: logmode = LOGMODE_SYSLOG;
+networking/isrv_identd.c: logmode = LOGMODE_SYSLOG;
+networking/telnetd.c: logmode = LOGMODE_SYSLOG;
+networking/udhcp/dhcpc.c: logmode = LOGMODE_NONE;
+networking/udhcp/dhcpc.c: logmode |= LOGMODE_SYSLOG;
+networking/udhcp/dhcpc.c: logmode &= ~LOGMODE_STDIO;
+networking/udhcp/dhcpd.c: logmode = LOGMODE_NONE;
+networking/udhcp/dhcpd.c: logmode |= LOGMODE_SYSLOG;
+networking/zcip.c: logmode |= LOGMODE_SYSLOG;
+
+
+These daemons never auto-background and never log to syslog:
+
+lpd - inetd service. Has nothing to log so far, though
+dhcprelay - standard behavior
+inotifyd - standard behavior
+runsv - standard behavior
+runsvdir - standard behavior
+svlogd - standard behavior
+tcpsvd, udpsvd - standard behavior
+tftpd - standard behavior
+
+
+Non-daemons (seems to be use syslog for a good reason):
+
+networking/nameif.c: logmode |= LOGMODE_SYSLOG;
+loginutils/chpasswd.c: logmode = LOGMODE_BOTH;
+loginutils/chpasswd.c: logmode = LOGMODE_STDIO;
+loginutils/getty.c: logmode = LOGMODE_BOTH;
+loginutils/getty.c: logmode = LOGMODE_NONE;
+loginutils/passwd.c: logmode = LOGMODE_STDIO;
+loginutils/passwd.c: logmode = LOGMODE_BOTH;
+loginutils/sulogin.c: logmode = LOGMODE_SYSLOG; (used if stdio isn't a tty)
+loginutils/sulogin.c: logmode = LOGMODE_BOTH;
+util-linux/mount.c: logmode = LOGMODE_SYSLOG; (used in a backgrounded NFS mount helper)
diff --git a/release/src/router/busybox/docs/mdev.txt b/release/src/router/busybox/docs/mdev.txt
index 63ad406021..a8a816ce9d 100644
--- a/release/src/router/busybox/docs/mdev.txt
+++ b/release/src/router/busybox/docs/mdev.txt
@@ -51,9 +51,11 @@ device nodes if your system needs something more than the default root/root
660 permissions.
The file has the format:
- :
+ :
+ or @ :
+
For example:
- hd[a-z][0-9]* 0:3 660
+ hd[a-z][0-9]* 0:3 660
The config file parsing stops at the first matching line. If no line is
matched, then the default of 0:0 660 is used. To set your own default, simply
diff --git a/release/src/router/busybox/e2fsprogs/e2fs_defs.h b/release/src/router/busybox/e2fsprogs/e2fs_defs.h
index b3ea3ae344..379640eb88 100644
--- a/release/src/router/busybox/e2fsprogs/e2fs_defs.h
+++ b/release/src/router/busybox/e2fsprogs/e2fs_defs.h
@@ -10,8 +10,8 @@
* Copyright (C) 1991, 1992 Linus Torvalds
*/
-#ifndef _LINUX_EXT2_FS_H
-#define _LINUX_EXT2_FS_H
+#ifndef LINUX_EXT2_FS_H
+#define LINUX_EXT2_FS_H 1
/*
* Special inode numbers
@@ -558,4 +558,4 @@ struct ext2_dir_entry_2 {
#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \
~EXT2_DIR_ROUND)
-#endif /* _LINUX_EXT2_FS_H */
+#endif
diff --git a/release/src/router/busybox/e2fsprogs/e2fs_lib.c b/release/src/router/busybox/e2fsprogs/e2fs_lib.c
index 839109e3f7..3e8d956872 100644
--- a/release/src/router/busybox/e2fsprogs/e2fs_lib.c
+++ b/release/src/router/busybox/e2fsprogs/e2fs_lib.c
@@ -2,8 +2,7 @@
/*
* See README for additional information
*
- * This file can be redistributed under the terms of the GNU Library General
- * Public License
+ * Licensed under GPLv2, see file LICENSE in this tarball for details.
*/
#include "libbb.h"
diff --git a/release/src/router/busybox/e2fsprogs/e2fs_lib.h b/release/src/router/busybox/e2fsprogs/e2fs_lib.h
index e21a0f917e..25b26d3824 100644
--- a/release/src/router/busybox/e2fsprogs/e2fs_lib.h
+++ b/release/src/router/busybox/e2fsprogs/e2fs_lib.h
@@ -9,9 +9,7 @@
/* Constants and structures */
#include "e2fs_defs.h"
-#if __GNUC_PREREQ(4,1)
-# pragma GCC visibility push(hidden)
-#endif
+PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
/* Iterate a function on each entry of a directory */
int iterate_on_dir(const char *dir_name,
@@ -46,6 +44,4 @@ extern const char e2attr_flags_sname[];
#define e2attr_flags_sname_chattr (&e2attr_flags_sname[1])
#endif
-#if __GNUC_PREREQ(4,1)
-# pragma GCC visibility pop
-#endif
+POP_SAVED_FUNCTION_VISIBILITY
diff --git a/release/src/router/busybox/e2fsprogs/fsck.c b/release/src/router/busybox/e2fsprogs/fsck.c
index 3c4dabc489..3c6cafbd3f 100644
--- a/release/src/router/busybox/e2fsprogs/fsck.c
+++ b/release/src/router/busybox/e2fsprogs/fsck.c
@@ -20,10 +20,7 @@
* Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
* 2001, 2002, 2003, 2004, 2005 by Theodore Ts'o.
*
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
+ * Licensed under GPLv2, see file LICENSE in this tarball for details.
*/
/* All filesystem specific hooks have been removed.
@@ -313,10 +310,10 @@ static void load_fs_info(const char *filename)
// Loop through entries
while (getmntent_r(fstab, &mte, bb_common_bufsiz1, COMMON_BUFSIZE)) {
//bb_info_msg("CREATE[%s][%s][%s][%s][%d]", mte.mnt_fsname, mte.mnt_dir,
- // mte.mnt_type, mte.mnt_opts,
+ // mte.mnt_type, mte.mnt_opts,
// mte.mnt_passno);
fs = create_fs_device(mte.mnt_fsname, mte.mnt_dir,
- mte.mnt_type, mte.mnt_opts,
+ mte.mnt_type, mte.mnt_opts,
mte.mnt_passno);
}
endmntent(fstab);
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/blkid.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/blkid.h
index 4fa9f6fdf8..9a3c2afdbd 100644
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/blkid.h
+++ b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/blkid.h
@@ -10,9 +10,8 @@
* GNU Lesser General Public License.
* %End-Header%
*/
-
-#ifndef _BLKID_BLKID_H
-#define _BLKID_BLKID_H
+#ifndef BLKID_BLKID_H
+#define BLKID_BLKID_H 1
#include
#include
@@ -102,4 +101,4 @@ extern int blkid_parse_tag_string(const char *token, char **ret_type,
}
#endif
-#endif /* _BLKID_BLKID_H */
+#endif
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/blkidP.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/blkidP.h
index c7cb8abe94..d6b2b42cc5 100644
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/blkidP.h
+++ b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/blkidP.h
@@ -10,9 +10,8 @@
* GNU Lesser General Public License.
* %End-Header%
*/
-
-#ifndef _BLKID_BLKIDP_H
-#define _BLKID_BLKIDP_H
+#ifndef BLKID_BLKIDP_H
+#define BLKID_BLKIDP_H 1
#include
#include
@@ -184,4 +183,4 @@ extern void blkid_free_dev(blkid_dev dev);
}
#endif
-#endif /* _BLKID_BLKIDP_H */
+#endif
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/devname.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/devname.c
index 5b9e48f13b..348e5d42e5 100644
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/devname.c
+++ b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/devname.c
@@ -273,7 +273,7 @@ int blkid_probe_all(blkid_cache cache)
return -BLKID_ERR_PARAM;
if (cache->bic_flags & BLKID_BIC_FL_PROBED &&
- time(0) - cache->bic_time < BLKID_PROBE_INTERVAL)
+ time(NULL) - cache->bic_time < BLKID_PROBE_INTERVAL)
return 0;
blkid_read_cache(cache);
@@ -335,7 +335,7 @@ int blkid_probe_all(blkid_cache cache)
fclose(proc);
- cache->bic_time = time(0);
+ cache->bic_time = time(NULL);
cache->bic_flags |= BLKID_BIC_FL_PROBED;
blkid_flush_cache(cache);
return 0;
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/list.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/list.h
index 8b06d853bb..a24baaa912 100644
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/list.h
+++ b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/list.h
@@ -1,6 +1,6 @@
/* vi: set sw=4 ts=4: */
#if !defined(_BLKID_LIST_H) && !defined(LIST_HEAD)
-#define _BLKID_LIST_H
+#define BLKID_LIST_H 1
#ifdef __cplusplus
extern "C" {
@@ -70,4 +70,4 @@ void list_splice(struct list_head *list, struct list_head *head);
}
#endif
-#endif /* _BLKID_LIST_H */
+#endif
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/probe.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/probe.c
index 48b240e98e..1f7188e6d6 100644
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/probe.c
+++ b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/probe.c
@@ -562,7 +562,7 @@ blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev)
if (!dev)
return NULL;
- now = time(0);
+ now = time(NULL);
diff = now - dev->bid_time;
if ((now < dev->bid_time) ||
@@ -659,7 +659,7 @@ try_again:
found_type:
if (dev && type) {
dev->bid_devno = st.st_rdev;
- dev->bid_time = time(0);
+ dev->bid_time = time(NULL);
dev->bid_flags |= BLKID_BID_FL_VERIFIED;
cache->bic_flags |= BLKID_BIC_FL_CHANGED;
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/probe.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/probe.h
index 0fd16a7716..b6d8f8e7dd 100644
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/probe.h
+++ b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/blkid/probe.h
@@ -11,9 +11,8 @@
* GNU Lesser General Public License.
* %End-Header%
*/
-
-#ifndef _BLKID_PROBE_H
-#define _BLKID_PROBE_H
+#ifndef BLKID_PROBE_H
+#define BLKID_PROBE_H 1
#include
@@ -308,9 +307,9 @@ _INLINE_ __u32 blkid_swab32(__u32 val)
#ifdef EXT2FS_REQUIRE_486
__asm__("bswap %0" : "=r" (val) : "0" (val));
#else
- __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */
- "rorl $16,%0\n\t" /* swap words */
- "xchgb %b0,%h0" /* swap higher bytes */
+ __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */
+ "rorl $16,%0\n\t" /* swap words */
+ "xchgb %b0,%h0" /* swap higher bytes */
:"=q" (val)
: "0" (val));
#endif
@@ -319,9 +318,9 @@ _INLINE_ __u32 blkid_swab32(__u32 val)
_INLINE_ __u16 blkid_swab16(__u16 val)
{
- __asm__("xchgb %b0,%h0" /* swap bytes */ \
- : "=q" (val) \
- : "0" (val)); \
+ __asm__("xchgb %b0,%h0" /* swap bytes */
+ : "=q" (val)
+ : "0" (val));
return val;
}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2fsbb.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2fsbb.h
index 78e7cbd04c..d31c319556 100644
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2fsbb.h
+++ b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2fsbb.h
@@ -6,8 +6,8 @@
* instead. This makes upgrade between e2fsprogs versions easy.
*/
-#ifndef __E2FSBB_H__
-#define __E2FSBB_H__ 1
+#ifndef E2FSBB_H
+#define E2FSBB_H 1
#include "libbb.h"
@@ -40,4 +40,4 @@ typedef long errcode_t;
#define WORDS_BIGENDIAN 1
#endif
-#endif /* __E2FSBB_H__ */
+#endif
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2fsck.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2fsck.c
index 7cb1227db3..d1f8d1ecb9 100644
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2fsck.c
+++ b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/e2fsck.c
@@ -192,10 +192,10 @@ struct buffer_head {
#define K_DEV_FS 1
#define K_DEV_JOURNAL 2
-#define lock_buffer(bh) do {} while(0)
-#define unlock_buffer(bh) do {} while(0)
+#define lock_buffer(bh) do {} while (0)
+#define unlock_buffer(bh) do {} while (0)
#define buffer_req(bh) 1
-#define do_readahead(journal, start) do {} while(0)
+#define do_readahead(journal, start) do {} while (0)
static e2fsck_t e2fsck_global_ctx; /* Try your very best not to use this! */
@@ -2270,7 +2270,7 @@ static void e2fsck_move_ext3_journal(e2fsck_t ctx)
ext2fs_mark_super_dirty(fs);
fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
inode.i_links_count = 0;
- inode.i_dtime = time(0);
+ inode.i_dtime = time(NULL);
if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0)
goto err_out;
@@ -3381,7 +3381,7 @@ static void e2fsck_pass1(e2fsck_t ctx)
*/
if (!LINUX_S_ISDIR(inode->i_mode)) {
if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
- inode->i_dtime = time(0);
+ inode->i_dtime = time(NULL);
inode->i_links_count = 0;
ext2fs_icount_store(ctx->inode_link_info,
ino, 0);
@@ -3475,7 +3475,7 @@ static void e2fsck_pass1(e2fsck_t ctx)
inode->i_dtime < ctx->fs->super->s_inodes_count) {
if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) {
inode->i_dtime = inode->i_links_count ?
- 0 : time(0);
+ 0 : time(NULL);
e2fsck_write_inode(ctx, ino, inode,
"pass1");
}
@@ -3489,7 +3489,7 @@ static void e2fsck_pass1(e2fsck_t ctx)
if (!inode->i_dtime && inode->i_mode) {
if (fix_problem(ctx,
PR_1_ZERO_DTIME, &pctx)) {
- inode->i_dtime = time(0);
+ inode->i_dtime = time(NULL);
e2fsck_write_inode(ctx, ino, inode,
"pass1");
}
@@ -3659,7 +3659,7 @@ static void e2fsck_pass1(e2fsck_t ctx)
}
e2fsck_read_inode(ctx, EXT2_RESIZE_INO, inode,
"recreate inode");
- inode->i_mtime = time(0);
+ inode->i_mtime = time(NULL);
e2fsck_write_inode(ctx, EXT2_RESIZE_INO, inode,
"recreate inode");
fs->block_map = save_bmap;
@@ -4169,7 +4169,7 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
if (pb.clear) {
inode->i_links_count = 0;
ext2fs_icount_store(ctx->inode_link_info, ino, 0);
- inode->i_dtime = time(0);
+ inode->i_dtime = time(NULL);
dirty_inode++;
ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
@@ -4202,7 +4202,7 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
inode->i_links_count = 0;
ext2fs_icount_store(ctx->inode_link_info, ino, 0);
- inode->i_dtime = time(0);
+ inode->i_dtime = time(NULL);
dirty_inode++;
ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
@@ -5147,7 +5147,7 @@ static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
/* Inode may have changed by block_iterate, so reread it */
e2fsck_read_inode(ctx, ino, &inode, "delete_file");
inode.i_links_count = 0;
- inode.i_dtime = time(0);
+ inode.i_dtime = time(NULL);
if (inode.i_file_acl &&
(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
count = 1;
@@ -6393,7 +6393,7 @@ static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
ext2fs_icount_store(ctx->inode_link_info, ino, 0);
e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
inode.i_links_count = 0;
- inode.i_dtime = time(0);
+ inode.i_dtime = time(NULL);
e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
clear_problem_context(&pctx);
pctx.ino = ino;
@@ -6890,7 +6890,7 @@ static void check_root(e2fsck_t ctx)
memset(&inode, 0, sizeof(inode));
inode.i_mode = 040755;
inode.i_size = fs->blocksize;
- inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
+ inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL);
inode.i_links_count = 2;
inode.i_blocks = fs->blocksize / 512;
inode.i_block[0] = blk;
@@ -7138,7 +7138,7 @@ ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
memset(&inode, 0, sizeof(inode));
inode.i_mode = 040700;
inode.i_size = fs->blocksize;
- inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
+ inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL);
inode.i_links_count = 2;
inode.i_blocks = fs->blocksize / 512;
inode.i_block[0] = blk;
@@ -7492,7 +7492,7 @@ static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
ext2fs_icount_store(ctx->inode_link_info, i, 0);
inode.i_links_count = 0;
- inode.i_dtime = time(0);
+ inode.i_dtime = time(NULL);
e2fsck_write_inode(ctx, i, &inode,
"disconnect_inode");
/*
@@ -10014,7 +10014,7 @@ static int do_one_pass(journal_t *journal,
* all of the sequence number checks. What are we going
* to do with it? That depends on the pass... */
- switch(blocktype) {
+ switch (blocktype) {
case JFS_DESCRIPTOR_BLOCK:
/* If it is a valid descriptor block, replay it
* in pass REPLAY; otherwise, just skip over the
@@ -11158,7 +11158,7 @@ int journal_init_revoke(journal_t *journal, int hash_size)
shift = 0;
tmp = hash_size;
- while((tmp >>= 1UL) != 0UL)
+ while ((tmp >>= 1UL) != 0UL)
shift++;
journal->j_revoke->hash_shift = shift;
@@ -11558,7 +11558,7 @@ static int release_orphan_inodes(e2fsck_t ctx)
if (!inode.i_links_count) {
ext2fs_inode_alloc_stats2(fs, ino, -1,
LINUX_S_ISDIR(inode.i_mode));
- inode.i_dtime = time(0);
+ inode.i_dtime = time(NULL);
} else {
inode.i_dtime = 0;
}
@@ -12251,7 +12251,7 @@ static int read_a_char(void)
int r;
int fail = 0;
- while(1) {
+ while (1) {
if (e2fsck_global_ctx &&
(e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
return 3;
@@ -12281,7 +12281,7 @@ static int ask_yn(const char * string, int def)
tmp.c_lflag &= ~(ICANON | ECHO);
tmp.c_cc[VMIN] = 1;
tmp.c_cc[VTIME] = 0;
- tcsetattr (0, TCSANOW, &tmp);
+ tcsetattr_stdin_TCSANOW(&tmp);
#endif
if (def == 1)
@@ -12297,7 +12297,7 @@ static int ask_yn(const char * string, int def)
break;
if (c == 3) {
#ifdef HAVE_TERMIOS_H
- tcsetattr (0, TCSANOW, &termios);
+ tcsetattr_stdin_TCSANOW(&termios);
#endif
if (e2fsck_global_ctx &&
e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) {
@@ -12323,7 +12323,7 @@ static int ask_yn(const char * string, int def)
else
puts ("no\n");
#ifdef HAVE_TERMIOS_H
- tcsetattr (0, TCSANOW, &termios);
+ tcsetattr_stdin_TCSANOW(&termios);
#endif
return def;
}
@@ -12632,7 +12632,7 @@ static void check_mount(e2fsck_t ctx)
retval = ext2fs_check_if_mounted(ctx->filesystem_name,
&ctx->mount_flags);
if (retval) {
- bb_error_msg(_("while determining whether %s is mounted."),
+ bb_error_msg(_("while determining whether %s is mounted"),
ctx->filesystem_name);
return;
}
@@ -12653,7 +12653,7 @@ static void check_mount(e2fsck_t ctx)
printf(_("%s is mounted. "), ctx->filesystem_name);
if (!ctx->interactive)
- bb_error_msg_and_die(_("Cannot continue, aborting."));
+ bb_error_msg_and_die(_("cannot continue, aborting"));
printf(_("\n\n\007\007\007\007WARNING!!! "
"Running e2fsck on a mounted filesystem may cause\n"
"SEVERE filesystem damage.\007\007\007\n\n"));
@@ -12714,7 +12714,7 @@ static void check_if_skip(e2fsck_t ctx)
unsigned int reason_arg = 0;
long next_check;
int batt = is_on_batt();
- time_t now = time(0);
+ time_t now = time(NULL);
if ((ctx->options & E2F_OPT_FORCE) || cflag || swapfs)
return;
@@ -12892,7 +12892,7 @@ static int e2fsck_update_progress(e2fsck_t ctx, int pass,
if (ctx->progress_fd) {
sprintf(buf, "%d %lu %lu\n", pass, cur, max);
- write(ctx->progress_fd, buf, strlen(buf));
+ xwrite_str(ctx->progress_fd, buf);
} else {
percent = calc_percent(&e2fsck_tbl, pass, cur, max);
e2fsck_simple_progress(ctx, ctx->device_name,
@@ -13060,7 +13060,7 @@ static errcode_t PRS(int argc, char **argv, e2fsck_t *ret_ctx)
case 'a':
if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
conflict_opt:
- bb_error_msg_and_die(_("Only one the options -p/-a, -n or -y may be specified."));
+ bb_error_msg_and_die(_("only one the options -p/-a, -n or -y may be specified"));
}
ctx->options |= E2F_OPT_PREEN;
break;
@@ -13405,7 +13405,7 @@ restart:
#ifdef ENABLE_COMPRESSION
/* FIXME - do we support this at all? */
if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
- bb_error_msg(_("Warning: compression support is experimental."));
+ bb_error_msg(_("warning: compression support is experimental"));
#endif
#ifndef ENABLE_HTREE
if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/bb_inode.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/bb_inode.c
index 855f86eac9..1deae54e81 100644
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/bb_inode.c
+++ b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/bb_inode.c
@@ -125,9 +125,9 @@ errcode_t ext2fs_update_bb_inode(ext2_filsys fs, ext2_badblocks_list bb_list)
if (retval)
goto cleanup;
- inode.i_atime = inode.i_mtime = time(0);
+ inode.i_atime = inode.i_mtime = time(NULL);
if (!inode.i_ctime)
- inode.i_ctime = time(0);
+ inode.i_ctime = time(NULL);
inode.i_blocks = rec.bad_block_count * (fs->blocksize / 512);
inode.i_size = rec.bad_block_count * fs->blocksize;
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/dirhash.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/dirhash.c
index ab3243fd77..09e34be3b6 100644
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/dirhash.c
+++ b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/dirhash.c
@@ -42,7 +42,7 @@ static void TEA_transform(__u32 buf[4], __u32 const in[])
sum += DELTA;
b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b);
b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d);
- } while(--n);
+ } while (--n);
buf[0] += b0;
buf[1] += b1;
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2_fs.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2_fs.h
index cb49d7a600..6f4f708628 100644
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2_fs.h
+++ b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2_fs.h
@@ -13,9 +13,8 @@
*
* Copyright (C) 1991, 1992 Linus Torvalds
*/
-
-#ifndef _LINUX_EXT2_FS_H
-#define _LINUX_EXT2_FS_H
+#ifndef LINUX_EXT2_FS_H
+#define LINUX_EXT2_FS_H 1
#include "ext2_types.h" /* Changed from linux/types.h */
@@ -567,4 +566,4 @@ struct ext2_dir_entry_2 {
#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \
~EXT2_DIR_ROUND)
-#endif /* _LINUX_EXT2_FS_H */
+#endif
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2_io.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2_io.h
index e6c9630e2c..1900a76392 100644
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2_io.h
+++ b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2_io.h
@@ -9,9 +9,8 @@
* License.
* %End-Header%
*/
-
-#ifndef _EXT2FS_EXT2_IO_H
-#define _EXT2FS_EXT2_IO_H
+#ifndef EXT2FS_EXT2_IO_H
+#define EXT2FS_EXT2_IO_H 1
/*
* ext2_loff_t is defined here since unix_io.c needs it.
@@ -110,5 +109,4 @@ extern void (*test_io_cb_write_blk)
extern void (*test_io_cb_set_blksize)
(int blksize, errcode_t err);
-#endif /* _EXT2FS_EXT2_IO_H */
-
+#endif
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2fs.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2fs.h
index 133fb1f1b1..9f772016f8 100644
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2fs.h
+++ b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/ext2fs.h
@@ -9,9 +9,8 @@
* License.
* %End-Header%
*/
-
-#ifndef _EXT2FS_EXT2FS_H
-#define _EXT2FS_EXT2FS_H
+#ifndef EXT2FS_EXT2FS_H
+#define EXT2FS_EXT2FS_H 1
#define EXT2FS_ATTR(x)
@@ -920,4 +919,4 @@ extern blk_t ext2fs_inode_data_blocks(ext2_filsys fs,
}
#endif
-#endif /* _EXT2FS_EXT2FS_H */
+#endif
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/kernel-jbd.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/kernel-jbd.h
index 4c6c7dedd3..853d97ac7f 100644
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/kernel-jbd.h
+++ b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/kernel-jbd.h
@@ -13,9 +13,8 @@
* Definitions for transaction data structures for the buffer cache
* filesystem journaling support.
*/
-
-#ifndef _LINUX_JBD_H
-#define _LINUX_JBD_H
+#ifndef LINUX_JBD_H
+#define LINUX_JBD_H 1
#include
#include
@@ -233,4 +232,4 @@ extern void journal_brelse_array(struct buffer_head *b[], int n);
extern void journal_destroy_revoke(journal_t *);
-#endif /* _LINUX_JBD_H */
+#endif
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/kernel-list.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/kernel-list.h
index 3392596ca8..d80716a454 100644
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/kernel-list.h
+++ b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/kernel-list.h
@@ -1,6 +1,6 @@
/* vi: set sw=4 ts=4: */
-#ifndef _LINUX_LIST_H
-#define _LINUX_LIST_H
+#ifndef LINUX_LIST_H
+#define LINUX_LIST_H 1
/*
* Simple doubly linked list implementation.
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/mkjournal.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/mkjournal.c
index 5bdd346820..af47aee18b 100644
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/mkjournal.c
+++ b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/mkjournal.c
@@ -231,7 +231,7 @@ static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino,
inode.i_size += fs->blocksize * size;
inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
- inode.i_mtime = inode.i_ctime = time(0);
+ inode.i_mtime = inode.i_ctime = time(NULL);
inode.i_links_count = 1;
inode.i_mode = LINUX_S_IFREG | 0600;
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/res_gdt.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/res_gdt.c
index f7ee8b1fb3..3c550d511e 100644
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/res_gdt.c
+++ b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/ext2fs/res_gdt.c
@@ -113,11 +113,11 @@ errcode_t ext2fs_create_resize_inode(ext2_filsys fs)
inode_size *= fs->blocksize;
inode.i_size = inode_size & 0xFFFFFFFF;
inode.i_size_high = (inode_size >> 32) & 0xFFFFFFFF;
- if(inode.i_size_high) {
+ if (inode.i_size_high) {
sb->s_feature_ro_compat |=
EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
}
- inode.i_ctime = time(0);
+ inode.i_ctime = time(NULL);
}
for (rsv_off = 0, gdt_off = fs->desc_blocks,
@@ -209,7 +209,7 @@ out_inode:
inode.i_size);
#endif
if (inode_dirty) {
- inode.i_atime = inode.i_mtime = time(0);
+ inode.i_atime = inode.i_mtime = time(NULL);
retval2 = ext2fs_write_inode(fs, EXT2_RESIZE_INO, &inode);
if (!retval)
retval = retval2;
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/fsck.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/fsck.c
index 9cb9f754db..98e4e38fee 100644
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/fsck.c
+++ b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/fsck.c
@@ -20,10 +20,7 @@
* Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
* 2001, 2002, 2003, 2004, 2005 by Theodore Ts'o.
*
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
+ * Licensed under GPLv2, see file LICENSE in this tarball for details.
*/
#include
@@ -533,21 +530,21 @@ static struct fs_info *lookup(char *filesys)
/* Find fsck program for a given fs type. */
static char *find_fsck(char *type)
{
- char *s;
- const char *tpl;
- char *p = string_copy(fsck_path);
- struct stat st;
+ char *s;
+ const char *tpl;
+ char *p = string_copy(fsck_path);
+ struct stat st;
- /* Are we looking for a program or just a type? */
- tpl = (strncmp(type, "fsck.", 5) ? "%s/fsck.%s" : "%s/%s");
+ /* Are we looking for a program or just a type? */
+ tpl = (strncmp(type, "fsck.", 5) ? "%s/fsck.%s" : "%s/%s");
- for(s = strtok(p, ":"); s; s = strtok(NULL, ":")) {
- s = xasprintf(tpl, s, type);
- if (stat(s, &st) == 0) break;
- free(s);
- }
- free(p);
- return s;
+ for (s = strtok(p, ":"); s; s = strtok(NULL, ":")) {
+ s = xasprintf(tpl, s, type);
+ if (stat(s, &st) == 0) break;
+ free(s);
+ }
+ free(p);
+ return s;
}
static int progress_active(void)
@@ -885,7 +882,7 @@ static void compile_fs_type(char *fs_type, struct fs_type_compile *cmp)
list = string_copy(fs_type);
num = 0;
s = strtok(list, ",");
- while(s) {
+ while (s) {
negate = 0;
if (strncmp(s, "no", 2) == 0) {
s += 2;
@@ -930,7 +927,7 @@ static int opt_in_list(char *opt, char *optlist)
list = string_copy(optlist);
s = strtok(list, ",");
- while(s) {
+ while (s) {
if (strcmp(s, opt) == 0) {
free(list);
return 1;
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/mke2fs.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/mke2fs.c
index 852c249b10..a1327437d7 100644
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/mke2fs.c
+++ b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/mke2fs.c
@@ -5,8 +5,7 @@
* Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
* 2003, 2004, 2005 by Theodore Ts'o.
*
- * This file may be redistributed under the terms of the GNU Public
- * License.
+ * Licensed under GPLv2, see file LICENSE in this tarball for details.
*/
/* Usage: mke2fs [options] device
@@ -676,7 +675,7 @@ static int set_os(struct ext2_super_block *sb, char *os)
return 1;
}
- if((sb->s_creator_os = e2p_string2os(os)) >= 0) {
+ if ((sb->s_creator_os = e2p_string2os(os)) >= 0) {
return 1;
} else if (!strcasecmp("GNU", os)) {
sb->s_creator_os = EXT2_OS_HURD;
@@ -1187,7 +1186,7 @@ int mke2fs_main (int argc, char **argv)
if (ENABLE_FEATURE_CLEAN_UP)
atexit(mke2fs_clean_up);
- if(!PRS(argc, argv))
+ if (!PRS(argc, argv))
return 0;
#ifdef CONFIG_TESTIO_DEBUG
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/tune2fs.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/tune2fs.c
index b7a1b21eb0..1d39ed1b04 100644
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/tune2fs.c
+++ b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/tune2fs.c
@@ -8,10 +8,7 @@
*
* Copyright 1995, 1996, 1997, 1998, 1999, 2000 by Theodore Ts'o.
*
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
+ * Licensed under GPLv2, see file LICENSE in this tarball for details.
*/
/*
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/util.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/util.c
index b30c294b8b..7ab6591d58 100644
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/util.c
+++ b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/util.c
@@ -4,10 +4,7 @@
*
* Copyright 1995, 1996, 1997, 1998, 1999, 2000 by Theodore Ts'o.
*
- * %Begin-Header%
- * This file may be redistributed under the terms of the GNU Public
- * License.
- * %End-Header%
+ * Licensed under GPLv2, see file LICENSE in this tarball for details.
*/
#include
@@ -37,7 +34,7 @@ void check_plausibility(const char *device, int force)
val = stat(device, &s);
if (force)
return;
- if(val == -1)
+ if (val == -1)
bb_perror_msg_and_die("cannot stat %s", device);
if (!S_ISBLK(s.st_mode)) {
printf("%s is not a block special device.\n", device);
@@ -220,13 +217,13 @@ void make_journal_device(char *journal_device, ext2_filsys fs, int quiet, int fo
fs->blocksize, io_ptr, &jfs);
if (retval)
bb_error_msg_and_die("cannot journal device %s", journal_device);
- if(!quiet)
+ if (!quiet)
printf("Adding journal to device %s: ", journal_device);
fflush(stdout);
retval = ext2fs_add_journal_device(fs, jfs);
- if(retval)
+ if (retval)
bb_error_msg_and_die("\nFailed to add journal to device %s", journal_device);
- if(!quiet)
+ if (!quiet)
puts("done");
ext2fs_close(jfs);
}
@@ -242,14 +239,14 @@ void make_journal_blocks(ext2_filsys fs, int journal_size, int journal_flags, in
~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
return;
}
- if(!quiet)
+ if (!quiet)
printf("Creating journal (%ld blocks): ", journal_blocks);
fflush(stdout);
retval = ext2fs_add_journal_inode(fs, journal_blocks,
journal_flags);
- if(retval)
+ if (retval)
bb_error_msg_and_die("cannot create journal");
- if(!quiet)
+ if (!quiet)
puts("done");
}
@@ -262,6 +259,6 @@ char *e2fs_set_sbin_path(void)
oldpath = xasprintf("%s:%s", PATH_SET, oldpath);
else
oldpath = PATH_SET;
- putenv (oldpath);
+ putenv(oldpath);
return oldpath;
}
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/gen_uuid.c b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/gen_uuid.c
index 03a9f376a5..4310c17db9 100644
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/gen_uuid.c
+++ b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/gen_uuid.c
@@ -165,7 +165,7 @@ static int get_node_id(unsigned char *node_id)
n = ifc.ifc_len;
for (i = 0; i < n; i+= ifreq_size(*ifrp) ) {
ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i);
- strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ);
+ strncpy_IFNAMSIZ(ifr.ifr_name, ifrp->ifr_name);
#ifdef SIOCGIFHWADDR
if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0)
continue;
diff --git a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/uuid.h b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/uuid.h
index b30ca3c629..7a9706449b 100644
--- a/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/uuid.h
+++ b/release/src/router/busybox/e2fsprogs/old_e2fsprogs/uuid/uuid.h
@@ -32,9 +32,8 @@
* DAMAGE.
* %End-Header%
*/
-
-#ifndef _UUID_UUID_H
-#define _UUID_UUID_H
+#ifndef UUID_UUID_H
+#define UUID_UUID_H 1
#include
#include
diff --git a/release/src/router/busybox/editors/Config.in b/release/src/router/busybox/editors/Config.in
index 27426bc2e3..7dbc9b6da6 100644
--- a/release/src/router/busybox/editors/Config.in
+++ b/release/src/router/busybox/editors/Config.in
@@ -12,9 +12,9 @@ config AWK
Awk is used as a pattern scanning and processing language. This is
the BusyBox implementation of that programming language.
-config FEATURE_AWK_MATH
+config FEATURE_AWK_LIBM
bool "Enable math functions (requires libm)"
- default y
+ default n
depends on AWK
help
Enable math functions of the Awk programming language.
diff --git a/release/src/router/busybox/editors/awk.c b/release/src/router/busybox/editors/awk.c
index 72eca245f0..89ce2cfc81 100644
--- a/release/src/router/busybox/editors/awk.c
+++ b/release/src/router/busybox/editors/awk.c
@@ -366,25 +366,22 @@ static const uint32_t tokeninfo[] = {
enum {
CONVFMT, OFMT, FS, OFS,
ORS, RS, RT, FILENAME,
- SUBSEP, ARGIND, ARGC, ARGV,
- ERRNO, FNR,
- NR, NF, IGNORECASE,
- ENVIRON, F0, NUM_INTERNAL_VARS
+ SUBSEP, F0, ARGIND, ARGC,
+ ARGV, ERRNO, FNR, NR,
+ NF, IGNORECASE, ENVIRON, NUM_INTERNAL_VARS
};
static const char vNames[] ALIGN1 =
"CONVFMT\0" "OFMT\0" "FS\0*" "OFS\0"
"ORS\0" "RS\0*" "RT\0" "FILENAME\0"
- "SUBSEP\0" "ARGIND\0" "ARGC\0" "ARGV\0"
- "ERRNO\0" "FNR\0"
- "NR\0" "NF\0*" "IGNORECASE\0*"
- "ENVIRON\0" "$\0*" "\0";
+ "SUBSEP\0" "$\0*" "ARGIND\0" "ARGC\0"
+ "ARGV\0" "ERRNO\0" "FNR\0" "NR\0"
+ "NF\0*" "IGNORECASE\0*" "ENVIRON\0" "\0";
static const char vValues[] ALIGN1 =
"%.6g\0" "%.6g\0" " \0" " \0"
"\n\0" "\n\0" "\0" "\0"
- "\034\0"
- "\377";
+ "\034\0" "\0" "\377";
/* hash size may grow to these values */
#define FIRST_PRIME 61
@@ -392,8 +389,12 @@ static const uint16_t PRIMES[] ALIGN2 = { 251, 1021, 4093, 16381, 65521 };
/* Globals. Split in two parts so that first one is addressed
- * with (mostly short) negative offsets */
+ * with (mostly short) negative offsets.
+ * NB: it's unsafe to put members of type "double"
+ * into globals2 (gcc may fail to align them).
+ */
struct globals {
+ double t_double;
chain beginseq, mainseq, endseq;
chain *seq;
node *break_ptr, *continue_ptr;
@@ -442,16 +443,16 @@ struct globals2 {
tsplitter exec_builtin__tspl;
/* biggest and least used members go last */
- double t_double;
tsplitter fsplitter, rsplitter;
};
#define G1 (ptr_to_globals[-1])
#define G (*(struct globals2 *)ptr_to_globals)
/* For debug. nm --size-sort awk.o | grep -vi ' [tr] ' */
-/* char G1size[sizeof(G1)]; - 0x6c */
-/* char Gsize[sizeof(G)]; - 0x1cc */
+/*char G1size[sizeof(G1)]; - 0x74 */
+/*char Gsize[sizeof(G)]; - 0x1c4 */
/* Trying to keep most of members accessible with short offsets: */
-/* char Gofs_seed[offsetof(struct globals2, evaluate__seed)]; - 0x90 */
+/*char Gofs_seed[offsetof(struct globals2, evaluate__seed)]; - 0x90 */
+#define t_double (G1.t_double )
#define beginseq (G1.beginseq )
#define mainseq (G1.mainseq )
#define endseq (G1.endseq )
@@ -479,7 +480,6 @@ struct globals2 {
#define t_info (G.t_info )
#define t_tclass (G.t_tclass )
#define t_string (G.t_string )
-#define t_double (G.t_double )
#define t_lineno (G.t_lineno )
#define t_rollback (G.t_rollback )
#define intvar (G.intvar )
@@ -512,7 +512,7 @@ static const char EMSG_TOO_FEW_ARGS[] ALIGN1 = "Too few arguments for builtin";
static const char EMSG_NOT_ARRAY[] ALIGN1 = "Not an array";
static const char EMSG_POSSIBLE_ERROR[] ALIGN1 = "Possible syntax error";
static const char EMSG_UNDEF_FUNC[] ALIGN1 = "Call to undefined function";
-#if !ENABLE_FEATURE_AWK_MATH
+#if !ENABLE_FEATURE_AWK_LIBM
static const char EMSG_NO_MATH[] ALIGN1 = "Math support is not compiled in";
#endif
@@ -604,8 +604,8 @@ static void *hash_find(xhash *hash, const char *name)
hash_rebuild(hash);
l = strlen(name) + 1;
- hi = xzalloc(sizeof(hash_item) + l);
- memcpy(hi->name, name, l);
+ hi = xzalloc(sizeof(*hi) + l);
+ strcpy(hi->name, name);
idx = hashidx(name) % hash->csize;
hi->next = hash->items[idx];
@@ -681,6 +681,18 @@ static ALWAYS_INLINE int isalnum_(int c)
return (isalnum(c) || c == '_');
}
+static double my_strtod(char **pp)
+{
+#if ENABLE_DESKTOP
+ if ((*pp)[0] == '0'
+ && ((((*pp)[1] | 0x20) == 'x') || isdigit((*pp)[1]))
+ ) {
+ return strtoull(*pp, pp, 0);
+ }
+#endif
+ return strtod(*pp, pp);
+}
+
/* -------- working with variables (set/get/copy/etc) -------- */
static xhash *iamarray(var *v)
@@ -790,7 +802,7 @@ static double getvar_i(var *v)
v->number = 0;
s = v->string;
if (s && *s) {
- v->number = strtod(s, &s);
+ v->number = my_strtod(&s);
if (v->type & VF_USER) {
skip_spaces(&s);
if (*s != '\0')
@@ -804,6 +816,19 @@ static double getvar_i(var *v)
return v->number;
}
+/* Used for operands of bitwise ops */
+static unsigned long getvar_i_int(var *v)
+{
+ double d = getvar_i(v);
+
+ /* Casting doubles to longs is undefined for values outside
+ * of target type range. Try to widen it as much as possible */
+ if (d >= 0)
+ return (unsigned long)d;
+ /* Why? Think about d == -4294967295.0 (assuming 32bit longs) */
+ return - (long) (unsigned long) (-d);
+}
+
static var *copyvar(var *dest, const var *src)
{
if (dest != src) {
@@ -973,12 +998,7 @@ static uint32_t next_token(uint32_t expected)
} else if (*p == '.' || isdigit(*p)) {
/* it's a number */
-#if ENABLE_DESKTOP
- if (p[0] == '0' && (p[1] | 0x20) == 'x')
- t_double = strtoll(p, &p, 0);
- else
-#endif
- t_double = strtod(p, &p);
+ t_double = my_strtod(&p);
if (*p == '.')
syntax_error(EMSG_UNEXP_TOKEN);
tc = TC_NUMBER;
@@ -1462,6 +1482,7 @@ static node *mk_splitter(const char *s, tsplitter *spl)
*/
static regex_t *as_regex(node *op, regex_t *preg)
{
+ int cflags;
var *v;
const char *s;
@@ -1470,7 +1491,17 @@ static regex_t *as_regex(node *op, regex_t *preg)
}
v = nvalloc(1);
s = getvar_s(evaluate(op, v));
- xregcomp(preg, s, icase ? REG_EXTENDED | REG_ICASE : REG_EXTENDED);
+
+ cflags = icase ? REG_EXTENDED | REG_ICASE : REG_EXTENDED;
+ /* Testcase where REG_EXTENDED fails (unpaired '{'):
+ * echo Hi | awk 'gsub("@(samp|code|file)\{","");'
+ * gawk 3.1.5 eats this. We revert to ~REG_EXTENDED
+ * (maybe gsub is not supposed to use REG_EXTENDED?).
+ */
+ if (regcomp(preg, s, cflags)) {
+ cflags &= ~REG_EXTENDED;
+ xregcomp(preg, s, cflags);
+ }
nvfree(v);
return preg;
}
@@ -1543,7 +1574,10 @@ static int awk_split(const char *s, node *spl, char **slist)
if (s[l]) pmatch[0].rm_eo++;
}
memcpy(s1, s, l);
- s1[l] = '\0';
+ /* make sure we remove *all* of the separator chars */
+ while (l < pmatch[0].rm_eo) {
+ s1[l++] = '\0';
+ }
nextword(&s1);
s += pmatch[0].rm_eo;
} while (*s);
@@ -1836,7 +1870,6 @@ static int fmt_num(char *b, int size, const char *format, double n, int int_as_i
return r;
}
-
/* formatted output into an allocated buffer, return ptr to buffer */
static char *awk_printf(node *n)
{
@@ -2004,8 +2037,8 @@ static var *exec_builtin(node *op, var *res)
switch (info & OPNMASK) {
case B_a2:
-#if ENABLE_FEATURE_AWK_MATH
- setvar_i(res, atan2(getvar_i(av[i]), getvar_i(av[1])));
+#if ENABLE_FEATURE_AWK_LIBM
+ setvar_i(res, atan2(getvar_i(av[0]), getvar_i(av[1])));
#else
syntax_error(EMSG_NO_MATH);
#endif
@@ -2022,7 +2055,7 @@ static var *exec_builtin(node *op, var *res)
n = awk_split(as[0], spl, &s);
s1 = s;
clear_array(iamarray(av[1]));
- for (i=1; i<=n; i++)
+ for (i = 1; i <= n; i++)
setari_u(av[1], i, nextword(&s1));
free(s);
setvar_i(res, n);
@@ -2042,27 +2075,27 @@ static var *exec_builtin(node *op, var *res)
/* Bitwise ops must assume that operands are unsigned. GNU Awk 3.1.5:
* awk '{ print or(-1,1) }' gives "4.29497e+09", not "-2.xxxe+09" */
case B_an:
- setvar_i(res, (unsigned long)getvar_i(av[0]) & (unsigned long)getvar_i(av[1]));
+ setvar_i(res, getvar_i_int(av[0]) & getvar_i_int(av[1]));
break;
case B_co:
- setvar_i(res, ~(unsigned long)getvar_i(av[0]));
+ setvar_i(res, ~getvar_i_int(av[0]));
break;
case B_ls:
- setvar_i(res, (unsigned long)getvar_i(av[0]) << (unsigned long)getvar_i(av[1]));
+ setvar_i(res, getvar_i_int(av[0]) << getvar_i_int(av[1]));
break;
case B_or:
- setvar_i(res, (unsigned long)getvar_i(av[0]) | (unsigned long)getvar_i(av[1]));
+ setvar_i(res, getvar_i_int(av[0]) | getvar_i_int(av[1]));
break;
case B_rs:
- setvar_i(res, (unsigned long)getvar_i(av[0]) >> (unsigned long)getvar_i(av[1]));
+ setvar_i(res, getvar_i_int(av[0]) >> getvar_i_int(av[1]));
break;
case B_xo:
- setvar_i(res, (unsigned long)getvar_i(av[0]) ^ (unsigned long)getvar_i(av[1]));
+ setvar_i(res, getvar_i_int(av[0]) ^ getvar_i_int(av[1]));
break;
case B_lo:
@@ -2445,7 +2478,7 @@ static var *evaluate(node *op, var *res)
case F_rn:
R.d = (double)rand() / (double)RAND_MAX;
break;
-#if ENABLE_FEATURE_AWK_MATH
+#if ENABLE_FEATURE_AWK_LIBM
case F_co:
R.d = cos(L.d);
break;
@@ -2613,7 +2646,7 @@ static var *evaluate(node *op, var *res)
L.d /= R.d;
break;
case '&':
-#if ENABLE_FEATURE_AWK_MATH
+#if ENABLE_FEATURE_AWK_LIBM
L.d = pow(L.d, R.d);
#else
syntax_error(EMSG_NO_MATH);
@@ -2846,18 +2879,18 @@ int awk_main(int argc, char **argv)
parse_program(s + 1);
free(s);
} while (list_f);
+ argc++;
} else { // no -f: take program from 1st parameter
if (!argc)
bb_show_usage();
g_progname = "cmd. line";
parse_program(*argv++);
- argc--;
}
if (opt & 0x8) // -W
bb_error_msg("warning: unrecognized option '-W %s' ignored", opt_W);
/* fill in ARGV array */
- setvar_i(intvar[ARGC], argc + 1);
+ setvar_i(intvar[ARGC], argc);
setari_u(intvar[ARGV], 0, "awk");
i = 0;
while (*argv)
diff --git a/release/src/router/busybox/editors/diff.c b/release/src/router/busybox/editors/diff.c
index 64ad6511da..7fce70d083 100644
--- a/release/src/router/busybox/editors/diff.c
+++ b/release/src/router/busybox/editors/diff.c
@@ -858,7 +858,7 @@ static void print_header(const char *file1, const char *file2)
* lines appended (beginning at b). If c is greater than d then there are
* lines missing from the to file.
*/
-static void change(char *file1, FILE *f1, char *file2, FILE *f2,
+static void change(const char *file1, FILE *f1, const char *file2, FILE *f2,
int a, int b, int c, int d)
{
if ((a > b && c > d) || (option_mask32 & FLAG_q)) {
@@ -902,7 +902,7 @@ static void change(char *file1, FILE *f1, char *file2, FILE *f2,
}
-static void output(char *file1, FILE *f1, char *file2, FILE *f2)
+static void output(const char *file1, FILE *f1, const char *file2, FILE *f2)
{
/* Note that j0 and j1 can't be used as they are defined in math.h.
* This also allows the rather amusing variable 'j00'... */
@@ -999,7 +999,7 @@ static void output(char *file1, FILE *f1, char *file2, FILE *f2)
*/
/* NB: files can be not REGular. The only sure thing that they
* are not both DIRectories. */
-static unsigned diffreg(char *file1, char *file2, int flags)
+static unsigned diffreg(const char *file1, const char *file2, int flags)
{
int *member; /* will be overlaid on nfile[1] */
int *class; /* will be overlaid on nfile[0] */
@@ -1022,13 +1022,11 @@ static unsigned diffreg(char *file1, char *file2, int flags)
if (flags & D_EMPTY1)
/* can't be stdin, but xfopen_stdin() is smaller code */
- f1 = xfopen_stdin(bb_dev_null);
- else
- f1 = xfopen_stdin(file1);
+ file1 = bb_dev_null;
+ f1 = xfopen_stdin(file1);
if (flags & D_EMPTY2)
- f2 = xfopen_stdin(bb_dev_null);
- else
- f2 = xfopen_stdin(file2);
+ file2 = bb_dev_null;
+ f2 = xfopen_stdin(file2);
/* NB: if D_EMPTY1/2 is set, other file is always a regular file,
* not pipe/fifo/chardev/etc - D_EMPTY is used by "diff -r" only,
@@ -1189,7 +1187,7 @@ static char **get_recursive_dirlist(char *path)
recursive_action(path, ACTION_RECURSE|ACTION_FOLLOWLINKS,
add_to_dirlist, /* file_action */
NULL, /* dir_action */
- (void*)(strlen(path) + 1),
+ (void*)(ptrdiff_t)(strlen(path) + 1),
0);
} else {
DIR *dp;
diff --git a/release/src/router/busybox/editors/vi.c b/release/src/router/busybox/editors/vi.c
index 08599c92c6..4885ee5605 100644
--- a/release/src/router/busybox/editors/vi.c
+++ b/release/src/router/busybox/editors/vi.c
@@ -57,30 +57,6 @@ enum {
MAX_SCR_ROWS = CONFIG_FEATURE_VI_MAX_LEN,
};
-// Misc. non-Ascii keys that report an escape sequence
-#define VI_K_UP (char)128 // cursor key Up
-#define VI_K_DOWN (char)129 // cursor key Down
-#define VI_K_RIGHT (char)130 // Cursor Key Right
-#define VI_K_LEFT (char)131 // cursor key Left
-#define VI_K_HOME (char)132 // Cursor Key Home
-#define VI_K_END (char)133 // Cursor Key End
-#define VI_K_INSERT (char)134 // Cursor Key Insert
-#define VI_K_DELETE (char)135 // Cursor Key Insert
-#define VI_K_PAGEUP (char)136 // Cursor Key Page Up
-#define VI_K_PAGEDOWN (char)137 // Cursor Key Page Down
-#define VI_K_FUN1 (char)138 // Function Key F1
-#define VI_K_FUN2 (char)139 // Function Key F2
-#define VI_K_FUN3 (char)140 // Function Key F3
-#define VI_K_FUN4 (char)141 // Function Key F4
-#define VI_K_FUN5 (char)142 // Function Key F5
-#define VI_K_FUN6 (char)143 // Function Key F6
-#define VI_K_FUN7 (char)144 // Function Key F7
-#define VI_K_FUN8 (char)145 // Function Key F8
-#define VI_K_FUN9 (char)146 // Function Key F9
-#define VI_K_FUN10 (char)147 // Function Key F10
-#define VI_K_FUN11 (char)148 // Function Key F11
-#define VI_K_FUN12 (char)149 // Function Key F12
-
/* vt102 typical ESC sequence */
/* terminal standout start/normal ESC sequence */
static const char SOs[] ALIGN1 = "\033[7m";
@@ -96,6 +72,12 @@ static const char CMrc[] ALIGN1 = "\033[%d;%dH";
static const char CMup[] ALIGN1 = "\033[A";
static const char CMdown[] ALIGN1 = "\n";
+#if ENABLE_FEATURE_VI_DOT_CMD || ENABLE_FEATURE_VI_YANKMARK
+// cmds modifying text[]
+// vda: removed "aAiIs" as they switch us into insert mode
+// and remembering input for replay after them makes no sense
+static const char modifying_cmds[] = "cCdDJoOpPrRxX<>~";
+#endif
enum {
YANKONLY = FALSE,
@@ -165,10 +147,11 @@ struct globals {
char *screen; // pointer to the virtual screen buffer
int screensize; // and its size
int tabstop;
+ int last_forward_char; // last char searched for with 'f' (int because of Unicode)
char erase_char; // the users erase character
char last_input_char; // last char read from user
- char last_forward_char; // last char searched for with 'f'
+ smalluint chars_to_parse;
#if ENABLE_FEATURE_VI_DOT_CMD
smallint adding2q; // are we currently adding user input to q
int lmc_len; // length of last_modifying_cmd
@@ -180,13 +163,10 @@ struct globals {
#if ENABLE_FEATURE_VI_USE_SIGNALS || ENABLE_FEATURE_VI_CRASHME
int my_pid;
#endif
-#if ENABLE_FEATURE_VI_DOT_CMD || ENABLE_FEATURE_VI_YANKMARK
- char *modifying_cmds; // cmds that modify text[]
-#endif
#if ENABLE_FEATURE_VI_SEARCH
char *last_search_pattern; // last pattern from a '/' or '?' search
#endif
- int chars_to_parse;
+
/* former statics */
#if ENABLE_FEATURE_VI_YANKMARK
char *edit_file__cur_line;
@@ -209,11 +189,11 @@ struct globals {
char *initial_cmds[3]; // currently 2 entries, NULL terminated
#endif
// Should be just enough to hold a key sequence,
- // but CRASME mode uses it as generated command buffer too
+ // but CRASHME mode uses it as generated command buffer too
#if ENABLE_FEATURE_VI_CRASHME
char readbuffer[128];
#else
- char readbuffer[32];
+ char readbuffer[KEYCODE_BUFFER_SIZE];
#endif
#define STATUS_BUFFER_LEN 200
char status_buffer[STATUS_BUFFER_LEN]; // messages to the user
@@ -252,9 +232,10 @@ struct globals {
#define screensize (G.screensize )
#define screenbegin (G.screenbegin )
#define tabstop (G.tabstop )
+#define last_forward_char (G.last_forward_char )
#define erase_char (G.erase_char )
#define last_input_char (G.last_input_char )
-#define last_forward_char (G.last_forward_char )
+#define chars_to_parse (G.chars_to_parse )
#if ENABLE_FEATURE_VI_READONLY
#define readonly_mode (G.readonly_mode )
#else
@@ -266,9 +247,7 @@ struct globals {
#define ioq_start (G.ioq_start )
#define last_row (G.last_row )
#define my_pid (G.my_pid )
-#define modifying_cmds (G.modifying_cmds )
#define last_search_pattern (G.last_search_pattern)
-#define chars_to_parse (G.chars_to_parse )
#define edit_file__cur_line (G.edit_file__cur_line)
#define refresh__old_offset (G.refresh__old_offset)
@@ -291,14 +270,14 @@ struct globals {
#define INIT_G() do { \
SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
last_file_modified = -1; \
- /* "" but has space for 2 chars */ \
+ /* "" but has space for 2 chars: */ \
USE_FEATURE_VI_SEARCH(last_search_pattern = xzalloc(2);) \
} while (0)
static int init_text_buffer(char *); // init from file or create new
static void edit_file(char *); // edit one file
-static void do_cmd(char); // execute a command
+static void do_cmd(int); // execute a command
static int next_tabstop(int);
static void sync_cursor(char *, int *, int *); // synchronize the screen cursor to dot
static char *begin_line(char *); // return pointer to cur line B-o-l
@@ -321,27 +300,31 @@ static void dot_delete(void); // delete the char at 'dot'
static char *bound_dot(char *); // make sure text[0] <= P < "end"
static char *new_screen(int, int); // malloc virtual screen memory
static char *char_insert(char *, char); // insert the char c at 'p'
-static char *stupid_insert(char *, char); // stupidly insert the char c at 'p'
+// might reallocate text[]! use p += stupid_insert(p, ...),
+// and be careful to not use pointers into potentially freed text[]!
+static uintptr_t stupid_insert(char *, char); // stupidly insert the char c at 'p'
static int find_range(char **, char **, char); // return pointers for an object
static int st_test(char *, int, int, char *); // helper for skip_thing()
static char *skip_thing(char *, int, int, int); // skip some object
static char *find_pair(char *, char); // find matching pair () [] {}
static char *text_hole_delete(char *, char *); // at "p", delete a 'size' byte hole
-static char *text_hole_make(char *, int); // at "p", make a 'size' byte hole
+// might reallocate text[]! use p += text_hole_make(p, ...),
+// and be careful to not use pointers into potentially freed text[]!
+static uintptr_t text_hole_make(char *, int); // at "p", make a 'size' byte hole
static char *yank_delete(char *, char *, int, int); // yank text[] into register then delete
static void show_help(void); // display some help info
static void rawmode(void); // set "raw" mode on tty
static void cookmode(void); // return to "cooked" mode on tty
// sleep for 'h' 1/100 seconds, return 1/0 if stdin is (ready for read)/(not ready)
static int mysleep(int);
-static char readit(void); // read (maybe cursor) key from stdin
-static char get_one_char(void); // read 1 char from stdin
+static int readit(void); // read (maybe cursor) key from stdin
+static int get_one_char(void); // read 1 char from stdin
static int file_size(const char *); // what is the byte size of "fn"
-#if ENABLE_FEATURE_VI_READONLY
-static int file_insert(const char *, char *, int);
-#else
-static int file_insert(const char *, char *);
+#if !ENABLE_FEATURE_VI_READONLY
+#define file_insert(fn, p, update_ro_status) file_insert(fn, p)
#endif
+// file_insert might reallocate text[]!
+static int file_insert(const char *, char *, int);
static int file_write(char *, char *, char *);
#if !ENABLE_FEATURE_VI_OPTIMIZE_CURSOR
#define place_cursor(a, b, optimize) place_cursor(a, b)
@@ -350,6 +333,7 @@ static void place_cursor(int, int, int);
static void screen_erase(void);
static void clear_to_eol(void);
static void clear_to_eos(void);
+static void go_bottom_and_clear_to_eol(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
@@ -390,7 +374,9 @@ static void end_cmd_q(void); // stop saving input chars
static void showmatching(char *); // show the matching pair () [] {}
#endif
#if ENABLE_FEATURE_VI_YANKMARK || (ENABLE_FEATURE_VI_COLON && ENABLE_FEATURE_VI_SEARCH) || ENABLE_FEATURE_VI_CRASHME
-static char *string_insert(char *, char *); // insert the string at 'p'
+// might reallocate text[]! use p += string_insert(p, ...),
+// and be careful to not use pointers into potentially freed text[]!
+static uintptr_t string_insert(char *, const char *); // insert the string at 'p'
#endif
#if ENABLE_FEATURE_VI_YANKMARK
static char *text_yank(char *, char *, int); // save copy of "p" into a register
@@ -430,10 +416,6 @@ int vi_main(int argc, char **argv)
#endif
vi_setops = VI_AUTOINDENT | VI_SHOWMATCH | VI_IGNORECASE;
-#if ENABLE_FEATURE_VI_DOT_CMD || ENABLE_FEATURE_VI_YANKMARK
- modifying_cmds = (char *) "aAcCdDiIJoOpPrRsxX<>~"; // cmds modifying text[]
-#endif
-
// 1- process $HOME/.exrc file (not inplemented yet)
// 2- process EXINIT variable from environment
// 3- process command line args
@@ -510,8 +492,7 @@ static int init_text_buffer(char *fn)
char_insert(text, '\n');
rc = 0;
} else {
- rc = file_insert(fn, text
- USE_FEATURE_VI_READONLY(, 1));
+ rc = file_insert(fn, text, 1);
}
file_modified = 0;
last_file_modified = -1;
@@ -527,7 +508,7 @@ static void edit_file(char *fn)
#if ENABLE_FEATURE_VI_YANKMARK
#define cur_line edit_file__cur_line
#endif
- char c;
+ int c;
int size;
#if ENABLE_FEATURE_VI_USE_SIGNALS
int sig;
@@ -608,7 +589,8 @@ static void edit_file(char *fn)
crash_dummy(); // generate a random command
} else {
crashme = 0;
- dot = string_insert(text, "\n\n##### Ran out of text to work on. #####\n\n"); // insert the string
+ string_insert(text, "\n\n##### Ran out of text to work on. #####\n\n"); // insert the string
+ dot = text;
refresh(FALSE);
}
}
@@ -625,18 +607,21 @@ static void edit_file(char *fn)
// These are commands that change text[].
// Remember the input for the "." command
if (!adding2q && ioq_start == NULL
- && c != '\0' && strchr(modifying_cmds, c)
+ && cmd_mode == 0 // command mode
+ && c > '\0' // exclude NUL and non-ASCII chars
+ && c < 0x7f // (Unicode and such)
+ && strchr(modifying_cmds, c)
) {
start_new_cmd_q(c);
}
#endif
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
+ if (!chars_to_parse && mysleep(0) == 0) {
+ // no input pending - so update output
refresh(FALSE);
show_status_line();
}
@@ -647,8 +632,7 @@ static void edit_file(char *fn)
}
//-------------------------------------------------------------------
- place_cursor(rows - 1, 0, FALSE); // go to bottom of screen
- clear_to_eol(); // erase to end of line
+ go_bottom_and_clear_to_eol();
cookmode();
#undef cur_line
}
@@ -678,7 +662,7 @@ static char *get_one_address(char *p, int *addr) // get colon addr, if present
c = c - 'a';
q = mark[(unsigned char) c];
if (q != NULL) { // is mark valid
- *addr = count_lines(text, q); // count lines
+ *addr = count_lines(text, q);
}
}
}
@@ -844,8 +828,7 @@ static void colon(char *buf)
else if (strncmp(cmd, "!", 1) == 0) { // run a cmd
int retcode;
// :!ls run the
- place_cursor(rows - 1, 0, FALSE); // go to Status line
- clear_to_eol(); // clear the line
+ go_bottom_and_clear_to_eol();
cookmode();
retcode = system(orig_buf + 1); // run the cmd
if (retcode)
@@ -922,8 +905,7 @@ static void colon(char *buf)
}
} else if (strncasecmp(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
+ go_bottom_and_clear_to_eol();
cookmode();
show_help();
rawmode();
@@ -933,8 +915,7 @@ static void colon(char *buf)
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
+ go_bottom_and_clear_to_eol();
puts("\r");
for (; q <= r; q++) {
int c_is_no_print;
@@ -1001,7 +982,11 @@ static void colon(char *buf)
// read after current line- unless user said ":0r foo"
if (b != 0)
q = next_line(q);
- ch = file_insert(fn, q USE_FEATURE_VI_READONLY(, 0));
+ { // dance around potentially-reallocated text[]
+ uintptr_t ofs = q - text;
+ ch = file_insert(fn, q, 0);
+ q = text + ofs;
+ }
if (ch < 0)
goto vc1; // nothing was inserted
// how many lines in text[]?
@@ -1015,7 +1000,7 @@ static void colon(char *buf)
// if the insert is before "dot" then we need to update
if (q <= dot)
dot += ch;
- file_modified++;
+ /*file_modified++; - done by file_insert */
}
} else if (strncasecmp(cmd, "rewind", i) == 0) { // rewind cmd line args
if (file_modified && !useforce) {
@@ -1034,8 +1019,7 @@ static void colon(char *buf)
// only blank is regarded as args delmiter. What about tab '\t' ?
if (!args[0] || strcasecmp(args, "all") == 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
+ go_bottom_and_clear_to_eol();
printf("----------------------------------------\r\n");
#if ENABLE_FEATURE_VI_SETOPTS
if (!autoindent)
@@ -1089,10 +1073,12 @@ static void colon(char *buf)
c = orig_buf[1]; // what is the delimiter
F = orig_buf + 2; // start of "find"
R = strchr(F, c); // middle delimiter
- if (!R) goto colon_s_fail;
+ if (!R)
+ goto colon_s_fail;
*R++ = '\0'; // terminate "find"
buf1 = strchr(R, c);
- if (!buf1) goto colon_s_fail;
+ if (!buf1)
+ goto colon_s_fail;
*buf1++ = '\0'; // terminate "replace"
if (*buf1 == 'g') { // :s/foo/bar/g
buf1++;
@@ -1110,10 +1096,14 @@ static void colon(char *buf)
vc4:
buf1 = char_search(q, F, FORWARD, LIMITED); // search cur line only for "find"
if (buf1) {
+ uintptr_t bias;
// we found the "find" pattern - delete it
text_hole_delete(buf1, buf1 + strlen(F) - 1);
// inset the "replace" patern
- string_insert(buf1, R); // insert the string
+ bias = string_insert(buf1, R); // insert the string
+ buf1 += bias;
+ ls += bias;
+ /*q += bias; - recalculated anyway */
// check for "global" :s/foo/bar/g
if (gflag == 1) {
if ((buf1 + strlen(R)) < end_line(ls)) {
@@ -1205,7 +1195,7 @@ static void colon(char *buf)
static void Hit_Return(void)
{
- char c;
+ int c;
standout_start();
write1("[Hit return to continue]");
@@ -1649,8 +1639,7 @@ static char *char_search(char *p, const char *pat, int dir, int range)
static char *char_insert(char *p, char 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 ^
+ p += stupid_insert(p, '^'); // use ^ to indicate literal next
refresh(FALSE); // show the ^
c = get_one_char();
*p = c;
@@ -1677,17 +1666,23 @@ static char *char_insert(char *p, char c) // insert the char c at 'p'
if (c == 13)
c = '\n'; // translate \r to \n
sp = p; // remember addr of insert
- p = stupid_insert(p, c); // insert the char
+ p += 1 + stupid_insert(p, c); // insert the char
#if ENABLE_FEATURE_VI_SETOPTS
if (showmatch && strchr(")]}", *sp) != NULL) {
showmatching(sp);
}
if (autoindent && c == '\n') { // auto indent the new line
char *q;
-
- q = prev_line(p); // use prev line as templet
- for (; isblank(*q); q++) {
- p = stupid_insert(p, *q); // insert the char
+ size_t len;
+ q = prev_line(p); // use prev line as template
+ len = strspn(q, " \t"); // space or tab
+ if (len) {
+ uintptr_t bias;
+ bias = text_hole_make(p, len);
+ p += bias;
+ q += bias;
+ memcpy(p, q, len);
+ p += len;
}
}
#endif
@@ -1695,12 +1690,16 @@ static char *char_insert(char *p, char c) // insert the char c at 'p'
return p;
}
-static char *stupid_insert(char *p, char c) // stupidly insert the char c at 'p'
+// might reallocate text[]! use p += stupid_insert(p, ...),
+// and be careful to not use pointers into potentially freed text[]!
+static uintptr_t stupid_insert(char *p, char c) // stupidly insert the char c at 'p'
{
- p = text_hole_make(p, 1);
+ uintptr_t bias;
+ bias = text_hole_make(p, 1);
+ p += bias;
*p = c;
//file_modified++; - done by text_hole_make()
- return p + 1;
+ return bias;
}
static int find_range(char **start, char **stop, char c)
@@ -1880,26 +1879,31 @@ static void showmatching(char *p)
}
#endif /* FEATURE_VI_SETOPTS */
-// open a hole in text[]
-static char *text_hole_make(char *p, int size) // at "p", make a 'size' byte hole
+// open a hole in text[]
+// might reallocate text[]! use p += text_hole_make(p, ...),
+// and be careful to not use pointers into potentially freed text[]!
+static uintptr_t text_hole_make(char *p, int size) // at "p", make a 'size' byte hole
{
+ uintptr_t bias = 0;
+
if (size <= 0)
- return p;
+ return bias;
end += size; // adjust the new END
if (end >= (text + text_size)) {
char *new_text;
text_size += end - (text + text_size) + 10240;
new_text = xrealloc(text, text_size);
- screenbegin = new_text + (screenbegin - text);
- dot = new_text + (dot - text);
- end = new_text + (end - text);
- p = new_text + (p - text);
+ bias = (new_text - text);
+ screenbegin += bias;
+ dot += bias;
+ end += bias;
+ p += bias;
text = new_text;
}
memmove(p + size, p, end - size - p);
memset(p, ' ', size); // clear new hole
file_modified++;
- return p;
+ return bias;
}
// close a hole in text[]
@@ -2032,42 +2036,41 @@ static void end_cmd_q(void)
#if ENABLE_FEATURE_VI_YANKMARK \
|| (ENABLE_FEATURE_VI_COLON && ENABLE_FEATURE_VI_SEARCH) \
|| ENABLE_FEATURE_VI_CRASHME
-static char *string_insert(char *p, char *s) // insert the string at 'p'
+// might reallocate text[]! use p += string_insert(p, ...),
+// and be careful to not use pointers into potentially freed text[]!
+static uintptr_t string_insert(char *p, const char *s) // insert the string at 'p'
{
- int cnt, i;
+ uintptr_t bias;
+ int i;
i = strlen(s);
- text_hole_make(p, i);
- strncpy(p, s, i);
- for (cnt = 0; *s != '\0'; s++) {
- if (*s == '\n')
- cnt++;
- }
+ bias = text_hole_make(p, i);
+ p += bias;
+ memcpy(p, s, i);
#if ENABLE_FEATURE_VI_YANKMARK
- status_line("Put %d lines (%d chars) from [%c]", cnt, i, what_reg());
+ {
+ int cnt;
+ for (cnt = 0; *s != '\0'; s++) {
+ if (*s == '\n')
+ cnt++;
+ }
+ status_line("Put %d lines (%d chars) from [%c]", cnt, i, what_reg());
+ }
#endif
- return p;
+ return bias;
}
#endif
#if ENABLE_FEATURE_VI_YANKMARK
static char *text_yank(char *p, char *q, int dest) // copy text into a register
{
- char *t;
- int cnt;
-
- if (q < p) { // they are backwards- reverse them
- t = q;
- q = p;
- p = t;
+ int cnt = q - p;
+ if (cnt < 0) { // they are backwards- reverse them
+ p = q;
+ cnt = -cnt;
}
- cnt = q - p + 1;
- t = reg[dest];
- free(t); // if already a yank register, free it
- t = xmalloc(cnt + 1); // get a new register
- memset(t, '\0', cnt + 1); // clear new text[]
- strncpy(t, p, cnt); // copy text[] into bufer
- reg[dest] = t;
+ free(reg[dest]); // if already a yank register, free it
+ reg[dest] = xstrndup(p, cnt + 1);
return p;
}
@@ -2132,13 +2135,13 @@ static void rawmode(void)
term_vi.c_cc[VMIN] = 1;
term_vi.c_cc[VTIME] = 0;
erase_char = term_vi.c_cc[VERASE];
- tcsetattr(0, TCSANOW, &term_vi);
+ tcsetattr_stdin_TCSANOW(&term_vi);
}
static void cookmode(void)
{
fflush(stdout);
- tcsetattr(0, TCSANOW, &term_orig);
+ tcsetattr_stdin_TCSANOW(&term_orig);
}
//----- Come here when we get a window resize signal ---------
@@ -2171,8 +2174,7 @@ static void cont_sig(int sig UNUSED_PARAM)
//----- Come here when we get a Suspend signal -------------------
static void suspend_sig(int sig UNUSED_PARAM)
{
- place_cursor(rows - 1, 0, FALSE); // go to bottom of screen
- clear_to_eol(); // erase to end of line
+ go_bottom_and_clear_to_eol();
cookmode(); // terminal to "cooked"
signal(SIGCONT, cont_sig);
@@ -2199,120 +2201,24 @@ static int mysleep(int hund) // sleep for 'h' 1/100 seconds
}
//----- IO Routines --------------------------------------------
-static char readit(void) // read (maybe cursor) key from stdin
+static int readit(void) // read (maybe cursor) key from stdin
{
- char c;
- int n;
- struct esc_cmds {
- const char seq[4];
- char val;
- };
-
- static const struct esc_cmds esccmds[] = {
- {"OA" , VI_K_UP }, // cursor key Up
- {"OB" , VI_K_DOWN }, // cursor key Down
- {"OC" , VI_K_RIGHT }, // Cursor Key Right
- {"OD" , VI_K_LEFT }, // cursor key Left
- {"OH" , VI_K_HOME }, // Cursor Key Home
- {"OF" , VI_K_END }, // Cursor Key End
- {"[A" , VI_K_UP }, // cursor key Up
- {"[B" , VI_K_DOWN }, // cursor key Down
- {"[C" , VI_K_RIGHT }, // Cursor Key Right
- {"[D" , VI_K_LEFT }, // cursor key Left
- {"[H" , VI_K_HOME }, // Cursor Key Home
- {"[F" , VI_K_END }, // Cursor Key End
- {"[1~" , VI_K_HOME }, // Cursor Key Home
- {"[2~" , VI_K_INSERT }, // Cursor Key Insert
- {"[3~" , VI_K_DELETE }, // Cursor Key Delete
- {"[4~" , VI_K_END }, // Cursor Key End
- {"[5~" , VI_K_PAGEUP }, // Cursor Key Page Up
- {"[6~" , VI_K_PAGEDOWN}, // Cursor Key Page Down
- {"OP" , VI_K_FUN1 }, // Function Key F1
- {"OQ" , VI_K_FUN2 }, // Function Key F2
- {"OR" , VI_K_FUN3 }, // Function Key F3
- {"OS" , VI_K_FUN4 }, // Function Key F4
- // careful: these have no terminating NUL!
- {"[11~", VI_K_FUN1 }, // Function Key F1
- {"[12~", VI_K_FUN2 }, // Function Key F2
- {"[13~", VI_K_FUN3 }, // Function Key F3
- {"[14~", VI_K_FUN4 }, // Function Key F4
- {"[15~", VI_K_FUN5 }, // Function Key F5
- {"[17~", VI_K_FUN6 }, // Function Key F6
- {"[18~", VI_K_FUN7 }, // Function Key F7
- {"[19~", VI_K_FUN8 }, // Function Key F8
- {"[20~", VI_K_FUN9 }, // Function Key F9
- {"[21~", VI_K_FUN10 }, // Function Key F10
- {"[23~", VI_K_FUN11 }, // Function Key F11
- {"[24~", VI_K_FUN12 }, // Function Key F12
- };
- enum { ESCCMDS_COUNT = ARRAY_SIZE(esccmds) };
+ int c;
fflush(stdout);
- n = chars_to_parse;
- // get input from User - are there already input chars in Q?
- if (n <= 0) {
- // the Q is empty, wait for a typed char
- again:
- n = safe_read(STDIN_FILENO, readbuffer, sizeof(readbuffer));
- if (n <= 0) {
- place_cursor(rows - 1, 0, FALSE); // go to bottom of screen
- clear_to_eol(); // erase to end of line
- cookmode(); // terminal to "cooked"
- bb_error_msg_and_die("can't read user input");
- }
- /* elsewhere we can get very confused by NULs */
- if (readbuffer[0] == '\0')
- goto again;
- if (readbuffer[0] == 27) {
- // 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.
- struct pollfd pfd[1];
- pfd[0].fd = 0;
- pfd[0].events = POLLIN;
- // keep reading while there are input chars, and room in buffer
- // for a complete ESC sequence (assuming 8 chars is enough)
- while ((safe_poll(pfd, 1, 0) > 0)
- && ((size_t)n <= (sizeof(readbuffer) - 8))
- ) {
- // read the rest of the ESC string
- int r = safe_read(STDIN_FILENO, readbuffer + n, sizeof(readbuffer) - n);
- if (r > 0)
- n += r;
- }
- }
- chars_to_parse = n;
- }
- c = readbuffer[0];
- if (c == 27 && n > 1) {
- // Maybe cursor or function key?
- const struct esc_cmds *eindex;
-
- for (eindex = esccmds; eindex < &esccmds[ESCCMDS_COUNT]; eindex++) {
- int cnt = strnlen(eindex->seq, 4);
- if (n <= cnt)
- continue;
- if (strncmp(eindex->seq, readbuffer + 1, cnt) != 0)
- continue;
- c = eindex->val; // magic char value
- n = cnt + 1; // squeeze out the ESC sequence
- goto found;
- }
- // defined ESC sequence not found
- }
- n = 1;
- found:
- // remove key sequence from Q
- chars_to_parse -= n;
- memmove(readbuffer, readbuffer + n, sizeof(readbuffer) - n);
+ c = read_key(STDIN_FILENO, &chars_to_parse, readbuffer);
+ if (c == -1) { // EOF/error
+ go_bottom_and_clear_to_eol();
+ cookmode(); // terminal to "cooked"
+ bb_error_msg_and_die("can't read user input");
+ }
return c;
}
//----- IO Routines --------------------------------------------
-static char get_one_char(void)
+static int get_one_char(void)
{
- char c;
+ int c;
#if ENABLE_FEATURE_VI_DOT_CMD
if (!adding2q) {
@@ -2323,7 +2229,8 @@ static char get_one_char(void)
c = readit(); // get the users input
} else {
// there is a queue to get chars from first
- c = *ioq++;
+ // careful with correct sign expansion!
+ c = (unsigned char)*ioq++;
if (c == '\0') {
// the end of the q, read from STDIN
free(ioq_start);
@@ -2353,13 +2260,12 @@ static char *get_input_line(const char *prompt)
// char [MAX_INPUT_LEN]
#define buf get_input_line__buf
- char c;
+ int c;
int i;
strcpy(buf, prompt);
last_status_cksum = 0; // force status update
- place_cursor(rows - 1, 0, FALSE); // go to Status line, bottom of screen
- clear_to_eol(); // clear the line
+ go_bottom_and_clear_to_eol();
write1(prompt); // write out the :, /, or ? prompt
i = strlen(buf);
@@ -2373,7 +2279,8 @@ static char *get_input_line(const char *prompt)
write1("\b \b"); // erase char on screen
if (i <= 0) // user backs up before b-o-l, exit
break;
- } else {
+ } else if (c > 0 && c < 256) { // exclude Unicode
+ // (TODO: need to handle Unicode)
buf[i] = c;
buf[++i] = '\0';
bb_putchar(c);
@@ -2395,8 +2302,8 @@ static int file_size(const char *fn) // what is the byte size of "fn"
return cnt;
}
-static int file_insert(const char *fn, char *p
- USE_FEATURE_VI_READONLY(, int update_ro_status))
+// might reallocate text[]!
+static int file_insert(const char *fn, char *p, int update_ro_status)
{
int cnt = -1;
int fd, size;
@@ -2424,7 +2331,7 @@ static int file_insert(const char *fn, char *p
goto fi0;
}
size = statbuf.st_size;
- p = text_hole_make(p, size);
+ p += text_hole_make(p, size);
cnt = safe_read(fd, p, size);
if (cnt < 0) {
status_line_bold("\"%s\" %s", fn, strerror(errno));
@@ -2465,13 +2372,13 @@ static int file_write(char *fn, char *first, char *last)
* but instead ftruncate() it _after_ successful write.
* Might reduce amount of data lost on power fail etc.
*/
-// fd = open(fn, (O_WRONLY | O_CREAT), 0666);
+/* fd = open(fn, (O_WRONLY | O_CREAT), 0666); */
fd = open(fn, (O_WRONLY | O_CREAT | O_TRUNC), 0666);
if (fd < 0)
return -1;
cnt = last - first + 1;
charcnt = full_write(fd, first, cnt);
-// ftruncate(fd, charcnt); // buggy? - zzz
+/* ftruncate(fd, charcnt); buggy for us - zzz */
if (charcnt == cnt) {
// good write
//file_modified = FALSE;
@@ -2564,6 +2471,12 @@ static void clear_to_eol(void)
write1(Ceol); // Erase from cursor to end of line
}
+static void go_bottom_and_clear_to_eol(void)
+{
+ place_cursor(rows - 1, 0, FALSE); // go to bottom of screen
+ clear_to_eol(); // erase to end of line
+}
+
//----- Erase from cursor to end of screen -----------------------
static void clear_to_eos(void)
{
@@ -2635,9 +2548,8 @@ static void show_status_line(void)
}
if (have_status_msg || ((cnt > 0 && last_status_cksum != cksum))) {
last_status_cksum = cksum; // remember if we have seen this line
- place_cursor(rows - 1, 0, FALSE); // put cursor on status line
+ go_bottom_and_clear_to_eol();
write1(status_buffer);
- clear_to_eol();
if (have_status_msg) {
if (((int)strlen(status_buffer) - (have_status_msg - 1)) >
(columns - 1) ) {
@@ -2972,13 +2884,14 @@ static void refresh(int full_screen)
//---------------------------------------------------------------------
//----- Execute a Vi Command -----------------------------------
-static void do_cmd(char c)
+static void do_cmd(int c)
{
const char *msg = msg; // for compiler
- char c1, *p, *q, *save_dot;
+ char *p, *q, *save_dot;
char buf[12];
int dir;
int cnt, i, j;
+ int c1;
// c1 = c; // quiet the compiler
// cnt = yf = 0; // quiet the compiler
@@ -2989,20 +2902,21 @@ static void do_cmd(char c)
/* if this is a cursor key, skip these checks */
switch (c) {
- case VI_K_UP:
- case VI_K_DOWN:
- case VI_K_LEFT:
- case VI_K_RIGHT:
- case VI_K_HOME:
- case VI_K_END:
- case VI_K_PAGEUP:
- case VI_K_PAGEDOWN:
+ case KEYCODE_UP:
+ case KEYCODE_DOWN:
+ case KEYCODE_LEFT:
+ case KEYCODE_RIGHT:
+ case KEYCODE_HOME:
+ case KEYCODE_END:
+ case KEYCODE_PAGEUP:
+ case KEYCODE_PAGEDOWN:
+ case KEYCODE_DELETE:
goto key_cmd_mode;
}
if (cmd_mode == 2) {
// flip-flop Insert/Replace mode
- if (c == VI_K_INSERT)
+ if (c == KEYCODE_INSERT)
goto dc_i;
// we are 'R'eplacing the current *dot with new char
if (*dot == '\n') {
@@ -3019,7 +2933,7 @@ static void do_cmd(char c)
}
if (cmd_mode == 1) {
// hitting "Insert" twice means "R" replace mode
- if (c == VI_K_INSERT) goto dc5;
+ if (c == KEYCODE_INSERT) goto dc5;
// insert the char c at "dot"
if (1 <= c || Isprint(c)) {
dot = char_insert(dot, c);
@@ -3083,7 +2997,7 @@ static void do_cmd(char c)
case 0x00: // nul- ignore
break;
case 2: // ctrl-B scroll up full screen
- case VI_K_PAGEUP: // Cursor Key Page Up
+ case KEYCODE_PAGEUP: // Cursor Key Page Up
dot_scroll(rows - 2, -1);
break;
case 4: // ctrl-D scroll down half screen
@@ -3093,14 +3007,14 @@ static void do_cmd(char c)
dot_scroll(1, 1);
break;
case 6: // ctrl-F scroll down full screen
- case VI_K_PAGEDOWN: // Cursor Key Page Down
+ case KEYCODE_PAGEDOWN: // Cursor Key Page Down
dot_scroll(rows - 2, 1);
break;
case 7: // ctrl-G show current status
last_status_cksum = 0; // force status update
break;
case 'h': // h- move left
- case VI_K_LEFT: // cursor key Left
+ case KEYCODE_LEFT: // cursor key Left
case 8: // ctrl-H- move left (This may be ERASE char)
case 0x7f: // DEL- move left (This may be ERASE char)
if (cmdcnt-- > 1) {
@@ -3110,7 +3024,7 @@ static void do_cmd(char c)
break;
case 10: // Newline ^J
case 'j': // j- goto next line, same col
- case VI_K_DOWN: // cursor key Down
+ case KEYCODE_DOWN: // cursor key Down
if (cmdcnt-- > 1) {
do_cmd(c);
} // repeat cnt
@@ -3149,7 +3063,7 @@ static void do_cmd(char c)
break;
case ' ': // move right
case 'l': // move right
- case VI_K_RIGHT: // Cursor Key Right
+ case KEYCODE_RIGHT: // Cursor Key Right
if (cmdcnt-- > 1) {
do_cmd(c);
} // repeat cnt
@@ -3157,21 +3071,18 @@ static void do_cmd(char c)
break;
#if ENABLE_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';
+ c1 = (get_one_char() | 0x20) - 'a'; // | 0x20 is tolower()
+ if ((unsigned)c1 <= 25) { // a-z?
+ YDreg = c1;
} else {
indicate_error(c);
}
break;
case '\'': // '- goto a specific mark
- c1 = get_one_char();
- c1 = tolower(c1);
- if (islower(c1)) {
- c1 = c1 - 'a';
+ c1 = (get_one_char() | 0x20) - 'a';
+ if ((unsigned)c1 <= 25) { // a-z?
// get the b-o-l
- q = mark[(unsigned char) c1];
+ q = mark[c1];
if (text <= q && q < end) {
dot = q;
dot_begin(); // go to B-o-l
@@ -3190,12 +3101,10 @@ static void do_cmd(char c)
// 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';
+ c1 = (get_one_char() | 0x20) - 'a';
+ if ((unsigned)c1 <= 25) { // a-z?
// remember the line
- mark[(int) c1] = dot;
+ mark[c1] = dot;
} else {
indicate_error(c);
}
@@ -3203,7 +3112,7 @@ static void do_cmd(char c)
case 'P': // P- Put register before
case 'p': // p- put register after
p = reg[YDreg];
- if (p == 0) {
+ if (p == NULL) {
status_line_bold("Nothing in register %c", what_reg());
break;
}
@@ -3224,7 +3133,7 @@ static void do_cmd(char c)
if (c == 'p')
dot_right(); // move to right, can move to NL
}
- dot = string_insert(dot, p); // insert the string
+ 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
@@ -3232,14 +3141,14 @@ static void do_cmd(char c)
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
+ p += string_insert(p, reg[Ureg]); // insert orig line
dot = p;
dot_skip_over_ws();
}
break;
#endif /* FEATURE_VI_YANKMARK */
case '$': // $- goto end of line
- case VI_K_END: // Cursor Key End
+ case KEYCODE_END: // Cursor Key End
if (cmdcnt-- > 1) {
do_cmd(c);
} // repeat cnt
@@ -3524,12 +3433,11 @@ static void do_cmd(char c)
end_cmd_q(); // stop adding to q
#endif
break;
- case 'g': // 'gg' goto a line number (from vim)
- // (default to first line in file)
+ case 'g': // 'gg' goto a line number (vim) (default: very first line)
c1 = get_one_char();
if (c1 != 'g') {
buf[0] = 'g';
- buf[1] = c1;
+ buf[1] = c1; // TODO: if Unicode?
buf[2] = '\0';
not_implemented(buf);
break;
@@ -3559,7 +3467,7 @@ static void do_cmd(char c)
dot_skip_over_ws();
//**** fall through to ... 'i'
case 'i': // i- insert before current char
- case VI_K_INSERT: // Cursor Key Insert
+ case KEYCODE_INSERT: // Cursor Key Insert
dc_i:
cmd_mode = 1; // start insrting
break;
@@ -3612,7 +3520,7 @@ static void do_cmd(char c)
dc5:
cmd_mode = 2;
break;
- case VI_K_DELETE:
+ case KEYCODE_DELETE:
c = 'x';
// fall through
case 'X': // X- delete char before dot
@@ -3686,7 +3594,7 @@ static void do_cmd(char c)
case 'y': // y- yank something
case 'Y': // Y- Yank a line
#endif
- {
+ {
int yf, ml, whole = 0;
yf = YANKDEL; // assume either "c" or "d"
#if ENABLE_FEATURE_VI_YANKMARK
@@ -3759,10 +3667,10 @@ static void do_cmd(char c)
#endif
end_cmd_q(); // stop adding to q
}
- }
break;
+ }
case 'k': // k- goto prev line, same col
- case VI_K_UP: // cursor key Up
+ case KEYCODE_UP: // cursor key Up
if (cmdcnt-- > 1) {
do_cmd(c);
} // repeat cnt
@@ -3782,7 +3690,7 @@ static void do_cmd(char c)
do_cmd(';');
if (*dot == last_forward_char)
dot_left();
- last_forward_char= 0;
+ last_forward_char = 0;
break;
case 'w': // w- forward a word
if (cmdcnt-- > 1) {
@@ -3827,23 +3735,25 @@ static void do_cmd(char c)
end_cmd_q(); // stop adding to q
break;
//----- The Cursor and Function Keys -----------------------------
- case VI_K_HOME: // Cursor Key Home
+ case KEYCODE_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
+#if 0
+ case KEYCODE_FUN1: // Function Key F1
+ case KEYCODE_FUN2: // Function Key F2
+ case KEYCODE_FUN3: // Function Key F3
+ case KEYCODE_FUN4: // Function Key F4
+ case KEYCODE_FUN5: // Function Key F5
+ case KEYCODE_FUN6: // Function Key F6
+ case KEYCODE_FUN7: // Function Key F7
+ case KEYCODE_FUN8: // Function Key F8
+ case KEYCODE_FUN9: // Function Key F9
+ case KEYCODE_FUN10: // Function Key F10
+ case KEYCODE_FUN11: // Function Key F11
+ case KEYCODE_FUN12: // Function Key F12
break;
+#endif
}
dc1:
diff --git a/release/src/router/busybox/examples/depmod-t.pl b/release/src/router/busybox/examples/depmod-t.pl
new file mode 100644
index 0000000000..fa5ca977ba
--- /dev/null
+++ b/release/src/router/busybox/examples/depmod-t.pl
@@ -0,0 +1,293 @@
+#!/usr/bin/perl -w
+# vi: set sw=4 ts=4:
+# Copyright (c) 2001 David Schleef
+# Copyright (c) 2001 Erik Andersen
+# Copyright (c) 2001 Stuart Hughes
+# Copyright (c) 2002 Steven J. Hill
+# Copyright (c) 2006 Freescale Semiconductor, Inc
+#
+# History:
+# March 2006: Stuart Hughes .
+# Significant updates, including implementing the '-F' option
+# and adding support for 2.6 kernels.
+
+# This program is free software; you can redistribute it and/or modify it
+# under the same terms as Perl itself.
+use Getopt::Long;
+use File::Find;
+use strict;
+
+# Set up some default values
+my $kdir="";
+my $basedir="";
+my $kernel="";
+my $kernelsyms="";
+my $symprefix="";
+my $stdout=0;
+my $verbose=0;
+my $help=0;
+my $nm = $ENV{'NM'} || "nm";
+
+# more globals
+my (@liblist) = ();
+my $exp = {};
+my $dep = {};
+my $mod = {};
+
+my $usage = < | -F } [options]...
+ Where:
+ -h --help : Show this help screen
+ -b --basedir : Modules base directory (e.g /lib/modules/<2.x.y>)
+ -k --kernel : Kernel binary for the target (e.g. vmlinux)
+ -F --kernelsyms : Kernel symbol file (e.g. System.map)
+ -n --stdout : Write to stdout instead of /modules.dep
+ -v --verbose : Print out lots of debugging stuff
+ -P --symbol-prefix : Symbol prefix
+TXT
+
+# get command-line options
+GetOptions(
+ "help|h" => \$help,
+ "basedir|b=s" => \$basedir,
+ "kernel|k=s" => \$kernel,
+ "kernelsyms|F=s" => \$kernelsyms,
+ "stdout|n" => \$stdout,
+ "verbose|v" => \$verbose,
+ "symbol-prefix|P=s" => \$symprefix,
+);
+
+die $usage if $help;
+die $usage unless $basedir && ( $kernel || $kernelsyms );
+die "can't use both -k and -F\n\n$usage" if $kernel && $kernelsyms;
+
+# Strip any trailing or multiple slashes from basedir
+$basedir =~ s-(/)\1+-/-g;
+
+# The base directory should contain /lib/modules somewhere
+if($basedir !~ m-/lib/modules-) {
+ warn "WARNING: base directory does not match ..../lib/modules\n";
+}
+
+# if no kernel version is contained in the basedir, try to find one
+if($basedir !~ m-/lib/modules/\d\.\d-) {
+ opendir(BD, $basedir) or die "can't open basedir $basedir : $!\n";
+ foreach ( readdir(BD) ) {
+ next if /^\.\.?$/;
+ next unless -d "$basedir/$_";
+ warn "dir = $_\n" if $verbose;
+ if( /^\d\.\d/ ) {
+ $kdir = $_;
+ warn("Guessed module directory as $basedir/$kdir\n");
+ last;
+ }
+ }
+ closedir(BD);
+ die "Cannot find a kernel version under $basedir\n" unless $kdir;
+ $basedir = "$basedir/$kdir";
+}
+
+# Find the list of .o or .ko files living under $basedir
+warn "**** Locating all modules\n" if $verbose;
+find sub {
+ my $file;
+ if ( -f $_ && ! -d $_ ) {
+ $file = $File::Find::name;
+ if ( $file =~ /\.k?o$/ ) {
+ push(@liblist, $file);
+ warn "$file\n" if $verbose;
+ }
+ }
+}, $basedir;
+warn "**** Finished locating modules\n" if $verbose;
+
+foreach my $obj ( @liblist ){
+ # turn the input file name into a target tag name
+ my ($tgtname) = $obj =~ m-(/lib/modules/.*)$-;
+
+ warn "\nMODULE = $tgtname\n" if $verbose;
+
+ # get a list of symbols
+ my @output=`$nm $obj`;
+
+ build_ref_tables($tgtname, \@output, $exp, $dep);
+}
+
+
+# vmlinux is a special name that is only used to resolve symbols
+my $tgtname = 'vmlinux';
+my @output = $kernelsyms ? `cat $kernelsyms` : `$nm $kernel`;
+warn "\nMODULE = $tgtname\n" if $verbose;
+build_ref_tables($tgtname, \@output, $exp, $dep);
+
+# resolve the dependencies for each module
+# reduce dependencies: remove unresolvable and resolved from vmlinux/System.map
+# remove duplicates
+foreach my $module (keys %$dep) {
+ warn "reducing module: $module\n" if $verbose;
+ $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";
+ }
+ }
+}
+
+# figure out where the output should go
+if ($stdout == 0) {
+ open(STDOUT, ">$basedir/modules.dep")
+ or die "cannot open $basedir/modules.dep: $!";
+}
+my $kseries = $basedir =~ m,/2\.6\.[^/]*, ? '2.6' : '2.4';
+
+foreach my $module ( keys %$mod ) {
+# \t breaks modprobe 1.13.2? -- zzz
+# if($kseries eq '2.4') {
+# print "$module:\t";
+# my @sorted = sort bydep keys %{$mod->{$module}};
+# print join(" \\\n\t",@sorted);
+# print "\n\n";
+# } else {
+ print "$module: ";
+ my @sorted = sort bydep keys %{$mod->{$module}};
+ print join(" ",@sorted);
+ print "\n";
+# }
+}
+
+
+sub build_ref_tables
+{
+ my ($name, $sym_ar, $exp, $dep) = @_;
+
+ my $ksymtab = grep m/ __ksymtab/, @$sym_ar;
+
+ # gather the exported symbols
+ if($ksymtab){
+ # explicitly exported
+ foreach ( @$sym_ar ) {
+ / __ksymtab_(.*)$/ and do {
+ warn "sym = $1\n" if $verbose;
+ $exp->{$1} = $name;
+ };
+ }
+ } else {
+ # exporting all symbols
+ foreach ( @$sym_ar ) {
+ / [ABCDGRSTW] (.*)$/ and do {
+ warn "syma = $1\n" if $verbose;
+ $exp->{$1} = $name;
+ };
+ }
+ }
+
+ # this takes makes sure modules with no dependencies get listed
+ push @{$dep->{$name}}, $symprefix . 'printk' unless $name eq 'vmlinux';
+
+ # gather the unresolved symbols
+ foreach ( @$sym_ar ) {
+ !/ __this_module/ && / U (.*)$/ and do {
+ warn "und = $1\n" if $verbose;
+ push @{$dep->{$name}}, $1;
+ };
+ }
+}
+
+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 (modules.conf) which can then be used by modprobe
+on the target platform.
+
+It supports Linux 2.4 and 2.6 styles of modules.conf (auto-detected)
+
+=head1 SYNOPSIS
+
+depmod.pl [OPTION]... [basedir]...
+
+Example:
+
+ depmod.pl -F linux/System.map -b target/lib/modules/2.6.11
+
+=head1 DESCRIPTION
+
+The purpose of this script is to automagically generate a list of of kernel
+module dependencies. This script produces dependency 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.
+
+If you don't specify the kernel version, this script will search for
+one under the specified based directory and use the first thing that
+looks like a kernel version.
+
+=item B<-k --kernel>
+
+Kernel binary for the target (vmlinux). 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 (System.map).
+
+=item B<-n --stdout>
+
+Write to stdout instead of modules.dep
+kernel binary for the target (using the -k option).
+
+=item B<--verbose>
+
+Verbose (debug) output
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+ Copyright (c) 2001 David Schleef
+ Copyright (c) 2001 Erik Andersen
+ Copyright (c) 2001 Stuart Hughes
+ Copyright (c) 2002 Steven J. Hill
+ Copyright (c) 2006 Freescale Semiconductor, Inc
+
+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
diff --git a/release/src/router/busybox/findutils/Config.in b/release/src/router/busybox/findutils/Config.in
index 9bb73d3f39..d69a2385b4 100644
--- a/release/src/router/busybox/findutils/Config.in
+++ b/release/src/router/busybox/findutils/Config.in
@@ -146,7 +146,7 @@ config FEATURE_FIND_DELETE
default n
depends on FIND && FEATURE_FIND_DEPTH
help
- Support the 'find -delete' option for deleting files and direcotries.
+ Support the 'find -delete' option for deleting files and directories.
WARNING: This option can do much harm if used wrong. Busybox will not
try to protect the user from doing stupid things. Use with care.
diff --git a/release/src/router/busybox/findutils/find.c b/release/src/router/busybox/findutils/find.c
index f2b89746f5..df632f2198 100644
--- a/release/src/router/busybox/findutils/find.c
+++ b/release/src/router/busybox/findutils/find.c
@@ -381,9 +381,11 @@ static int FAST_FUNC fileAction(const char *fileName,
{
int i;
#if ENABLE_FEATURE_FIND_MAXDEPTH
- int maxdepth = (int)(ptrdiff_t)userData;
+#define minmaxdepth ((int*)userData)
- if (depth > maxdepth) return SKIP;
+ if (depth < minmaxdepth[0]) return TRUE;
+ if (depth > minmaxdepth[1]) return SKIP;
+#undef minmaxdepth
#endif
#if ENABLE_FEATURE_FIND_XDEV
@@ -812,19 +814,21 @@ int find_main(int argc, char **argv)
static const char options[] ALIGN1 =
"-follow\0"
USE_FEATURE_FIND_XDEV( "-xdev\0" )
-USE_FEATURE_FIND_MAXDEPTH("-maxdepth\0")
+USE_FEATURE_FIND_MAXDEPTH("-mindepth\0""-maxdepth\0")
;
enum {
OPT_FOLLOW,
USE_FEATURE_FIND_XDEV( OPT_XDEV ,)
-USE_FEATURE_FIND_MAXDEPTH(OPT_MAXDEPTH,)
+USE_FEATURE_FIND_MAXDEPTH(OPT_MINDEPTH,)
};
char *arg;
char **argp;
int i, firstopt, status = EXIT_SUCCESS;
#if ENABLE_FEATURE_FIND_MAXDEPTH
- int maxdepth = INT_MAX;
+ int minmaxdepth[2] = { 0, INT_MAX };
+#else
+#define minmaxdepth NULL
#endif
for (firstopt = 1; firstopt < argc; firstopt++) {
@@ -875,10 +879,10 @@ USE_FEATURE_FIND_MAXDEPTH(OPT_MAXDEPTH,)
}
#endif
#if ENABLE_FEATURE_FIND_MAXDEPTH
- if (opt == OPT_MAXDEPTH) {
+ if (opt == OPT_MINDEPTH || opt == OPT_MINDEPTH + 1) {
if (!argp[1])
bb_show_usage();
- maxdepth = xatoi_u(argp[1]);
+ minmaxdepth[opt - OPT_MINDEPTH] = xatoi_u(argp[1]);
argp[0] = (char*)"-a";
argp[1] = (char*)"-a";
argp++;
@@ -895,9 +899,7 @@ USE_FEATURE_FIND_MAXDEPTH(OPT_MAXDEPTH,)
fileAction, /* file action */
fileAction, /* dir action */
#if ENABLE_FEATURE_FIND_MAXDEPTH
- /* double cast suppresses
- * "cast to ptr from int of different size" */
- (void*)(ptrdiff_t)maxdepth,/* user data */
+ minmaxdepth, /* user data */
#else
NULL, /* user data */
#endif
diff --git a/release/src/router/busybox/findutils/grep.c b/release/src/router/busybox/findutils/grep.c
index 73e74f4b38..e23f9bcf3a 100644
--- a/release/src/router/busybox/findutils/grep.c
+++ b/release/src/router/busybox/findutils/grep.c
@@ -28,7 +28,9 @@
USE_FEATURE_GREP_CONTEXT("A:B:C:") \
USE_FEATURE_GREP_EGREP_ALIAS("E") \
USE_DESKTOP("w") \
+ USE_EXTRA_COMPAT("z") \
"aI"
+
/* ignored: -a "assume all files to be text" */
/* ignored: -I "assume binary files have no matches" */
@@ -54,6 +56,7 @@ enum {
USE_FEATURE_GREP_CONTEXT( OPTBIT_C ,) /* -C NUM: -A and -B combined */
USE_FEATURE_GREP_EGREP_ALIAS(OPTBIT_E ,) /* extended regexp */
USE_DESKTOP( OPTBIT_w ,) /* whole word match */
+ USE_EXTRA_COMPAT( OPTBIT_z ,) /* input is NUL terminated */
OPT_l = 1 << OPTBIT_l,
OPT_n = 1 << OPTBIT_n,
OPT_q = 1 << OPTBIT_q,
@@ -75,6 +78,7 @@ enum {
OPT_C = USE_FEATURE_GREP_CONTEXT( (1 << OPTBIT_C)) + 0,
OPT_E = USE_FEATURE_GREP_EGREP_ALIAS((1 << OPTBIT_E)) + 0,
OPT_w = USE_DESKTOP( (1 << OPTBIT_w)) + 0,
+ OPT_z = USE_EXTRA_COMPAT( (1 << OPTBIT_z)) + 0,
};
#define PRINT_FILES_WITH_MATCHES (option_mask32 & OPT_l)
@@ -84,6 +88,7 @@ enum {
#define PRINT_MATCH_COUNTS (option_mask32 & OPT_c)
#define FGREP_FLAG (option_mask32 & OPT_F)
#define PRINT_FILES_WITHOUT_MATCHES (option_mask32 & OPT_L)
+#define NUL_DELIMITED (option_mask32 & OPT_z)
struct globals {
int max_matches;
@@ -186,7 +191,7 @@ static void print_line(const char *line, size_t line_len, int linenum, char deco
puts(line);
#else
fwrite(line, 1, line_len, stdout);
- putchar('\n');
+ putchar(NUL_DELIMITED ? '\0' : '\n');
#endif
}
}
@@ -197,12 +202,13 @@ static ssize_t FAST_FUNC bb_getline(char **line_ptr, size_t *line_alloc_len, FIL
{
ssize_t res_sz;
char *line;
+ int delim = (NUL_DELIMITED ? '\0' : '\n');
- res_sz = getline(line_ptr, line_alloc_len, file);
+ res_sz = getdelim(line_ptr, line_alloc_len, delim, file);
line = *line_ptr;
if (res_sz > 0) {
- if (line[res_sz - 1] == '\n')
+ if (line[res_sz - 1] == delim)
line[--res_sz] = '\0';
} else {
free(line); /* uclibc allocates a buffer even on EOF. WTF? */
@@ -374,11 +380,11 @@ static int grep_file(FILE *file)
break;
#else
if (re_search(&gl->compiled_regex, line, line_len,
- gl->matched_range.rm_eo, line_len - gl->matched_range.rm_eo,
+ gl->matched_range.rm_eo, line_len - gl->matched_range.rm_eo,
&gl->matched_range) < 0)
break;
#endif
- }
+ }
} else {
print_line(line, line_len, linenum, ':');
}
@@ -407,8 +413,11 @@ static int grep_file(FILE *file)
#endif
/* Did we print all context after last requested match? */
if ((option_mask32 & OPT_m)
- && !print_n_lines_after && nmatches == max_matches)
+ && !print_n_lines_after
+ && nmatches == max_matches
+ ) {
break;
+ }
} /* while (read line) */
/* special-case file post-processing for options where we don't print line
diff --git a/release/src/router/busybox/include/applets.h b/release/src/router/busybox/include/applets.h
index 0c9930d459..1d932589bf 100644
--- a/release/src/router/busybox/include/applets.h
+++ b/release/src/router/busybox/include/applets.h
@@ -69,6 +69,7 @@ s - suid type:
USE_TEST(APPLET_NOFORK([, test, _BB_DIR_USR_BIN, _BB_SUID_NEVER, test))
USE_TEST(APPLET_NOFORK([[, test, _BB_DIR_USR_BIN, _BB_SUID_NEVER, test))
+USE_ACPID(APPLET(acpid, _BB_DIR_SBIN, _BB_SUID_NEVER))
USE_ADDGROUP(APPLET(addgroup, _BB_DIR_BIN, _BB_SUID_NEVER))
USE_ADDUSER(APPLET(adduser, _BB_DIR_BIN, _BB_SUID_NEVER))
USE_ADJTIMEX(APPLET(adjtimex, _BB_DIR_SBIN, _BB_SUID_NEVER))
@@ -80,6 +81,7 @@ USE_AWK(APPLET_NOEXEC(awk, awk, _BB_DIR_USR_BIN, _BB_SUID_NEVER, awk))
USE_BASENAME(APPLET_NOFORK(basename, basename, _BB_DIR_USR_BIN, _BB_SUID_NEVER, basename))
USE_BBCONFIG(APPLET(bbconfig, _BB_DIR_BIN, _BB_SUID_NEVER))
//USE_BBSH(APPLET(bbsh, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_BLKID(APPLET(blkid, _BB_DIR_SBIN, _BB_SUID_NEVER))
USE_BRCTL(APPLET(brctl, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
USE_BUNZIP2(APPLET(bunzip2, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_BUNZIP2(APPLET_ODDNAME(bzcat, bunzip2, _BB_DIR_USR_BIN, _BB_SUID_NEVER, bzcat))
@@ -118,6 +120,7 @@ USE_DELUSER(APPLET(deluser, _BB_DIR_BIN, _BB_SUID_NEVER))
USE_DEPMOD(APPLET(depmod, _BB_DIR_SBIN, _BB_SUID_NEVER))
USE_MODPROBE_SMALL(APPLET_ODDNAME(depmod, modprobe, _BB_DIR_SBIN, _BB_SUID_NEVER, modprobe))
USE_DEVFSD(APPLET(devfsd, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_DEVMEM(APPLET(devmem, _BB_DIR_SBIN, _BB_SUID_NEVER))
USE_DF(APPLET(df, _BB_DIR_BIN, _BB_SUID_NEVER))
USE_APP_DHCPRELAY(APPLET(dhcprelay, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
USE_DIFF(APPLET(diff, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
@@ -149,10 +152,11 @@ USE_FBSPLASH(APPLET(fbsplash, _BB_DIR_SBIN, _BB_SUID_NEVER))
USE_FDFLUSH(APPLET_ODDNAME(fdflush, freeramdisk, _BB_DIR_BIN, _BB_SUID_NEVER, fdflush))
USE_FDFORMAT(APPLET(fdformat, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_FDISK(APPLET(fdisk, _BB_DIR_SBIN, _BB_SUID_NEVER))
-USE_FETCHMAIL(APPLET_ODDNAME(fetchmail, sendgetmail, _BB_DIR_USR_BIN, _BB_SUID_NEVER, fetchmail))
USE_FEATURE_GREP_FGREP_ALIAS(APPLET_ODDNAME(fgrep, grep, _BB_DIR_BIN, _BB_SUID_NEVER, fgrep))
USE_FIND(APPLET_NOEXEC(find, find, _BB_DIR_USR_BIN, _BB_SUID_NEVER, find))
USE_FINDFS(APPLET(findfs, _BB_DIR_SBIN, _BB_SUID_MAYBE))
+//USE_FLASH_ERASEALL(APPLET_ODDNAME(flash_eraseall, flash_eraseall, _BB_DIR_USR_SBIN, _BB_SUID_NEVER, flash_eraseall))
+USE_FLASH_ERASEALL(APPLET(flash_eraseall, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
USE_FOLD(APPLET(fold, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_FREE(APPLET(free, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_FREERAMDISK(APPLET(freeramdisk, _BB_DIR_SBIN, _BB_SUID_NEVER))
@@ -160,6 +164,7 @@ USE_FSCK(APPLET(fsck, _BB_DIR_SBIN, _BB_SUID_NEVER))
//USE_E2FSCK(APPLET_ODDNAME(fsck.ext2, e2fsck, _BB_DIR_SBIN, _BB_SUID_NEVER, fsck_ext2))
//USE_E2FSCK(APPLET_ODDNAME(fsck.ext3, e2fsck, _BB_DIR_SBIN, _BB_SUID_NEVER, fsck_ext3))
USE_FSCK_MINIX(APPLET_ODDNAME(fsck.minix, fsck_minix, _BB_DIR_SBIN, _BB_SUID_NEVER, fsck_minix))
+USE_FTPD(APPLET(ftpd, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
USE_FTPGET(APPLET_ODDNAME(ftpget, ftpgetput, _BB_DIR_USR_BIN, _BB_SUID_NEVER, ftpget))
USE_FTPPUT(APPLET_ODDNAME(ftpput, ftpgetput, _BB_DIR_USR_BIN, _BB_SUID_NEVER, ftpput))
USE_FUSER(APPLET(fuser, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
@@ -191,6 +196,7 @@ USE_INOTIFYD(APPLET(inotifyd, _BB_DIR_SBIN, _BB_SUID_NEVER))
USE_INSMOD(APPLET(insmod, _BB_DIR_SBIN, _BB_SUID_NEVER))
USE_MODPROBE_SMALL(APPLET_ODDNAME(insmod, modprobe, _BB_DIR_SBIN, _BB_SUID_NEVER, modprobe))
USE_INSTALL(APPLET(install, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_IONICE(APPLET(ionice, _BB_DIR_BIN, _BB_SUID_NEVER))
#if ENABLE_FEATURE_IP_ADDRESS \
|| ENABLE_FEATURE_IP_ROUTE \
|| ENABLE_FEATURE_IP_LINK \
@@ -236,6 +242,7 @@ USE_LSMOD(APPLET(lsmod, _BB_DIR_SBIN, _BB_SUID_NEVER))
USE_MODPROBE_SMALL(APPLET_ODDNAME(lsmod, modprobe, _BB_DIR_SBIN, _BB_SUID_NEVER, modprobe))
USE_UNLZMA(APPLET_ODDNAME(lzmacat, unlzma, _BB_DIR_USR_BIN, _BB_SUID_NEVER, lzmacat))
USE_MAKEDEVS(APPLET(makedevs, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_MAKEMIME(APPLET(makemime, _BB_DIR_BIN, _BB_SUID_NEVER))
USE_MAN(APPLET(man, _BB_DIR_SBIN, _BB_SUID_NEVER))
USE_MATCHPATHCON(APPLET(matchpathcon, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
USE_MD5SUM(APPLET_ODDNAME(md5sum, md5_sha1_sum, _BB_DIR_USR_BIN, _BB_SUID_NEVER, md5sum))
@@ -243,12 +250,15 @@ USE_MDEV(APPLET(mdev, _BB_DIR_SBIN, _BB_SUID_NEVER))
USE_MESG(APPLET(mesg, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_MICROCOM(APPLET(microcom, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_MKDIR(APPLET_NOFORK(mkdir, mkdir, _BB_DIR_BIN, _BB_SUID_NEVER, mkdir))
+USE_MKFS_VFAT(APPLET_ODDNAME(mkdosfs, mkfs_vfat, _BB_DIR_SBIN, _BB_SUID_NEVER, mkfs_vfat))
//USE_MKE2FS(APPLET(mke2fs, _BB_DIR_SBIN, _BB_SUID_NEVER))
USE_MKFIFO(APPLET(mkfifo, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
//USE_MKE2FS(APPLET_ODDNAME(mkfs.ext2, mke2fs, _BB_DIR_SBIN, _BB_SUID_NEVER, mkfs_ext2))
//USE_MKE2FS(APPLET_ODDNAME(mkfs.ext3, mke2fs, _BB_DIR_SBIN, _BB_SUID_NEVER, mkfs_ext3))
USE_MKFS_MINIX(APPLET_ODDNAME(mkfs.minix, mkfs_minix, _BB_DIR_SBIN, _BB_SUID_NEVER, mkfs_minix))
+USE_MKFS_VFAT(APPLET_ODDNAME(mkfs.vfat, mkfs_vfat, _BB_DIR_SBIN, _BB_SUID_NEVER, mkfs_vfat))
USE_MKNOD(APPLET(mknod, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_CRYPTPW(APPLET_ODDNAME(mkpasswd, cryptpw, _BB_DIR_USR_BIN, _BB_SUID_NEVER, mkpasswd))
USE_MKSWAP(APPLET(mkswap, _BB_DIR_SBIN, _BB_SUID_NEVER))
USE_MKTEMP(APPLET(mktemp, _BB_DIR_BIN, _BB_SUID_NEVER))
USE_MODPROBE(APPLET(modprobe, _BB_DIR_SBIN, _BB_SUID_NEVER))
@@ -268,7 +278,7 @@ USE_NOHUP(APPLET(nohup, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_NSLOOKUP(APPLET(nslookup, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_OD(APPLET(od, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_OPENVT(APPLET(openvt, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
-USE_PARSE(APPLET(parse, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+//USE_PARSE(APPLET(parse, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_PASSWD(APPLET(passwd, _BB_DIR_USR_BIN, _BB_SUID_ALWAYS))
USE_PATCH(APPLET(patch, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_PGREP(APPLET(pgrep, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
@@ -278,6 +288,7 @@ USE_PING6(APPLET(ping6, _BB_DIR_BIN, _BB_SUID_NEVER))
USE_PIPE_PROGRESS(APPLET(pipe_progress, _BB_DIR_BIN, _BB_SUID_NEVER))
USE_PIVOT_ROOT(APPLET(pivot_root, _BB_DIR_SBIN, _BB_SUID_NEVER))
USE_PKILL(APPLET_ODDNAME(pkill, pgrep, _BB_DIR_USR_BIN, _BB_SUID_NEVER, pkill))
+USE_POPMAILDIR(APPLET(popmaildir, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
USE_HALT(APPLET_ODDNAME(poweroff, halt, _BB_DIR_SBIN, _BB_SUID_NEVER, poweroff))
USE_PRINTENV(APPLET(printenv, _BB_DIR_BIN, _BB_SUID_NEVER))
USE_PRINTF(APPLET_NOFORK(printf, printf, _BB_DIR_USR_BIN, _BB_SUID_NEVER, printf))
@@ -292,6 +303,7 @@ USE_READLINK(APPLET(readlink, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_READPROFILE(APPLET(readprofile, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
USE_REALPATH(APPLET(realpath, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_HALT(APPLET_ODDNAME(reboot, halt, _BB_DIR_SBIN, _BB_SUID_NEVER, reboot))
+USE_REFORMIME(APPLET(reformime, _BB_DIR_BIN, _BB_SUID_NEVER))
USE_RENICE(APPLET(renice, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_RESET(APPLET(reset, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_RESIZE(APPLET(resize, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
@@ -313,7 +325,7 @@ USE_RX(APPLET(rx, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_SCRIPT(APPLET(script, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_SED(APPLET(sed, _BB_DIR_BIN, _BB_SUID_NEVER))
USE_SELINUXENABLED(APPLET(selinuxenabled, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
-USE_SENDMAIL(APPLET_ODDNAME(sendmail, sendgetmail, _BB_DIR_USR_SBIN, _BB_SUID_NEVER, sendmail))
+USE_SENDMAIL(APPLET(sendmail, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
USE_SEQ(APPLET_NOFORK(seq, seq, _BB_DIR_USR_BIN, _BB_SUID_NEVER, seq))
USE_SESTATUS(APPLET(sestatus, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
USE_SETARCH(APPLET(setarch, _BB_DIR_BIN, _BB_SUID_NEVER))
@@ -330,6 +342,8 @@ USE_FEATURE_SH_IS_ASH(APPLET_ODDNAME(sh, ash, _BB_DIR_BIN, _BB_SUID_NEVER, sh))
USE_FEATURE_SH_IS_HUSH(APPLET_ODDNAME(sh, hush, _BB_DIR_BIN, _BB_SUID_NEVER, sh))
USE_FEATURE_SH_IS_MSH(APPLET_ODDNAME(sh, msh, _BB_DIR_BIN, _BB_SUID_NEVER, sh))
USE_SHA1SUM(APPLET_ODDNAME(sha1sum, md5_sha1_sum, _BB_DIR_USR_BIN, _BB_SUID_NEVER, sha1sum))
+USE_SHA256SUM(APPLET_ODDNAME(sha256sum, md5_sha1_sum, _BB_DIR_USR_BIN, _BB_SUID_NEVER, sha256sum))
+USE_SHA512SUM(APPLET_ODDNAME(sha512sum, md5_sha1_sum, _BB_DIR_USR_BIN, _BB_SUID_NEVER, sha512sum))
USE_SHOWKEY(APPLET(showkey, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_SLATTACH(APPLET(slattach, _BB_DIR_SBIN, _BB_SUID_NEVER))
USE_SLEEP(APPLET_NOFORK(sleep, sleep, _BB_DIR_BIN, _BB_SUID_NEVER, sleep))
@@ -355,6 +369,7 @@ USE_TAC(APPLET_NOEXEC(tac, tac, _BB_DIR_USR_BIN, _BB_SUID_NEVER, tac))
USE_TAIL(APPLET(tail, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_TAR(APPLET(tar, _BB_DIR_BIN, _BB_SUID_NEVER))
USE_TASKSET(APPLET(taskset, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+/* USE_TC(APPLET(tc, _BB_DIR_SBIN, _BB_SUID_NEVER)) */
USE_TCPSVD(APPLET_ODDNAME(tcpsvd, tcpudpsvd, _BB_DIR_USR_BIN, _BB_SUID_NEVER, tcpsvd))
USE_TEE(APPLET(tee, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_TELNET(APPLET(telnet, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
@@ -365,6 +380,7 @@ USE_TFTP(APPLET(tftp, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_TFTPD(APPLET(tftpd, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
#endif
USE_TIME(APPLET(time, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_TIMEOUT(APPLET(timeout, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_TOP(APPLET(top, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_TOUCH(APPLET_NOFORK(touch, touch, _BB_DIR_BIN, _BB_SUID_NEVER, touch))
USE_TR(APPLET(tr, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
@@ -372,6 +388,7 @@ USE_TRACEROUTE(APPLET(traceroute, _BB_DIR_USR_BIN, _BB_SUID_MAYBE))
USE_TRUE(APPLET_NOFORK(true, true, _BB_DIR_BIN, _BB_SUID_NEVER, true))
USE_TTY(APPLET(tty, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_TTYSIZE(APPLET(ttysize, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
+USE_TUNCTL(APPLET(tunctl, _BB_DIR_SBIN, _BB_SUID_NEVER))
//USE_TUNE2FS(APPLET(tune2fs, _BB_DIR_SBIN, _BB_SUID_NEVER))
USE_APP_UDHCPC(APPLET(udhcpc, _BB_DIR_SBIN, _BB_SUID_NEVER))
USE_APP_UDHCPD(APPLET(udhcpd, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
diff --git a/release/src/router/busybox/include/busybox.h b/release/src/router/busybox/include/busybox.h
index 314b95126f..54c278f87d 100644
--- a/release/src/router/busybox/include/busybox.h
+++ b/release/src/router/busybox/include/busybox.h
@@ -4,14 +4,12 @@
*
* Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
*/
-#ifndef _BB_INTERNAL_H_
-#define _BB_INTERNAL_H_ 1
+#ifndef BUSYBOX_H
+#define BUSYBOX_H 1
#include "libbb.h"
-#if __GNUC_PREREQ(4,1)
-# pragma GCC visibility push(hidden)
-#endif
+PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
/* order matters: used as index into "install_dir[]" in appletlib.c */
typedef enum bb_install_loc_t {
@@ -71,8 +69,6 @@ int lbb_main(char **argv);
#endif
#endif
-#if __GNUC_PREREQ(4,1)
-# pragma GCC visibility pop
-#endif
+POP_SAVED_FUNCTION_VISIBILITY
-#endif /* _BB_INTERNAL_H_ */
+#endif
diff --git a/release/src/router/busybox/include/dump.h b/release/src/router/busybox/include/dump.h
index 44f2082b7c..925270d9cc 100644
--- a/release/src/router/busybox/include/dump.h
+++ b/release/src/router/busybox/include/dump.h
@@ -1,8 +1,6 @@
/* vi: set sw=4 ts=4: */
-#if __GNUC_PREREQ(4,1)
-# pragma GCC visibility push(hidden)
-#endif
+PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
#define F_IGNORE 0x01 /* %_A */
#define F_SETREP 0x02 /* rep count set, not default */
@@ -55,6 +53,4 @@ dumper_t* alloc_dumper(void) FAST_FUNC;
extern void bb_dump_add(dumper_t *dumper, const char *fmt) FAST_FUNC;
extern int bb_dump_dump(dumper_t *dumper, char **argv) FAST_FUNC;
-#if __GNUC_PREREQ(4,1)
-# pragma GCC visibility pop
-#endif
+POP_SAVED_FUNCTION_VISIBILITY
diff --git a/release/src/router/busybox/include/grp_.h b/release/src/router/busybox/include/grp_.h
index 23c4dcc035..deaf9e6a32 100644
--- a/release/src/router/busybox/include/grp_.h
+++ b/release/src/router/busybox/include/grp_.h
@@ -15,27 +15,20 @@
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
-
+ 02111-1307 USA.
+ */
/*
* POSIX Standard: 9.2.1 Group Database Access
*/
+#ifndef BB_GRP_H
+#define BB_GRP_H 1
-#ifndef _GRP_H
-#define _GRP_H 1
-
-#if __GNUC_PREREQ(4,1)
-# pragma GCC visibility push(hidden)
-#endif
-
-/* The group structure. */
-struct group {
- char *gr_name; /* Group name. */
- char *gr_passwd; /* Password. */
- gid_t gr_gid; /* Group ID. */
- char **gr_mem; /* Member list. */
-};
+PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
+/* This file is #included after #include
+ * We will use libc-defined structures, but will #define function names
+ * so that function calls are directed to bb_internal_XXX replacements
+ */
#define setgrent bb_internal_setgrent
#define endgrent bb_internal_endgrent
@@ -53,9 +46,7 @@ struct group {
/* All function names below should be remapped by #defines above
- * in order to not collide with libc names.
- * In theory it isn't necessary, but I saw weird interactions at link time.
- * Let's play safe */
+ * in order to not collide with libc names. */
/* Rewind the group-file stream. */
@@ -71,14 +62,14 @@ extern struct group *getgrent(void);
extern struct group *fgetgrent(FILE *__stream);
/* Write the given entry onto the given stream. */
-extern int putgrent(__const struct group *__restrict __p,
+extern int putgrent(const struct group *__restrict __p,
FILE *__restrict __f);
/* Search for an entry with a matching group ID. */
extern struct group *getgrgid(gid_t __gid);
/* Search for an entry with a matching group name. */
-extern struct group *getgrnam(__const char *__name);
+extern struct group *getgrnam(const char *__name);
/* Reentrant versions of some of the functions above.
@@ -98,7 +89,7 @@ extern int getgrgid_r(gid_t __gid, struct group *__restrict __resultbuf,
struct group **__restrict __result);
/* Search for an entry with a matching group name. */
-extern int getgrnam_r(__const char *__restrict __name,
+extern int getgrnam_r(const char *__restrict __name,
struct group *__restrict __resultbuf,
char *__restrict __buffer, size_t __buflen,
struct group **__restrict __result);
@@ -113,16 +104,14 @@ extern int fgetgrent_r(FILE *__restrict __stream,
/* Store at most *NGROUPS members of the group set for USER into
*GROUPS. Also include GROUP. The actual number of groups found is
returned in *NGROUPS. Return -1 if the if *NGROUPS is too small. */
-extern int getgrouplist(__const char *__user, gid_t __group,
+extern int getgrouplist(const char *__user, gid_t __group,
gid_t *__groups, int *__ngroups);
/* Initialize the group set for the current user
by reading the group database and using all groups
of which USER is a member. Also include GROUP. */
-extern int initgroups(__const char *__user, gid_t __group);
+extern int initgroups(const char *__user, gid_t __group);
-#if __GNUC_PREREQ(4,1)
-# pragma GCC visibility pop
-#endif
+POP_SAVED_FUNCTION_VISIBILITY
#endif
diff --git a/release/src/router/busybox/include/libbb.h b/release/src/router/busybox/include/libbb.h
index ef1f6c934d..1faa9e9fd2 100644
--- a/release/src/router/busybox/include/libbb.h
+++ b/release/src/router/busybox/include/libbb.h
@@ -7,8 +7,8 @@
*
* Licensed under the GPL version 2, see the file LICENSE in this tarball.
*/
-#ifndef __LIBBUSYBOX_H__
-#define __LIBBUSYBOX_H__ 1
+#ifndef LIBBB_H
+#define LIBBB_H 1
#include "platform.h"
@@ -69,21 +69,15 @@
#include
#endif
-#if !ENABLE_USE_BB_PWD_GRP
-# include
-# include
-#endif
+#include
+#include
#if ENABLE_FEATURE_SHADOWPASSWDS
-# if !ENABLE_USE_BB_SHADOW
-# include
-# endif
+# include
#endif
/* Some libc's forget to declare these, do it ourself */
-extern char **environ;
-/* Set the group set for the current user to GROUPS (N of them). */
-int setgroups(size_t n, const gid_t *groups);
+extern char **environ;
#if defined(__GLIBC__) && __GLIBC__ < 2
int vdprintf(int d, const char *format, va_list ap);
#endif
@@ -109,16 +103,14 @@ struct sysinfo {
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.. */
+ char _f[20 - 2 * sizeof(long) - sizeof(int)]; /* Padding: libc5 uses this.. */
};
int sysinfo(struct sysinfo* info);
/* Make all declarations hidden (-fvisibility flag only affects definitions) */
/* (don't include system headers after this until corresponding pop!) */
-#if __GNUC_PREREQ(4,1)
-# pragma GCC visibility push(hidden)
-#endif
+PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
#if ENABLE_USE_BB_PWD_GRP
@@ -156,6 +148,7 @@ int sysinfo(struct sysinfo* info);
/* CONFIG_LFS is on */
# if ULONG_MAX > 0xffffffff
/* "long" is long enough on this system */
+typedef unsigned long uoff_t;
# define XATOOFF(a) xatoul_range(a, 0, LONG_MAX)
/* usage: sz = BB_STRTOOFF(s, NULL, 10); if (errno || sz < 0) die(); */
# define BB_STRTOOFF bb_strtoul
@@ -164,6 +157,7 @@ int sysinfo(struct sysinfo* info);
# define OFF_FMT "l"
# else
/* "long" is too short, need "long long" */
+typedef unsigned long long uoff_t;
# define XATOOFF(a) xatoull_range(a, 0, LLONG_MAX)
# define BB_STRTOOFF bb_strtoull
# define STRTOOFF strtoull
@@ -174,11 +168,13 @@ int sysinfo(struct sysinfo* info);
# if UINT_MAX == 0xffffffff
/* While sizeof(off_t) == sizeof(int), off_t is typedef'ed to long anyway.
* gcc will throw warnings on printf("%d", off_t). Crap... */
+typedef unsigned long uoff_t;
# define XATOOFF(a) xatoi_u(a)
# define BB_STRTOOFF bb_strtou
# define STRTOOFF strtol
# define OFF_FMT "l"
# else
+typedef unsigned long uoff_t;
# define XATOOFF(a) xatoul_range(a, 0, LONG_MAX)
# define BB_STRTOOFF bb_strtoul
# define STRTOOFF strtol
@@ -359,8 +355,8 @@ enum {
void bb_signals(int sigs, void (*f)(int)) FAST_FUNC;
/* Unlike signal() and bb_signals, sets handler with sigaction()
* and in a way that while signal handler is run, no other signals
- * will be blocked: */
-void bb_signals_recursive(int sigs, void (*f)(int)) FAST_FUNC;
+ * will be blocked; syscalls will not be restarted: */
+void bb_signals_recursive_norestart(int sigs, void (*f)(int)) FAST_FUNC;
/* syscalls like read() will be interrupted with EINTR: */
void signal_no_SA_RESTART_empty_mask(int sig, void (*handler)(int)) FAST_FUNC;
/* syscalls like read() won't be interrupted (though select/poll will be): */
@@ -373,6 +369,9 @@ void sig_unblock(int sig) FAST_FUNC;
int sigaction_set(int sig, const struct sigaction *act) FAST_FUNC;
/* SIG_BLOCK/SIG_UNBLOCK all signals: */
int sigprocmask_allsigs(int how) FAST_FUNC;
+/* Standard handler which just records signo */
+extern smallint bb_got_signal;
+void record_signo(int signo); /* not FAST_FUNC! */
void xsetgid(gid_t gid) FAST_FUNC;
@@ -380,6 +379,7 @@ void xsetuid(uid_t uid) FAST_FUNC;
void xchdir(const char *path) FAST_FUNC;
void xchroot(const char *path) FAST_FUNC;
void xsetenv(const char *key, const char *value) FAST_FUNC;
+void bb_unsetenv(const char *key) FAST_FUNC;
void xunlink(const char *pathname) FAST_FUNC;
void xstat(const char *pathname, struct stat *buf) FAST_FUNC;
int xopen(const char *pathname, int flags) FAST_FUNC FAST_FUNC;
@@ -440,6 +440,7 @@ ssize_t xsendto(int s, const void *buf, size_t len, const struct sockaddr *to,
* Turn it on before you call bind(). */
void setsockopt_reuseaddr(int fd) FAST_FUNC; /* On Linux this never fails. */
int setsockopt_broadcast(int fd) FAST_FUNC;
+int setsockopt_bindtodevice(int fd, const char *iface) FAST_FUNC;
/* NB: returns port in host byte order */
unsigned bb_lookup_port(const char *port, const char *protocol, unsigned default_port) FAST_FUNC;
typedef struct len_and_sockaddr {
@@ -490,6 +491,8 @@ int create_and_bind_dgram_or_die(const char *bindaddr, int port) FAST_FUNC;
int create_and_connect_stream_or_die(const char *peer, int port) FAST_FUNC;
/* Connect to peer identified by lsa */
int xconnect_stream(const len_and_sockaddr *lsa) FAST_FUNC;
+/* Get local address of bound or accepted socket */
+len_and_sockaddr *get_sock_lsa(int fd) FAST_FUNC;
/* Return malloc'ed len_and_sockaddr with socket address of host:port
* Currently will return IPv4 or IPv6 sockaddrs only
* (depending on host), but in theory nothing prevents e.g.
@@ -543,6 +546,7 @@ char *xstrdup(const char *s) FAST_FUNC;
char *xstrndup(const char *s, int n) FAST_FUNC;
void overlapping_strcpy(char *dst, const char *src) FAST_FUNC;
char *safe_strncpy(char *dst, const char *src, size_t size) FAST_FUNC;
+char *strncpy_IFNAMSIZ(char *dst, const char *src) FAST_FUNC;
/* Guaranteed to NOT be a macro (smallest code). Saves nearly 2k on uclibc.
* But potentially slow, don't use in one-billion-times loops */
int bb_putchar(int ch) FAST_FUNC;
@@ -592,9 +596,9 @@ extern ssize_t open_read_close(const char *filename, void *buf, size_t maxsz) FA
// Reads byte-by-byte. Useful when it is important to not read ahead.
// Bytes are appended to pfx (which must be malloced, or NULL).
extern char *xmalloc_reads(int fd, char *pfx, size_t *maxsz_p) FAST_FUNC;
-/* Reads block up to *maxsz_p (default: MAX_INT(ssize_t)) */
+/* Reads block up to *maxsz_p (default: INT_MAX - 4095) */
extern void *xmalloc_read(int fd, size_t *maxsz_p) FAST_FUNC;
-/* Returns NULL if file can't be opened */
+/* Returns NULL if file can't be opened (default max size: INT_MAX - 4095) */
extern void *xmalloc_open_read_close(const char *filename, size_t *maxsz_p) FAST_FUNC;
/* Autodetects .gz etc */
extern int open_zipped(const char *fname) FAST_FUNC;
@@ -607,6 +611,7 @@ extern ssize_t safe_write(int fd, const void *buf, size_t count) FAST_FUNC;
// if some data was written before error occurred
extern ssize_t full_write(int fd, const void *buf, size_t count) FAST_FUNC;
extern void xwrite(int fd, const void *buf, size_t count) FAST_FUNC;
+extern void xwrite_str(int fd, const char *str) FAST_FUNC;
extern void xopen_xwrite_close(const char* file, const char *str) FAST_FUNC;
/* Reads and prints to stdout till eof, then closes FILE. Exits on error: */
@@ -616,6 +621,8 @@ extern char *bb_get_chunk_from_file(FILE *file, int *end) FAST_FUNC;
extern char *bb_get_chunk_with_continuation(FILE *file, int *end, int *lineno) FAST_FUNC;
/* Reads up to (and including) TERMINATING_STRING: */
extern char *xmalloc_fgets_str(FILE *file, const char *terminating_string) FAST_FUNC;
+/* Same, with limited max size, and returns the length (excluding NUL): */
+extern char *xmalloc_fgets_str_len(FILE *file, const char *terminating_string, size_t *maxsz_p) FAST_FUNC;
/* Chops off TERMINATING_STRING from the end: */
extern char *xmalloc_fgetline_str(FILE *file, const char *terminating_string) FAST_FUNC;
/* Reads up to (and including) "\n" or NUL byte: */
@@ -704,14 +711,16 @@ int get_uidgid(struct bb_uidgid_t*, const char*, int numeric_ok) FAST_FUNC;
void xget_uidgid(struct bb_uidgid_t*, const char*) FAST_FUNC;
/* chown-like handling of "user[:[group]" */
void parse_chown_usergroup_or_die(struct bb_uidgid_t *u, char *user_group) FAST_FUNC;
-/* bb_getpwuid, bb_getgrgid:
- * bb_getXXXid(buf, bufsz, id) - copy user/group name or id
- * as a string to buf, return user/group name or NULL
- * bb_getXXXid(NULL, 0, id) - return user/group name or NULL
- * bb_getXXXid(NULL, -1, id) - return user/group name or exit
-*/
-char *bb_getpwuid(char *name, int bufsize, long uid) FAST_FUNC;
-char *bb_getgrgid(char *group, int bufsize, long gid) FAST_FUNC;
+struct passwd* xgetpwnam(const char *name) FAST_FUNC;
+struct group* xgetgrnam(const char *name) FAST_FUNC;
+struct passwd* xgetpwuid(uid_t uid) FAST_FUNC;
+struct group* xgetgrgid(gid_t gid) FAST_FUNC;
+char* xuid2uname(uid_t uid) FAST_FUNC;
+char* xgid2group(gid_t gid) FAST_FUNC;
+char* uid2uname(uid_t uid) FAST_FUNC;
+char* gid2group(gid_t gid) FAST_FUNC;
+char* uid2uname_utoa(long uid) FAST_FUNC;
+char* gid2group_utoa(long gid) FAST_FUNC;
/* versions which cache results (useful for ps, ls etc) */
const char* get_cached_username(uid_t uid) FAST_FUNC;
const char* get_cached_groupname(gid_t gid) FAST_FUNC;
@@ -746,7 +755,7 @@ int bb_execvp(const char *file, char *const argv[]) FAST_FUNC;
pid_t spawn(char **argv) FAST_FUNC;
pid_t xspawn(char **argv) FAST_FUNC;
-int safe_waitpid(int pid, int *wstat, int options) FAST_FUNC;
+pid_t safe_waitpid(pid_t pid, int *wstat, int options) FAST_FUNC;
/* Unlike waitpid, waits ONLY for one process.
* It's safe to pass negative 'pids' from failed [v]fork -
* wait4pid will return -1 (and will not clobber [v]fork's errno).
@@ -754,14 +763,14 @@ int safe_waitpid(int pid, int *wstat, int options) FAST_FUNC;
* if (rc < 0) bb_perror_msg("%s", argv[0]);
* if (rc > 0) bb_error_msg("exit code: %d", rc);
*/
-int wait4pid(int pid) FAST_FUNC;
-int wait_any_nohang(int *wstat) FAST_FUNC;
+int wait4pid(pid_t pid) FAST_FUNC;
+pid_t wait_any_nohang(int *wstat) FAST_FUNC;
#define wait_crashed(w) ((w) & 127)
#define wait_exitcode(w) ((w) >> 8)
#define wait_stopsig(w) ((w) >> 8)
#define wait_stopped(w) (((w) & 127) == 127)
/* wait4pid(spawn(argv)) + NOFORK/NOEXEC (if configured) */
-int spawn_and_wait(char **argv) FAST_FUNC;
+pid_t spawn_and_wait(char **argv) FAST_FUNC;
struct nofork_save_area {
jmp_buf die_jmp;
const char *applet_name;
@@ -790,9 +799,9 @@ int run_nofork_applet_prime(struct nofork_save_area *old, int applet_no, char **
* Both of the above will redirect fd 0,1,2 to /dev/null and drop ctty
* (will do setsid()).
*
- * forkexit_or_rexec(argv) = bare-bones "fork + parent exits" on MMU,
+ * fork_or_rexec(argv) = bare-bones "fork" on MMU,
* "vfork + re-exec ourself" on NOMMU. No fd redirection, no setsid().
- * Currently used for openvt and setsid. On MMU ignores argv.
+ * On MMU ignores argv.
*
* Helper for network daemons in foreground mode:
*
@@ -806,14 +815,14 @@ enum {
DAEMON_ONLY_SANITIZE = 8, /* internal use */
};
#if BB_MMU
- void forkexit_or_rexec(void) FAST_FUNC;
+ pid_t fork_or_rexec(void) FAST_FUNC;
enum { re_execed = 0 };
-# define forkexit_or_rexec(argv) forkexit_or_rexec()
+# define fork_or_rexec(argv) fork_or_rexec()
# define bb_daemonize_or_rexec(flags, argv) bb_daemonize_or_rexec(flags)
# define bb_daemonize(flags) bb_daemonize_or_rexec(flags, bogus)
#else
void re_exec(char **argv) NORETURN FAST_FUNC;
- void forkexit_or_rexec(char **argv) FAST_FUNC;
+ pid_t fork_or_rexec(char **argv) FAST_FUNC;
extern bool re_execed;
int BUG_fork_is_unavailable_on_nommu(void) FAST_FUNC;
int BUG_daemon_is_unavailable_on_nommu(void) FAST_FUNC;
@@ -850,6 +859,7 @@ void *llist_pop(llist_t **elm) FAST_FUNC;
void llist_unlink(llist_t **head, llist_t *elm) FAST_FUNC;
void llist_free(llist_t *elm, void (*freeit)(void *data)) FAST_FUNC;
llist_t *llist_rev(llist_t *list) FAST_FUNC;
+llist_t *llist_find_str(llist_t *first, const char *str) FAST_FUNC;
/* BTW, surprisingly, changing API to
* llist_t *llist_add_to(llist_t *old_head, void *data)
* etc does not result in smaller code... */
@@ -885,7 +895,7 @@ extern void bb_error_msg_and_die(const char *s, ...) __attribute__ ((noreturn, f
extern void bb_perror_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))) FAST_FUNC;
extern void bb_simple_perror_msg(const char *s) FAST_FUNC;
extern void bb_perror_msg_and_die(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2))) FAST_FUNC;
-extern void bb_simple_perror_msg_and_die(const char *s) __attribute__ ((noreturn)) FAST_FUNC;
+extern void bb_simple_perror_msg_and_die(const char *s) NORETURN FAST_FUNC;
extern void bb_herror_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))) FAST_FUNC;
extern void bb_herror_msg_and_die(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2))) FAST_FUNC;
extern void bb_perror_nomsg_and_die(void) NORETURN FAST_FUNC;
@@ -912,18 +922,52 @@ int test_main(int argc, char **argv) USE_TEST(MAIN_EXTERNALLY_VISIBLE);
int kill_main(int argc, char **argv) USE_KILL(MAIN_EXTERNALLY_VISIBLE);
/* Similar, but used by chgrp, not shell */
int chown_main(int argc, char **argv) USE_CHOWN(MAIN_EXTERNALLY_VISIBLE);
+/* Used by ftpd */
+int ls_main(int argc, char **argv) USE_LS(MAIN_EXTERNALLY_VISIBLE);
/* Don't need USE_xxx() guard for these */
int gunzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int bunzip2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int bbunpack(char **argv,
- char* (*make_new_name)(char *filename),
- USE_DESKTOP(long long) int (*unpacker)(void)
-) FAST_FUNC;
+
#if ENABLE_ROUTE
void bb_displayroutes(int noresolve, int netstatfmt) FAST_FUNC;
#endif
+/* "Keycodes" that report an escape sequence.
+ * We use something which fits into signed char,
+ * yet doesn't represent any valid Unicode characher.
+ * Also, -1 is reserved for error indication and we don't use it. */
+enum {
+ KEYCODE_UP = -2,
+ KEYCODE_DOWN = -3,
+ KEYCODE_RIGHT = -4,
+ KEYCODE_LEFT = -5,
+ KEYCODE_HOME = -6,
+ KEYCODE_END = -7,
+ KEYCODE_INSERT = -8,
+ KEYCODE_DELETE = -9,
+ KEYCODE_PAGEUP = -10,
+ KEYCODE_PAGEDOWN = -11,
+#if 0
+ KEYCODE_FUN1 = -12,
+ KEYCODE_FUN2 = -13,
+ KEYCODE_FUN3 = -14,
+ KEYCODE_FUN4 = -15,
+ KEYCODE_FUN5 = -16,
+ KEYCODE_FUN6 = -17,
+ KEYCODE_FUN7 = -18,
+ KEYCODE_FUN8 = -19,
+ KEYCODE_FUN9 = -20,
+ KEYCODE_FUN10 = -21,
+ KEYCODE_FUN11 = -22,
+ KEYCODE_FUN12 = -23,
+#endif
+ /* How long the longest ESC sequence we know? */
+ KEYCODE_BUFFER_SIZE = 4
+};
+int read_key(int fd, smalluint *nbuffered, char *buffer) FAST_FUNC;
+
+
/* Networking */
int create_icmp_socket(void) FAST_FUNC;
int create_icmp6_socket(void) FAST_FUNC;
@@ -991,9 +1035,10 @@ extern int del_loop(const char *device) FAST_FUNC;
* return value: 1: read-only loopdev was setup, 0: rw, < 0: error */
extern int set_loop(char **devname, const char *file, unsigned long long offset) FAST_FUNC;
-
+/* Like bb_ask below, but asks on stdin with no timeout. */
+char *bb_ask_stdin(const char * prompt) FAST_FUNC;
//TODO: pass buf pointer or return allocated buf (avoid statics)?
-char *bb_askpass(int timeout, const char * prompt) FAST_FUNC;
+char *bb_ask(const int fd, int timeout, const char * prompt) FAST_FUNC;
int bb_ask_confirmation(void) FAST_FUNC;
int bb_parse_mode(const char* s, mode_t* theMode) FAST_FUNC;
@@ -1008,7 +1053,7 @@ enum {
PARSE_GREEDY = 0x00040000, // last token takes entire remainder of the line
PARSE_MIN_DIE = 0x00100000, // die if < min tokens found
// keep a copy of current line
- PARSE_KEEP_COPY = 0x00200000 * ENABLE_DEBUG_CROND_OPTION,
+ PARSE_KEEP_COPY = 0x00200000 * ENABLE_FEATURE_CROND_D,
// PARSE_ESCAPE = 0x00400000, // process escape sequences in tokens
// NORMAL is:
// * remove leading and trailing delimiters and collapse
@@ -1097,9 +1142,16 @@ extern int obscure(const char *old, const char *newval, const struct passwd *pwd
* (otherwise we risk having same salt generated)
*/
extern int crypt_make_salt(char *p, int cnt, int rnd) FAST_FUNC;
+
/* Returns number of lines changed, or -1 on error */
-extern int update_passwd(const char *filename, const char *username,
- const char *new_pw) FAST_FUNC;
+#if !(ENABLE_FEATURE_ADDUSER_TO_GROUP || ENABLE_FEATURE_DEL_USER_FROM_GROUP)
+#define update_passwd(filename, username, data, member) \
+ update_passwd(filename, username, data)
+#endif
+extern int update_passwd(const char *filename,
+ const char *username,
+ const char *data,
+ const char *member) FAST_FUNC;
int index_in_str_array(const char *const string_array[], const char *key) FAST_FUNC;
int index_in_strings(const char *strings, const char *key) FAST_FUNC;
@@ -1110,9 +1162,12 @@ const char *nth_string(const char *strings, int n) FAST_FUNC;
extern void print_login_issue(const char *issue_file, const char *tty) FAST_FUNC;
extern void print_login_prompt(void) FAST_FUNC;
+char *xmalloc_ttyname(int fd) FAST_FUNC;
/* NB: typically you want to pass fd 0, not 1. Think 'applet | grep something' */
int get_terminal_width_height(int fd, unsigned *width, unsigned *height) FAST_FUNC;
+int tcsetattr_stdin_TCSANOW(const struct termios *tp) FAST_FUNC;
+
/* NB: "unsigned request" is crucial! "int request" will break some arches! */
int ioctl_or_perror(int fd, unsigned request, void *argp, const char *fmt,...) __attribute__ ((format (printf, 4, 5))) FAST_FUNC;
int ioctl_or_perror_and_die(int fd, unsigned request, void *argp, const char *fmt,...) __attribute__ ((format (printf, 4, 5))) FAST_FUNC;
@@ -1142,9 +1197,9 @@ unsigned long long bb_makedev(unsigned int major, unsigned int minor) FAST_FUNC;
#if ENABLE_FEATURE_EDITING
/* It's NOT just ENABLEd or disabled. It's a number: */
#ifdef CONFIG_FEATURE_EDITING_HISTORY
-#define MAX_HISTORY (CONFIG_FEATURE_EDITING_HISTORY + 0)
+# define MAX_HISTORY (CONFIG_FEATURE_EDITING_HISTORY + 0)
#else
-#define MAX_HISTORY 0
+# define MAX_HISTORY 0
#endif
typedef struct line_input_t {
int flags;
@@ -1152,7 +1207,10 @@ typedef struct line_input_t {
#if MAX_HISTORY
int cnt_history;
int cur_history;
- USE_FEATURE_EDITING_SAVEHISTORY(const char *hist_file;)
+#if ENABLE_FEATURE_EDITING_SAVEHISTORY
+ unsigned cnt_history_in_file;
+ const char *hist_file;
+#endif
char *history[MAX_HISTORY + 1];
#endif
} line_input_t;
@@ -1166,6 +1224,7 @@ enum {
FOR_SHELL = DO_HISTORY | SAVE_HISTORY | TAB_COMPLETION | USERNAME_COMPLETION,
};
line_input_t *new_line_input_t(int flags) FAST_FUNC;
+/* so far static: void free_line_input_t(line_input_t *n) FAST_FUNC; */
/* Returns:
* -1 on read errors or EOF, or on bare Ctrl-D,
* 0 on ctrl-C (the line entered is still returned in 'command'),
@@ -1222,6 +1281,9 @@ typedef struct procps_status_t {
* by link target or interpreter name) */
char comm[COMM_LEN];
/* user/group? - use passwd/group parsing functions */
+#if ENABLE_FEATURE_TOP_SMP_PROCESS
+ int last_seen_on_cpu;
+#endif
} procps_status_t;
enum {
PSSCAN_PID = 1 << 0,
@@ -1240,15 +1302,25 @@ enum {
PSSCAN_UTIME = 1 << 13,
PSSCAN_TTY = 1 << 14,
PSSCAN_SMAPS = (1 << 15) * ENABLE_FEATURE_TOPMEM,
- PSSCAN_ARGVN = (1 << 16) * (ENABLE_PGREP || ENABLE_PKILL || ENABLE_PIDOF),
+ /* NB: used by find_pid_by_name(). Any applet using it
+ * needs to be mentioned here. */
+ PSSCAN_ARGVN = (1 << 16) * (ENABLE_KILLALL
+ || ENABLE_PGREP || ENABLE_PKILL
+ || ENABLE_PIDOF
+ || ENABLE_SESTATUS
+ ),
USE_SELINUX(PSSCAN_CONTEXT = 1 << 17,)
PSSCAN_START_TIME = 1 << 18,
+ PSSCAN_CPU = 1 << 19,
/* These are all retrieved from proc/NN/stat in one go: */
PSSCAN_STAT = PSSCAN_PPID | PSSCAN_PGID | PSSCAN_SID
- | PSSCAN_COMM | PSSCAN_STATE
- | PSSCAN_VSZ | PSSCAN_RSS
- | PSSCAN_STIME | PSSCAN_UTIME | PSSCAN_START_TIME
- | PSSCAN_TTY,
+ /**/ | PSSCAN_COMM | PSSCAN_STATE
+ /**/ | PSSCAN_VSZ | PSSCAN_RSS
+ /**/ | PSSCAN_STIME | PSSCAN_UTIME | PSSCAN_START_TIME
+ /**/ | PSSCAN_TTY
+#if ENABLE_FEATURE_TOP_SMP_PROCESS
+ /**/ | PSSCAN_CPU
+#endif
};
//procps_status_t* alloc_procps_scan(void) FAST_FUNC;
void free_procps_scan(procps_status_t* sp) FAST_FUNC;
@@ -1265,14 +1337,27 @@ extern const char bb_uuenc_tbl_std[];
void bb_uuencode(char *store, const void *s, int length, const char *tbl) FAST_FUNC;
typedef struct sha1_ctx_t {
- uint32_t count[2];
- uint32_t hash[5];
- uint32_t wbuf[16];
+ uint32_t hash[8]; /* 5, +3 elements for sha256 */
+ uint64_t total64;
+ uint8_t wbuffer[64]; /* NB: always correctly aligned for uint64_t */
+ void (*process_block)(struct sha1_ctx_t*) FAST_FUNC;
} sha1_ctx_t;
void sha1_begin(sha1_ctx_t *ctx) FAST_FUNC;
void sha1_hash(const void *data, size_t length, sha1_ctx_t *ctx) FAST_FUNC;
-void *sha1_end(void *resbuf, sha1_ctx_t *ctx) FAST_FUNC;
-
+void sha1_end(void *resbuf, sha1_ctx_t *ctx) FAST_FUNC;
+typedef struct sha1_ctx_t sha256_ctx_t;
+void sha256_begin(sha256_ctx_t *ctx) FAST_FUNC;
+#define sha256_hash sha1_hash
+#define sha256_end sha1_end
+typedef struct sha512_ctx_t {
+ uint64_t hash[8];
+ uint64_t total64[2];
+ uint8_t wbuffer[128]; /* NB: always correctly aligned for uint64_t */
+} sha512_ctx_t;
+void sha512_begin(sha512_ctx_t *ctx) FAST_FUNC;
+void sha512_hash(const void *buffer, size_t len, sha512_ctx_t *ctx) FAST_FUNC;
+void sha512_end(void *resbuf, sha512_ctx_t *ctx) FAST_FUNC;
+#if 1
typedef struct md5_ctx_t {
uint32_t A;
uint32_t B;
@@ -1282,9 +1367,18 @@ typedef struct md5_ctx_t {
uint32_t buflen;
char buffer[128];
} md5_ctx_t;
+#else
+/* libbb/md5prime.c uses a bit different one: */
+typedef struct md5_ctx_t {
+ uint32_t state[4]; /* state (ABCD) */
+ uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */
+ unsigned char buffer[64]; /* input buffer */
+} md5_ctx_t;
+#endif
void md5_begin(md5_ctx_t *ctx) FAST_FUNC;
void md5_hash(const void *data, size_t length, md5_ctx_t *ctx) FAST_FUNC;
-void *md5_end(void *resbuf, md5_ctx_t *ctx) FAST_FUNC;
+void md5_end(void *resbuf, md5_ctx_t *ctx) FAST_FUNC;
+
uint32_t *crc32_filltable(uint32_t *tbl256, int endian) FAST_FUNC;
@@ -1329,7 +1423,7 @@ extern const char bb_busybox_exec_path[];
* but I want to save a few bytes here */
extern const char bb_PATH_root_path[]; /* "PATH=/sbin:/usr/sbin:/bin:/usr/bin" */
#define bb_default_root_path (bb_PATH_root_path + sizeof("PATH"))
-#define bb_default_path (bb_PATH_root_path + sizeof("PATH=/bin:/usr/bin:/sbin:/usr/sbin"))
+#define bb_default_path (bb_PATH_root_path + sizeof("PATH=/sbin:/usr/sbin"))
extern const int const_int_0;
extern const int const_int_1;
@@ -1444,9 +1538,6 @@ extern const char bb_default_login_shell[];
#define ARRAY_SIZE(x) ((unsigned)(sizeof(x) / sizeof((x)[0])))
-#if __GNUC_PREREQ(4,1)
-# pragma GCC visibility pop
-#endif
-
+POP_SAVED_FUNCTION_VISIBILITY
-#endif /* __LIBBUSYBOX_H__ */
+#endif
diff --git a/release/src/router/busybox/include/platform.h b/release/src/router/busybox/include/platform.h
index 0f2f83a7dd..47fd5f63d2 100644
--- a/release/src/router/busybox/include/platform.h
+++ b/release/src/router/busybox/include/platform.h
@@ -1,11 +1,11 @@
/* vi: set sw=4 ts=4: */
/*
- Copyright 2006, Bernhard Fischer
+ Copyright 2006, Bernhard Reutner-Fischer
Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
*/
-#ifndef __PLATFORM_H
-#define __PLATFORM_H 1
+#ifndef BB_PLATFORM_H
+#define BB_PLATFORM_H 1
/* Convenience macros to test the version of gcc. */
#undef __GNUC_PREREQ
@@ -78,7 +78,7 @@
//__attribute__ ((__externally_visible__))
#else
# define EXTERNALLY_VISIBLE
-#endif /* GNUC >= 4.1 */
+#endif
/* We use __extension__ in some places to suppress -pedantic warnings
about GCC extensions. This feature didn't work properly before
@@ -110,6 +110,16 @@
# define FAST_FUNC
#endif
+/* Make all declarations hidden (-fvisibility flag only affects definitions) */
+/* (don't include system headers after this until corresponding pop!) */
+#if __GNUC_PREREQ(4,1)
+# define PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN _Pragma("GCC visibility push(hidden)")
+# define POP_SAVED_FUNCTION_VISIBILITY _Pragma("GCC visibility pop")
+#else
+# define PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
+# define POP_SAVED_FUNCTION_VISIBILITY
+#endif
+
/* ---- Endian Detection ------------------------------------ */
#if (defined __digital__ && defined __unix__)
@@ -132,6 +142,7 @@
# define BB_LITTLE_ENDIAN 1
#endif
+/* SWAP_LEnn means "convert CPU<->little_endian by swapping bytes" */
#if BB_BIG_ENDIAN
#define SWAP_BE16(x) (x)
#define SWAP_BE32(x) (x)
@@ -150,13 +161,19 @@
/* ---- Unaligned access ------------------------------------ */
-/* parameter is supposed to be an uint32_t* ptr */
+/* NB: unaligned parameter should be a pointer, aligned one -
+ * a lvalue. This makes it more likely to not swap them by mistake
+ */
#if defined(i386) || defined(__x86_64__)
-#define get_unaligned_u32p(u32p) (*(u32p))
+#define move_from_unaligned16(v, u16p) ((v) = *(uint16_t*)(u16p))
+#define move_from_unaligned32(v, u32p) ((v) = *(uint32_t*)(u32p))
+#define move_to_unaligned32(u32p, v) (*(uint32_t*)(u32p) = (v))
/* #elif ... - add your favorite arch today! */
#else
/* performs reasonably well (gcc usually inlines memcpy here) */
-#define get_unaligned_u32p(u32p) ({ uint32_t __t; memcpy(&__t, (u32p), 4); __t; })
+#define move_from_unaligned16(v, u16p) (memcpy(&(v), (u16p), 2))
+#define move_from_unaligned32(v, u32p) (memcpy(&(v), (u32p), 4))
+#define move_to_unaligned32(u32p, v) (memcpy((u32p), &(v), 4))
#endif
/* ---- Networking ------------------------------------------ */
@@ -184,7 +201,7 @@ typedef int socklen_t;
* until userspace is widely fixed. */
#if (defined __INTEL_COMPILER && !defined __GNUC__) || \
(defined __GNUC__ && defined __STRICT_ANSI__)
-__extension__ typedef __signed__ long long __s64;
+__extension__ typedef long long __s64;
__extension__ typedef unsigned long long __u64;
#endif
@@ -295,30 +312,32 @@ static ALWAYS_INLINE char* strchrnul(const char *s, char c)
#endif
#if (defined __digital__ && defined __unix__)
-#include
-#define HAVE_STANDARDS_H
-#include
-#define HAVE_INTTYPES_H
-#define PRIu32 "u"
+# include
+# define HAVE_STANDARDS_H
+# include
+# define HAVE_INTTYPES_H
+# define PRIu32 "u"
/* use legacy setpgrp(pid_t,pid_t) for now. move to platform.c */
-#define bb_setpgrp() do { pid_t __me = getpid(); setpgrp(__me,__me); } while (0)
+# define bb_setpgrp() do { pid_t __me = getpid(); setpgrp(__me,__me); } while (0)
-#if !defined ADJ_OFFSET_SINGLESHOT && defined MOD_CLKA && defined MOD_OFFSET
-#define ADJ_OFFSET_SINGLESHOT (MOD_CLKA | MOD_OFFSET)
-#endif
-#if !defined ADJ_FREQUENCY && defined MOD_FREQUENCY
-#define ADJ_FREQUENCY MOD_FREQUENCY
-#endif
-#if !defined ADJ_TIMECONST && defined MOD_TIMECONST
-#define ADJ_TIMECONST MOD_TIMECONST
-#endif
-#if !defined ADJ_TICK && defined MOD_CLKB
-#define ADJ_TICK MOD_CLKB
-#endif
+# if !defined ADJ_OFFSET_SINGLESHOT && defined MOD_CLKA && defined MOD_OFFSET
+# define ADJ_OFFSET_SINGLESHOT (MOD_CLKA | MOD_OFFSET)
+# endif
+# if !defined ADJ_FREQUENCY && defined MOD_FREQUENCY
+# define ADJ_FREQUENCY MOD_FREQUENCY
+# endif
+# if !defined ADJ_TIMECONST && defined MOD_TIMECONST
+# define ADJ_TIMECONST MOD_TIMECONST
+# endif
+# if !defined ADJ_TICK && defined MOD_CLKB
+# define ADJ_TICK MOD_CLKB
+# endif
+
+#else /* !__digital__ */
+
+# define bb_setpgrp() setpgrp()
-#else
-#define bb_setpgrp() setpgrp()
#endif
#if defined(__linux__)
@@ -362,4 +381,4 @@ static ALWAYS_INLINE char* strchrnul(const char *s, char c)
#endif
#endif
-#endif /* platform.h */
+#endif
diff --git a/release/src/router/busybox/include/pwd_.h b/release/src/router/busybox/include/pwd_.h
index 6199034d2b..f52445ceba 100644
--- a/release/src/router/busybox/include/pwd_.h
+++ b/release/src/router/busybox/include/pwd_.h
@@ -21,24 +21,15 @@
* POSIX Standard: 9.2.2 User Database Access
*/
-#ifndef _PWD_H
-#define _PWD_H 1
+#ifndef BB_PWD_H
+#define BB_PWD_H 1
-#if __GNUC_PREREQ(4,1)
-# pragma GCC visibility push(hidden)
-#endif
-
-/* The passwd structure. */
-struct passwd {
- char *pw_name; /* Username. */
- char *pw_passwd; /* Password. */
- uid_t pw_uid; /* User ID. */
- gid_t pw_gid; /* Group ID. */
- char *pw_gecos; /* Real name. */
- char *pw_dir; /* Home directory. */
- char *pw_shell; /* Shell program. */
-};
+PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
+/* This file is #included after #include
+ * We will use libc-defined structures, but will #define function names
+ * so that function calls are directed to bb_internal_XXX replacements
+ */
#define setpwent bb_internal_setpwent
#define endpwent bb_internal_endpwent
@@ -51,13 +42,11 @@ struct passwd {
#define getpwuid_r bb_internal_getpwuid_r
#define getpwnam_r bb_internal_getpwnam_r
#define fgetpwent_r bb_internal_fgetpwent_r
-#define getpw bb_internal_getpw
+//#define getpw bb_internal_getpw
/* All function names below should be remapped by #defines above
- * in order to not collide with libc names.
- * In theory it isn't necessary, but I saw weird interactions at link time.
- * Let's play safe */
+ * in order to not collide with libc names. */
/* Rewind the password-file stream. */
@@ -73,14 +62,14 @@ extern struct passwd *getpwent(void);
extern struct passwd *fgetpwent(FILE *__stream);
/* Write the given entry onto the given stream. */
-extern int putpwent(__const struct passwd *__restrict __p,
+extern int putpwent(const struct passwd *__restrict __p,
FILE *__restrict __f);
/* Search for an entry with a matching user ID. */
extern struct passwd *getpwuid(uid_t __uid);
/* Search for an entry with a matching username. */
-extern struct passwd *getpwnam(__const char *__name);
+extern struct passwd *getpwnam(const char *__name);
/* Reentrant versions of some of the functions above.
@@ -99,7 +88,7 @@ extern int getpwuid_r(uid_t __uid,
char *__restrict __buffer, size_t __buflen,
struct passwd **__restrict __result);
-extern int getpwnam_r(__const char *__restrict __name,
+extern int getpwnam_r(const char *__restrict __name,
struct passwd *__restrict __resultbuf,
char *__restrict __buffer, size_t __buflen,
struct passwd **__restrict __result);
@@ -114,10 +103,8 @@ extern int fgetpwent_r(FILE *__restrict __stream,
/* Re-construct the password-file line for the given uid
in the given buffer. This knows the format that the caller
will expect, but this need not be the format of the password file. */
-extern int getpw(uid_t __uid, char *__buffer);
+/* UNUSED extern int getpw(uid_t __uid, char *__buffer); */
-#if __GNUC_PREREQ(4,1)
-# pragma GCC visibility pop
-#endif
+POP_SAVED_FUNCTION_VISIBILITY
#endif /* pwd.h */
diff --git a/release/src/router/busybox/include/rtc_.h b/release/src/router/busybox/include/rtc_.h
index 2e990581fa..74bb695a08 100644
--- a/release/src/router/busybox/include/rtc_.h
+++ b/release/src/router/busybox/include/rtc_.h
@@ -4,14 +4,12 @@
* Licensed under the GPL-2 or later.
*/
-#ifndef _BB_RTC_H_
-#define _BB_RTC_H_
+#ifndef BB_RTC_H
+#define BB_RTC_H 1
#include "libbb.h"
-#if __GNUC_PREREQ(4,1)
-# pragma GCC visibility push(hidden)
-#endif
+PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
extern int rtc_adjtime_is_utc(void) FAST_FUNC;
extern int rtc_xopen(const char **default_rtc, int flags) FAST_FUNC;
@@ -44,27 +42,26 @@ struct linux_rtc_wkalrm {
* ioctl calls that are permitted to the /dev/rtc interface, if
* any of the RTC drivers are enabled.
*/
+#define RTC_AIE_ON _IO('p', 0x01) /* Alarm int. enable on */
+#define RTC_AIE_OFF _IO('p', 0x02) /* ... off */
+#define RTC_UIE_ON _IO('p', 0x03) /* Update int. enable on */
+#define RTC_UIE_OFF _IO('p', 0x04) /* ... off */
+#define RTC_PIE_ON _IO('p', 0x05) /* Periodic int. enable on */
+#define RTC_PIE_OFF _IO('p', 0x06) /* ... off */
+#define RTC_WIE_ON _IO('p', 0x0f) /* Watchdog int. enable on */
+#define RTC_WIE_OFF _IO('p', 0x10) /* ... off */
-#define RTC_AIE_ON _IO('p', 0x01) /* Alarm int. enable on */
-#define RTC_AIE_OFF _IO('p', 0x02) /* ... off */
-#define RTC_UIE_ON _IO('p', 0x03) /* Update int. enable on */
-#define RTC_UIE_OFF _IO('p', 0x04) /* ... off */
-#define RTC_PIE_ON _IO('p', 0x05) /* Periodic int. enable on */
-#define RTC_PIE_OFF _IO('p', 0x06) /* ... off */
-#define RTC_WIE_ON _IO('p', 0x0f) /* Watchdog int. enable on */
-#define RTC_WIE_OFF _IO('p', 0x10) /* ... off */
-
-#define RTC_ALM_SET _IOW('p', 0x07, struct linux_rtc_time) /* Set alarm time */
-#define RTC_ALM_READ _IOR('p', 0x08, struct linux_rtc_time) /* Read alarm time */
-#define RTC_RD_TIME _IOR('p', 0x09, struct linux_rtc_time) /* Read RTC time */
-#define RTC_SET_TIME _IOW('p', 0x0a, struct linux_rtc_time) /* Set RTC time */
-#define RTC_IRQP_READ _IOR('p', 0x0b, unsigned long) /* Read IRQ rate */
-#define RTC_IRQP_SET _IOW('p', 0x0c, unsigned long) /* Set IRQ rate */
-#define RTC_EPOCH_READ _IOR('p', 0x0d, unsigned long) /* Read epoch */
-#define RTC_EPOCH_SET _IOW('p', 0x0e, unsigned long) /* Set epoch */
+#define RTC_ALM_SET _IOW('p', 0x07, struct linux_rtc_time) /* Set alarm time */
+#define RTC_ALM_READ _IOR('p', 0x08, struct linux_rtc_time) /* Read alarm time */
+#define RTC_RD_TIME _IOR('p', 0x09, struct linux_rtc_time) /* Read RTC time */
+#define RTC_SET_TIME _IOW('p', 0x0a, struct linux_rtc_time) /* Set RTC time */
+#define RTC_IRQP_READ _IOR('p', 0x0b, unsigned long) /* Read IRQ rate */
+#define RTC_IRQP_SET _IOW('p', 0x0c, unsigned long) /* Set IRQ rate */
+#define RTC_EPOCH_READ _IOR('p', 0x0d, unsigned long) /* Read epoch */
+#define RTC_EPOCH_SET _IOW('p', 0x0e, unsigned long) /* Set epoch */
-#define RTC_WKALM_SET _IOW('p', 0x0f, struct linux_rtc_wkalrm)/* Set wakeup alarm*/
-#define RTC_WKALM_RD _IOR('p', 0x10, struct linux_rtc_wkalrm)/* Get wakeup alarm*/
+#define RTC_WKALM_SET _IOW('p', 0x0f, struct linux_rtc_wkalrm)/* Set wakeup alarm*/
+#define RTC_WKALM_RD _IOR('p', 0x10, struct linux_rtc_wkalrm)/* Get wakeup alarm*/
/* interrupt flags */
#define RTC_IRQF 0x80 /* any of the following is active */
@@ -72,8 +69,6 @@ struct linux_rtc_wkalrm {
#define RTC_AF 0x20
#define RTC_UF 0x10
-#if __GNUC_PREREQ(4,1)
-# pragma GCC visibility pop
-#endif
+POP_SAVED_FUNCTION_VISIBILITY
#endif
diff --git a/release/src/router/busybox/include/shadow_.h b/release/src/router/busybox/include/shadow_.h
index 5a8b71a471..02d3bf9a56 100644
--- a/release/src/router/busybox/include/shadow_.h
+++ b/release/src/router/busybox/include/shadow_.h
@@ -19,32 +19,21 @@
/* Declaration of types and functions for shadow password suite */
-#ifndef _SHADOW_H
-#define _SHADOW_H 1
+#ifndef BB_SHADOW_H
+#define BB_SHADOW_H 1
-#if __GNUC_PREREQ(4,1)
-# pragma GCC visibility push(hidden)
-#endif
+PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
+
+/* This file is #included after #include
+ * We will use libc-defined structures, but will #define function names
+ * so that function calls are directed to bb_internal_XXX replacements
+ */
/* Paths to the user database files */
#ifndef _PATH_SHADOW
#define _PATH_SHADOW "/etc/shadow"
#endif
-/* Structure of the password file */
-struct spwd {
- char *sp_namp; /* Login name */
- char *sp_pwdp; /* Encrypted password */
- long sp_lstchg; /* Date of last change */
- long sp_min; /* Minimum number of days between changes */
- long sp_max; /* Maximum number of days between changes */
- long sp_warn; /* Number of days to warn user to change the password */
- long sp_inact; /* Number of days the account may be inactive */
- long sp_expire; /* Number of days since 1970-01-01 until account expires */
- unsigned long sp_flag; /* Reserved */
-};
-
-
#define setspent bb_internal_setspent
#define endspent bb_internal_endspent
#define getspent bb_internal_getspent
@@ -61,9 +50,7 @@ struct spwd {
/* All function names below should be remapped by #defines above
- * in order to not collide with libc names.
- * In theory it isn't necessary, but I saw weird interactions at link time.
- * Let's play safe */
+ * in order to not collide with libc names. */
/* Open database for reading */
@@ -76,26 +63,26 @@ extern void endspent(void);
extern struct spwd *getspent(void);
/* Get shadow entry matching NAME */
-extern struct spwd *getspnam(__const char *__name);
+extern struct spwd *getspnam(const char *__name);
/* Read shadow entry from STRING */
-extern struct spwd *sgetspent(__const char *__string);
+extern struct spwd *sgetspent(const char *__string);
/* Read next shadow entry from STREAM */
extern struct spwd *fgetspent(FILE *__stream);
/* Write line containing shadow password entry to stream */
-extern int putspent(__const struct spwd *__p, FILE *__stream);
+extern int putspent(const struct spwd *__p, FILE *__stream);
/* Reentrant versions of some of the functions above */
extern int getspent_r(struct spwd *__result_buf, char *__buffer,
size_t __buflen, struct spwd **__result);
-extern int getspnam_r(__const char *__name, struct spwd *__result_buf,
+extern int getspnam_r(const char *__name, struct spwd *__result_buf,
char *__buffer, size_t __buflen,
struct spwd **__result);
-extern int sgetspent_r(__const char *__string, struct spwd *__result_buf,
+extern int sgetspent_r(const char *__string, struct spwd *__result_buf,
char *__buffer, size_t __buflen,
struct spwd **__result);
@@ -108,8 +95,6 @@ extern int lckpwdf(void);
/* Unlock password file */
extern int ulckpwdf(void);
-#if __GNUC_PREREQ(4,1)
-# pragma GCC visibility pop
-#endif
+POP_SAVED_FUNCTION_VISIBILITY
#endif /* shadow.h */
diff --git a/release/src/router/busybox/include/unarchive.h b/release/src/router/busybox/include/unarchive.h
index 7ff791be53..beb962c8ff 100644
--- a/release/src/router/busybox/include/unarchive.h
+++ b/release/src/router/busybox/include/unarchive.h
@@ -1,10 +1,8 @@
/* vi: set sw=4 ts=4: */
-#ifndef __UNARCHIVE_H__
-#define __UNARCHIVE_H__
+#ifndef UNARCHIVE_H
+#define UNARCHIVE_H 1
-#if __GNUC_PREREQ(4,1)
-# pragma GCC visibility push(hidden)
-#endif
+PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
#define ARCHIVE_PRESERVE_DATE 1
#define ARCHIVE_CREATE_LEADING_DIRS 2
@@ -77,6 +75,12 @@ typedef struct archive_handle_t {
} archive_handle_t;
+/* Info struct unpackers can fill out to inform users of thing like
+ * timestamps of unpacked files */
+typedef struct unpack_info_t {
+ time_t mtime;
+} unpack_info_t;
+
extern archive_handle_t *init_handle(void) FAST_FUNC;
extern char filter_accept_all(archive_handle_t *archive_handle) FAST_FUNC;
@@ -126,10 +130,15 @@ USE_DESKTOP(long long) int unpack_lzma_stream(int src_fd, int dst_fd) FAST_FUNC;
/* the rest wants 2 first bytes already skipped by the caller */
USE_DESKTOP(long long) int unpack_bz2_stream(int src_fd, int dst_fd) FAST_FUNC;
USE_DESKTOP(long long) int unpack_gz_stream(int src_fd, int dst_fd) FAST_FUNC;
+USE_DESKTOP(long long) int unpack_gz_stream_with_info(int src_fd, int dst_fd, unpack_info_t *info) FAST_FUNC;
USE_DESKTOP(long long) int unpack_Z_stream(int fd_in, int fd_out) FAST_FUNC;
/* wrapper which checks first two bytes to be "BZ" */
USE_DESKTOP(long long) int unpack_bz2_stream_prime(int src_fd, int dst_fd) FAST_FUNC;
+int bbunpack(char **argv,
+ char* (*make_new_name)(char *filename),
+ USE_DESKTOP(long long) int (*unpacker)(unpack_info_t *info)) FAST_FUNC;
+
#if BB_MMU
void open_transformer(int fd,
USE_DESKTOP(long long) int FAST_FUNC (*transformer)(int src_fd, int dst_fd)) FAST_FUNC;
@@ -139,8 +148,6 @@ void open_transformer(int src_fd, const char *transform_prog) FAST_FUNC;
#define open_transformer(fd, transformer, transform_prog) open_transformer(fd, transform_prog)
#endif
-#if __GNUC_PREREQ(4,1)
-# pragma GCC visibility pop
-#endif
+POP_SAVED_FUNCTION_VISIBILITY
#endif
diff --git a/release/src/router/busybox/include/usage.h b/release/src/router/busybox/include/usage.h
index 57a9f99b8a..d3bf7849e0 100644
--- a/release/src/router/busybox/include/usage.h
+++ b/release/src/router/busybox/include/usage.h
@@ -9,25 +9,41 @@
* or
* |<5 spaces>"\ntext with tabs"....
*/
-
-#ifndef __BB_USAGE_H__
-#define __BB_USAGE_H__
+#ifndef BB_USAGE_H
+#define BB_USAGE_H 1
#define NOUSAGE_STR "\b"
+#define acpid_trivial_usage \
+ "[-d] [-c CONFDIR] [-l LOGFILE] [-e PROC_EVENT_FILE] [EVDEV_EVENT_FILE...]"
+
+#define acpid_full_usage "\n\n" \
+ "Listen to ACPI events and spawn specific helpers on event arrival\n" \
+ "\nOptions:" \
+ "\n -d Do not daemonize and log to stderr" \
+ "\n -c DIR Config directory [/etc/acpi]" \
+ "\n -e FILE /proc event file [/proc/acpi/event]" \
+ "\n -l FILE Log file [/var/log/acpid]" \
+ USE_FEATURE_ACPID_COMPAT( \
+ "\n\nAccept and ignore compatibility options -g -m -s -S -v" \
+ )
+
+#define acpid_example_usage \
+ "# acpid -l /var/log/my-acpi-log\n" \
+ "# acpid -d /dev/input/event*\n"
#define addgroup_trivial_usage \
"[-g GID] " USE_FEATURE_ADDUSER_TO_GROUP("[user_name] ") "group_name"
#define addgroup_full_usage "\n\n" \
- "Add a group " USE_FEATURE_ADDUSER_TO_GROUP("or add an user to a group") "\n" \
+ "Add a group " USE_FEATURE_ADDUSER_TO_GROUP("or add a user to a group") "\n" \
"\nOptions:" \
"\n -g GID Group id" \
#define adduser_trivial_usage \
"[OPTIONS] user_name"
#define adduser_full_usage "\n\n" \
- "Add an user\n" \
+ "Add a user\n" \
"\nOptions:" \
"\n -h DIR Home directory" \
"\n -g GECOS GECOS field" \
@@ -61,12 +77,11 @@
"\n -v Verbose" \
#define arp_trivial_usage \
- "\n" \
- "[-vn] [-H type] [-i if] -a [hostname]\n" \
- "[-v] [-i if] -d hostname [pub]\n" \
- "[-v] [-H type] [-i if] -s hostname hw_addr [temp]\n" \
- "[-v] [-H type] [-i if] -s hostname hw_addr [netmask nm] pub\n" \
- "[-v] [-H type] [-i if] -Ds hostname ifa [netmask nm] pub\n"
+ "\n[-vn] [-H type] [-i if] -a [hostname]" \
+ "\n[-v] [-i if] -d hostname [pub]" \
+ "\n[-v] [-H type] [-i if] -s hostname hw_addr [temp]" \
+ "\n[-v] [-H type] [-i if] -s hostname hw_addr [netmask nm] pub" \
+ "\n[-v] [-H type] [-i if] -Ds hostname ifa [netmask nm] pub"
#define arp_full_usage "\n\n" \
"Manipulate ARP cache\n" \
"\nOptions:" \
@@ -515,33 +530,38 @@
"\n -l,-s Create (sym)links" \
#define cpio_trivial_usage \
- "-[dim" USE_FEATURE_CPIO_O("o") "tuv][F cpiofile]" \
- USE_FEATURE_CPIO_O( "[H newc]" )
+ "-[ti" USE_FEATURE_CPIO_O("o") USE_FEATURE_CPIO_P("p") "dmvu] [-F FILE]" \
+ USE_FEATURE_CPIO_O( " [-H newc]" )
#define cpio_full_usage "\n\n" \
"Extract or list files from a cpio archive" \
USE_FEATURE_CPIO_O( ", or create a cpio archive" ) \
- "\n" \
- "Main operation mode:" \
- "\n d Make leading directories" \
- "\n i Extract" \
- "\n m Preserve mtime" \
+ "\nMain operation mode:" \
+ "\n -t List" \
+ "\n -i Extract" \
USE_FEATURE_CPIO_O( \
- "\n o Create" \
- "\n H newc Define format" \
+ "\n -o Create" \
+ ) \
+ USE_FEATURE_CPIO_P( \
+ "\n -p Passthrough" \
+ ) \
+ "\nOptions:" \
+ "\n -d Make leading directories" \
+ "\n -m Preserve mtime" \
+ "\n -v Verbose" \
+ "\n -u Overwrite" \
+ "\n -F Input file" \
+ USE_FEATURE_CPIO_O( \
+ "\n -H Define format" \
) \
- "\n t List" \
- "\n v Verbose" \
- "\n u Unconditional overwrite" \
- "\n F Input from file" \
#define crond_trivial_usage \
- "-fbS -l N " USE_DEBUG_CROND_OPTION("-d N ") "-L LOGFILE -c DIR"
+ "-fbS -l N " USE_FEATURE_CROND_D("-d N ") "-L LOGFILE -c DIR"
#define crond_full_usage "\n\n" \
" -f Foreground" \
"\n -b Background (default)" \
"\n -S Log to syslog (default)" \
"\n -l Set log level. 0 is the most verbose, default 8" \
- USE_DEBUG_CROND_OPTION( \
+ USE_FEATURE_CROND_D( \
"\n -d Set log level, log to stderr" \
) \
"\n -L Log to file" \
@@ -558,12 +578,44 @@
"\n FILE Replace crontab by FILE ('-': stdin)" \
#define cryptpw_trivial_usage \
- "[-a des|md5] [string]"
+ "[OPTIONS] [PASSWORD] [SALT]"
+/* We do support -s, we just don't mention it */
#define cryptpw_full_usage "\n\n" \
- "Output crypted string.\n" \
- "If string isn't supplied on cmdline, read it from stdin.\n" \
+ "Crypt the PASSWORD using crypt(3)\n" \
+ "\nOptions:" \
+ USE_GETOPT_LONG( \
+ "\n -P,--password-fd=NUM Read password from fd NUM" \
+/* "\n -s,--stdin Use stdin; like -P0" */ \
+ "\n -m,--method=TYPE Encryption method TYPE" \
+ "\n -S,--salt=SALT" \
+ ) \
+ SKIP_GETOPT_LONG( \
+ "\n -P NUM Read password from fd NUM" \
+/* "\n -s Use stdin; like -P0" */ \
+ "\n -m TYPE Encryption method TYPE" \
+ "\n -S SALT" \
+ ) \
+
+/* mkpasswd is an alias to cryptpw */
+
+#define mkpasswd_trivial_usage \
+ "[OPTIONS] [PASSWORD] [SALT]"
+/* We do support -s, we just don't mention it */
+#define mkpasswd_full_usage "\n\n" \
+ "Crypt the PASSWORD using crypt(3)\n" \
"\nOptions:" \
- "\n -a Algorithm to use (default: md5)" \
+ USE_GETOPT_LONG( \
+ "\n -P,--password-fd=NUM Read password from fd NUM" \
+/* "\n -s,--stdin Use stdin; like -P0" */ \
+ "\n -m,--method=TYPE Encryption method TYPE" \
+ "\n -S,--salt=SALT" \
+ ) \
+ SKIP_GETOPT_LONG( \
+ "\n -P NUM Read password from fd NUM" \
+/* "\n -s Use stdin; like -P0" */ \
+ "\n -m TYPE Encryption method TYPE" \
+ "\n -S SALT" \
+ ) \
#define cttyhack_trivial_usage NOUSAGE_STR
#define cttyhack_full_usage ""
@@ -690,6 +742,15 @@
#define depmod_trivial_usage NOUSAGE_STR
#define depmod_full_usage ""
+#define devmem_trivial_usage \
+ "ADDRESS [WIDTH [VALUE]]"
+
+#define devmem_full_usage "\n\n" \
+ "Read/write from physical address\n" \
+ "\n ADDRESS Address to act upon" \
+ "\n WIDTH Width (8/16/...)" \
+ "\n VALUE Data to be written" \
+
#define devfsd_trivial_usage \
"mntpnt [-v]" USE_DEVFSD_FG_NP("[-fg][-np]")
#define devfsd_full_usage "\n\n" \
@@ -705,42 +766,45 @@
"\n do not poll for events" \
)
-/* -k is accepted but ignored for !HUMAN_READABLE,
- * but we won't mention this (unimportant) */
-#if ENABLE_FEATURE_HUMAN_READABLE || ENABLE_FEATURE_DF_INODE
-#define DF_HAS_OPTIONS(x) x
-#else
-#define DF_HAS_OPTIONS(x)
-#endif
#define df_trivial_usage \
- DF_HAS_OPTIONS("[-") \
- USE_FEATURE_HUMAN_READABLE("hmk") USE_FEATURE_DF_INODE("i") \
- DF_HAS_OPTIONS("] ") "[FILESYSTEM...]"
+ "[-Pk" \
+ USE_FEATURE_HUMAN_READABLE("mh") \
+ USE_FEATURE_DF_FANCY("ai] [-B SIZE") \
+ "] [FILESYSTEM...]"
#define df_full_usage "\n\n" \
"Print filesystem usage statistics\n" \
- DF_HAS_OPTIONS("\nOptions:") \
+ "\nOptions:" \
+ "\n -P POSIX output format" \
+ "\n -k 1024-byte blocks (default)" \
USE_FEATURE_HUMAN_READABLE( \
+ "\n -m 1M-byte blocks" \
"\n -h Human readable (e.g. 1K 243M 2G)" \
- "\n -m 1024*1024 blocks" \
- "\n -k 1024 blocks" \
) \
- USE_FEATURE_DF_INODE( \
+ USE_FEATURE_DF_FANCY( \
+ "\n -a Show all filesystems" \
"\n -i Inodes" \
- )
+ "\n -B SIZE Blocksize" \
+ ) \
+
#define df_example_usage \
"$ df\n" \
- "Filesystem 1k-blocks Used Available Use% Mounted on\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"
+ "Filesystem 1K-blocks Used Available Use% Mounted on\n" \
+ "/dev/sda3 8690864 8553540 137324 98% /\n" \
+ "$ POSIXLY_CORRECT=sure df /dev/sda3\n" \
+ "Filesystem 512B-blocks Used Available Use% Mounted on\n" \
+ "/dev/sda3 17381728 17107080 274648 98% /\n" \
+ "$ POSIXLY_CORRECT=yep df -P /dev/sda3\n" \
+ "Filesystem 512-blocks Used Available Capacity Mounted on\n" \
+ "/dev/sda3 17381728 17107080 274648 98% /\n"
#define dhcprelay_trivial_usage \
- "[client1,client2,...] [server_device]"
+ "CLIENT_IFACE[,CLIENT_IFACE2...] SERVER_IFACE [SERVER_IP]"
#define dhcprelay_full_usage "\n\n" \
- "Relay dhcp requests from client devices to server device.\n" \
- "Pass clients as CSV"
+ "Relay DHCP requests between clients and server" \
#define diff_trivial_usage \
"[-abdiNqrTstw] [-L LABEL] [-S FILE] [-U LINES] FILE1 FILE2"
@@ -1082,17 +1146,10 @@
"\n -H HEADS\n" \
"\n -S SECTORS" \
-#define fetchmail_trivial_usage \
- "[-w timeout] [-H [user:pass@]server[:port]] [-S] [-t] [-z] maildir [prog]"
-#define fetchmail_full_usage "\n\n" \
- "Fetch content of remote mailbox to local maildir\n" \
- "\nOptions:" \
- "\n -w timeout Network timeout" \
- "\n -H [user:pass@]server[:port] Server" \
- "\n -S Use openssl connection helper for secure servers" \
- "\n -t Get only headers" \
- "\n -z Delete messages on server" \
- "\n prog Run 'prog ' on message delivery" \
+#define blkid_trivial_usage \
+ ""
+#define blkid_full_usage "\n\n" \
+ "Print UUIDs of all filesystems."
#define findfs_trivial_usage \
"LABEL=label or UUID=uuid"
@@ -1113,6 +1170,7 @@
USE_FEATURE_FIND_MAXDEPTH( \
"\n -maxdepth N Descend at most N levels. -maxdepth 0 applies" \
"\n tests/actions to command line arguments only") \
+ "\n -mindepth N Do not act on first N levels" \
"\n -name PATTERN File name (w/o directory name) matches PATTERN" \
"\n -iname PATTERN Case insensitive -name" \
USE_FEATURE_FIND_PATH( \
@@ -1163,6 +1221,14 @@
"$ find / -name passwd\n" \
"/etc/passwd\n"
+#define flash_eraseall_trivial_usage \
+ "[-jq] MTD_DEVICE"
+#define flash_eraseall_full_usage "\n\n" \
+ "Erase an MTD device\n" \
+ "\nOptions:" \
+ "\n -j format the device for jffs2" \
+ "\n -q don't display progress messages"
+
#define fold_trivial_usage \
"[-bs] [-w WIDTH] [FILE]"
#define fold_full_usage "\n\n" \
@@ -1218,19 +1284,36 @@
"\n -m Show \"mode not cleared\" warnings" \
"\n -f Force file system check" \
+#define ftpd_trivial_usage \
+ "[-wvS] [-t N] [-T N] [DIR]"
+#define ftpd_full_usage "\n\n" \
+ "FTP server\n" \
+ "\n" \
+ "ftpd should be used as an inetd service.\n" \
+ "ftpd's line for inetd.conf:\n" \
+ " 21 stream tcp nowait root ftpd ftpd /files/to/serve\n" \
+ "It also can be ran from tcpsvd:\n" \
+ " tcpsvd -vE 0.0.0.0 21 ftpd /files/to/serve\n" \
+ "\nOptions:" \
+ "\n -w Allow upload" \
+ "\n -v Log to stderr" \
+ "\n -S Log to syslog" \
+ "\n -t,-T Idle and absolute timeouts" \
+ "\n DIR Change root to this directory" \
+
#define ftpget_trivial_usage \
"[options] remote-host local-file remote-file"
#define ftpget_full_usage "\n\n" \
"Retrieve a remote file via FTP\n" \
"\nOptions:" \
- USE_GETOPT_LONG( \
+ USE_FEATURE_FTPGETPUT_LONG_OPTIONS( \
"\n -c,--continue Continue previous transfer" \
"\n -v,--verbose Verbose" \
"\n -u,--username Username" \
"\n -p,--password Password" \
"\n -P,--port Port number" \
) \
- SKIP_GETOPT_LONG( \
+ SKIP_FEATURE_FTPGETPUT_LONG_OPTIONS( \
"\n -c Continue previous transfer" \
"\n -v Verbose" \
"\n -u Username" \
@@ -1243,13 +1326,13 @@
#define ftpput_full_usage "\n\n" \
"Store a local file on a remote machine via FTP\n" \
"\nOptions:" \
- USE_GETOPT_LONG( \
+ USE_FEATURE_FTPGETPUT_LONG_OPTIONS( \
"\n -v,--verbose Verbose" \
"\n -u,--username Username" \
"\n -p,--password Password" \
"\n -P,--port Port number" \
) \
- SKIP_GETOPT_LONG( \
+ SKIP_FEATURE_FTPGETPUT_LONG_OPTIONS( \
"\n -v Verbose" \
"\n -u Username" \
"\n -p Password" \
@@ -1346,6 +1429,7 @@
"eF" \
USE_FEATURE_GREP_EGREP_ALIAS("E") \
USE_FEATURE_GREP_CONTEXT("ABC") \
+ USE_EXTRA_COMPAT("z") \
"] PATTERN [FILEs...]"
#define grep_full_usage "\n\n" \
"Search for PATTERN in each FILE or standard input\n" \
@@ -1374,6 +1458,8 @@
"\n -A Print NUM lines of trailing context" \
"\n -B Print NUM lines of leading context" \
"\n -C Print NUM lines of output context") \
+ USE_EXTRA_COMPAT( \
+ "\n -z Input is NUL terminated") \
#define grep_example_usage \
"$ grep root /etc/passwd\n" \
@@ -1420,7 +1506,7 @@
"-rw-rw-r-- 1 andersen andersen 554058 Apr 14 17:49 /tmp/busybox.tar.gz\n"
#define halt_trivial_usage \
- "[-d delay] [-n] [-f]"
+ "[-d delay] [-n] [-f]" USE_FEATURE_WTMP(" [-w]")
#define halt_full_usage "\n\n" \
"Halt the system\n" \
"\nOptions:" \
@@ -1572,12 +1658,12 @@
"\n -d STRING URL decode STRING" \
#define hwclock_trivial_usage \
- USE_GETOPT_LONG( \
+ USE_FEATURE_HWCLOCK_LONG_OPTIONS( \
"[-r|--show] [-s|--hctosys] [-w|--systohc]" \
" [-l|--localtime] [-u|--utc]" \
" [-f FILE]" \
) \
- SKIP_GETOPT_LONG( \
+ SKIP_FEATURE_HWCLOCK_LONG_OPTIONS( \
"[-r] [-s] [-w] [-l] [-u] [-f FILE]" \
)
#define hwclock_full_usage "\n\n" \
@@ -1598,8 +1684,9 @@
USE_SELINUX( \
"\n -Z Print the security context" \
) \
- "\n -g Print group ID" \
"\n -u Print user ID" \
+ "\n -g Print group ID" \
+ "\n -G Print supplementary group IDs" \
"\n -n Print name instead of a number" \
"\n -r Print real user ID instead of effective ID" \
@@ -1827,31 +1914,38 @@
" ::shutdown:/sbin/swapoff -a\n"
#define inotifyd_trivial_usage \
- "/user/space/agent dir/or/file/being/watched[:mask] ..."
+ "PROG FILE1[:MASK] ..."
#define inotifyd_full_usage "\n\n" \
- "Spawn userspace agent on filesystem changes." \
- "\nWhen a filesystem event matching the mask occurs" \
- "\non specified file/directory an userspace agent is spawned" \
- "\nwith the parameters:" \
- "\n1. actual event(s)" \
- "\n2. file/directory name" \
- "\n3. name of subfile (if any), in case of watching a directory" \
- "\n" \
+ "Run PROG on filesystem changes." \
+ "\nWhen a filesystem event matching MASK occurs on FILEn," \
+ "\nPROG [] is run." \
+ "\nEvents:" \
"\n a File is accessed" \
"\n c File is modified" \
"\n e Metadata changed" \
"\n w Writtable file is closed" \
"\n 0 Unwrittable file is closed" \
"\n r File is opened" \
- "\n m File is moved from X" \
- "\n y File is moved to Y" \
+ "\n D File is deleted" \
+ "\n M File is moved" \
+ "\n u Backing fs is unmounted" \
+ "\n o Event queue overflowed" \
+ "\n x File can't be watched anymore" \
+ "\nIf watching a directory:" \
+ "\n m Subfile is moved into dir" \
+ "\n y Subfile is moved out of dir" \
"\n n Subfile is created" \
"\n d Subfile is deleted" \
- "\n D Self is deleted" \
- "\n M Self is moved" \
+ "\n" \
+ "\ninotifyd waits for PROG to exit." \
+ "\nWhen x event happens for all FILEs, inotifyd exits" \
+/* 2.6 style insmod has no options and required filename
+ * (not module name - .ko can't be omitted) */
#define insmod_trivial_usage \
- USE_FEATURE_2_4_MODULES("[OPTION]... ") "MODULE [symbol=value]..."
+ USE_FEATURE_2_4_MODULES("[OPTION]... MODULE ") \
+ SKIP_FEATURE_2_4_MODULES("FILE ") \
+ "[symbol=value]..."
#define insmod_full_usage "\n\n" \
"Load the specified kernel modules into the kernel" \
USE_FEATURE_2_4_MODULES( "\n" \
@@ -1868,22 +1962,32 @@
"\n -x Do not export externs" \
)
+/* -v, -b, -c are ignored */
#define install_trivial_usage \
- "[-cgmops] [sources] dest|directory"
+ "[-cdDsp] [-o USER] [-g GRP] [-m MODE] [source] dest|directory"
#define install_full_usage "\n\n" \
"Copy files and set attributes\n" \
"\nOptions:" \
- "\n -c Copy the file, default" \
+ "\n -c Just copy (default)" \
"\n -d Create directories" \
- "\n -g Set group ownership" \
- "\n -m Set permissions" \
- "\n -o Set ownership" \
+ "\n -D Create leading target directories" \
+ "\n -s Strip symbol table" \
"\n -p Preserve date" \
- "\n -s Strip symbol tables" \
+ "\n -o USER Set ownership" \
+ "\n -g GRP Set group ownership" \
+ "\n -m MODE Set permissions" \
USE_SELINUX( \
- "\n -Z Set security context of copy" \
+ "\n -Z Set security context" \
)
+#define ionice_trivial_usage \
+ "[-c 1-3] [-n 0-7] [-p PID] [PROG]"
+#define ionice_full_usage "\n\n" \
+ "Change I/O scheduling class and priority\n" \
+ "\nOptions:" \
+ "\n -c Class. 1:realtime 2:best-effort 3:idle" \
+ "\n -n Priority" \
+
/* would need to make the " | " optional depending on more than one selected: */
#define ip_trivial_usage \
"[OPTIONS] {" \
@@ -1985,7 +2089,8 @@
" [oif STRING] [tos TOS]\n" \
"iproute { add | del | change | append | replace | monitor } ROUTE\n" \
" SELECTOR := [root PREFIX] [match PREFIX] [proto RTPROTO]\n" \
- " ROUTE := [TYPE] PREFIX [tos TOS] [proto RTPROTO]" \
+ " ROUTE := [TYPE] PREFIX [tos TOS] [proto RTPROTO]\n" \
+ " [metric METRIC]" \
#define iprule_trivial_usage \
"{[list | add | del] RULE}"
@@ -2009,7 +2114,7 @@
" [ttl TTL] [tos TOS] [[no]pmtudisc] [dev PHYS_DEV]" \
#define kbd_mode_trivial_usage \
- "[-a|k|s|u]"
+ "[-a|k|s|u] [-C TTY]"
#define kbd_mode_full_usage "\n\n" \
"Report or set the keyboard mode\n" \
"\nOptions set mode:" \
@@ -2017,13 +2122,15 @@
"\n -k Medium-raw (keyboard)" \
"\n -s Raw (scancode)" \
"\n -u Unicode (utf-8)" \
+ "\n -C TTY Affect TTY instead of /dev/tty" \
#define kill_trivial_usage \
- "[-l] [-signal] process-id..."
+ "[-l] [-SIG] PID..."
#define kill_full_usage "\n\n" \
- "Send a signal (default is TERM) to the specified process(es)\n" \
+ "Send a signal (default is TERM) to given PIDs\n" \
"\nOptions:" \
"\n -l List all signal names and numbers" \
+/* "\n -s SIG Yet another way of specifying SIG" */ \
#define kill_example_usage \
"$ ps | grep apache\n" \
@@ -2036,22 +2143,25 @@
"$ kill 252\n"
#define killall_trivial_usage \
- "[-l] [-q] [-signal] process-name..."
+ "[-l] [-q] [-SIG] process-name..."
#define killall_full_usage "\n\n" \
- "Send a signal (default is TERM) to the specified process(es)\n" \
+ "Send a signal (default is TERM) to given processes\n" \
"\nOptions:" \
"\n -l List all signal names and numbers" \
+/* "\n -s SIG Yet another way of specifying SIG" */ \
"\n -q Do not complain if no processes were killed" \
#define killall_example_usage \
"$ killall apache\n"
#define killall5_trivial_usage \
- "[-l] [-signal]"
+ "[-l] [-SIG] [-o PID]..."
#define killall5_full_usage "\n\n" \
"Send a signal (default is TERM) to all processes outside current session\n" \
"\nOptions:" \
"\n -l List all signal names and numbers" \
+ "\n -o PID Do not signal this PID" \
+/* "\n -s SIG Yet another way of specifying SIG" */ \
#define klogd_trivial_usage \
"[-c N] [-n]"
@@ -2071,7 +2181,7 @@
"5\n"
#define less_trivial_usage \
- "[-EMNmh~?] [FILE...]"
+ "[-EMNmh~I?] [FILE...]"
#define less_full_usage "\n\n" \
"View a file or list of files. The position within files can be\n" \
"changed, and files can be manipulated in various ways.\n" \
@@ -2080,6 +2190,7 @@
"\n -M,-m Display a status line containing the line numbers" \
"\n and percentage through the file" \
"\n -N Prefix line numbers to each line" \
+ "\n -I Ignore case in all searches" \
"\n -~ Suppress ~s displayed past the end of the file" \
#define linux32_trivial_usage NOUSAGE_STR
@@ -2115,20 +2226,23 @@
"lrwxrwxrwx 1 root root 7 Apr 12 18:39 ls -> BusyBox*\n"
#define load_policy_trivial_usage NOUSAGE_STR
-
#define load_policy_full_usage ""
#define loadfont_trivial_usage \
"< font"
#define loadfont_full_usage "\n\n" \
- "Load a console font from standard input"
+ "Load a console font from standard input" \
+/* "\n -C TTY Affect TTY instead of /dev/tty" */ \
+
#define loadfont_example_usage \
"$ loadfont < /etc/i18n/fontname\n"
#define loadkmap_trivial_usage \
"< keymap"
#define loadkmap_full_usage "\n\n" \
- "Load a binary keyboard translation table from standard input"
+ "Load a binary keyboard translation table from standard input\n" \
+/* "\n -C TTY Affect TTY instead of /dev/tty" */ \
+
#define loadkmap_example_usage \
"$ loadkmap < /etc/i18n/lang-keymap\n"
@@ -2229,21 +2343,21 @@
#define ls_full_usage "\n\n" \
"List directory contents\n" \
"\nOptions:" \
- "\n -1 List files in a single column" \
- "\n -A Do not list implied . and .." \
- "\n -a Do not hide entries starting with ." \
- "\n -C List entries by columns" \
+ "\n -1 List in a single column" \
+ "\n -A Don't list . and .." \
+ "\n -a Don't hide entries starting with ." \
+ "\n -C List by columns" \
USE_FEATURE_LS_TIMESTAMPS( \
- "\n -c With -l: show ctime") \
+ "\n -c With -l: sort by ctime") \
USE_FEATURE_LS_COLOR( \
"\n --color[={always,never,auto}] Control coloring") \
"\n -d List directory entries instead of contents" \
USE_FEATURE_LS_TIMESTAMPS( \
- "\n -e List both full date and full time") \
+ "\n -e List full date and time") \
USE_FEATURE_LS_FILETYPES( \
"\n -F Append indicator (one of */=@|) to entries") \
- "\n -i List the i-node for each file" \
- "\n -l Use a long listing format" \
+ "\n -i List inode numbers" \
+ "\n -l Long listing format" \
"\n -n List numeric UIDs and GIDs instead of names" \
USE_FEATURE_LS_FILETYPES( \
"\n -p Append indicator (one of /=@|) to entries") \
@@ -2252,31 +2366,31 @@
USE_FEATURE_LS_RECURSIVE( \
"\n -R List subdirectories recursively") \
USE_FEATURE_LS_SORTFILES( \
- "\n -r Sort the listing in reverse order") \
+ "\n -r Sort in reverse order") \
USE_FEATURE_LS_SORTFILES( \
- "\n -S Sort the listing by file size") \
+ "\n -S Sort by file size") \
"\n -s List the size of each file, in blocks" \
USE_FEATURE_AUTOWIDTH( \
- "\n -T NUM Assume Tabstop every NUM columns") \
+ "\n -T NUM Assume tabstop every NUM columns") \
USE_FEATURE_LS_TIMESTAMPS( \
- "\n -t With -l: show modification time") \
+ "\n -t With -l: sort by modification time") \
USE_FEATURE_LS_TIMESTAMPS( \
- "\n -u With -l: show access time") \
+ "\n -u With -l: sort by access time") \
USE_FEATURE_LS_SORTFILES( \
- "\n -v Sort the listing by version") \
+ "\n -v Sort by version") \
USE_FEATURE_AUTOWIDTH( \
"\n -w NUM Assume the terminal is NUM columns wide") \
- "\n -x List entries by lines instead of by columns" \
+ "\n -x List by lines" \
USE_FEATURE_LS_SORTFILES( \
- "\n -X Sort the listing by extension") \
+ "\n -X Sort by extension") \
USE_FEATURE_HUMAN_READABLE( \
- "\n -h Print sizes in human readable format (e.g., 1K 243M 2G)") \
+ "\n -h List sizes in human readable format (1K 243M 2G)") \
USE_SELINUX( \
- "\n -k Print security context") \
+ "\n -k List security context") \
USE_SELINUX( \
- "\n -K Print security context in long format") \
+ "\n -K List security context in long format") \
USE_SELINUX( \
- "\n -Z Print security context and permission") \
+ "\n -Z List security context and permission") \
#define lsattr_trivial_usage \
"[-Radlv] [files...]"
@@ -2286,7 +2400,7 @@
"\n -R Recursively list subdirectories" \
"\n -a Do not hide entries starting with ." \
"\n -d List directory entries instead of contents" \
- "\n -l Print long flag names" \
+ "\n -l List long flag names" \
"\n -v List the file's version/generation number" \
#define lsmod_trivial_usage \
@@ -2352,6 +2466,16 @@
"/dev/hda[0-15]\n"
#endif
+#define makemime_trivial_usage \
+ "[OPTION]... [FILE]..."
+#define makemime_full_usage "\n\n" \
+ "Create MIME-encoded message\n" \
+ "\nOptions:" \
+ "\n -C Charset" \
+ "\n -e Transfer encoding. Ignored. base64 is assumed" \
+ "\n" \
+ "\nOther options are silently ignored." \
+
#define man_trivial_usage \
"[OPTION]... [MANPAGE]..."
#define man_full_usage "\n\n" \
@@ -2376,9 +2500,10 @@
"Print" USE_FEATURE_MD5_SHA1_SUM_CHECK(" or check") " MD5 checksums" \
USE_FEATURE_MD5_SHA1_SUM_CHECK( "\n" \
"\nOptions:" \
- "\n -c Check MD5 sums against given list" \
+ "\n -c Check sums against given list" \
"\n -s Don't output anything, status code shows success" \
- "\n -w Warn about improperly formatted MD5 checksum lines") \
+ "\n -w Warn about improperly formatted checksum lines" \
+ )
#define md5sum_example_usage \
"$ md5sum < busybox\n" \
@@ -2390,13 +2515,55 @@
"busybox: OK\n" \
"^D\n"
+#define sha1sum_trivial_usage \
+ "[OPTION] [FILEs...]" \
+ USE_FEATURE_MD5_SHA1_SUM_CHECK("\n or: sha1sum [OPTION] -c [FILE]")
+#define sha1sum_full_usage "\n\n" \
+ "Print" USE_FEATURE_MD5_SHA1_SUM_CHECK(" or check") " SHA1 checksums." \
+ USE_FEATURE_MD5_SHA1_SUM_CHECK( "\n" \
+ "\nOptions:" \
+ "\n -c Check sums against given list" \
+ "\n -s Don't output anything, status code shows success" \
+ "\n -w Warn about improperly formatted checksum lines" \
+ )
+
+#define sha256sum_trivial_usage \
+ "[OPTION] [FILEs...]" \
+ USE_FEATURE_MD5_SHA1_SUM_CHECK("\n or: sha256sum [OPTION] -c [FILE]")
+#define sha256sum_full_usage "\n\n" \
+ "Print" USE_FEATURE_MD5_SHA1_SUM_CHECK(" or check") " SHA1 checksums." \
+ USE_FEATURE_MD5_SHA1_SUM_CHECK( "\n" \
+ "\nOptions:" \
+ "\n -c Check sums against given list" \
+ "\n -s Don't output anything, status code shows success" \
+ "\n -w Warn about improperly formatted checksum lines" \
+ )
+
+#define sha512sum_trivial_usage \
+ "[OPTION] [FILEs...]" \
+ USE_FEATURE_MD5_SHA1_SUM_CHECK("\n or: sha512sum [OPTION] -c [FILE]")
+#define sha512sum_full_usage "\n\n" \
+ "Print" USE_FEATURE_MD5_SHA1_SUM_CHECK(" or check") " SHA1 checksums." \
+ USE_FEATURE_MD5_SHA1_SUM_CHECK( "\n" \
+ "\nOptions:" \
+ "\n -c Check sums against given list" \
+ "\n -s Don't output anything, status code shows success" \
+ "\n -w Warn about improperly formatted checksum lines" \
+ )
+
#define mdev_trivial_usage \
"[-s]"
#define mdev_full_usage "\n\n" \
" -s Scan /sys and populate /dev during system boot\n" \
"\n" \
- "Called with no options (via hotplug) it uses environment variables\n" \
- "to determine which device to add/remove."
+ "It can be run by kernel as a hotplug helper. To activate it:\n" \
+ " echo /bin/mdev >/proc/sys/kernel/hotplug\n" \
+ USE_FEATURE_MDEV_CONF( \
+ "It uses /etc/mdev.conf with lines\n" \
+ "[-]DEVNAME UID:GID PERM" \
+ USE_FEATURE_MDEV_RENAME(" [>|=PATH]") \
+ USE_FEATURE_MDEV_EXEC(" [@|$|*COMMAND]") \
+ ) \
#define mdev_notes_usage "" \
USE_FEATURE_MDEV_CONFIG( \
@@ -2507,6 +2674,22 @@
"\n -l FILENAME Read bad blocks list from FILENAME" \
"\n -v Make version 2 filesystem" \
+#define mkfs_vfat_trivial_usage \
+ "[-v] [-n LABEL] FILE_OR_DEVICE [SIZE_IN_KB]"
+/* Accepted but ignored:
+ "[-c] [-C] [-I] [-l bad-block-file] [-b backup-boot-sector] "
+ "[-m boot-msg-file] [-i volume-id] "
+ "[-s sectors-per-cluster] [-S logical-sector-size] [-f number-of-FATs] "
+ "[-h hidden-sectors] [-F fat-size] [-r root-dir-entries] [-R reserved-sectors] "
+*/
+#define mkfs_vfat_full_usage "\n\n" \
+ "Make a FAT32 filesystem\n" \
+ "\nOptions:" \
+/* "\n -c Check device for bad blocks" */ \
+ "\n -v Verbose" \
+/* "\n -I Allow to use entire disk device (e.g. /dev/hda)" */ \
+ "\n -n LBL Volume label" \
+
#define mknod_trivial_usage \
"[OPTIONS] NAME TYPE MAJOR MINOR"
#define mknod_full_usage "\n\n" \
@@ -2562,19 +2745,24 @@
"[-knqrsv] MODULE [symbol=value...]"
#define modprobe_full_usage "\n\n" \
"Options:" \
+ USE_FEATURE_2_4_MODULES( \
"\n -k Make module autoclean-able" \
+ ) \
"\n -n Dry run" \
"\n -q Quiet" \
"\n -r Remove module (stacks) or do autoclean" \
"\n -s Report via syslog instead of stderr" \
"\n -v Verbose" \
+ USE_FEATURE_MODPROBE_BLACKLIST( \
+ "\n -b Apply blacklist to module names too" \
+ )
#define modprobe_notes_usage \
"modprobe can (un)load a stack of modules, passing each module options (when\n" \
"loading). modprobe uses a configuration file to determine what option(s) to\n" \
"pass each module it loads.\n" \
"\n" \
-"The configuration file is searched (in order) amongst:\n" \
+"The configuration file is searched (in this order):\n" \
"\n" \
" /etc/modprobe.conf (2.6 only)\n" \
" /etc/modules.conf\n" \
@@ -2638,45 +2826,50 @@
"$ dmesg | more\n"
#define mount_trivial_usage \
- "[flags] DEVICE NODE [-o options,more-options]"
+ "[flags] DEVICE NODE [-o OPT,OPT]"
#define mount_full_usage "\n\n" \
"Mount a filesystem. Filesystem autodetection requires /proc be mounted.\n" \
"\nOptions:" \
"\n -a Mount all filesystems in fstab" \
USE_FEATURE_MOUNT_FAKE( \
- "\n -f "USE_FEATURE_MTAB_SUPPORT("Update /etc/mtab, but ")"don't mount" \
+ USE_FEATURE_MTAB_SUPPORT( \
+ "\n -f Update /etc/mtab, but don't mount" \
+ ) \
+ SKIP_FEATURE_MTAB_SUPPORT( \
+ "\n -f Dry run" \
+ ) \
) \
USE_FEATURE_MTAB_SUPPORT( \
"\n -n Don't update /etc/mtab" \
) \
"\n -r Read-only mount" \
- "\n -t fs-type Filesystem type" \
"\n -w Read-write mount (default)" \
- "\n" \
- "-o option:\n" \
+ "\n -t FSTYPE Filesystem type" \
+ "\n -O OPT Mount only filesystems with option OPT (-a only)" \
+ "\n-o OPT:" \
USE_FEATURE_MOUNT_LOOP( \
- " loop Ignored (loop devices are autodetected)\n" \
+ "\n loop Ignored (loop devices are autodetected)" \
) \
USE_FEATURE_MOUNT_FLAGS( \
- " [a]sync Writes are asynchronous / synchronous\n" \
- " [no]atime Disable / enable updates to inode access times\n" \
- " [no]diratime Disable / enable atime updates to directories\n" \
- " [no]relatime Disable / enable atime updates relative to modification time\n" \
- " [no]dev Allow use of special device files / disallow them\n" \
- " [no]exec Allow use of executable files / disallow them\n" \
- " [no]suid Allow set-user-id-root programs / disallow them\n" \
- " [r]shared Convert [recursively] to a shared subtree\n" \
- " [r]slave Convert [recursively] to a slave subtree\n" \
- " [r]private Convert [recursively] to a private subtree\n" \
- " [un]bindable Make mount point [un]able to be bind mounted\n" \
- " bind Bind a directory to an additional location\n" \
- " move Relocate an existing mount point\n" \
+ "\n [a]sync Writes are [a]synchronous" \
+ "\n [no]atime Disable/enable updates to inode access times" \
+ "\n [no]diratime Disable/enable atime updates to directories" \
+ "\n [no]relatime Disable/enable atime updates relative to modification time" \
+ "\n [no]dev (Dis)allow use of special device files" \
+ "\n [no]exec (Dis)allow use of executable files" \
+ "\n [no]suid (Dis)allow set-user-id-root programs" \
+ "\n [r]shared Convert [recursively] to a shared subtree" \
+ "\n [r]slave Convert [recursively] to a slave subtree" \
+ "\n [r]private Convert [recursively] to a private subtree" \
+ "\n [un]bindable Make mount point [un]able to be bind mounted" \
+ "\n bind Bind a directory to an additional location" \
+ "\n move Relocate an existing mount point" \
) \
- " remount Remount a mounted filesystem, changing its flags\n" \
- " ro/rw Mount for read-only / read-write\n" \
- "\n" \
- "There are EVEN MORE flags that are specific to each filesystem\n" \
- "You'll have to see the written documentation for those filesystems" \
+ "\n remount Remount a mounted filesystem, changing its flags" \
+ "\n ro/rw Read-only/read-write mount" \
+ "\n" \
+ "\nThere are EVEN MORE flags that are specific to each filesystem" \
+ "\nYou'll have to see the written documentation for those filesystems" \
#define mount_example_usage \
"$ mount\n" \
@@ -2690,12 +2883,13 @@
"Returns 0 for success, number of failed mounts for -a, or errno for one mount."
#define mountpoint_trivial_usage \
- "[-q] <[-d] DIR | -x DEVICE>"
+ "[-q] <[-dn] DIR | -x DEVICE>"
#define mountpoint_full_usage "\n\n" \
- "mountpoint checks if the directory is a mountpoint\n" \
+ "Check if the directory is a mountpoint\n" \
"\nOptions:" \
"\n -q Quiet" \
"\n -d Print major/minor device number of the filesystem" \
+ "\n -n Print device name of the filesystem" \
"\n -x Print major/minor device number of the blockdevice" \
#define mountpoint_example_usage \
@@ -3064,6 +3258,33 @@
"\n -v Negate the matching" \
"\n -x Match whole name (not substring)" \
+#define popmaildir_trivial_usage \
+ "[OPTIONS] Maildir [connection-helper ...]"
+#define popmaildir_full_usage "\n\n" \
+ "Fetch content of remote mailbox to local maildir\n" \
+ "\nOptions:" \
+ "\n -b Binary mode. Ignored" \
+ "\n -d Debug. Ignored" \
+ "\n -m Show used memory. Ignored" \
+ "\n -V Show version. Ignored" \
+ "\n -c Use tcpclient. Ignored" \
+ "\n -a Use APOP protocol. Implied. If server supports APOP -> use it" \
+ "\n -s Skip authorization" \
+ "\n -T Get messages with TOP instead with RETR" \
+ "\n -k Keep retrieved messages on the server" \
+ "\n -t timeout Set network timeout" \
+ USE_FEATURE_POPMAILDIR_DELIVERY( \
+ "\n -F \"program arg1 arg2 ...\" Filter by program. May be multiple" \
+ "\n -M \"program arg1 arg2 ...\" Deliver by program" \
+ ) \
+ "\n -R size Remove old messages on the server >= size (in bytes). Ignored" \
+ "\n -Z N1-N2 Remove messages from N1 to N2 (dangerous). Ignored" \
+ "\n -L size Do not retrieve new messages >= size (in bytes). Ignored" \
+ "\n -H lines Type specified number of lines of a message. Ignored"
+#define popmaildir_example_usage \
+ "$ popmaildir -k ~/Maildir -- nc pop.drvv.ru 110 [ after signal is processed" \
#define rx_trivial_usage \
"FILE"
@@ -3442,31 +3687,39 @@
#define selinuxenabled_full_usage ""
#define sendmail_trivial_usage \
- "[-w timeout] [-H [user:pass@]server[:port]] [-S]\n" \
- "[-c charset] [-N type] [-i] [-s subject] [-a attach]... [-t] [-f sender] [rcpt]..."
+ "[OPTIONS] [rcpt]..."
#define sendmail_full_usage "\n\n" \
"Send an email\n" \
- "\nOptions:" \
- "\n -w timeout Network timeout" \
- "\n -H [user:pass@]server[:port] Server" \
- "\n -S Use openssl connection helper for secure servers" \
- "\n -c charset Assume charset for body and subject (utf-8)" \
- "\n -N type Request delivery notification. Type is ignored" \
- "\n -i Ignore single dots in mail body. Implied" \
- "\n -s subject Subject" \
- "\n -a file File to attach. May be multiple" \
- "\n -t Read recipients and subject from body" \
- "\n -f sender Sender" \
+ "\nStandard options:" \
+ "\n -t Read recipients from message body, add them to those on cmdline" \
+ "\n -f sender Sender. REQUIRED!" \
+ "\n -o options various options. -oi IMPLIED! others are IGNORED!" \
+ "\n" \
+ "\nBusybox specific options:" \
+ "\n -w seconds Network timeout" \
+ "\n -H 'prog args' Run connection helper" \
+ "\n Examples:" \
+ "\n -H 'exec openssl s_client -quiet -tls1 -starttls smtp" \
+ "\n -connect smtp.gmail.com:25' -ap]" \
+ "\n -H 'exec openssl s_client -quiet -tls1" \
+ "\n -connect smtp.gmail.com:465' -ap]" \
+ "\n -S server[:port] Server" \
+ "\n -au Username for AUTH LOGIN" \
+ "\n -ap Password for AUTH LOGIN" \
+ "\n -am Authentication method. Ignored. login is implied." \
+ "\n" \
+ "\nOther options are silently ignored; -oi -t is implied" \
#define seq_trivial_usage \
- "[first [increment]] last"
+ "[-w] [-s SEP] [FIRST [INC]] LAST"
#define seq_full_usage "\n\n" \
- "Print numbers from FIRST to LAST, in steps of INCREMENT.\n" \
- "FIRST, INCREMENT default to 1\n" \
- "\nArguments:" \
- "\n LAST" \
- "\n FIRST LAST" \
- "\n FIRST INCREMENT LAST" \
+ "Print numbers from FIRST to LAST, in steps of INC.\n" \
+ "FIRST, INC default to 1\n" \
+ "\nOptions:" \
+ "\n -w Pad to last with leading zeros" \
+ "\n -s SEP String separator" \
#define sestatus_trivial_usage \
"[-vb]"
@@ -3510,11 +3763,13 @@
"\n -W Display warnings about entries that had no matching files" \
#define setfont_trivial_usage \
- "[-m mapfile] font"
+ "FONT [-m MAPFILE] [-C TTY]"
#define setfont_full_usage "\n\n" \
"Load a console font\n" \
"\nOptions:" \
- "\n -m mapfile Load console screen map from mapfile"
+ "\n -m MAPFILE Load console screen map" \
+ "\n -C TTY Affect TTY instead of /dev/tty" \
+
#define setfont_example_usage \
"$ setfont -m koi8-r /etc/i18n/fontname\n"
@@ -3564,18 +3819,6 @@
"\n -f file Read from file instead of /var/log/wtmp" \
)
-#define sha1sum_trivial_usage \
- "[OPTION] [FILEs...]" \
- USE_FEATURE_MD5_SHA1_SUM_CHECK("\n or: sha1sum [OPTION] -c [FILE]")
-#define sha1sum_full_usage "\n\n" \
- "Print" USE_FEATURE_MD5_SHA1_SUM_CHECK(" or check") " SHA1 checksums." \
- USE_FEATURE_MD5_SHA1_SUM_CHECK( "\n" \
- "\nOptions:" \
- "\n -c Check SHA1 sums against given list" \
- "\n -s Don't output anything, status code shows success" \
- "\n -w Warn about improperly formatted SHA1 checksum lines" \
- )
-
#define showkey_trivial_usage \
"[-a | -k | -s]"
#define showkey_full_usage "\n\n" \
@@ -3679,7 +3922,7 @@
"Search for matching processes, and then\n" \
"-K: stop all matching processes.\n" \
"-S: start a process unless a matching process is found.\n" \
- USE_GETOPT_LONG( \
+ USE_FEATURE_START_STOP_DAEMON_LONG_OPTIONS( \
"\nProcess matching:" \
"\n -u,--user USERNAME|UID Match only this user's processes" \
"\n -n,--name NAME Match processes with NAME" \
@@ -3703,11 +3946,11 @@
"\nOther:" \
USE_FEATURE_START_STOP_DAEMON_FANCY( \
"\n -o,--oknodo Exit with status 0 if nothing is done" \
- "\n -q,--quiet Quiet" \
- ) \
"\n -v,--verbose Verbose" \
) \
- SKIP_GETOPT_LONG( \
+ "\n -q,--quiet Quiet" \
+ ) \
+ SKIP_FEATURE_START_STOP_DAEMON_LONG_OPTIONS( \
"\nProcess matching:" \
"\n -u USERNAME|UID Match only this user's processes" \
"\n -n NAME Match processes with NAME" \
@@ -3731,10 +3974,10 @@
"\nOther:" \
USE_FEATURE_START_STOP_DAEMON_FANCY( \
"\n -o Exit with status 0 if nothing is done" \
- "\n -q Quiet" \
- ) \
"\n -v Verbose" \
) \
+ "\n -q Quiet" \
+ ) \
#define stat_trivial_usage \
"[OPTION] FILE..."
@@ -4094,6 +4337,26 @@
"$ echo $?\n" \
"1\n"
+#define tc_trivial_usage \
+ /*"[OPTIONS] "*/"OBJECT CMD [dev STRING]"
+#define tc_full_usage "\n\n" \
+ "OBJECT: {qdisc|class|filter}\n" \
+ "CMD: {add|del|change|replace|show}\n" \
+ "\n" \
+ "qdisc [ handle QHANDLE ] [ root |"USE_FEATURE_TC_INGRESS(" ingress |")" parent CLASSID ]\n" \
+ /* "\t[ estimator INTERVAL TIME_CONSTANT ]\n" */ \
+ "\t[ [ QDISC_KIND ] [ help | OPTIONS ] ]\n" \
+ "\tQDISC_KIND := { [p|b]fifo | tbf | prio | cbq | red | etc. }\n" \
+ "qdisc show [ dev STRING ]"USE_FEATURE_TC_INGRESS(" [ingress]")"\n" \
+ "class [ classid CLASSID ] [ root | parent CLASSID ]\n" \
+ "\t[ [ QDISC_KIND ] [ help | OPTIONS ] ]\n" \
+ "class show [ dev STRING ] [ root | parent CLASSID ]\n" \
+ "filter [ pref PRIO ] [ protocol PROTO ]\n" \
+ /* "\t[ estimator INTERVAL TIME_CONSTANT ]\n" */ \
+ "\t[ root | classid CLASSID ] [ handle FILTERID ]\n" \
+ "\t[ [ FILTER_TYPE ] [ help | OPTIONS ] ]\n" \
+ "filter show [ dev STRING ] [ root | parent CLASSID ]"
+
#define tcpsvd_trivial_usage \
"[-hEv] [-c n] [-C n:msg] [-b n] [-u user] [-l name] ip port prog..."
/* with not-implemented options: */
@@ -4152,6 +4415,12 @@
"[-cr] [-u USER] [DIR]"
#define tftpd_full_usage "\n\n" \
"Transfer a file on tftp client's request.\n" \
+ "\n" \
+ "tftpd should be used as an inetd service.\n" \
+ "tftpd's line for inetd.conf:\n" \
+ " 69 dgram udp nowait root tftpd tftpd /files/to/serve\n" \
+ "It also can be ran from udpsvd:\n" \
+ " udpsvd -vE 0.0.0.0 69 tftpd /files/to/serve\n" \
"\nOptions:" \
"\n -r Prohibit upload" \
"\n -c Allow file creation via upload" \
@@ -4165,8 +4434,14 @@
"\nOptions:" \
"\n -v Verbose" \
+#define timeout_trivial_usage \
+ "[-t SECS] [-s SIG] PROG [ARGS]"
+#define timeout_full_usage "\n\n" \
+ "Runs PROG. Sends SIG to it if it is not gone in SECS seconds.\n" \
+ "Defaults: SECS: 10, SIG: TERM." \
+
#define top_trivial_usage \
- "[-b] [-n COUNT] [-d SECONDS]"
+ "[-b] [-nCOUNT] [-dSECONDS]"
#define top_full_usage "\n\n" \
"Provide a view of process activity in real time.\n" \
"Read the status of all processes from /proc each SECONDS\n" \
@@ -4250,6 +4525,23 @@
#define ttysize_full_usage "\n\n" \
"Print dimension(s) of standard input's terminal, on error return 80x25"
+#define tunctl_trivial_usage \
+ "[-f device] ([-t name] | -d name)" USE_FEATURE_TUNCTL_UG(" [-u owner] [-g group] [-b]")
+#define tunctl_full_usage "\n\n" \
+ "Create or delete tun interfaces" \
+ "\nOptions:" \
+ "\n -f name tun device (/dev/net/tun)" \
+ "\n -t name Create iface 'name'" \
+ "\n -d name Delete iface 'name'" \
+USE_FEATURE_TUNCTL_UG( \
+ "\n -u owner Set iface owner" \
+ "\n -g group Set iface group" \
+ "\n -b Brief output" \
+)
+#define tunctl_example_usage \
+ "# tunctl\n" \
+ "# tunctl -d tun0\n"
+
#define tune2fs_trivial_usage \
"[-c max-mounts-count] [-e errors-behavior] [-g group] " \
"[-i interval[d|m|w]] [-j] [-J journal-options] [-l] [-s sparse-flag] " \
@@ -4272,7 +4564,7 @@
"\n -C,--clientid-none Suppress default client identifier" \
"\n -p,--pidfile=file Create pidfile" \
"\n -r,--request=IP IP address to request" \
- "\n -s,--script=file Run file at DHCP events (default "CONFIG_DHCPC_DEFAULT_SCRIPT")" \
+ "\n -s,--script=file Run file at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")" \
"\n -t,--retries=N Send up to N request packets" \
"\n -T,--timeout=N Try to get a lease for N seconds (default 3)" \
"\n -A,--tryagain=N Wait N seconds (default 20) after failure" \
@@ -4301,7 +4593,7 @@
"\n -C Suppress default client identifier" \
"\n -p file Create pidfile" \
"\n -r IP IP address to request" \
- "\n -s file Run file at DHCP events (default "CONFIG_DHCPC_DEFAULT_SCRIPT")" \
+ "\n -s file Run file at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")" \
"\n -t N Send up to N request packets" \
"\n -T N Try to get a lease for N seconds (default 3)" \
"\n -A N Wait N seconds (default 20) after failure" \
@@ -4524,14 +4816,15 @@
"Mon Dec 17 10:31:44 GMT 2000"
#define watchdog_trivial_usage \
- "[-t N[ms]] [-F] DEV"
+ "[-t N[ms]] [-T N[ms]] [-F] DEV"
#define watchdog_full_usage "\n\n" \
"Periodically write to watchdog device DEV\n" \
"\nOptions:" \
- "\n -t N Timer period (default 30)" \
+ "\n -T N Reboot after N seconds if not reset (default 60)" \
+ "\n -t N Reset every N seconds (default 30)" \
"\n -F Run in foreground" \
"\n" \
- "\nUse -t 500ms to specify period in milliseconds" \
+ "\nUse 500ms to specify period in milliseconds" \
#define wc_trivial_usage \
"[OPTION]... [FILE]..."
@@ -4549,12 +4842,12 @@
" 31 46 1365 /etc/passwd\n"
#define wget_trivial_usage \
- USE_GETOPT_LONG( \
+ USE_FEATURE_WGET_LONG_OPTIONS( \
"[-c|--continue] [-s|--spider] [-q|--quiet] [-O|--output-document file]\n" \
" [--header 'header: value'] [-Y|--proxy on/off] [-P DIR]\n" \
" [-U|--user-agent agent] url" \
) \
- SKIP_GETOPT_LONG( \
+ SKIP_FEATURE_WGET_LONG_OPTIONS( \
"[-csq] [-O file] [-Y on/off] [-P DIR] [-U agent] url" \
)
#define wget_full_usage "\n\n" \
@@ -4599,7 +4892,7 @@
USE_FEATURE_XARGS_SUPPORT_ZERO_TERM( \
"\n -0 Input is separated by NUL characters") \
"\n -t Print the command on stderr before execution" \
- "\n -e[STR] STR stops input processing (default _)" \
+ "\n -e[STR] STR stops input processing" \
"\n -n N Pass no more than N args to COMMAND" \
"\n -s N Pass command line of no more than N bytes" \
USE_FEATURE_XARGS_SUPPORT_TERMOPT( \
@@ -4625,8 +4918,12 @@
"Manage a ZeroConf IPv4 link-local address\n" \
"\nOptions:" \
"\n -f Run in foreground" \
- "\n -q Quit after address (no daemon)" \
+ "\n -q Quit after obtaining address" \
"\n -r 169.254.x.x Request this address first" \
"\n -v Verbose" \
+ "\n" \
+ "\nWith no -q, runs continuously monitoring for ARP conflicts," \
+ "\nexits only on I/O errors (link down etc)" \
-#endif /* __BB_USAGE_H__ */
+
+#endif
diff --git a/release/src/router/busybox/include/volume_id.h b/release/src/router/busybox/include/volume_id.h
index 99cb11ff60..bba32c0baf 100644
--- a/release/src/router/busybox/include/volume_id.h
+++ b/release/src/router/busybox/include/volume_id.h
@@ -20,3 +20,4 @@
char *get_devname_from_label(const char *spec);
char *get_devname_from_uuid(const char *spec);
+void display_uuid_cache(void);
diff --git a/release/src/router/busybox/include/xatonum.h b/release/src/router/busybox/include/xatonum.h
index 86a3472d96..ee816efb40 100644
--- a/release/src/router/busybox/include/xatonum.h
+++ b/release/src/router/busybox/include/xatonum.h
@@ -7,9 +7,7 @@
* Licensed under GPLv2, see file LICENSE in this tarball for details.
*/
-#if __GNUC_PREREQ(4,1)
-# pragma GCC visibility push(hidden)
-#endif
+PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
/* Provides extern declarations of functions */
#define DECLARE_STR_CONV(type, T, UT) \
@@ -171,6 +169,4 @@ uint32_t bb_strtou32(const char *arg, char **endp, int base)
double bb_strtod(const char *arg, char **endp) FAST_FUNC;
-#if __GNUC_PREREQ(4,1)
-# pragma GCC visibility pop
-#endif
+POP_SAVED_FUNCTION_VISIBILITY
diff --git a/release/src/router/busybox/include/xregex.h b/release/src/router/busybox/include/xregex.h
index 90cf124eea..61658ed859 100644
--- a/release/src/router/busybox/include/xregex.h
+++ b/release/src/router/busybox/include/xregex.h
@@ -8,20 +8,16 @@
*
* Licensed under GPLv2 or later, see file License in this tarball for details.
*/
-#ifndef __BB_REGEX__
-#define __BB_REGEX__
+#ifndef BB_REGEX_H
+#define BB_REGEX_H 1
#include
-#if __GNUC_PREREQ(4,1)
-# pragma GCC visibility push(hidden)
-#endif
+PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
char* regcomp_or_errmsg(regex_t *preg, const char *regex, int cflags) FAST_FUNC;
void xregcomp(regex_t *preg, const char *regex, int cflags) FAST_FUNC;
-#if __GNUC_PREREQ(4,1)
-# pragma GCC visibility pop
-#endif
+POP_SAVED_FUNCTION_VISIBILITY
#endif
diff --git a/release/src/router/busybox/init/Config.in b/release/src/router/busybox/init/Config.in
index c26c4c5e6b..1a1be4a9b2 100644
--- a/release/src/router/busybox/init/Config.in
+++ b/release/src/router/busybox/init/Config.in
@@ -12,14 +12,6 @@ config INIT
help
init is the first program run when the system boots.
-config DEBUG_INIT
- bool "Debugging aid"
- default n
- depends on INIT
- help
- Turn this on to disable all the dangerous
- rebooting stuff when debugging.
-
config FEATURE_USE_INITTAB
bool "Support reading an inittab file"
default y
@@ -40,11 +32,12 @@ config FEATURE_KILL_DELAY
int "How long to wait between TERM and KILL (0 - send TERM only)" if FEATURE_KILL_REMOVED
range 0 1024
default 0
+ depends on FEATURE_KILL_REMOVED
help
With nonzero setting, init sends TERM, forks, child waits N
seconds, sends KILL and exits. Setting it too high is unwise
- (child will hang around for too long and can actually kill
- wrong process!)
+ (child will hang around for too long and could actually kill
+ the wrong process!)
config FEATURE_INIT_SCTTY
bool "Run commands with leading dash with controlling tty"
@@ -83,8 +76,6 @@ config FEATURE_INIT_COREDUMPS
core file sizes. If this option is disabled, processes
will not generate any core files.
-
-
config FEATURE_INITRD
bool "Support running init from within an initrd (not initramfs)"
default y
diff --git a/release/src/router/busybox/init/halt.c b/release/src/router/busybox/init/halt.c
index 8c1f30b08c..3a23ecabb5 100644
--- a/release/src/router/busybox/init/halt.c
+++ b/release/src/router/busybox/init/halt.c
@@ -13,60 +13,69 @@
#if ENABLE_FEATURE_WTMP
#include
#include
+
+static void write_wtmp(void)
+{
+ struct utmp utmp;
+ struct utsname uts;
+ if (access(bb_path_wtmp_file, R_OK|W_OK) == -1) {
+ close(creat(bb_path_wtmp_file, 0664));
+ }
+ memset(&utmp, 0, sizeof(utmp));
+ utmp.ut_tv.tv_sec = time(NULL);
+ safe_strncpy(utmp.ut_user, "shutdown", UT_NAMESIZE);
+ utmp.ut_type = RUN_LVL;
+ safe_strncpy(utmp.ut_id, "~~", sizeof(utmp.ut_id));
+ safe_strncpy(utmp.ut_line, "~~", UT_LINESIZE);
+ if (uname(&uts) == 0)
+ safe_strncpy(utmp.ut_host, uts.release, sizeof(utmp.ut_host));
+ updwtmp(bb_path_wtmp_file, &utmp);
+
+}
+#else
+#define write_wtmp() ((void)0)
+#endif
+
+#ifndef RB_HALT_SYSTEM
+#define RB_HALT_SYSTEM RB_HALT
+#endif
+
+#ifndef RB_POWER_OFF
+#define RB_POWER_OFF RB_POWERDOWN
#endif
int halt_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int halt_main(int argc UNUSED_PARAM, char **argv)
{
static const int magic[] = {
-#ifdef RB_HALT_SYSTEM
-RB_HALT_SYSTEM,
-#elif defined RB_HALT
-RB_HALT,
-#endif
-#ifdef RB_POWER_OFF
-RB_POWER_OFF,
-#elif defined RB_POWERDOWN
-RB_POWERDOWN,
-#endif
-RB_AUTOBOOT
+ RB_HALT_SYSTEM,
+ RB_POWER_OFF,
+ RB_AUTOBOOT
};
static const smallint signals[] = { SIGUSR1, SIGUSR2, SIGTERM };
int delay = 0;
int which, flags, rc;
-#if ENABLE_FEATURE_WTMP
- struct utmp utmp;
- struct utsname uts;
-#endif
/* Figure out which applet we're running */
- for (which = 0; "hpr"[which] != *applet_name; which++)
+ for (which = 0; "hpr"[which] != applet_name[0]; which++)
continue;
/* Parse and handle arguments */
opt_complementary = "d+"; /* -d N */
- flags = getopt32(argv, "d:nfw", &delay);
+ /* We support -w even if !ENABLE_FEATURE_WTMP,
+ * in order to not break scripts.
+ * -i (shut down network interfaces) is ignored.
+ */
+ flags = getopt32(argv, "d:nfwi", &delay);
sleep(delay);
-#if ENABLE_FEATURE_WTMP
- if (access(bb_path_wtmp_file, R_OK|W_OK) == -1) {
- close(creat(bb_path_wtmp_file, 0664));
- }
- memset(&utmp, 0, sizeof(utmp));
- utmp.ut_tv.tv_sec = time(NULL);
- safe_strncpy(utmp.ut_user, "shutdown", UT_NAMESIZE);
- utmp.ut_type = RUN_LVL;
- safe_strncpy(utmp.ut_id, "~~", sizeof(utmp.ut_id));
- safe_strncpy(utmp.ut_line, "~~", UT_LINESIZE);
- if (uname(&uts) == 0)
- safe_strncpy(utmp.ut_host, uts.release, sizeof(utmp.ut_host));
- updwtmp(bb_path_wtmp_file, &utmp);
-#endif /* !ENABLE_FEATURE_WTMP */
+ write_wtmp();
if (flags & 8) /* -w */
return EXIT_SUCCESS;
+
if (!(flags & 2)) /* no -n */
sync();
@@ -82,12 +91,14 @@ RB_AUTOBOOT
if (ENABLE_FEATURE_CLEAN_UP)
free(pidlist);
}
- if (rc)
+ if (rc) {
rc = kill(1, signals[which]);
- } else
+ }
+ } else {
rc = reboot(magic[which]);
+ }
if (rc)
- bb_error_msg("no");
+ bb_perror_nomsg_and_die();
return rc;
}
diff --git a/release/src/router/busybox/init/init.c b/release/src/router/busybox/init/init.c
index e02773cc0d..ce264283a1 100644
--- a/release/src/router/busybox/init/init.c
+++ b/release/src/router/busybox/init/init.c
@@ -13,37 +13,64 @@
#include
#include
#include
+#include
+#include
-#define COMMAND_SIZE 256
-#define CONSOLE_NAME_SIZE 32
-#define MAXENV 16 /* Number of env. vars */
-/*
- * 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
+/* Was a CONFIG_xxx option. A lot of people were building
+ * not fully functional init by switching it on! */
+#define DEBUG_INIT 0
-#define INITTAB "/etc/inittab" /* inittab file location */
+#define COMMAND_SIZE 256
+#define CONSOLE_NAME_SIZE 32
+
+/* Default sysinit script. */
#ifndef INIT_SCRIPT
-#define INIT_SCRIPT "/etc/init.d/rcS" /* Default sysinit script. */
+#define INIT_SCRIPT "/etc/init.d/rcS"
#endif
-/* Allowed init action types */
+/* Each type of actions can appear many times. They will be
+ * handled in order. RESTART is an exception, only 1st is used.
+ */
+/* Start these actions first and wait for completion */
#define SYSINIT 0x01
-#define RESPAWN 0x02
-/* like respawn, but wait for to be pressed on tty: */
-#define ASKFIRST 0x04
-#define WAIT 0x08
-#define ONCE 0x10
+/* Start these after SYSINIT and wait for completion */
+#define WAIT 0x02
+/* Start these after WAIT and *dont* wait for completion */
+#define ONCE 0x04
+/*
+ * NB: while SYSINIT/WAIT/ONCE are being processed,
+ * SIGHUP ("reread /etc/inittab") will be ignored.
+ * Rationale: it would be ambiguous whether SYSINIT/WAIT/ONCE
+ * need to be rerun or not.
+ */
+/* Start these after ONCE are started, restart on exit */
+#define RESPAWN 0x08
+/* Like RESPAWN, but wait for to be pressed on tty */
+#define ASKFIRST 0x10
+/*
+ * Start these on SIGINT, and wait for completion.
+ * Then go back to respawning RESPAWN and ASKFIRST actions.
+ * NB: kernel sends SIGINT to us if Ctrl-Alt-Del was pressed.
+ */
#define CTRLALTDEL 0x20
+/*
+ * Start these before killing all processes in preparation for
+ * running RESTART actions or doing low-level halt/reboot/poweroff
+ * (initiated by SIGUSR1/SIGTERM/SIGUSR2).
+ * Wait for completion before proceeding.
+ */
#define SHUTDOWN 0x40
+/*
+ * exec() on SIGQUIT. SHUTDOWN actions are started and waited for,
+ * then all processes are killed, then init exec's 1st RESTART action,
+ * replacing itself by it. If no RESTART action specified,
+ * SIGQUIT has no effect.
+ */
#define RESTART 0x80
-/* Set up a linked list of init_actions, to be read from inittab */
+
+/* A linked list of init_actions, to be read from inittab */
struct init_action {
struct init_action *next;
pid_t pid;
@@ -52,22 +79,14 @@ struct init_action {
char command[COMMAND_SIZE];
};
-/* Static variables */
static struct init_action *init_action_list = NULL;
static const char *log_console = VC_5;
-static sig_atomic_t got_cont = 0;
enum {
L_LOG = 0x1,
L_CONSOLE = 0x2,
-
-#if ENABLE_FEATURE_EXTRA_QUIET
- MAYBE_CONSOLE = 0x0,
-#else
- MAYBE_CONSOLE = L_CONSOLE,
-#endif
-
+ MAYBE_CONSOLE = L_CONSOLE * !ENABLE_FEATURE_EXTRA_QUIET,
#ifndef RB_HALT_SYSTEM
RB_HALT_SYSTEM = 0xcdef0123, /* FIXME: this overflows enum */
RB_ENABLE_CAD = 0x89abcdef,
@@ -77,68 +96,41 @@ enum {
#endif
};
-static const char *const environment[] = {
- "HOME=/",
- bb_PATH_root_path,
- "SHELL=/bin/sh",
- "USER=root",
- NULL
-};
-
-/* Function prototypes */
-static void halt_reboot_pwoff(int sig) NORETURN;
-
-static void waitfor(pid_t pid)
-{
- /* waitfor(run(x)): protect against failed fork inside run() */
- if (pid <= 0)
- return;
-
- /* Wait for any child (prevent zombies from exiting orphaned processes)
- * but exit the loop only when specified one has exited. */
- while (wait(NULL) != pid)
- continue;
-}
-
-static void loop_forever(void) NORETURN;
-static void loop_forever(void)
-{
- while (1)
- sleep(1);
-}
-
/* Print a message to the specified device.
* "where" may be bitwise-or'd from L_LOG | L_CONSOLE
* NB: careful, we can be called after vfork!
*/
-#define messageD(...) do { if (ENABLE_DEBUG_INIT) message(__VA_ARGS__); } while (0)
+#define dbg_message(...) do { if (DEBUG_INIT) message(__VA_ARGS__); } while (0)
static void message(int where, const char *fmt, ...)
__attribute__ ((format(printf, 2, 3)));
static void message(int where, const char *fmt, ...)
{
- static int log_fd = -1;
va_list arguments;
- int l;
+ unsigned l;
char msg[128];
msg[0] = '\r';
va_start(arguments, fmt);
- vsnprintf(msg + 1, sizeof(msg) - 2, fmt, arguments);
+ l = 1 + vsnprintf(msg + 1, sizeof(msg) - 2, fmt, arguments);
+ if (l > sizeof(msg) - 1)
+ l = sizeof(msg) - 1;
va_end(arguments);
- msg[sizeof(msg) - 2] = '\0';
- l = strlen(msg);
- if (ENABLE_FEATURE_INIT_SYSLOG) {
+#if ENABLE_FEATURE_INIT_SYSLOG
+ msg[l] = '\0';
+ if (where & L_LOG) {
/* Log the message to syslogd */
- if (where & L_LOG) {
- /* don't print out "\r" */
- openlog(applet_name, 0, LOG_DAEMON);
- syslog(LOG_INFO, "init: %s", msg + 1);
- closelog();
- }
- msg[l++] = '\n';
- msg[l] = '\0';
- } else {
+ openlog("init", 0, LOG_DAEMON);
+ /* don't print "\r" */
+ syslog(LOG_INFO, "%s", msg + 1);
+ closelog();
+ }
+ msg[l++] = '\n';
+ msg[l] = '\0';
+#else
+ {
+ static int log_fd = -1;
+
msg[l++] = '\n';
msg[l] = '\0';
/* Take full control of the log tty, and never close it.
@@ -162,6 +154,7 @@ static void message(int where, const char *fmt, ...)
return; /* don't print dup messages */
}
}
+#endif
if (where & L_CONSOLE) {
/* Send console messages to console so people will see them. */
@@ -169,33 +162,9 @@ static void message(int where, const char *fmt, ...)
}
}
-/* From */
-struct serial_struct {
- int type;
- int line;
- unsigned int port;
- int irq;
- int flags;
- int xmit_fifo_size;
- int custom_divisor;
- int baud_base;
- unsigned short close_delay;
- char io_type;
- char reserved_char[1];
- int hub6;
- unsigned short closing_wait; /* time to wait before closing */
- unsigned short closing_wait2; /* no longer used... */
- unsigned char *iomem_base;
- unsigned short iomem_reg_shift;
- unsigned int port_high;
- unsigned long iomap_base; /* cookie passed into ioremap */
- int reserved[1];
- /* Paranoia (imagine 64bit kernel overwriting 32bit userspace stack) */
- uint32_t bbox_reserved[16];
-};
static void console_init(void)
{
- struct serial_struct sr;
+ int vtno;
char *s;
s = getenv("CONSOLE");
@@ -208,16 +177,20 @@ static void console_init(void)
dup2(fd, STDOUT_FILENO);
xmove_fd(fd, STDERR_FILENO);
}
- messageD(L_LOG, "console='%s'", s);
+ dbg_message(L_LOG, "console='%s'", s);
} else {
/* Make sure fd 0,1,2 are not closed
* (so that they won't be used by future opens) */
bb_sanitize_stdio();
+// Users report problems
+// /* Make sure init can't be blocked by writing to stderr */
+// fcntl(STDERR_FILENO, F_SETFL, fcntl(STDERR_FILENO, F_GETFL) | O_NONBLOCK);
}
s = getenv("TERM");
- if (ioctl(STDIN_FILENO, TIOCGSERIAL, &sr) == 0) {
- /* Force the TERM setting to vt102 for serial console
+ if (ioctl(STDIN_FILENO, VT_OPENQRY, &vtno) != 0) {
+ /* Not a linux terminal, probably serial console.
+ * Force the TERM setting to vt102
* if TERM is set to linux (the default) */
if (!s || strcmp(s, "linux") == 0)
putenv((char*)"TERM=vt102");
@@ -262,34 +235,30 @@ static void set_sane_term(void)
tty.c_lflag =
ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN;
- tcsetattr(STDIN_FILENO, TCSANOW, &tty);
+ tcsetattr_stdin_TCSANOW(&tty);
}
/* Open the new terminal device.
* NB: careful, we can be called after vfork! */
-static void open_stdio_to_tty(const char* tty_name, int exit_on_failure)
+static int open_stdio_to_tty(const char* tty_name)
{
/* empty tty_name means "use init's tty", else... */
if (tty_name[0]) {
int fd;
+
close(STDIN_FILENO);
/* fd can be only < 0 or 0: */
fd = device_open(tty_name, O_RDWR);
if (fd) {
message(L_LOG | L_CONSOLE, "can't open %s: %s",
tty_name, strerror(errno));
- if (exit_on_failure)
- _exit(EXIT_FAILURE);
- if (ENABLE_DEBUG_INIT)
- _exit(2);
- /* NB: we don't reach this if we were called after vfork.
- * Thus halt_reboot_pwoff() itself need not be vfork-safe. */
- halt_reboot_pwoff(SIGUSR1); /* halt the system */
+ return 0; /* failure */
}
dup2(STDIN_FILENO, STDOUT_FILENO);
dup2(STDIN_FILENO, STDERR_FILENO);
}
set_sane_term();
+ return 1; /* success */
}
/* Wrapper around exec:
@@ -344,22 +313,19 @@ static void init_exec(const char *command)
static pid_t run(const struct init_action *a)
{
pid_t pid;
- sigset_t nmask, omask;
- /* Block sigchild while forking (why?) */
- sigemptyset(&nmask);
- sigaddset(&nmask, SIGCHLD);
- sigprocmask(SIG_BLOCK, &nmask, &omask);
+ /* Careful: don't be affected by a signal in vforked child */
+ sigprocmask_allsigs(SIG_BLOCK);
if (BB_MMU && (a->action_type & ASKFIRST))
pid = fork();
else
pid = vfork();
- sigprocmask(SIG_SETMASK, &omask, NULL);
-
if (pid < 0)
message(L_LOG | L_CONSOLE, "can't fork");
- if (pid)
- return pid;
+ if (pid) {
+ sigprocmask_allsigs(SIG_UNBLOCK);
+ return pid; /* Parent or error */
+ }
/* Child */
@@ -367,65 +333,20 @@ static pid_t run(const struct init_action *a)
bb_signals(0
+ (1 << SIGUSR1)
+ (1 << SIGUSR2)
- + (1 << SIGINT)
+ (1 << SIGTERM)
- + (1 << SIGHUP)
+ (1 << SIGQUIT)
- + (1 << SIGCONT)
- + (1 << SIGSTOP)
+ + (1 << SIGINT)
+ + (1 << SIGHUP)
+ (1 << SIGTSTP)
, SIG_DFL);
+ sigprocmask_allsigs(SIG_UNBLOCK);
- /* Create a new session and make ourself the process
- * group leader */
+ /* Create a new session and make ourself the process group leader */
setsid();
/* Open the new terminal device */
- open_stdio_to_tty(a->terminal, 1 /* - exit if open fails */);
-
-// NB: do not enable unless you change vfork to fork above
-#ifdef BUT_RUN_ACTIONS_ALREADY_DOES_WAITING
- /* If the init Action requires us to wait, then force the
- * supplied terminal to be the controlling tty. */
- if (a->action_type & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN | RESTART)) {
- /* Now fork off another process to just hang around */
- pid = fork();
- if (pid < 0) {
- message(L_LOG | L_CONSOLE, "can't fork");
- _exit(EXIT_FAILURE);
- }
-
- if (pid > 0) {
- /* Parent - wait till the child is done */
- bb_signals(0
- + (1 << SIGINT)
- + (1 << SIGTSTP)
- + (1 << SIGQUIT)
- , SIG_IGN);
- signal(SIGCHLD, SIG_DFL);
-
- waitfor(pid);
- /* See if stealing the controlling tty back is necessary */
- if (tcgetpgrp(0) != getpid())
- _exit(EXIT_SUCCESS);
-
- /* Use a temporary process to steal the controlling tty. */
- pid = fork();
- if (pid < 0) {
- message(L_LOG | L_CONSOLE, "can't fork");
- _exit(EXIT_FAILURE);
- }
- if (pid == 0) {
- setsid();
- ioctl(0, TIOCSCTTY, 1);
- _exit(EXIT_SUCCESS);
- }
- waitfor(pid);
- _exit(EXIT_SUCCESS);
- }
- /* Child - fall though to actually execute things */
- }
-#endif
+ if (!open_stdio_to_tty(a->terminal))
+ _exit(EXIT_FAILURE);
/* NB: on NOMMU we can't wait for input in child, so
* "askfirst" will work the same as "respawn". */
@@ -444,7 +365,7 @@ static pid_t run(const struct init_action *a)
* be allowed to start a shell or whatever an init script
* specifies.
*/
- messageD(L_LOG, "waiting for enter to start '%s'"
+ dbg_message(L_LOG, "waiting for enter to start '%s'"
"(pid %d, tty '%s')\n",
a->command, getpid(), a->terminal);
full_write(STDOUT_FILENO, press_enter, sizeof(press_enter) - 1);
@@ -452,9 +373,14 @@ static pid_t run(const struct init_action *a)
continue;
}
+ /*
+ * When a file named /.init_enable_core 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....
+ */
if (ENABLE_FEATURE_INIT_COREDUMPS) {
- struct stat sb;
- if (stat(CORE_ENABLE_FLAG_FILE, &sb) == 0) {
+ if (access("/.init_enable_core", F_OK) == 0) {
struct rlimit limit;
limit.rlim_cur = RLIM_INFINITY;
limit.rlim_max = RLIM_INFINITY;
@@ -473,196 +399,106 @@ static pid_t run(const struct init_action *a)
_exit(-1);
}
-static void delete_init_action(struct init_action *action)
+static struct init_action *mark_terminated(pid_t pid)
{
- struct init_action *a, *b = NULL;
-
- for (a = init_action_list; a; b = a, a = a->next) {
- if (a == action) {
- if (b == NULL) {
- init_action_list = a->next;
- } else {
- b->next = a->next;
- }
- free(a);
- break;
- }
- }
-}
+ struct init_action *a;
-/* Run all commands of a particular type */
-static void run_actions(int action_type)
-{
- struct init_action *a, *tmp;
-
- for (a = init_action_list; a; a = tmp) {
- tmp = a->next;
- if (a->action_type & action_type) {
- // Pointless: run() will error out if open of device fails.
- ///* a->terminal of "" means "init's console" */
- //if (a->terminal[0] && access(a->terminal, R_OK | W_OK)) {
- // //message(L_LOG | L_CONSOLE, "Device %s cannot be opened in RW mode", a->terminal /*, strerror(errno)*/);
- // delete_init_action(a);
- //} else
- if (a->action_type & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN | RESTART)) {
- waitfor(run(a));
- delete_init_action(a);
- } else if (a->action_type & ONCE) {
- run(a);
- delete_init_action(a);
- } else if (a->action_type & (RESPAWN | ASKFIRST)) {
- /* Only run stuff with pid==0. If they have
- * a pid, that means it is still running */
- if (a->pid == 0) {
- a->pid = run(a);
- }
+ if (pid > 0) {
+ for (a = init_action_list; a; a = a->next) {
+ if (a->pid == pid) {
+ a->pid = 0;
+ return a;
}
}
}
+ return NULL;
}
-static void init_reboot(unsigned long magic)
-{
- pid_t pid;
- /* We have to fork here, since the kernel calls do_exit(EXIT_SUCCESS) in
- * linux/kernel/sys.c, which can cause the machine to panic when
- * the init process is killed.... */
- pid = vfork();
- if (pid == 0) { /* child */
- reboot(magic);
- _exit(EXIT_SUCCESS);
- }
- waitfor(pid);
-}
-
-static void kill_all_processes(void)
-{
- /* run everything to be run at "shutdown". This is done _prior_
- * to killing everything, in case people wish to use scripts to
- * shut things down gracefully... */
- run_actions(SHUTDOWN);
-
- /* first disable all our signals */
- sigprocmask_allsigs(SIG_BLOCK);
-
- message(L_CONSOLE | L_LOG, "The system is going down NOW!");
-
- /* Allow Ctrl-Alt-Del to reboot system. */
- init_reboot(RB_ENABLE_CAD);
-
- /* Send signals to every process _except_ pid 1 */
- message(L_CONSOLE | L_LOG, "Sending SIG%s to all processes", "TERM");
- kill(-1, SIGTERM);
- sync();
- sleep(1);
-
- message(L_CONSOLE | L_LOG, "Sending SIG%s to all processes", "KILL");
- kill(-1, SIGKILL);
- sync();
- sleep(1);
-}
-
-static void halt_reboot_pwoff(int sig)
+static void waitfor(pid_t pid)
{
- const char *m = "halt";
- int rb;
-
- kill_all_processes();
+ /* waitfor(run(x)): protect against failed fork inside run() */
+ if (pid <= 0)
+ return;
- rb = RB_HALT_SYSTEM;
- if (sig == SIGTERM) {
- m = "reboot";
- rb = RB_AUTOBOOT;
- } else if (sig == SIGUSR2) {
- m = "poweroff";
- rb = RB_POWER_OFF;
+ /* Wait for any child (prevent zombies from exiting orphaned processes)
+ * but exit the loop only when specified one has exited. */
+ while (1) {
+ pid_t wpid = wait(NULL);
+ mark_terminated(wpid);
+ /* Unsafe. SIGTSTP handler might have wait'ed it already */
+ /*if (wpid == pid) break;*/
+ /* More reliable: */
+ if (kill(pid, 0))
+ break;
}
- message(L_CONSOLE | L_LOG, "Requesting system %s", m);
- /* allow time for last message to reach serial console */
- sleep(2);
- init_reboot(rb);
- loop_forever();
}
-/* Handler for QUIT - exec "restart" action,
- * else (no such action defined) do nothing */
-static void exec_restart_action(int sig UNUSED_PARAM)
+/* Run all commands of a particular type */
+static void run_actions(int action_type)
{
struct init_action *a;
for (a = init_action_list; a; a = a->next) {
- if (a->action_type & RESTART) {
- kill_all_processes();
-
- /* unblock all signals (blocked in kill_all_processes()) */
- sigprocmask_allsigs(SIG_UNBLOCK);
-
- /* Open the new terminal device */
- open_stdio_to_tty(a->terminal, 0 /* - halt if open fails */);
+ if (!(a->action_type & action_type))
+ continue;
- messageD(L_CONSOLE | L_LOG, "Trying to re-exec %s", a->command);
- init_exec(a->command);
- sleep(2);
- init_reboot(RB_HALT_SYSTEM);
- loop_forever();
+ if (a->action_type & (SYSINIT | WAIT | ONCE | CTRLALTDEL | SHUTDOWN)) {
+ pid_t pid = run(a);
+ if (a->action_type & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN))
+ waitfor(pid);
+ }
+ if (a->action_type & (RESPAWN | ASKFIRST)) {
+ /* Only run stuff with pid == 0. If pid != 0,
+ * it is already running
+ */
+ if (a->pid == 0)
+ a->pid = run(a);
}
}
}
-static void ctrlaltdel_signal(int sig UNUSED_PARAM)
-{
- run_actions(CTRLALTDEL);
-}
-
-/* The SIGSTOP & SIGTSTP handler */
-static void stop_handler(int sig UNUSED_PARAM)
-{
- int saved_errno = errno;
-
- got_cont = 0;
- while (!got_cont)
- pause();
-
- errno = saved_errno;
-}
-
-/* The SIGCONT handler */
-static void cont_handler(int sig UNUSED_PARAM)
-{
- got_cont = 1;
-}
-
static void new_init_action(uint8_t action_type, const char *command, const char *cons)
{
- struct init_action *a, *last;
-
-// Why?
-// if (strcmp(cons, bb_dev_null) == 0 && (action & ASKFIRST))
-// return;
-
- /* Append to the end of the list */
- for (a = last = init_action_list; a; a = a->next) {
- /* don't enter action if it's already in the list,
- * but do overwrite existing actions */
+ struct init_action *a, **nextp;
+
+ /* Scenario:
+ * old inittab:
+ * ::shutdown:umount -a -r
+ * ::shutdown:swapoff -a
+ * new inittab:
+ * ::shutdown:swapoff -a
+ * ::shutdown:umount -a -r
+ * On reload, we must ensure entries end up in correct order.
+ * To achieve that, if we find a matching entry, we move it
+ * to the end.
+ */
+ nextp = &init_action_list;
+ while ((a = *nextp) != NULL) {
+ /* Don't enter action if it's already in the list,
+ * This prevents losing running RESPAWNs.
+ */
if ((strcmp(a->command, command) == 0)
&& (strcmp(a->terminal, cons) == 0)
) {
- a->action_type = action_type;
- return;
+ /* Remove from list */
+ *nextp = a->next;
+ /* Find the end of the list */
+ while (*nextp != NULL)
+ nextp = &(*nextp)->next;
+ a->next = NULL;
+ break;
}
- last = a;
+ nextp = &a->next;
}
- a = xzalloc(sizeof(*a));
- if (last) {
- last->next = a;
- } else {
- init_action_list = a;
- }
+ if (!a)
+ a = xzalloc(sizeof(*a));
+ /* Append to the end of the list */
+ *nextp = a;
a->action_type = action_type;
safe_strncpy(a->command, command, sizeof(a->command));
safe_strncpy(a->terminal, cons, sizeof(a->terminal));
- messageD(L_LOG | L_CONSOLE, "command='%s' action=%d tty='%s'\n",
+ dbg_message(L_LOG | L_CONSOLE, "command='%s' action=%d tty='%s'\n",
a->command, a->action_type, a->terminal);
}
@@ -675,15 +511,14 @@ static void new_init_action(uint8_t action_type, const char *command, const char
*/
static void parse_inittab(void)
{
+#if ENABLE_FEATURE_USE_INITTAB
char *token[4];
- /* order must correspond to SYSINIT..RESTART constants */
- static const char actions[] ALIGN1 =
- "sysinit\0""respawn\0""askfirst\0""wait\0""once\0"
- "ctrlaltdel\0""shutdown\0""restart\0";
-
- parser_t *parser = config_open2(INITTAB, fopen_for_read);
- /* No inittab file -- set up some default behavior */
- if (parser == NULL) {
+ parser_t *parser = config_open2("/etc/inittab", fopen_for_read);
+
+ if (parser == NULL)
+#endif
+ {
+ /* No inittab file - set up some default behavior */
/* Reboot on Ctrl-Alt-Del */
new_init_action(CTRLALTDEL, "reboot", "");
/* Umount all filesystems on halt/reboot */
@@ -703,11 +538,17 @@ static void parse_inittab(void)
new_init_action(SYSINIT, INIT_SCRIPT, "");
return;
}
+
+#if ENABLE_FEATURE_USE_INITTAB
/* optional_tty:ignored_runlevel:action:command
* Delims are not to be collapsed and need exactly 4 tokens
*/
while (config_read(parser, token, 4, 0, "#:",
PARSE_NORMAL & ~(PARSE_TRIM | PARSE_COLLAPSE))) {
+ /* order must correspond to SYSINIT..RESTART constants */
+ static const char actions[] ALIGN1 =
+ "sysinit\0""wait\0""once\0""respawn\0""askfirst\0"
+ "ctrlaltdel\0""shutdown\0""restart\0";
int action;
char *tty = token[0];
@@ -731,93 +572,271 @@ static void parse_inittab(void)
parser->lineno);
}
config_close(parser);
+#endif
+}
+
+static void pause_and_low_level_reboot(unsigned magic) NORETURN;
+static void pause_and_low_level_reboot(unsigned magic)
+{
+ pid_t pid;
+
+ /* Allow time for last message to reach serial console, etc */
+ sleep(1);
+
+ /* We have to fork here, since the kernel calls do_exit(EXIT_SUCCESS)
+ * in linux/kernel/sys.c, which can cause the machine to panic when
+ * the init process exits... */
+ pid = vfork();
+ if (pid == 0) { /* child */
+ reboot(magic);
+ _exit(EXIT_SUCCESS);
+ }
+ while (1)
+ sleep(1);
+}
+
+static void run_shutdown_and_kill_processes(void)
+{
+ /* Run everything to be run at "shutdown". This is done _prior_
+ * to killing everything, in case people wish to use scripts to
+ * shut things down gracefully... */
+ run_actions(SHUTDOWN);
+
+ message(L_CONSOLE | L_LOG, "The system is going down NOW!");
+
+ /* Send signals to every process _except_ pid 1 */
+ kill(-1, SIGTERM);
+ message(L_CONSOLE | L_LOG, "Sent SIG%s to all processes", "TERM");
+ sync();
+ sleep(1);
+
+ kill(-1, SIGKILL);
+ message(L_CONSOLE, "Sent SIG%s to all processes", "KILL");
+ sync();
+ /*sleep(1); - callers take care about making a pause */
+}
+
+/* Signal handling by init:
+ *
+ * For process with PID==1, on entry kernel sets all signals to SIG_DFL
+ * and unmasks all signals. However, for process with PID==1,
+ * default action (SIG_DFL) on any signal is to ignore it,
+ * even for special signals SIGKILL and SIGCONT.
+ * Also, any signal can be caught or blocked.
+ * (but SIGSTOP is still handled specially, at least in 2.6.20)
+ *
+ * We install two kinds of handlers, "immediate" and "delayed".
+ *
+ * Immediate handlers execute at any time, even while, say, sysinit
+ * is running.
+ *
+ * Delayed handlers just set a flag variable. The variable is checked
+ * in the main loop and acted upon.
+ *
+ * halt/poweroff/reboot and restart have immediate handlers.
+ * They only traverse linked list of struct action's, never modify it,
+ * this should be safe to do even in signal handler. Also they
+ * never return.
+ *
+ * SIGSTOP and SIGTSTP have immediate handlers. They just wait
+ * for SIGCONT to happen.
+ *
+ * SIGHUP has a delayed handler, because modifying linked list
+ * of struct action's from a signal handler while it is manipulated
+ * by the program may be disastrous.
+ *
+ * Ctrl-Alt-Del has a delayed handler. Not a must, but allowing
+ * it to happen even somewhere inside "sysinit" would be a bit awkward.
+ *
+ * There is a tiny probability that SIGHUP and Ctrl-Alt-Del will collide
+ * and only one will be remembered and acted upon.
+ */
+
+static void halt_reboot_pwoff(int sig) NORETURN;
+static void halt_reboot_pwoff(int sig)
+{
+ const char *m;
+ unsigned rb;
+
+ run_shutdown_and_kill_processes();
+
+ m = "halt";
+ rb = RB_HALT_SYSTEM;
+ if (sig == SIGTERM) {
+ m = "reboot";
+ rb = RB_AUTOBOOT;
+ } else if (sig == SIGUSR2) {
+ m = "poweroff";
+ rb = RB_POWER_OFF;
+ }
+ message(L_CONSOLE, "Requesting system %s", m);
+ pause_and_low_level_reboot(rb);
+ /* not reached */
+}
+
+/* The SIGSTOP/SIGTSTP handler
+ * NB: inside it, all signals except SIGCONT are masked
+ * via appropriate setup in sigaction().
+ */
+static void stop_handler(int sig UNUSED_PARAM)
+{
+ smallint saved_bb_got_signal;
+ int saved_errno;
+
+ saved_bb_got_signal = bb_got_signal;
+ saved_errno = errno;
+ signal(SIGCONT, record_signo);
+
+ while (1) {
+ pid_t wpid;
+
+ if (bb_got_signal == SIGCONT)
+ break;
+ /* NB: this can accidentally wait() for a process
+ * which we waitfor() elsewhere! waitfor() must have
+ * code which is resilient against this.
+ */
+ wpid = wait_any_nohang(NULL);
+ mark_terminated(wpid);
+ sleep(1);
+ }
+
+ signal(SIGCONT, SIG_DFL);
+ errno = saved_errno;
+ bb_got_signal = saved_bb_got_signal;
+}
+
+/* Handler for QUIT - exec "restart" action,
+ * else (no such action defined) do nothing */
+static void restart_handler(int sig UNUSED_PARAM)
+{
+ struct init_action *a;
+
+ for (a = init_action_list; a; a = a->next) {
+ if (!(a->action_type & RESTART))
+ continue;
+
+ /* Starting from here, we won't return.
+ * Thus don't need to worry about preserving errno
+ * and such.
+ */
+ run_shutdown_and_kill_processes();
+
+ /* Allow Ctrl-Alt-Del to reboot the system.
+ * This is how kernel sets it up for init, we follow suit.
+ */
+ reboot(RB_ENABLE_CAD); /* misnomer */
+
+ if (open_stdio_to_tty(a->terminal)) {
+ dbg_message(L_CONSOLE, "Trying to re-exec %s", a->command);
+ /* Theoretically should be safe.
+ * But in practice, kernel bugs may leave
+ * unkillable processes, and wait() may block forever.
+ * Oh well. Hoping "new" init won't be too surprised
+ * by having children it didn't create.
+ */
+ //while (wait(NULL) > 0)
+ // continue;
+ init_exec(a->command);
+ }
+ /* Open or exec failed */
+ pause_and_low_level_reboot(RB_HALT_SYSTEM);
+ /* not reached */
+ }
}
#if ENABLE_FEATURE_USE_INITTAB
-static void reload_signal(int sig UNUSED_PARAM)
+static void reload_inittab(void)
{
- struct init_action *a, *tmp;
+ struct init_action *a, **nextp;
message(L_LOG, "reloading /etc/inittab");
- /* disable old entrys */
- for (a = init_action_list; a; a = a->next) {
+ /* Disable old entries */
+ for (a = init_action_list; a; a = a->next)
a->action_type = ONCE;
- }
+ /* Append new entries, or modify existing entries
+ * (set a->action_type) if cmd and device name
+ * match new ones. End result: only entries with
+ * a->action_type == ONCE are stale.
+ */
parse_inittab();
- if (ENABLE_FEATURE_KILL_REMOVED) {
- /* Be nice and send SIGTERM first */
- for (a = init_action_list; a; a = a->next) {
- pid_t pid = a->pid;
- if ((a->action_type & ONCE) && pid != 0) {
- kill(pid, SIGTERM);
- }
- }
-#if CONFIG_FEATURE_KILL_DELAY
+#if ENABLE_FEATURE_KILL_REMOVED
+ /* Kill stale entries */
+ /* Be nice and send SIGTERM first */
+ for (a = init_action_list; a; a = a->next)
+ if (a->action_type == ONCE && a->pid != 0)
+ kill(a->pid, SIGTERM);
+ if (CONFIG_FEATURE_KILL_DELAY) {
/* NB: parent will wait in NOMMU case */
if ((BB_MMU ? fork() : vfork()) == 0) { /* child */
sleep(CONFIG_FEATURE_KILL_DELAY);
- for (a = init_action_list; a; a = a->next) {
- pid_t pid = a->pid;
- if ((a->action_type & ONCE) && pid != 0) {
- kill(pid, SIGKILL);
- }
- }
+ for (a = init_action_list; a; a = a->next)
+ if (a->action_type == ONCE && a->pid != 0)
+ kill(a->pid, SIGKILL);
_exit(EXIT_SUCCESS);
}
-#endif
}
+#endif
- /* remove unused entrys */
- for (a = init_action_list; a; a = tmp) {
- tmp = a->next;
- if ((a->action_type & (ONCE | SYSINIT | WAIT)) && a->pid == 0) {
- delete_init_action(a);
+ /* Remove stale (ONCE) and not useful (SYSINIT,WAIT) entries */
+ nextp = &init_action_list;
+ while ((a = *nextp) != NULL) {
+ if (a->action_type & (ONCE | SYSINIT | WAIT)) {
+ *nextp = a->next;
+ free(a);
+ } else {
+ nextp = &a->next;
}
}
- run_actions(RESPAWN | ASKFIRST);
+
+ /* Not needed: */
+ /* run_actions(RESPAWN | ASKFIRST); */
+ /* - we return to main loop, which does this automagically */
}
#endif
+static int check_delayed_sigs(void)
+{
+ int sigs_seen = 0;
+
+ while (1) {
+ smallint sig = bb_got_signal;
+
+ if (!sig)
+ return sigs_seen;
+ bb_got_signal = 0;
+ sigs_seen = 1;
+#if ENABLE_FEATURE_USE_INITTAB
+ if (sig == SIGHUP)
+ reload_inittab();
+#endif
+ if (sig == SIGINT)
+ run_actions(CTRLALTDEL);
+ }
+}
+
int init_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int init_main(int argc UNUSED_PARAM, char **argv)
{
- struct init_action *a;
- pid_t wpid;
-
- die_sleep = 30 * 24*60*60; /* if xmalloc will ever die... */
+ die_sleep = 30 * 24*60*60; /* if xmalloc would ever die... */
if (argv[1] && !strcmp(argv[1], "-q")) {
return kill(1, SIGHUP);
}
- if (!ENABLE_DEBUG_INIT) {
+ if (!DEBUG_INIT) {
/* Expect to be invoked as init with PID=1 or be invoked as linuxrc */
if (getpid() != 1
&& (!ENABLE_FEATURE_INITRD || !strstr(applet_name, "linuxrc"))
) {
bb_show_usage();
}
- /* Set up sig handlers -- be sure to
- * clear all of these in run() */
- signal(SIGQUIT, exec_restart_action);
- bb_signals(0
- + (1 << SIGUSR1) /* halt */
- + (1 << SIGUSR2) /* poweroff */
- + (1 << SIGTERM) /* reboot */
- , halt_reboot_pwoff);
- signal(SIGINT, ctrlaltdel_signal);
- signal(SIGCONT, cont_handler);
- bb_signals(0
- + (1 << SIGSTOP)
- + (1 << SIGTSTP)
- , stop_handler);
-
- /* Turn off rebooting via CTL-ALT-DEL -- we get a
+ /* 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);
+ reboot(RB_DISABLE_CAD); /* misnomer */
}
/* Figure out where the default console should be */
@@ -825,15 +844,15 @@ int init_main(int argc UNUSED_PARAM, char **argv)
set_sane_term();
xchdir("/");
setsid();
- {
- const char *const *e;
- /* Make sure environs is set to something sane */
- for (e = environment; *e; e++)
- putenv((char *) *e);
- }
+
+ /* Make sure environs is set to something sane */
+ putenv((char *) "HOME=/");
+ putenv((char *) bb_PATH_root_path);
+ putenv((char *) "SHELL=/bin/sh");
+ putenv((char *) "USER=root"); /* needed? why? */
if (argv[1])
- setenv("RUNLEVEL", argv[1], 1);
+ xsetenv("RUNLEVEL", argv[1]);
/* Hello world */
message(MAYBE_CONSOLE | L_LOG, "init started: %s", bb_banner);
@@ -842,9 +861,9 @@ int init_main(int argc UNUSED_PARAM, char **argv)
if (ENABLE_SWAPONOFF) {
struct sysinfo info;
- if (!sysinfo(&info) &&
- (info.mem_unit ? : 1) * (long long)info.totalram < 1024*1024)
- {
+ if (sysinfo(&info) == 0
+ && (info.mem_unit ? : 1) * (long long)info.totalram < 1024*1024
+ ) {
message(L_CONSOLE, "Low memory, forcing swapon");
/* swapon -a requires /proc typically */
new_init_action(SYSINIT, "mount -t proc proc /proc", "");
@@ -862,11 +881,11 @@ int init_main(int argc UNUSED_PARAM, char **argv)
/* Start a shell on console */
new_init_action(RESPAWN, bb_default_login_shell, "");
} else {
- /* Not in single user mode -- see what inittab says */
+ /* Not in single user mode - see what inittab says */
/* 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
+ * actions(i.e., INIT_SCRIPT and a pair
* of "askfirst" shells */
parse_inittab();
}
@@ -885,7 +904,7 @@ int init_main(int argc UNUSED_PARAM, char **argv)
exit(EXIT_FAILURE);
}
}
-#endif /* CONFIG_SELINUX */
+#endif
/* Make the command line just say "init" - thats all, nothing else */
strncpy(argv[0], "init", strlen(argv[0]));
@@ -893,48 +912,93 @@ int init_main(int argc UNUSED_PARAM, char **argv)
while (*++argv)
memset(*argv, 0, strlen(*argv));
- /* Now run everything that needs to be run */
+ /* Set up signal handlers */
+ if (!DEBUG_INIT) {
+ struct sigaction sa;
+
+ bb_signals(0
+ + (1 << SIGUSR1) /* halt */
+ + (1 << SIGTERM) /* reboot */
+ + (1 << SIGUSR2) /* poweroff */
+ , halt_reboot_pwoff);
+ signal(SIGQUIT, restart_handler); /* re-exec another init */
+
+ /* Stop handler must allow only SIGCONT inside itself */
+ memset(&sa, 0, sizeof(sa));
+ sigfillset(&sa.sa_mask);
+ sigdelset(&sa.sa_mask, SIGCONT);
+ sa.sa_handler = stop_handler;
+ /* NB: sa_flags doesn't have SA_RESTART.
+ * It must be able to interrupt wait().
+ */
+ sigaction_set(SIGTSTP, &sa); /* pause */
+ /* Does not work as intended, at least in 2.6.20.
+ * SIGSTOP is simply ignored by init:
+ */
+ sigaction_set(SIGSTOP, &sa); /* pause */
+
+ /* SIGINT (Ctrl-Alt-Del) must interrupt wait(),
+ * setting handler without SA_RESTART flag.
+ */
+ bb_signals_recursive_norestart((1 << SIGINT), record_signo);
+ }
+ /* Now run everything that needs to be run */
/* First run the sysinit command */
run_actions(SYSINIT);
-
+ check_delayed_sigs();
/* Next run anything that wants to block */
run_actions(WAIT);
-
+ check_delayed_sigs();
/* Next run anything to be run only once */
run_actions(ONCE);
- /* Redefine SIGHUP to reread /etc/inittab */
-#if ENABLE_FEATURE_USE_INITTAB
- signal(SIGHUP, reload_signal);
-#else
- signal(SIGHUP, SIG_IGN);
-#endif
+ /* Set up "reread /etc/inittab" handler.
+ * Handler is set up without SA_RESTART, it will interrupt syscalls.
+ */
+ if (!DEBUG_INIT && ENABLE_FEATURE_USE_INITTAB)
+ bb_signals_recursive_norestart((1 << SIGHUP), record_signo);
- /* Now run the looping stuff for the rest of forever */
+ /* Now run the looping stuff for the rest of forever.
+ * NB: if delayed signal happened, avoid blocking in wait().
+ */
while (1) {
- /* run the respawn/askfirst stuff */
+ int maybe_WNOHANG;
+
+ maybe_WNOHANG = check_delayed_sigs();
+
+ /* (Re)run the respawn/askfirst stuff */
run_actions(RESPAWN | ASKFIRST);
+ maybe_WNOHANG |= check_delayed_sigs();
- /* Don't consume all CPU time -- sleep a bit */
+ /* Don't consume all CPU time - sleep a bit */
sleep(1);
+ maybe_WNOHANG |= check_delayed_sigs();
- /* Wait for any child process to exit */
- wpid = wait(NULL);
- while (wpid > 0) {
- /* Find out who died and clean up their corpse */
- for (a = init_action_list; a; a = a->next) {
- if (a->pid == wpid) {
- /* Set the pid to 0 so that the process gets
- * restarted by run_actions() */
- a->pid = 0;
- message(L_LOG, "process '%s' (pid %d) exited. "
- "Scheduling for restart.",
- a->command, wpid);
- }
+ /* Wait for any child process(es) to exit.
+ * NB: "delayed" signals will also interrupt this wait(),
+ * bb_signals_recursive_norestart() set them up for that.
+ * This guarantees we won't be stuck here
+ * till next orphan dies.
+ */
+ if (maybe_WNOHANG)
+ maybe_WNOHANG = WNOHANG;
+ while (1) {
+ pid_t wpid;
+ struct init_action *a;
+
+ wpid = waitpid(-1, NULL, maybe_WNOHANG);
+ if (wpid <= 0)
+ break;
+
+ a = mark_terminated(wpid);
+ if (a) {
+ message(L_LOG, "process '%s' (pid %d) exited. "
+ "Scheduling for restart.",
+ a->command, wpid);
}
- /* see if anyone else is waiting to be reaped */
- wpid = wait_any_nohang(NULL);
+ /* See if anyone else is waiting to be reaped */
+ maybe_WNOHANG = WNOHANG;
}
- }
+ } /* while (1) */
}
diff --git a/release/src/router/busybox/init/mesg.c b/release/src/router/busybox/init/mesg.c
index cfb517f60a..ca230f3639 100644
--- a/release/src/router/busybox/init/mesg.c
+++ b/release/src/router/busybox/init/mesg.c
@@ -25,7 +25,7 @@ int mesg_main(int argc, char **argv)
if (--argc == 0
|| (argc == 1 && ((c = **++argv) == 'y' || c == 'n'))
) {
- tty = ttyname(STDERR_FILENO);
+ tty = xmalloc_ttyname(STDERR_FILENO);
if (tty == NULL) {
tty = "ttyname";
} else if (stat(tty, &sb) == 0) {
diff --git a/release/src/router/busybox/libbb/Kbuild b/release/src/router/busybox/libbb/Kbuild
index 7262006753..8fddabdba0 100644
--- a/release/src/router/busybox/libbb/Kbuild
+++ b/release/src/router/busybox/libbb/Kbuild
@@ -58,6 +58,8 @@ lib-y += make_directory.o
lib-y += makedev.o
lib-y += match_fstype.o
lib-y += md5.o
+# Alternative (disabled) implementation
+#lib-y += md5prime.o
lib-y += messages.o
lib-y += mode_string.o
lib-y += mtab_file.o
@@ -75,6 +77,7 @@ lib-y += process_escape_sequence.o
lib-y += procps.o
lib-y += ptr_to_globals.o
lib-y += read.o
+lib-y += read_key.o
lib-y += recursive_action.o
lib-y += remove_file.o
lib-y += restricted_shell.o
@@ -117,9 +120,13 @@ lib-y += xrealloc_vector.o
lib-$(CONFIG_FEATURE_MOUNT_LOOP) += loop.o
lib-$(CONFIG_LOSETUP) += loop.o
lib-$(CONFIG_FEATURE_MTAB_SUPPORT) += mtab.o
-lib-$(CONFIG_PASSWD) += pw_encrypt.o crypt_make_salt.o update_passwd.o
-lib-$(CONFIG_CHPASSWD) += pw_encrypt.o crypt_make_salt.o update_passwd.o
-lib-$(CONFIG_CRYPTPW) += pw_encrypt.o crypt_make_salt.o
+lib-$(CONFIG_ADDGROUP) += update_passwd.o
+lib-$(CONFIG_ADDUSER) += update_passwd.o
+lib-$(CONFIG_DELGROUP) += update_passwd.o
+lib-$(CONFIG_DELUSER) += update_passwd.o
+lib-$(CONFIG_PASSWD) += pw_encrypt.o update_passwd.o
+lib-$(CONFIG_CHPASSWD) += pw_encrypt.o update_passwd.o
+lib-$(CONFIG_CRYPTPW) += pw_encrypt.o
lib-$(CONFIG_SULOGIN) += pw_encrypt.o
lib-$(CONFIG_FEATURE_HTTPD_AUTH_MD5) += pw_encrypt.o
lib-$(CONFIG_VLOCK) += pw_encrypt.o correct_password.o
diff --git a/release/src/router/busybox/libbb/appletlib.c b/release/src/router/busybox/libbb/appletlib.c
index 2bab0eba61..80380ae08b 100644
--- a/release/src/router/busybox/libbb/appletlib.c
+++ b/release/src/router/busybox/libbb/appletlib.c
@@ -99,7 +99,7 @@ static const char *unpack_usage_messages(void)
static void full_write2_str(const char *str)
{
- full_write(STDERR_FILENO, str, strlen(str));
+ xwrite_str(STDERR_FILENO, str);
}
void FAST_FUNC bb_show_usage(void)
@@ -111,9 +111,9 @@ void FAST_FUNC bb_show_usage(void)
const char *usage_string = p = unpack_usage_messages();
if (*p == '\b') {
- full_write2_str("\nNo help available.\n\n");
+ full_write2_str("No help available.\n\n");
} else {
- full_write2_str("\nUsage: "SINGLE_APPLET_STR" ");
+ full_write2_str("Usage: "SINGLE_APPLET_STR" ");
full_write2_str(p);
full_write2_str("\n\n");
}
diff --git a/release/src/router/busybox/libbb/bb_askpass.c b/release/src/router/busybox/libbb/bb_askpass.c
index fba82a07bf..c0dcf0c5ff 100644
--- a/release/src/router/busybox/libbb/bb_askpass.c
+++ b/release/src/router/busybox/libbb/bb_askpass.c
@@ -8,8 +8,6 @@
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
-#include
-
#include "libbb.h"
/* do nothing signal handler */
@@ -17,7 +15,11 @@ static void askpass_timeout(int UNUSED_PARAM ignore)
{
}
-char* FAST_FUNC bb_askpass(int timeout, const char *prompt)
+char* FAST_FUNC bb_ask_stdin(const char *prompt)
+{
+ return bb_ask(STDIN_FILENO, 0, prompt);
+}
+char* FAST_FUNC bb_ask(const int fd, int timeout, const char *prompt)
{
/* Was static char[BIGNUM] */
enum { sizeof_passwd = 128 };
@@ -32,12 +34,12 @@ char* FAST_FUNC bb_askpass(int timeout, const char *prompt)
passwd = xmalloc(sizeof_passwd);
memset(passwd, 0, sizeof_passwd);
- tcgetattr(STDIN_FILENO, &oldtio);
- tcflush(STDIN_FILENO, TCIFLUSH);
+ tcgetattr(fd, &oldtio);
+ tcflush(fd, TCIFLUSH);
tio = oldtio;
tio.c_iflag &= ~(IUCLC|IXON|IXOFF|IXANY);
tio.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|TOSTOP);
- tcsetattr(STDIN_FILENO, TCSANOW, &tio);
+ tcsetattr_stdin_TCSANOW(&tio);
memset(&sa, 0, sizeof(sa));
/* sa.sa_flags = 0; - no SA_RESTART! */
@@ -54,7 +56,7 @@ char* FAST_FUNC bb_askpass(int timeout, const char *prompt)
ret = NULL;
/* On timeout or Ctrl-C, read will hopefully be interrupted,
* and we return NULL */
- if (read(STDIN_FILENO, passwd, sizeof_passwd - 1) > 0) {
+ if (read(fd, passwd, sizeof_passwd - 1) > 0) {
ret = passwd;
i = 0;
/* Last byte is guaranteed to be 0
@@ -70,7 +72,7 @@ char* FAST_FUNC bb_askpass(int timeout, const char *prompt)
}
sigaction_set(SIGINT, &oldsa);
- tcsetattr(STDIN_FILENO, TCSANOW, &oldtio);
+ tcsetattr_stdin_TCSANOW(&oldtio);
bb_putchar('\n');
fflush(stdout);
return ret;
diff --git a/release/src/router/busybox/libbb/bb_pwd.c b/release/src/router/busybox/libbb/bb_pwd.c
dissimilarity index 73%
index 65eb69200a..d728577714 100644
--- a/release/src/router/busybox/libbb/bb_pwd.c
+++ b/release/src/router/busybox/libbb/bb_pwd.c
@@ -1,99 +1,112 @@
-/* vi: set sw=4 ts=4: */
-/*
- * password utility routines.
- *
- * Copyright (C) 1999-2004 by Erik Andersen
- *
- * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
- */
-
-#include "libbb.h"
-
-#define assert(x) ((void)0)
-
-/* internal function for bb_getpwuid and bb_getgrgid */
-/* Hacked by Tito Ragusa (c) 2004 to make it more
- * flexible:
- *
- * bufsize > 0: If idname is not NULL it is copied to buffer,
- * and buffer is returned. Else id as string is written
- * to buffer, and NULL is returned.
- *
- * bufsize == 0: idname is returned.
- *
- * bufsize < 0: If idname is not NULL it is returned.
- * Else an error message is printed and the program exits.
- */
-static char* bb_getug(char *buffer, int bufsize, char *idname, long id, char prefix)
-{
- if (bufsize > 0) {
- assert(buffer != NULL);
- if (idname) {
- return safe_strncpy(buffer, idname, bufsize);
- }
- snprintf(buffer, bufsize, "%ld", id);
- } else if (bufsize < 0 && !idname) {
- bb_error_msg_and_die("unknown %cid %ld", prefix, id);
- }
- return idname;
-}
-
-/* bb_getpwuid, bb_getgrgid:
- * bb_getXXXid(buf, bufsz, id) - copy user/group name or id
- * as a string to buf, return user/group name or NULL
- * bb_getXXXid(NULL, 0, id) - return user/group name or NULL
- * bb_getXXXid(NULL, -1, id) - return user/group name or exit
- */
-/* gets a username given a uid */
-char* FAST_FUNC bb_getpwuid(char *name, int bufsize, long uid)
-{
- struct passwd *myuser = getpwuid(uid);
-
- return bb_getug(name, bufsize,
- (myuser ? myuser->pw_name : (char*)myuser),
- uid, 'u');
-}
-/* gets a groupname given a gid */
-char* FAST_FUNC bb_getgrgid(char *group, int bufsize, long gid)
-{
- struct group *mygroup = getgrgid(gid);
-
- return bb_getug(group, bufsize,
- (mygroup ? mygroup->gr_name : (char*)mygroup),
- gid, 'g');
-}
-
-/* returns a gid given a group name */
-long FAST_FUNC xgroup2gid(const char *name)
-{
- struct group *mygroup;
-
- mygroup = getgrnam(name);
- if (mygroup == NULL)
- bb_error_msg_and_die("unknown group name: %s", name);
-
- return mygroup->gr_gid;
-}
-
-/* returns a uid given a username */
-long FAST_FUNC xuname2uid(const char *name)
-{
- struct passwd *myuser;
-
- myuser = getpwnam(name);
- if (myuser == NULL)
- bb_error_msg_and_die("unknown user %s", name);
-
- return myuser->pw_uid;
-}
-
-unsigned long FAST_FUNC get_ug_id(const char *s,
- long FAST_FUNC (*xname2id)(const char *))
-{
- unsigned long r;
-
- r = bb_strtoul(s, NULL, 10);
- if (errno)
- return xname2id(s);
- return r;
-}
+/* vi: set sw=4 ts=4: */
+/*
+ * password utility routines.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen
+ * Copyright (C) 2008 by Tito Ragusa
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+#include "libbb.h"
+
+/* TODO: maybe change API to return malloced data?
+ * This will allow to stop using libc functions returning
+ * pointers to static data (getpwuid)
+ */
+
+struct passwd* FAST_FUNC xgetpwnam(const char *name)
+{
+ struct passwd *pw = getpwnam(name);
+ if (!pw)
+ bb_error_msg_and_die("unknown user %s", name);
+ return pw;
+}
+
+struct group* FAST_FUNC xgetgrnam(const char *name)
+{
+ struct group *gr = getgrnam(name);
+ if (!gr)
+ bb_error_msg_and_die("unknown group %s", name);
+ return gr;
+}
+
+
+struct passwd* FAST_FUNC xgetpwuid(uid_t uid)
+{
+ struct passwd *pw = getpwuid(uid);
+ if (!pw)
+ bb_error_msg_and_die("unknown uid %u", (unsigned)uid);
+ return pw;
+}
+
+struct group* FAST_FUNC xgetgrgid(gid_t gid)
+{
+ struct group *gr = getgrgid(gid);
+ if (!gr)
+ bb_error_msg_and_die("unknown gid %u", (unsigned)gid);
+ return gr;
+}
+
+char* FAST_FUNC xuid2uname(uid_t uid)
+{
+ struct passwd *pw = xgetpwuid(uid);
+ return pw->pw_name;
+}
+
+char* FAST_FUNC xgid2group(gid_t gid)
+{
+ struct group *gr = xgetgrgid(gid);
+ return gr->gr_name;
+}
+
+char* FAST_FUNC uid2uname(uid_t uid)
+{
+ struct passwd *pw = getpwuid(uid);
+ return (pw) ? pw->pw_name : NULL;
+}
+
+char* FAST_FUNC gid2group(gid_t gid)
+{
+ struct group *gr = getgrgid(gid);
+ return (gr) ? gr->gr_name : NULL;
+}
+
+char* FAST_FUNC uid2uname_utoa(long uid)
+{
+ char *name = uid2uname(uid);
+ return (name) ? name : utoa(uid);
+}
+
+char* FAST_FUNC gid2group_utoa(long gid)
+{
+ char *name = gid2group(gid);
+ return (name) ? name : utoa(gid);
+}
+
+long FAST_FUNC xuname2uid(const char *name)
+{
+ struct passwd *myuser;
+
+ myuser = xgetpwnam(name);
+ return myuser->pw_uid;
+}
+
+long FAST_FUNC xgroup2gid(const char *name)
+{
+ struct group *mygroup;
+
+ mygroup = xgetgrnam(name);
+ return mygroup->gr_gid;
+}
+
+unsigned long FAST_FUNC get_ug_id(const char *s,
+ long FAST_FUNC (*xname2id)(const char *))
+{
+ unsigned long r;
+
+ r = bb_strtoul(s, NULL, 10);
+ if (errno)
+ return xname2id(s);
+ return r;
+}
diff --git a/release/src/router/busybox/libbb/bb_strtod.c b/release/src/router/busybox/libbb/bb_strtod.c
index 0515ff8678..39bdeb5e54 100644
--- a/release/src/router/busybox/libbb/bb_strtod.c
+++ b/release/src/router/busybox/libbb/bb_strtod.c
@@ -17,7 +17,8 @@ double FAST_FUNC bb_strtod(const char *arg, char **endp)
double v;
char *endptr;
- if (arg[0] != '-' && NOT_DIGIT(arg[0]))
+ /* Allow .NN form. People want to use "sleep .15" etc */
+ if (arg[0] != '-' && arg[0] != '.' && NOT_DIGIT(arg[0]))
goto err;
errno = 0;
v = strtod(arg, &endptr);
diff --git a/release/src/router/busybox/libbb/correct_password.c b/release/src/router/busybox/libbb/correct_password.c
index 255b048706..6301589e6a 100644
--- a/release/src/router/busybox/libbb/correct_password.c
+++ b/release/src/router/busybox/libbb/correct_password.c
@@ -68,7 +68,7 @@ int FAST_FUNC correct_password(const struct passwd *pw)
return 1;
fake_it:
- unencrypted = bb_askpass(0, "Password: ");
+ unencrypted = bb_ask_stdin("Password: ");
if (!unencrypted) {
return 0;
}
diff --git a/release/src/router/busybox/libbb/crc32.c b/release/src/router/busybox/libbb/crc32.c
index 42079b9c59..36ac860425 100644
--- a/release/src/router/busybox/libbb/crc32.c
+++ b/release/src/router/busybox/libbb/crc32.c
@@ -12,6 +12,8 @@
*
* endian = 1: big-endian
* endian = 0: little-endian
+ *
+ * Licensed under GPLv2, see file LICENSE in this tarball for details.
*/
#include "libbb.h"
diff --git a/release/src/router/busybox/libbb/create_icmp6_socket.c b/release/src/router/busybox/libbb/create_icmp6_socket.c
index 20655170e4..91e478ec83 100644
--- a/release/src/router/busybox/libbb/create_icmp6_socket.c
+++ b/release/src/router/busybox/libbb/create_icmp6_socket.c
@@ -4,6 +4,8 @@
*
* create raw socket for icmp (IPv6 version) protocol
* and drop root privileges if running setuid
+ *
+ * Licensed under GPLv2, see file LICENSE in this tarball for details.
*/
#include "libbb.h"
diff --git a/release/src/router/busybox/libbb/create_icmp_socket.c b/release/src/router/busybox/libbb/create_icmp_socket.c
index 1fa016ab87..d75f8452d1 100644
--- a/release/src/router/busybox/libbb/create_icmp_socket.c
+++ b/release/src/router/busybox/libbb/create_icmp_socket.c
@@ -4,6 +4,8 @@
*
* create raw socket for icmp protocol
* and drop root privileges if running setuid
+ *
+ * Licensed under GPLv2, see file LICENSE in this tarball for details.
*/
#include "libbb.h"
diff --git a/release/src/router/busybox/libbb/crypt_make_salt.c b/release/src/router/busybox/libbb/crypt_make_salt.c
deleted file mode 100644
index 393eba5f9b..0000000000
--- a/release/src/router/busybox/libbb/crypt_make_salt.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * crypt_make_salt
- *
- * i64c was also put here, this is the only function that uses it.
- *
- * Lifted from loginutils/passwd.c by Thomas Lundquist
- *
- */
-
-#include "libbb.h"
-
-static int i64c(int i)
-{
- i &= 0x3f;
- if (i == 0)
- return '.';
- if (i == 1)
- return '/';
- if (i < 12)
- return ('0' - 2 + i);
- if (i < 38)
- return ('A' - 12 + i);
- return ('a' - 38 + i);
-}
-
-int FAST_FUNC crypt_make_salt(char *p, int cnt, int x)
-{
- x += getpid() + time(NULL);
- do {
- /* x = (x*1664525 + 1013904223) % 2^32 generator is lame
- * (low-order bit is not "random", etc...),
- * but for our purposes it is good enough */
- x = x*1664525 + 1013904223;
- /* BTW, Park and Miller's "minimal standard generator" is
- * x = x*16807 % ((2^31)-1)
- * It has no problem with visibly alternating lowest bit
- * but is also weak in cryptographic sense + needs div,
- * which needs more code (and slower) on many CPUs */
- *p++ = i64c(x >> 16);
- *p++ = i64c(x >> 22);
- } while (--cnt);
- *p = '\0';
- return x;
-}
diff --git a/release/src/router/busybox/libbb/die_if_bad_username.c b/release/src/router/busybox/libbb/die_if_bad_username.c
index 602aadc0cf..c1641d376a 100644
--- a/release/src/router/busybox/libbb/die_if_bad_username.c
+++ b/release/src/router/busybox/libbb/die_if_bad_username.c
@@ -1,6 +1,6 @@
/* vi: set sw=4 ts=4: */
/*
- * Ckeck user and group names for illegal characters
+ * Check user and group names for illegal characters
*
* Copyright (C) 2008 Tito Ragusa
*
diff --git a/release/src/router/busybox/libbb/dump.c b/release/src/router/busybox/libbb/dump.c
index 74c5e16917..2e777c358b 100644
--- a/release/src/router/busybox/libbb/dump.c
+++ b/release/src/router/busybox/libbb/dump.c
@@ -298,7 +298,7 @@ static void rewrite(priv_dumper_t *dumper, FS *fs)
* if, rep count is greater than 1, no trailing whitespace
* gets output from the last iteration of the format unit.
*/
- for (fu = fs->nextfu;; fu = fu->nextfu) {
+ for (fu = fs->nextfu; fu; fu = fu->nextfu) {
if (!fu->nextfu && fs->bcnt < dumper->blocksize
&& !(fu->flags & F_SETREP) && fu->bcnt
) {
@@ -579,11 +579,11 @@ static void display(priv_dumper_t* dumper)
switch (pr->bcnt) {
case 4:
- memmove(&fval, bp, sizeof(fval));
+ memcpy(&fval, bp, sizeof(fval));
printf(pr->fmt, fval);
break;
case 8:
- memmove(&dval, bp, sizeof(dval));
+ memcpy(&dval, bp, sizeof(dval));
printf(pr->fmt, dval);
break;
}
@@ -598,11 +598,11 @@ static void display(priv_dumper_t* dumper)
printf(pr->fmt, (int) *bp);
break;
case 2:
- memmove(&sval, bp, sizeof(sval));
+ memcpy(&sval, bp, sizeof(sval));
printf(pr->fmt, (int) sval);
break;
case 4:
- memmove(&ival, bp, sizeof(ival));
+ memcpy(&ival, bp, sizeof(ival));
printf(pr->fmt, ival);
break;
}
@@ -629,11 +629,11 @@ static void display(priv_dumper_t* dumper)
printf(pr->fmt, (unsigned) *bp);
break;
case 2:
- memmove(&sval, bp, sizeof(sval));
+ memcpy(&sval, bp, sizeof(sval));
printf(pr->fmt, (unsigned) sval);
break;
case 4:
- memmove(&ival, bp, sizeof(ival));
+ memcpy(&ival, bp, sizeof(ival));
printf(pr->fmt, ival);
break;
}
@@ -723,7 +723,8 @@ void FAST_FUNC bb_dump_add(dumper_t* pub_dumper, const char *fmt)
nextfupp = &tfs->nextfu;
/* take the format string and break it up into format units */
- for (p = fmt;;) {
+ p = fmt;
+ for (;;) {
p = skip_whitespace(p);
if (!*p) {
break;
diff --git a/release/src/router/busybox/libbb/fgets_str.c b/release/src/router/busybox/libbb/fgets_str.c
index 8026a15da5..3fe61cdc39 100644
--- a/release/src/router/busybox/libbb/fgets_str.c
+++ b/release/src/router/busybox/libbb/fgets_str.c
@@ -10,7 +10,7 @@
#include "libbb.h"
-static char *xmalloc_fgets_internal(FILE *file, const char *terminating_string, int chop_off)
+static char *xmalloc_fgets_internal(FILE *file, const char *terminating_string, int chop_off, size_t *maxsz_p)
{
char *linebuf = NULL;
const int term_length = strlen(terminating_string);
@@ -18,6 +18,7 @@ static char *xmalloc_fgets_internal(FILE *file, const char *terminating_string,
int linebufsz = 0;
int idx = 0;
int ch;
+ size_t maxsz = *maxsz_p;
while (1) {
ch = fgetc(file);
@@ -30,6 +31,11 @@ static char *xmalloc_fgets_internal(FILE *file, const char *terminating_string,
if (idx >= linebufsz) {
linebufsz += 200;
linebuf = xrealloc(linebuf, linebufsz);
+ if (idx >= maxsz) {
+ linebuf[idx] = ch;
+ idx++;
+ break;
+ }
}
linebuf[idx] = ch;
@@ -48,6 +54,7 @@ static char *xmalloc_fgets_internal(FILE *file, const char *terminating_string,
/* Grow/shrink *first*, then store NUL */
linebuf = xrealloc(linebuf, idx + 1);
linebuf[idx] = '\0';
+ *maxsz_p = idx;
return linebuf;
}
@@ -57,10 +64,23 @@ static char *xmalloc_fgets_internal(FILE *file, const char *terminating_string,
* Return NULL if EOF is reached immediately. */
char* FAST_FUNC xmalloc_fgets_str(FILE *file, const char *terminating_string)
{
- return xmalloc_fgets_internal(file, terminating_string, 0);
+ size_t maxsz = INT_MAX - 4095;
+ return xmalloc_fgets_internal(file, terminating_string, 0, &maxsz);
+}
+
+char* FAST_FUNC xmalloc_fgets_str_len(FILE *file, const char *terminating_string, size_t *maxsz_p)
+{
+ size_t maxsz;
+
+ if (!maxsz_p) {
+ maxsz = INT_MAX - 4095;
+ maxsz_p = &maxsz;
+ }
+ return xmalloc_fgets_internal(file, terminating_string, 0, maxsz_p);
}
char* FAST_FUNC xmalloc_fgetline_str(FILE *file, const char *terminating_string)
{
- return xmalloc_fgets_internal(file, terminating_string, 1);
+ size_t maxsz = INT_MAX - 4095;
+ return xmalloc_fgets_internal(file, terminating_string, 1, &maxsz);
}
diff --git a/release/src/router/busybox/libbb/find_pid_by_name.c b/release/src/router/busybox/libbb/find_pid_by_name.c
index 2ee423cb7b..600d4e1a89 100644
--- a/release/src/router/busybox/libbb/find_pid_by_name.c
+++ b/release/src/router/busybox/libbb/find_pid_by_name.c
@@ -67,15 +67,14 @@ static int comm_match(procps_status_t *p, const char *procName)
return 1;
}
-/* find_pid_by_name()
+/* This finds the pid of the specified process.
+ * Currently, it's implemented by rummaging through
+ * the proc filesystem.
*
- * Modified by Vladimir Oleynik for use with libbb/procps.c
- * This finds the pid of the specified process.
- * Currently, it's implemented by rummaging through
- * the proc filesystem.
+ * Returns a list of all matching PIDs
+ * It is the caller's duty to free the returned pidlist.
*
- * Returns a list of all matching PIDs
- * It is the caller's duty to free the returned pidlist.
+ * Modified by Vladimir Oleynik for use with libbb/procps.c
*/
pid_t* FAST_FUNC find_pid_by_name(const char *procName)
{
@@ -88,7 +87,7 @@ pid_t* FAST_FUNC find_pid_by_name(const char *procName)
if (comm_match(p, procName)
/* or we require argv0 to match (essential for matching reexeced /proc/self/exe)*/
|| (p->argv0 && strcmp(bb_basename(p->argv0), procName) == 0)
- /* TOOD: we can also try /proc/NUM/exe link, do we want that? */
+ /* TODO: we can also try /proc/NUM/exe link, do we want that? */
) {
pidList = xrealloc_vector(pidList, 2, i);
pidList[i++] = p->pid;
diff --git a/release/src/router/busybox/libbb/get_console.c b/release/src/router/busybox/libbb/get_console.c
index ad56e740f7..74022b5437 100644
--- a/release/src/router/busybox/libbb/get_console.c
+++ b/release/src/router/busybox/libbb/get_console.c
@@ -13,7 +13,6 @@
/* From */
enum { KDGKBTYPE = 0x4B33 }; /* get keyboard type */
-
static int open_a_console(const char *fnam)
{
int fd;
@@ -37,7 +36,6 @@ static int open_a_console(const char *fnam)
* We try several things because opening /dev/console will fail
* if someone else used X (which does a chown on /dev/console).
*/
-
int FAST_FUNC get_console_fd_or_die(void)
{
static const char *const console_names[] = {
diff --git a/release/src/router/busybox/libbb/getopt32.c b/release/src/router/busybox/libbb/getopt32.c
index f33ead1c6e..5190fa61a9 100644
--- a/release/src/router/busybox/libbb/getopt32.c
+++ b/release/src/router/busybox/libbb/getopt32.c
@@ -155,9 +155,9 @@ Special characters:
Allows any arguments to be given without a dash (./program w x)
as well as with a dash (./program -x).
- NB: getopt32() will leak a small amount of memory if you use
- this option! Do not use it if there is a possibility of recursive
- getopt32() calls.
+ NB: getopt32() will leak a small amount of memory if you use
+ this option! Do not use it if there is a possibility of recursive
+ getopt32() calls.
"--" A double dash at the beginning of opt_complementary means the
argv[1] string should always be treated as options, even if it isn't
@@ -165,9 +165,9 @@ Special characters:
such as "ar" and "tar":
tar xvf foo.tar
- NB: getopt32() will leak a small amount of memory if you use
- this option! Do not use it if there is a possibility of recursive
- getopt32() calls.
+ NB: getopt32() will leak a small amount of memory if you use
+ this option! Do not use it if there is a possibility of recursive
+ getopt32() calls.
"-N" A dash as the first char in a opt_complementary group followed
by a single digit (0-9) means that at least N non-option
@@ -510,7 +510,7 @@ getopt32(char **argv, const char *applet_opts, ...)
*pargv = pp;
}
if (!(spec_flgs & ALL_ARGV_IS_OPTS))
- break;
+ break;
pargv++;
}
}
diff --git a/release/src/router/busybox/libbb/human_readable.c b/release/src/router/busybox/libbb/human_readable.c
index dad26edcff..05e7d86ec7 100644
--- a/release/src/router/busybox/libbb/human_readable.c
+++ b/release/src/router/busybox/libbb/human_readable.c
@@ -24,6 +24,8 @@
*
* Some code to omit the decimal point and tenths digit is sketched out
* and "#if 0"'d below.
+ *
+ * Licensed under GPLv2, see file LICENSE in this tarball for details.
*/
#include "libbb.h"
@@ -32,7 +34,9 @@ const char* FAST_FUNC make_human_readable_str(unsigned long long size,
unsigned long block_size, unsigned long display_unit)
{
/* The code will adjust for additional (appended) units */
- static const char zero_and_units[] ALIGN1 = { '0', 0, 'k', 'M', 'G', 'T' };
+ static const char unit_chars[] ALIGN1 = {
+ '\0', 'K', 'M', 'G', 'T', 'P', 'E'
+ };
static const char fmt[] ALIGN1 = "%llu";
static const char fmt_tenths[] ALIGN1 = "%llu.%d%c";
@@ -42,26 +46,33 @@ const char* FAST_FUNC make_human_readable_str(unsigned long long size,
int frac;
const char *u;
const char *f;
+ smallint no_tenths;
- u = zero_and_units;
- f = fmt;
- frac = 0;
+ if (size == 0)
+ return "0";
- val = size * block_size;
- if (val == 0) {
- return u;
+ /* If block_size is 0 then do not print tenths */
+ no_tenths = 0;
+ if (block_size == 0) {
+ no_tenths = 1;
+ block_size = 1;
}
+ u = unit_chars;
+ val = size * block_size;
+ f = fmt;
+ frac = 0;
+
if (display_unit) {
val += display_unit/2; /* Deal with rounding */
val /= display_unit; /* Don't combine with the line above!!! */
+ /* will just print it as ulonglong (below) */
} else {
- ++u;
while ((val >= 1024)
- && (u < zero_and_units + sizeof(zero_and_units) - 1)
+ && (u < unit_chars + sizeof(unit_chars) - 1)
) {
f = fmt_tenths;
- ++u;
+ u++;
frac = (((int)(val % 1024)) * 10 + 1024/2) / 1024;
val /= 1024;
}
@@ -69,9 +80,9 @@ const char* FAST_FUNC make_human_readable_str(unsigned long long size,
++val;
frac = 0;
}
-#if 0
+#if 1
/* Sample code to omit decimal point and tenths digit. */
- if (/* no_tenths */ 1) {
+ if (no_tenths) {
if (frac >= 5) {
++val;
}
diff --git a/release/src/router/busybox/libbb/inet_common.c b/release/src/router/busybox/libbb/inet_common.c
index 3a20b4a16f..fa4d8672fe 100644
--- a/release/src/router/busybox/libbb/inet_common.c
+++ b/release/src/router/busybox/libbb/inet_common.c
@@ -5,7 +5,7 @@
*
* Heavily modified by Manuel Novoa III Mar 12, 2001
*
- *
+ * Licensed under GPLv2, see file LICENSE in this tarball for details.
*/
#include "libbb.h"
@@ -63,9 +63,6 @@ int FAST_FUNC INET_resolve(const char *name, struct sockaddr_in *s_in, int hostf
#ifdef DEBUG
res_init();
_res.options |= RES_DEBUG;
-#endif
-
-#ifdef DEBUG
bb_error_msg("gethostbyname(%s)", name);
#endif
hp = gethostbyname(name);
diff --git a/release/src/router/busybox/libbb/info_msg.c b/release/src/router/busybox/libbb/info_msg.c
index ffef05e546..8b8a1fcca2 100644
--- a/release/src/router/busybox/libbb/info_msg.c
+++ b/release/src/router/busybox/libbb/info_msg.c
@@ -12,6 +12,7 @@
void FAST_FUNC bb_info_msg(const char *s, ...)
{
+#ifdef THIS_ONE_DOESNT_DO_SINGLE_WRITE
va_list p;
/* va_copy is used because it is not portable
* to use va_list p twice */
@@ -27,4 +28,29 @@ void FAST_FUNC bb_info_msg(const char *s, ...)
vsyslog(LOG_INFO, s, p2);
va_end(p2);
va_end(p);
+#else
+ int used;
+ char *msg;
+ va_list p;
+
+ if (logmode == 0)
+ return;
+
+ va_start(p, s);
+ used = vasprintf(&msg, s, p);
+ if (used < 0)
+ return;
+
+ if (ENABLE_FEATURE_SYSLOG && (logmode & LOGMODE_SYSLOG))
+ syslog(LOG_INFO, "%s", msg);
+ if (logmode & LOGMODE_STDIO) {
+ fflush(stdout);
+ /* used = strlen(msg); - must be true already */
+ msg[used++] = '\n';
+ full_write(STDOUT_FILENO, msg, used);
+ }
+
+ free(msg);
+ va_end(p);
+#endif
}
diff --git a/release/src/router/busybox/libbb/inode_hash.c b/release/src/router/busybox/libbb/inode_hash.c
index 4469671ddb..b32bd26bf6 100644
--- a/release/src/router/busybox/libbb/inode_hash.c
+++ b/release/src/router/busybox/libbb/inode_hash.c
@@ -67,7 +67,7 @@ void FAST_FUNC add_to_ino_dev_hashtable(const struct stat *statbuf, const char *
ino_dev_hashtable[i] = bucket;
}
-#if ENABLE_FEATURE_CLEAN_UP
+#if ENABLE_DU || ENABLE_FEATURE_CLEAN_UP
/* Clear statbuf hash table */
void FAST_FUNC reset_ino_dev_hashtable(void)
{
diff --git a/release/src/router/busybox/libbb/lineedit.c b/release/src/router/busybox/libbb/lineedit.c
index 2388b3721f..7bcdb954c5 100644
--- a/release/src/router/busybox/libbb/lineedit.c
+++ b/release/src/router/busybox/libbb/lineedit.c
@@ -954,6 +954,14 @@ static void input_tab(smallint *lastWasTab)
#endif /* FEATURE_COMMAND_TAB_COMPLETION */
+line_input_t* FAST_FUNC new_line_input_t(int flags)
+{
+ line_input_t *n = xzalloc(sizeof(*n));
+ n->flags = flags;
+ return n;
+}
+
+
#if MAX_HISTORY > 0
static void save_command_ps_at_cur_history(void)
@@ -990,56 +998,128 @@ static int get_next_history(void)
}
#if ENABLE_FEATURE_EDITING_SAVEHISTORY
+/* We try to ensure that concurrent additions to the history
+ * do not overwrite each other.
+ * Otherwise shell users get unhappy.
+ *
+ * History file is trimmed lazily, when it grows several times longer
+ * than configured MAX_HISTORY lines.
+ */
+
+static void free_line_input_t(line_input_t *n)
+{
+ int i = n->cnt_history;
+ while (i > 0)
+ free(n->history[--i]);
+ free(n);
+}
+
/* state->flags is already checked to be nonzero */
-static void load_history(const char *fromfile)
+static void load_history(line_input_t *st_parm)
{
+ char *temp_h[MAX_HISTORY];
+ char *line;
FILE *fp;
- int hi;
+ unsigned idx, i, line_len;
/* NB: do not trash old history if file can't be opened */
- fp = fopen_for_read(fromfile);
+ fp = fopen_for_read(st_parm->hist_file);
if (fp) {
/* clean up old history */
- for (hi = state->cnt_history; hi > 0;) {
- hi--;
- free(state->history[hi]);
- state->history[hi] = NULL;
+ for (idx = st_parm->cnt_history; idx > 0;) {
+ idx--;
+ free(st_parm->history[idx]);
+ st_parm->history[idx] = NULL;
}
- for (hi = 0; hi < MAX_HISTORY;) {
- char *hl = xmalloc_fgetline(fp);
- int l;
-
- if (!hl)
- break;
- l = strlen(hl);
- if (l >= MAX_LINELEN)
- hl[MAX_LINELEN-1] = '\0';
- if (l == 0) {
- free(hl);
+ /* fill temp_h[], retaining only last MAX_HISTORY lines */
+ memset(temp_h, 0, sizeof(temp_h));
+ st_parm->cnt_history_in_file = idx = 0;
+ while ((line = xmalloc_fgetline(fp)) != NULL) {
+ if (line[0] == '\0') {
+ free(line);
continue;
}
- state->history[hi++] = hl;
+ free(temp_h[idx]);
+ temp_h[idx] = line;
+ st_parm->cnt_history_in_file++;
+ idx++;
+ if (idx == MAX_HISTORY)
+ idx = 0;
}
fclose(fp);
- state->cnt_history = hi;
+
+ /* find first non-NULL temp_h[], if any */
+ if (st_parm->cnt_history_in_file) {
+ while (temp_h[idx] == NULL) {
+ idx++;
+ if (idx == MAX_HISTORY)
+ idx = 0;
+ }
+ }
+
+ /* copy temp_h[] to st_parm->history[] */
+ for (i = 0; i < MAX_HISTORY;) {
+ line = temp_h[idx];
+ if (!line)
+ break;
+ idx++;
+ if (idx == MAX_HISTORY)
+ idx = 0;
+ line_len = strlen(line);
+ if (line_len >= MAX_LINELEN)
+ line[MAX_LINELEN-1] = '\0';
+ st_parm->history[i++] = line;
+ }
+ st_parm->cnt_history = i;
}
}
/* state->flags is already checked to be nonzero */
-static void save_history(const char *tofile)
+static void save_history(char *str)
{
- FILE *fp;
+ int fd;
+ int len, len2;
- fp = fopen_for_write(tofile);
- if (fp) {
+ fd = open(state->hist_file, O_WRONLY | O_CREAT | O_APPEND, 0666);
+ if (fd < 0)
+ return;
+ xlseek(fd, 0, SEEK_END); /* paranoia */
+ len = strlen(str);
+ str[len] = '\n'; /* we (try to) do atomic write */
+ len2 = full_write(fd, str, len + 1);
+ str[len] = '\0';
+ close(fd);
+ if (len2 != len + 1)
+ return; /* "wtf?" */
+
+ /* did we write so much that history file needs trimming? */
+ state->cnt_history_in_file++;
+ if (state->cnt_history_in_file > MAX_HISTORY * 4) {
+ FILE *fp;
+ char *new_name;
+ line_input_t *st_temp;
int i;
- for (i = 0; i < state->cnt_history; i++) {
- fprintf(fp, "%s\n", state->history[i]);
+ /* we may have concurrently written entries from others.
+ * load them */
+ st_temp = new_line_input_t(state->flags);
+ st_temp->hist_file = state->hist_file;
+ load_history(st_temp);
+
+ /* write out temp file and replace hist_file atomically */
+ new_name = xasprintf("%s.%u.new", state->hist_file, (int) getpid());
+ fp = fopen_for_write(new_name);
+ if (fp) {
+ for (i = 0; i < st_temp->cnt_history; i++)
+ fprintf(fp, "%s\n", st_temp->history[i]);
+ fclose(fp);
+ if (rename(new_name, state->hist_file) == 0)
+ state->cnt_history_in_file = st_temp->cnt_history;
}
- fclose(fp);
+ free(new_name);
+ free_line_input_t(st_temp);
}
}
#else
@@ -1047,7 +1127,7 @@ static void save_history(const char *tofile)
#define save_history(a) ((void)0)
#endif /* FEATURE_COMMAND_SAVEHISTORY */
-static void remember_in_history(const char *str)
+static void remember_in_history(char *str)
{
int i;
@@ -1078,7 +1158,7 @@ static void remember_in_history(const char *str)
state->cnt_history = i;
#if ENABLE_FEATURE_EDITING_SAVEHISTORY
if ((state->flags & SAVE_HISTORY) && state->hist_file)
- save_history(state->hist_file);
+ save_history(str);
#endif
USE_FEATURE_EDITING_FANCY_PROMPT(num_ok_lines++;)
}
@@ -1413,12 +1493,11 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
state = st ? st : (line_input_t*) &const_int_0;
#if ENABLE_FEATURE_EDITING_SAVEHISTORY
if ((state->flags & SAVE_HISTORY) && state->hist_file)
- load_history(state->hist_file);
+ if (state->cnt_history == 0)
+ load_history(state);
#endif
-#if MAX_HISTORY > 0
if (state->flags & DO_HISTORY)
state->cur_history = state->cnt_history;
-#endif
/* prepare before init handlers */
cmdedit_y = 0; /* quasireal y, not true if line > xt*yt */
@@ -1438,7 +1517,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
#define _POSIX_VDISABLE '\0'
#endif
new_settings.c_cc[VINTR] = _POSIX_VDISABLE;
- tcsetattr(STDIN_FILENO, TCSANOW, &new_settings);
+ tcsetattr_stdin_TCSANOW(&new_settings);
/* Now initialize things */
previous_SIGWINCH_handler = signal(SIGWINCH, win_changed);
@@ -1862,7 +1941,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
#endif
/* restore initial_settings */
- tcsetattr(STDIN_FILENO, TCSANOW, &initial_settings);
+ tcsetattr_stdin_TCSANOW(&initial_settings);
/* restore SIGWINCH handler */
signal(SIGWINCH, previous_SIGWINCH_handler);
fflush(stdout);
@@ -1873,13 +1952,6 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
return len; /* can't return command_len, DEINIT_S() destroys it */
}
-line_input_t* FAST_FUNC new_line_input_t(int flags)
-{
- line_input_t *n = xzalloc(sizeof(*n));
- n->flags = flags;
- return n;
-}
-
#else
#undef read_line_input
diff --git a/release/src/router/busybox/libbb/llist.c b/release/src/router/busybox/libbb/llist.c
index 094c652461..51b1ce6c99 100644
--- a/release/src/router/busybox/libbb/llist.c
+++ b/release/src/router/busybox/libbb/llist.c
@@ -4,7 +4,7 @@
*
* Copyright (C) 2003 Glenn McGrath
* Copyright (C) 2005 Vladimir Oleynik
- * Copyright (C) 2005 Bernhard Fischer
+ * Copyright (C) 2005 Bernhard Reutner-Fischer
* Copyright (C) 2006 Rob Landley
*
* Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
@@ -25,56 +25,38 @@ void FAST_FUNC llist_add_to(llist_t **old_head, void *data)
/* Add data to the end of the linked list. */
void FAST_FUNC llist_add_to_end(llist_t **list_head, void *data)
{
- llist_t *new_item = xmalloc(sizeof(llist_t));
-
- new_item->data = data;
- new_item->link = NULL;
-
- if (!*list_head)
- *list_head = new_item;
- else {
- llist_t *tail = *list_head;
-
- while (tail->link)
- tail = tail->link;
- tail->link = new_item;
- }
+ while (*list_head)
+ list_head = &(*list_head)->link;
+ *list_head = xzalloc(sizeof(llist_t));
+ (*list_head)->data = data;
+ /*(*list_head)->link = NULL;*/
}
/* Remove first element from the list and return it */
void* FAST_FUNC llist_pop(llist_t **head)
{
- void *data, *next;
-
- if (!*head)
- return NULL;
-
- data = (*head)->data;
- next = (*head)->link;
- free(*head);
- *head = next;
+ void *data = NULL;
+ llist_t *temp = *head;
+ if (temp) {
+ data = temp->data;
+ *head = temp->link;
+ free(temp);
+ }
return data;
}
/* Unlink arbitrary given element from the list */
void FAST_FUNC llist_unlink(llist_t **head, llist_t *elm)
{
- llist_t *crt;
-
- if (!(elm && *head))
+ if (!elm)
return;
-
- if (elm == *head) {
- *head = (*head)->link;
- return;
- }
-
- for (crt = *head; crt; crt = crt->link) {
- if (crt->link == elm) {
- crt->link = elm->link;
- return;
+ while (*head) {
+ if (*head == elm) {
+ *head = (*head)->link;
+ break;
}
+ head = &(*head)->link;
}
}
@@ -90,7 +72,6 @@ void FAST_FUNC llist_free(llist_t *elm, void (*freeit) (void *data))
}
}
-#ifdef UNUSED
/* Reverse list order. */
llist_t* FAST_FUNC llist_rev(llist_t *list)
{
@@ -105,4 +86,13 @@ llist_t* FAST_FUNC llist_rev(llist_t *list)
}
return rev;
}
-#endif
+
+llist_t* FAST_FUNC llist_find_str(llist_t *list, const char *str)
+{
+ while (list) {
+ if (strcmp(list->data, str) == 0)
+ break;
+ list = list->link;
+ }
+ return list;
+}
diff --git a/release/src/router/busybox/libbb/make_directory.c b/release/src/router/busybox/libbb/make_directory.c
index df0b4a13d4..391493cda8 100644
--- a/release/src/router/busybox/libbb/make_directory.c
+++ b/release/src/router/busybox/libbb/make_directory.c
@@ -71,7 +71,7 @@ int FAST_FUNC bb_make_directory(char *path, long mode, int flags)
}
/* Since the directory exists, don't attempt to change
* permissions if it was the full target. Note that
- * this is not an error conditon. */
+ * this is not an error condition. */
if (!c) {
umask(mask);
return 0;
diff --git a/release/src/router/busybox/libbb/match_fstype.c b/release/src/router/busybox/libbb/match_fstype.c
index 99e2767848..9360e757a6 100644
--- a/release/src/router/busybox/libbb/match_fstype.c
+++ b/release/src/router/busybox/libbb/match_fstype.c
@@ -5,40 +5,38 @@
* This allows us to match fstypes that start with no like so
* mount -at ,noddy
*
- * Returns 0 for a match, otherwise -1
+ * Returns 1 for a match, otherwise 0
*
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
#include "libbb.h"
-int FAST_FUNC match_fstype(const struct mntent *mt, const char *fstype)
+int FAST_FUNC match_fstype(const struct mntent *mt, const char *t_fstype)
{
- int no = 0;
+ int match = 1;
int len;
- if (!mt)
- return -1;
+ if (!t_fstype)
+ return match;
- if (!fstype)
- return 0;
-
- if (fstype[0] == 'n' && fstype[1] == 'o') {
- no = -1;
- fstype += 2;
+ if (t_fstype[0] == 'n' && t_fstype[1] == 'o') {
+ match--;
+ t_fstype += 2;
}
len = strlen(mt->mnt_type);
- while (fstype) {
- if (!strncmp(mt->mnt_type, fstype, len)
- && (!fstype[len] || fstype[len] == ',')
+ while (1) {
+ if (strncmp(mt->mnt_type, t_fstype, len) == 0
+ && (t_fstype[len] == '\0' || t_fstype[len] == ',')
) {
- return no;
+ return match;
}
- fstype = strchr(fstype, ',');
- if (fstype)
- fstype++;
+ t_fstype = strchr(t_fstype, ',');
+ if (!t_fstype)
+ break;
+ t_fstype++;
}
- return -(no + 1);
+ return !match;
}
diff --git a/release/src/router/busybox/libbb/md5.c b/release/src/router/busybox/libbb/md5.c
dissimilarity index 64%
index 4ab06eb17b..768dfbcb78 100644
--- a/release/src/router/busybox/libbb/md5.c
+++ b/release/src/router/busybox/libbb/md5.c
@@ -1,446 +1,429 @@
-/* vi: set sw=4 ts=4: */
-/*
- * md5.c - Compute MD5 checksum of strings according to the
- * definition of MD5 in RFC 1321 from April 1992.
- *
- * Written by Ulrich Drepper , 1995.
- *
- * Copyright (C) 1995-1999 Free Software Foundation, Inc.
- * Copyright (C) 2001 Manuel Novoa III
- * Copyright (C) 2003 Glenn L. McGrath
- * Copyright (C) 2003 Erik Andersen
- *
- * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
- */
-
-#include "libbb.h"
-
-#if CONFIG_MD5_SIZE_VS_SPEED < 0 || CONFIG_MD5_SIZE_VS_SPEED > 3
-# define MD5_SIZE_VS_SPEED 2
-#else
-# define MD5_SIZE_VS_SPEED CONFIG_MD5_SIZE_VS_SPEED
-#endif
-
-/* Initialize structure containing state of computation.
- * (RFC 1321, 3.3: Step 3)
- */
-void FAST_FUNC md5_begin(md5_ctx_t *ctx)
-{
- ctx->A = 0x67452301;
- ctx->B = 0xefcdab89;
- ctx->C = 0x98badcfe;
- ctx->D = 0x10325476;
-
- ctx->total = 0;
- ctx->buflen = 0;
-}
-
-/* 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))
-
-/* Hash a single block, 64 bytes long and 4-byte aligned. */
-static void md5_hash_block(const void *buffer, md5_ctx_t *ctx)
-{
- uint32_t correct_words[16];
- const uint32_t *words = buffer;
-
-# if MD5_SIZE_VS_SPEED > 0
- static const uint32_t 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[] ALIGN1 = {
-# if MD5_SIZE_VS_SPEED > 1
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 1 */
-# endif /* MD5_SIZE_VS_SPEED > 1 */
- 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 MD5_SIZE_VS_SPEED > 1
- static const char S_array[] ALIGN1 = {
- 7, 12, 17, 22,
- 5, 9, 14, 20,
- 4, 11, 16, 23,
- 6, 10, 15, 21
- };
-# endif /* MD5_SIZE_VS_SPEED > 1 */
-# endif
-
- uint32_t A = ctx->A;
- uint32_t B = ctx->B;
- uint32_t C = ctx->C;
- uint32_t D = ctx->D;
-
- /* Process all bytes in the buffer with 64 bytes in each round of
- the loop. */
- uint32_t *cwp = correct_words;
- uint32_t A_save = A;
- uint32_t B_save = B;
- uint32_t C_save = C;
- uint32_t D_save = D;
-
-# if MD5_SIZE_VS_SPEED > 1
-# define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
-
- const uint32_t *pc;
- const char *pp;
- const char *ps;
- int i;
- uint32_t temp;
-
- for (i = 0; i < 16; i++) {
- cwp[i] = SWAP_LE32(words[i]);
- }
- words += 16;
-
-# if MD5_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++;
- 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++;
- 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++;
- 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++;
- 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++;
- CYCLIC(temp, ps[i & 3]);
- temp += B;
- A = D;
- D = C;
- C = B;
- B = temp;
- }
-
-# endif /* MD5_SIZE_VS_SPEED > 2 */
-# 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_LE32(*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 MD5_SIZE_VS_SPEED == 1
- const uint32_t *pc;
- const char *pp;
- int i;
-# endif /* MD5_SIZE_VS_SPEED */
-
- /* Round 1. */
-# if MD5_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 /* MD5_SIZE_VS_SPEED == 1 */
-
- /* 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 MD5_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 /* MD5_SIZE_VS_SPEED == 1 */
-
- /* Round 3. */
-# if MD5_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 /* MD5_SIZE_VS_SPEED == 1 */
-
- /* Round 4. */
-# if MD5_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 /* MD5_SIZE_VS_SPEED == 1 */
-# endif /* MD5_SIZE_VS_SPEED > 1 */
-
- /* 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;
-}
-
-/* Feed data through a temporary buffer to call md5_hash_aligned_block()
- * with chunks of data that are 4-byte aligned and a multiple of 64 bytes.
- * This function's internal buffer remembers previous data until it has 64
- * bytes worth to pass on. Call md5_end() to flush this buffer. */
-
-void FAST_FUNC md5_hash(const void *buffer, size_t len, md5_ctx_t *ctx)
-{
- char *buf=(char *)buffer;
-
- /* RFC 1321 specifies the possible length of the file up to 2^64 bits,
- * Here we only track the number of bytes. */
-
- ctx->total += len;
-
- // Process all input.
-
- while (len) {
- unsigned i = 64 - ctx->buflen;
-
- // Copy data into aligned buffer.
-
- if (i > len) i = len;
- memcpy(ctx->buffer + ctx->buflen, buf, i);
- len -= i;
- ctx->buflen += i;
- buf += i;
-
- // When buffer fills up, process it.
-
- if (ctx->buflen == 64) {
- md5_hash_block(ctx->buffer, ctx);
- ctx->buflen = 0;
- }
- }
-}
-
-/* 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.
- */
-void* FAST_FUNC md5_end(void *resbuf, md5_ctx_t *ctx)
-{
- char *buf = ctx->buffer;
- int i;
-
- /* Pad data to block size. */
-
- buf[ctx->buflen++] = 0x80;
- memset(buf + ctx->buflen, 0, 128 - ctx->buflen);
-
- /* Put the 64-bit file length in *bits* at the end of the buffer. */
- ctx->total <<= 3;
- if (ctx->buflen > 56) buf += 64;
- for (i = 0; i < 8; i++) buf[56 + i] = ctx->total >> (i*8);
-
- /* Process last bytes. */
- if (buf != ctx->buffer) md5_hash_block(ctx->buffer, ctx);
- md5_hash_block(buf, 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.
- */
- ((uint32_t *) resbuf)[0] = SWAP_LE32(ctx->A);
- ((uint32_t *) resbuf)[1] = SWAP_LE32(ctx->B);
- ((uint32_t *) resbuf)[2] = SWAP_LE32(ctx->C);
- ((uint32_t *) resbuf)[3] = SWAP_LE32(ctx->D);
-
- return resbuf;
-}
-
+/* vi: set sw=4 ts=4: */
+/*
+ * md5.c - Compute MD5 checksum of strings according to the
+ * definition of MD5 in RFC 1321 from April 1992.
+ *
+ * Written by Ulrich Drepper , 1995.
+ *
+ * Copyright (C) 1995-1999 Free Software Foundation, Inc.
+ * Copyright (C) 2001 Manuel Novoa III
+ * Copyright (C) 2003 Glenn L. McGrath
+ * Copyright (C) 2003 Erik Andersen
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+#include "libbb.h"
+
+/* 0: fastest, 3: smallest */
+#if CONFIG_MD5_SIZE_VS_SPEED < 0
+# define MD5_SIZE_VS_SPEED 0
+#elif CONFIG_MD5_SIZE_VS_SPEED > 3
+# define MD5_SIZE_VS_SPEED 3
+#else
+# define MD5_SIZE_VS_SPEED CONFIG_MD5_SIZE_VS_SPEED
+#endif
+
+/* Initialize structure containing state of computation.
+ * (RFC 1321, 3.3: Step 3)
+ */
+void FAST_FUNC md5_begin(md5_ctx_t *ctx)
+{
+ ctx->A = 0x67452301;
+ ctx->B = 0xefcdab89;
+ ctx->C = 0x98badcfe;
+ ctx->D = 0x10325476;
+ ctx->total = 0;
+ ctx->buflen = 0;
+}
+
+/* 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))
+
+#define rotl32(w, s) (((w) << (s)) | ((w) >> (32 - (s))))
+
+/* Hash a single block, 64 bytes long and 4-byte aligned. */
+static void md5_hash_block(const void *buffer, md5_ctx_t *ctx)
+{
+ uint32_t correct_words[16];
+ const uint32_t *words = buffer;
+
+#if MD5_SIZE_VS_SPEED > 0
+ static const uint32_t 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[] ALIGN1 = {
+# if MD5_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 MD5_SIZE_VS_SPEED > 1
+ static const char S_array[] ALIGN1 = {
+ 7, 12, 17, 22,
+ 5, 9, 14, 20,
+ 4, 11, 16, 23,
+ 6, 10, 15, 21
+ };
+# endif /* MD5_SIZE_VS_SPEED > 1 */
+#endif
+ uint32_t A = ctx->A;
+ uint32_t B = ctx->B;
+ uint32_t C = ctx->C;
+ uint32_t D = ctx->D;
+
+ /* Process all bytes in the buffer with 64 bytes in each round of
+ the loop. */
+ uint32_t *cwp = correct_words;
+ uint32_t A_save = A;
+ uint32_t B_save = B;
+ uint32_t C_save = C;
+ uint32_t D_save = D;
+
+#if MD5_SIZE_VS_SPEED > 1
+ const uint32_t *pc;
+ const char *pp;
+ const char *ps;
+ int i;
+ uint32_t temp;
+
+ for (i = 0; i < 16; i++)
+ cwp[i] = SWAP_LE32(words[i]);
+ words += 16;
+
+# if MD5_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 = rotl32(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 = rotl32(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 = rotl32(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 = rotl32(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 = rotl32(temp, ps[i & 3]);
+ temp += B;
+ A = D;
+ D = C;
+ C = B;
+ B = temp;
+ }
+
+# endif /* MD5_SIZE_VS_SPEED > 2 */
+#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_LE32(*words)) + T; \
+ ++words; \
+ a = rotl32(a, s); \
+ a += b; \
+ } while (0)
+
+ /* 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 MD5_SIZE_VS_SPEED == 1
+ const uint32_t *pc;
+ const char *pp;
+ int i;
+# endif /* MD5_SIZE_VS_SPEED */
+
+ /* Round 1. */
+# if MD5_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/* MD5_SIZE_VS_SPEED == 1 */
+
+ /* 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; \
+ a = rotl32(a, s); \
+ a += b; \
+ } while (0)
+
+ /* Round 2. */
+# if MD5_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/* MD5_SIZE_VS_SPEED == 1 */
+
+ /* Round 3. */
+# if MD5_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/* MD5_SIZE_VS_SPEED == 1 */
+
+ /* Round 4. */
+# if MD5_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 /* MD5_SIZE_VS_SPEED == 1 */
+#endif /* MD5_SIZE_VS_SPEED > 1 */
+
+ /* 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;
+}
+
+/* Feed data through a temporary buffer to call md5_hash_aligned_block()
+ * with chunks of data that are 4-byte aligned and a multiple of 64 bytes.
+ * This function's internal buffer remembers previous data until it has 64
+ * bytes worth to pass on. Call md5_end() to flush this buffer. */
+void FAST_FUNC md5_hash(const void *buffer, size_t len, md5_ctx_t *ctx)
+{
+ char *buf = (char *)buffer;
+
+ /* RFC 1321 specifies the possible length of the file up to 2^64 bits,
+ * Here we only track the number of bytes. */
+ ctx->total += len;
+
+ /* Process all input. */
+ while (len) {
+ unsigned i = 64 - ctx->buflen;
+
+ /* Copy data into aligned buffer. */
+ if (i > len) i = len;
+ memcpy(ctx->buffer + ctx->buflen, buf, i);
+ len -= i;
+ ctx->buflen += i;
+ buf += i;
+
+ /* When buffer fills up, process it. */
+ if (ctx->buflen == 64) {
+ md5_hash_block(ctx->buffer, ctx);
+ ctx->buflen = 0;
+ }
+ }
+}
+
+/* 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.
+ */
+void FAST_FUNC md5_end(void *resbuf, md5_ctx_t *ctx)
+{
+ char *buf = ctx->buffer;
+ int i;
+
+ /* Pad data to block size. */
+ buf[ctx->buflen++] = 0x80;
+ memset(buf + ctx->buflen, 0, 128 - ctx->buflen);
+
+ /* Put the 64-bit file length in *bits* at the end of the buffer. */
+ ctx->total <<= 3;
+ if (ctx->buflen > 56)
+ buf += 64;
+ for (i = 0; i < 8; i++)
+ buf[56 + i] = ctx->total >> (i*8);
+
+ /* Process last bytes. */
+ if (buf != ctx->buffer)
+ md5_hash_block(ctx->buffer, ctx);
+ md5_hash_block(buf, ctx);
+
+ /* The MD5 result is in little endian byte order.
+ * We (ab)use the fact that A-D are consecutive in memory.
+ */
+#if BB_BIG_ENDIAN
+ ctx->A = SWAP_LE32(ctx->A);
+ ctx->B = SWAP_LE32(ctx->B);
+ ctx->C = SWAP_LE32(ctx->C);
+ ctx->D = SWAP_LE32(ctx->D);
+#endif
+ memcpy(resbuf, &ctx->A, sizeof(ctx->A) * 4);
+}
diff --git a/release/src/router/busybox/libbb/md5prime.c b/release/src/router/busybox/libbb/md5prime.c
new file mode 100644
index 0000000000..7986f4d292
--- /dev/null
+++ b/release/src/router/busybox/libbb/md5prime.c
@@ -0,0 +1,460 @@
+/* This file is not used by busybox right now.
+ * However, the code here seems to be a tiny bit smaller
+ * than one in md5.c. Need to investigate which one
+ * is better overall...
+ * Hint: grep for md5prime to find places where you can switch
+ * md5.c/md5prime.c
+ */
+
+/*
+ * MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
+ *
+ * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ * rights reserved.
+ *
+ * License to copy and use this software is granted provided that it
+ * is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+ * Algorithm" in all material mentioning or referencing this software
+ * or this function.
+ *
+ * License is also granted to make and use derivative works provided
+ * that such works are identified as "derived from the RSA Data
+ * Security, Inc. MD5 Message-Digest Algorithm" in all material
+ * mentioning or referencing the derived work.
+ *
+ * RSA Data Security, Inc. makes no representations concerning either
+ * the merchantability of this software or the suitability of this
+ * software for any particular purpose. It is provided "as is"
+ * without express or implied warranty of any kind.
+ *
+ * These notices must be retained in any copies of any part of this
+ * documentation and/or software.
+ *
+ * $FreeBSD: src/lib/libmd/md5c.c,v 1.9.2.1 1999/08/29 14:57:12 peter Exp $
+ *
+ * This code is the same as the code published by RSA Inc. It has been
+ * edited for clarity and style only.
+ *
+ * ----------------------------------------------------------------------------
+ * The md5_crypt() function was taken from freeBSD's libcrypt and contains
+ * this license:
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * wrote this file. As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
+ *
+ * $FreeBSD: src/lib/libcrypt/crypt.c,v 1.7.2.1 1999/08/29 14:56:33 peter Exp $
+ *
+ * ----------------------------------------------------------------------------
+ * On April 19th, 2001 md5_crypt() was modified to make it reentrant
+ * by Erik Andersen
+ *
+ * June 28, 2001 Manuel Novoa III
+ *
+ * "Un-inlined" code using loops and static const tables in order to
+ * reduce generated code size (on i386 from approx 4k to approx 2.5k).
+ *
+ * June 29, 2001 Manuel Novoa III
+ *
+ * Completely removed static PADDING array.
+ *
+ * Reintroduced the loop unrolling in md5_transform and added the
+ * MD5_SIZE_VS_SPEED option for configurability. Define below as:
+ * 0 fully unrolled loops
+ * 1 partially unrolled (4 ops per loop)
+ * 2 no unrolling -- introduces the need to swap 4 variables (slow)
+ * 3 no unrolling and all 4 loops merged into one with switch
+ * in each loop (glacial)
+ * On i386, sizes are roughly (-Os -fno-builtin):
+ * 0: 3k 1: 2.5k 2: 2.2k 3: 2k
+ *
+ * Since SuSv3 does not require crypt_r, modified again August 7, 2002
+ * by Erik Andersen to remove reentrance stuff...
+ */
+
+#include "libbb.h"
+
+/* 1: fastest, 3: smallest */
+#if CONFIG_MD5_SIZE_VS_SPEED < 1
+# define MD5_SIZE_VS_SPEED 1
+#elif CONFIG_MD5_SIZE_VS_SPEED > 3
+# define MD5_SIZE_VS_SPEED 3
+#else
+# define MD5_SIZE_VS_SPEED CONFIG_MD5_SIZE_VS_SPEED
+#endif
+
+#if BB_LITTLE_ENDIAN
+#define memcpy32_cpu2le memcpy
+#define memcpy32_le2cpu memcpy
+#else
+/* Encodes input (uint32_t) into output (unsigned char).
+ * Assumes len is a multiple of 4. */
+static void
+memcpy32_cpu2le(unsigned char *output, uint32_t *input, unsigned len)
+{
+ unsigned i, j;
+ for (i = 0, j = 0; j < len; i++, j += 4) {
+ output[j] = input[i];
+ output[j+1] = (input[i] >> 8);
+ output[j+2] = (input[i] >> 16);
+ output[j+3] = (input[i] >> 24);
+ }
+}
+/* Decodes input (unsigned char) into output (uint32_t).
+ * Assumes len is a multiple of 4. */
+static void
+memcpy32_le2cpu(uint32_t *output, const unsigned char *input, unsigned len)
+{
+ unsigned i, j;
+ for (i = 0, j = 0; j < len; i++, j += 4)
+ output[i] = ((uint32_t)input[j])
+ | (((uint32_t)input[j+1]) << 8)
+ | (((uint32_t)input[j+2]) << 16)
+ | (((uint32_t)input[j+3]) << 24);
+}
+#endif /* i386 */
+
+/* F, G, H and I are basic MD5 functions. */
+#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | ~(z)))
+
+/* rotl32 rotates x left n bits. */
+#define rotl32(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+
+/*
+ * FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+ * Rotation is separate from addition to prevent recomputation.
+ */
+#define FF(a, b, c, d, x, s, ac) { \
+ (a) += F((b), (c), (d)) + (x) + (uint32_t)(ac); \
+ (a) = rotl32((a), (s)); \
+ (a) += (b); \
+ }
+#define GG(a, b, c, d, x, s, ac) { \
+ (a) += G((b), (c), (d)) + (x) + (uint32_t)(ac); \
+ (a) = rotl32((a), (s)); \
+ (a) += (b); \
+ }
+#define HH(a, b, c, d, x, s, ac) { \
+ (a) += H((b), (c), (d)) + (x) + (uint32_t)(ac); \
+ (a) = rotl32((a), (s)); \
+ (a) += (b); \
+ }
+#define II(a, b, c, d, x, s, ac) { \
+ (a) += I((b), (c), (d)) + (x) + (uint32_t)(ac); \
+ (a) = rotl32((a), (s)); \
+ (a) += (b); \
+ }
+
+/* MD5 basic transformation. Transforms state based on block. */
+static void md5_transform(uint32_t state[4], const unsigned char block[64])
+{
+ uint32_t a, b, c, d, x[16];
+#if MD5_SIZE_VS_SPEED > 1
+ uint32_t temp;
+ const unsigned char *ps;
+
+ static const unsigned char S[] = {
+ 7, 12, 17, 22,
+ 5, 9, 14, 20,
+ 4, 11, 16, 23,
+ 6, 10, 15, 21
+ };
+#endif /* MD5_SIZE_VS_SPEED > 1 */
+
+#if MD5_SIZE_VS_SPEED > 0
+ const uint32_t *pc;
+ const unsigned char *pp;
+ int i;
+
+ static const uint32_t C[] = {
+ /* 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 unsigned char P[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 1 */
+ 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 */
+ };
+
+#endif /* MD5_SIZE_VS_SPEED > 0 */
+
+ memcpy32_le2cpu(x, block, 64);
+
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+
+#if MD5_SIZE_VS_SPEED > 2
+ pc = C;
+ pp = P;
+ ps = S - 4;
+ for (i = 0; i < 64; i++) {
+ if ((i & 0x0f) == 0) ps += 4;
+ temp = a;
+ switch (i>>4) {
+ case 0:
+ temp += F(b, c, d);
+ break;
+ case 1:
+ temp += G(b, c, d);
+ break;
+ case 2:
+ temp += H(b, c, d);
+ break;
+ case 3:
+ temp += I(b, c, d);
+ break;
+ }
+ temp += x[*pp++] + *pc++;
+ temp = rotl32(temp, ps[i & 3]);
+ temp += b;
+ a = d; d = c; c = b; b = temp;
+ }
+#elif MD5_SIZE_VS_SPEED > 1
+ pc = C;
+ pp = P;
+ ps = S;
+ /* Round 1 */
+ for (i = 0; i < 16; i++) {
+ FF(a, b, c, d, x[*pp], ps[i & 0x3], *pc); pp++; pc++;
+ temp = d; d = c; c = b; b = a; a = temp;
+ }
+ /* Round 2 */
+ ps += 4;
+ for (; i < 32; i++) {
+ GG(a, b, c, d, x[*pp], ps[i & 0x3], *pc); pp++; pc++;
+ temp = d; d = c; c = b; b = a; a = temp;
+ }
+ /* Round 3 */
+ ps += 4;
+ for (; i < 48; i++) {
+ HH(a, b, c, d, x[*pp], ps[i & 0x3], *pc); pp++; pc++;
+ temp = d; d = c; c = b; b = a; a = temp;
+ }
+ /* Round 4 */
+ ps += 4;
+ for (; i < 64; i++) {
+ II(a, b, c, d, x[*pp], ps[i & 0x3], *pc); pp++; pc++;
+ temp = d; d = c; c = b; b = a; a = temp;
+ }
+#elif MD5_SIZE_VS_SPEED > 0
+ pc = C;
+ pp = P;
+ /* Round 1 */
+ for (i = 0; i < 4; i++) {
+ FF(a, b, c, d, x[*pp], 7, *pc); pp++; pc++;
+ FF(d, a, b, c, x[*pp], 12, *pc); pp++; pc++;
+ FF(c, d, a, b, x[*pp], 17, *pc); pp++; pc++;
+ FF(b, c, d, a, x[*pp], 22, *pc); pp++; pc++;
+ }
+ /* Round 2 */
+ for (i = 0; i < 4; i++) {
+ GG(a, b, c, d, x[*pp], 5, *pc); pp++; pc++;
+ GG(d, a, b, c, x[*pp], 9, *pc); pp++; pc++;
+ GG(c, d, a, b, x[*pp], 14, *pc); pp++; pc++;
+ GG(b, c, d, a, x[*pp], 20, *pc); pp++; pc++;
+ }
+ /* Round 3 */
+ for (i = 0; i < 4; i++) {
+ HH(a, b, c, d, x[*pp], 4, *pc); pp++; pc++;
+ HH(d, a, b, c, x[*pp], 11, *pc); pp++; pc++;
+ HH(c, d, a, b, x[*pp], 16, *pc); pp++; pc++;
+ HH(b, c, d, a, x[*pp], 23, *pc); pp++; pc++;
+ }
+ /* Round 4 */
+ for (i = 0; i < 4; i++) {
+ II(a, b, c, d, x[*pp], 6, *pc); pp++; pc++;
+ II(d, a, b, c, x[*pp], 10, *pc); pp++; pc++;
+ II(c, d, a, b, x[*pp], 15, *pc); pp++; pc++;
+ II(b, c, d, a, x[*pp], 21, *pc); pp++; pc++;
+ }
+#else
+ /* Round 1 */
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+ FF(a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
+ FF(d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
+ FF(c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
+ FF(b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
+ FF(a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
+ FF(d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
+ FF(c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
+ FF(b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
+ FF(a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
+ FF(d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
+ FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+ FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+ FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+ FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+ FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+ FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+ /* Round 2 */
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+ GG(a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
+ GG(d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
+ GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+ GG(b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
+ GG(a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
+ GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
+ GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+ GG(b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
+ GG(a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
+ GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+ GG(c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
+ GG(b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
+ GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+ GG(d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
+ GG(c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
+ GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+ /* Round 3 */
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+ HH(a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
+ HH(d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
+ HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+ HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+ HH(a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
+ HH(d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
+ HH(c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
+ HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+ HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+ HH(d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
+ HH(c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
+ HH(b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
+ HH(a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
+ HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+ HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+ HH(b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
+ /* Round 4 */
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+ II(a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
+ II(d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
+ II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+ II(b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
+ II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+ II(d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
+ II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+ II(b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
+ II(a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
+ II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+ II(c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
+ II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+ II(a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
+ II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+ II(c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
+ II(b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
+#endif
+
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+
+ /* Zeroize sensitive information. */
+ memset(x, 0, sizeof(x));
+}
+
+
+/* MD5 initialization. */
+void FAST_FUNC md5_begin(md5_ctx_t *context)
+{
+ context->count[0] = context->count[1] = 0;
+ /* Load magic initialization constants. */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xefcdab89;
+ context->state[2] = 0x98badcfe;
+ context->state[3] = 0x10325476;
+}
+
+/*
+ * MD5 block update operation. Continues an MD5 message-digest
+ * operation, processing another message block, and updating
+ * the context.
+ */
+void FAST_FUNC md5_hash(const void *buffer, size_t inputLen, md5_ctx_t *context)
+{
+ unsigned i, idx, partLen;
+ const unsigned char *input = buffer;
+
+ /* Compute number of bytes mod 64 */
+ idx = (context->count[0] >> 3) & 0x3F;
+
+ /* Update number of bits */
+ context->count[0] += (inputLen << 3);
+ if (context->count[0] < (inputLen << 3))
+ context->count[1]++;
+ context->count[1] += (inputLen >> 29);
+
+ /* Transform as many times as possible. */
+ i = 0;
+ partLen = 64 - idx;
+ if (inputLen >= partLen) {
+ memcpy(&context->buffer[idx], input, partLen);
+ md5_transform(context->state, context->buffer);
+ for (i = partLen; i + 63 < inputLen; i += 64)
+ md5_transform(context->state, &input[i]);
+ idx = 0;
+ }
+
+ /* Buffer remaining input */
+ memcpy(&context->buffer[idx], &input[i], inputLen - i);
+}
+
+/*
+ * MD5 finalization. Ends an MD5 message-digest operation,
+ * writing the message digest.
+ */
+void FAST_FUNC md5_end(void *digest, md5_ctx_t *context)
+{
+ unsigned idx, padLen;
+ unsigned char bits[8];
+ unsigned char padding[64];
+
+ /* Add padding followed by original length. */
+ memset(padding, 0, sizeof(padding));
+ padding[0] = 0x80;
+ /* save number of bits */
+ memcpy32_cpu2le(bits, context->count, 8);
+ /* pad out to 56 mod 64 */
+ idx = (context->count[0] >> 3) & 0x3f;
+ padLen = (idx < 56) ? (56 - idx) : (120 - idx);
+ md5_hash(padding, padLen, context);
+ /* append length (before padding) */
+ md5_hash(bits, 8, context);
+
+ /* Store state in digest */
+ memcpy32_cpu2le(digest, context->state, 16);
+}
diff --git a/release/src/router/busybox/libbb/parse_config.c b/release/src/router/busybox/libbb/parse_config.c
index a0599d4b45..74f0524e53 100644
--- a/release/src/router/busybox/libbb/parse_config.c
+++ b/release/src/router/busybox/libbb/parse_config.c
@@ -5,11 +5,12 @@
* Copyright (C) 2008 by Vladimir Dronnikov
*
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ * Also for use in uClibc (http://uclibc.org/) licensed under LGPLv2.1 or later.
*/
#include "libbb.h"
-#if ENABLE_PARSE
+#if defined ENABLE_PARSE && ENABLE_PARSE
int parse_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int parse_main(int argc UNUSED_PARAM, char **argv)
{
diff --git a/release/src/router/busybox/libbb/process_escape_sequence.c b/release/src/router/busybox/libbb/process_escape_sequence.c
index 4d03bd61f3..6de2cacddc 100644
--- a/release/src/router/busybox/libbb/process_escape_sequence.c
+++ b/release/src/router/busybox/libbb/process_escape_sequence.c
@@ -18,17 +18,20 @@
char FAST_FUNC bb_process_escape_sequence(const char **ptr)
{
+ /* bash builtin "echo -e '\ec'" interprets \e as ESC,
+ * but coreutils "/bin/echo -e '\ec'" does not.
+ * manpages tend to support coreutils way. */
static const char charmap[] ALIGN1 = {
- 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', 0,
- '\a', '\b', '\f', '\n', '\r', '\t', '\v', '\\', '\\' };
+ 'a', 'b', /*'e',*/ 'f', 'n', 'r', 't', 'v', '\\', 0,
+ '\a', '\b', /*27,*/ '\f', '\n', '\r', '\t', '\v', '\\', '\\' };
const char *p;
const char *q;
- unsigned int num_digits;
- unsigned int r;
- unsigned int n;
- unsigned int d;
- unsigned int base;
+ unsigned num_digits;
+ unsigned r;
+ unsigned n;
+ unsigned d;
+ unsigned base;
num_digits = n = 0;
base = 8;
diff --git a/release/src/router/busybox/libbb/procps.c b/release/src/router/busybox/libbb/procps.c
index fd19621db0..c5e40bf885 100644
--- a/release/src/router/busybox/libbb/procps.c
+++ b/release/src/router/busybox/libbb/procps.c
@@ -13,7 +13,7 @@
typedef struct unsigned_to_name_map_t {
- unsigned id;
+ long id;
char name[USERNAME_MAX_SIZE];
} unsigned_to_name_map_t;
@@ -52,8 +52,8 @@ static int get_cached(cache_t *cp, unsigned id)
}
#endif
-typedef char* FAST_FUNC ug_func(char *name, int bufsize, long uid);
-static char* get_cached(cache_t *cp, unsigned id, ug_func* fp)
+static char* get_cached(cache_t *cp, long id,
+ char* FAST_FUNC x2x_utoa(long id))
{
int i;
for (i = 0; i < cp->size; i++)
@@ -63,16 +63,16 @@ static char* get_cached(cache_t *cp, unsigned id, ug_func* fp)
cp->cache = xrealloc_vector(cp->cache, 2, i);
cp->cache[i].id = id;
/* Never fails. Generates numeric string if name isn't found */
- fp(cp->cache[i].name, sizeof(cp->cache[i].name), id);
+ safe_strncpy(cp->cache[i].name, x2x_utoa(id), sizeof(cp->cache[i].name));
return cp->cache[i].name;
}
const char* FAST_FUNC get_cached_username(uid_t uid)
{
- return get_cached(&username, uid, bb_getpwuid);
+ return get_cached(&username, uid, uid2uname_utoa);
}
const char* FAST_FUNC get_cached_groupname(gid_t gid)
{
- return get_cached(&groupname, gid, bb_getgrgid);
+ return get_cached(&groupname, gid, gid2group_utoa);
}
@@ -219,7 +219,6 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
#if !ENABLE_FEATURE_FAST_TOP
unsigned long vsz, rss;
#endif
-
/* see proc(5) for some details on this */
strcpy(filename_tail, "/stat");
n = read_to_buf(filename, buf);
@@ -247,9 +246,12 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
"%lu " /* start_time */
"%lu " /* vsize */
"%lu " /* rss */
- /* "%lu %lu %lu %lu %lu %lu " rss_rlim, start_code, end_code, start_stack, kstk_esp, kstk_eip */
- /* "%u %u %u %u " signal, blocked, sigignore, sigcatch */
- /* "%lu %lu %lu" wchan, nswap, cnswap */
+#if ENABLE_FEATURE_TOP_SMP_PROCESS
+ "%*s %*s %*s %*s %*s %*s " /*rss_rlim, start_code, end_code, start_stack, kstk_esp, kstk_eip */
+ "%*s %*s %*s %*s " /*signal, blocked, sigignore, sigcatch */
+ "%*s %*s %*s %*s " /*wchan, nswap, cnswap, exit_signal */
+ "%d" /*cpu last seen on*/
+#endif
,
sp->state, &sp->ppid,
&sp->pgid, &sp->sid, &tty,
@@ -257,9 +259,19 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
&tasknice,
&sp->start_time,
&vsz,
- &rss);
- if (n != 11)
+ &rss
+#if ENABLE_FEATURE_TOP_SMP_PROCESS
+ , &sp->last_seen_on_cpu
+#endif
+ );
+
+ if (n < 11)
break;
+#if ENABLE_FEATURE_TOP_SMP_PROCESS
+ if (n < 11+15)
+ sp->last_seen_on_cpu = 0;
+#endif
+
/* vsz is in bytes and we want kb */
sp->vsz = vsz >> 10;
/* vsz is in bytes but rss is in *PAGES*! Can you believe that? */
@@ -288,7 +300,15 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
sp->vsz = fast_strtoul_10(&cp) >> 10;
/* vsz is in bytes but rss is in *PAGES*! Can you believe that? */
sp->rss = fast_strtoul_10(&cp) << sp->shift_pages_to_kb;
+#if ENABLE_FEATURE_TOP_SMP_PROCESS
+ /* (6): rss_rlim, start_code, end_code, start_stack, kstk_esp, kstk_eip */
+ /* (4): signal, blocked, sigignore, sigcatch */
+ /* (4): wchan, nswap, cnswap, exit_signal */
+ cp = skip_fields(cp, 14);
+//FIXME: is it safe to assume this field exists?
+ sp->last_seen_on_cpu = fast_strtoul_10(&cp);
#endif
+#endif /* end of !ENABLE_FEATURE_TOP_SMP_PROCESS */
if (sp->vsz == 0 && sp->state[0] != 'Z')
sp->state[1] = 'W';
@@ -300,7 +320,6 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
sp->state[2] = 'N';
else
sp->state[2] = ' ';
-
}
#if ENABLE_FEATURE_TOPMEM
diff --git a/release/src/router/busybox/libbb/pw_encrypt.c b/release/src/router/busybox/libbb/pw_encrypt.c
index 469e71f6cc..6fc0ba87c7 100644
--- a/release/src/router/busybox/libbb/pw_encrypt.c
+++ b/release/src/router/busybox/libbb/pw_encrypt.c
@@ -1,6 +1,6 @@
/* vi: set sw=4 ts=4: */
/*
- * Utility routine.
+ * Utility routines.
*
* Copyright (C) 1999-2004 by Erik Andersen
*
@@ -9,17 +9,70 @@
#include "libbb.h"
+/* static const uint8_t ascii64[] =
+ * "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+ */
+
+static int i64c(int i)
+{
+ i &= 0x3f;
+ if (i == 0)
+ return '.';
+ if (i == 1)
+ return '/';
+ if (i < 12)
+ return ('0' - 2 + i);
+ if (i < 38)
+ return ('A' - 12 + i);
+ return ('a' - 38 + i);
+}
+
+int FAST_FUNC crypt_make_salt(char *p, int cnt, int x)
+{
+ x += getpid() + time(NULL);
+ do {
+ /* x = (x*1664525 + 1013904223) % 2^32 generator is lame
+ * (low-order bit is not "random", etc...),
+ * but for our purposes it is good enough */
+ x = x*1664525 + 1013904223;
+ /* BTW, Park and Miller's "minimal standard generator" is
+ * x = x*16807 % ((2^31)-1)
+ * It has no problem with visibly alternating lowest bit
+ * but is also weak in cryptographic sense + needs div,
+ * which needs more code (and slower) on many CPUs */
+ *p++ = i64c(x >> 16);
+ *p++ = i64c(x >> 22);
+ } while (--cnt);
+ *p = '\0';
+ return x;
+}
+
#if ENABLE_USE_BB_CRYPT
+static char*
+to64(char *s, unsigned v, int n)
+{
+ while (--n >= 0) {
+ /* *s++ = ascii64[v & 0x3f]; */
+ *s++ = i64c(v);
+ v >>= 6;
+ }
+ return s;
+}
+
/*
* DES and MD5 crypt implementations are taken from uclibc.
* They were modified to not use static buffers.
*/
-/* Common for them */
-static const uint8_t ascii64[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
#include "pw_encrypt_des.c"
#include "pw_encrypt_md5.c"
+#if ENABLE_USE_BB_CRYPT_SHA
+#include "pw_encrypt_sha.c"
+#endif
+/* Other advanced crypt ids (TODO?): */
+/* $2$ or $2a$: Blowfish */
static struct const_des_ctx *des_cctx;
static struct des_ctx *des_ctx;
@@ -27,18 +80,20 @@ static struct des_ctx *des_ctx;
/* my_crypt returns malloc'ed data */
static char *my_crypt(const char *key, const char *salt)
{
- /* First, check if we are supposed to be using the MD5 replacement
- * instead of DES... */
- if (salt[0] == '$' && salt[1] == '1' && salt[2] == '$') {
- return md5_crypt(xzalloc(MD5_OUT_BUFSIZE), (unsigned char*)key, (unsigned char*)salt);
+ /* MD5 or SHA? */
+ if (salt[0] == '$' && salt[1] && salt[2] == '$') {
+ if (salt[1] == '1')
+ return md5_crypt(xzalloc(MD5_OUT_BUFSIZE), (unsigned char*)key, (unsigned char*)salt);
+#if ENABLE_USE_BB_CRYPT_SHA
+ if (salt[1] == '5' || salt[1] == '6')
+ return sha_crypt((char*)key, (char*)salt);
+#endif
}
- {
- if (!des_cctx)
- des_cctx = const_des_init();
- des_ctx = des_init(des_ctx, des_cctx);
- return des_crypt(des_ctx, xzalloc(DES_OUT_BUFSIZE), (unsigned char*)key, (unsigned char*)salt);
- }
+ if (!des_cctx)
+ des_cctx = const_des_init();
+ des_ctx = des_init(des_ctx, des_cctx);
+ return des_crypt(des_ctx, xzalloc(DES_OUT_BUFSIZE), (unsigned char*)key, (unsigned char*)salt);
}
/* So far nobody wants to have it public */
@@ -54,12 +109,6 @@ char* FAST_FUNC pw_encrypt(const char *clear, const char *salt, int cleanup)
{
char *encrypted;
-#if 0 /* was CONFIG_FEATURE_SHA1_PASSWORDS, but there is no such thing??? */
- if (strncmp(salt, "$2$", 3) == 0) {
- return sha1_crypt(clear);
- }
-#endif
-
encrypted = my_crypt(clear, salt);
if (cleanup)
@@ -72,12 +121,6 @@ char* FAST_FUNC pw_encrypt(const char *clear, const char *salt, int cleanup)
char* FAST_FUNC pw_encrypt(const char *clear, const char *salt, int cleanup)
{
-#if 0 /* was CONFIG_FEATURE_SHA1_PASSWORDS, but there is no such thing??? */
- if (strncmp(salt, "$2$", 3) == 0) {
- return xstrdup(sha1_crypt(clear));
- }
-#endif
-
return xstrdup(crypt(clear, salt));
}
diff --git a/release/src/router/busybox/libbb/pw_encrypt_des.c b/release/src/router/busybox/libbb/pw_encrypt_des.c
index cd19a63f78..52548d6239 100644
--- a/release/src/router/busybox/libbb/pw_encrypt_des.c
+++ b/release/src/router/busybox/libbb/pw_encrypt_des.c
@@ -696,13 +696,28 @@ do_des(struct des_ctx *ctx, /*uint32_t l_in, uint32_t r_in,*/ uint32_t *l_out, u
#define DES_OUT_BUFSIZE 21
+static void
+to64_msb_first(char *s, unsigned v)
+{
+#if 0
+ *s++ = ascii64[(v >> 18) & 0x3f]; /* bits 23..18 */
+ *s++ = ascii64[(v >> 12) & 0x3f]; /* bits 17..12 */
+ *s++ = ascii64[(v >> 6) & 0x3f]; /* bits 11..6 */
+ *s = ascii64[v & 0x3f]; /* bits 5..0 */
+#endif
+ *s++ = i64c(v >> 18); /* bits 23..18 */
+ *s++ = i64c(v >> 12); /* bits 17..12 */
+ *s++ = i64c(v >> 6); /* bits 11..6 */
+ *s = i64c(v); /* bits 5..0 */
+}
+
static char *
NOINLINE
des_crypt(struct des_ctx *ctx, char output[DES_OUT_BUFSIZE],
const unsigned char *key, const unsigned char *setting)
{
- uint32_t salt, l, r0, r1, keybuf[2];
- uint8_t *p, *q;
+ uint32_t salt, r0, r1, keybuf[2];
+ uint8_t *q;
/*
* Copy the key, shifting each character up by one bit
@@ -733,34 +748,39 @@ des_crypt(struct des_ctx *ctx, char output[DES_OUT_BUFSIZE],
*/
output[1] = setting[1] ? setting[1] : output[0];
- p = (uint8_t *)output + 2;
-
setup_salt(ctx, salt);
- /*
- * Do it.
- */
+ /* Do it. */
do_des(ctx, /*0, 0,*/ &r0, &r1, 25 /* count */);
- /*
- * Now encode the result...
- */
- l = (r0 >> 8);
- *p++ = ascii64[(l >> 18) & 0x3f];
- *p++ = ascii64[(l >> 12) & 0x3f];
- *p++ = ascii64[(l >> 6) & 0x3f];
- *p++ = ascii64[l & 0x3f];
-
+ /* Now encode the result. */
+#if 0
+{
+ uint32_t l = (r0 >> 8);
+ q = (uint8_t *)output + 2;
+ *q++ = ascii64[(l >> 18) & 0x3f]; /* bits 31..26 of r0 */
+ *q++ = ascii64[(l >> 12) & 0x3f]; /* bits 25..20 of r0 */
+ *q++ = ascii64[(l >> 6) & 0x3f]; /* bits 19..14 of r0 */
+ *q++ = ascii64[l & 0x3f]; /* bits 13..8 of r0 */
l = ((r0 << 16) | (r1 >> 16));
- *p++ = ascii64[(l >> 18) & 0x3f];
- *p++ = ascii64[(l >> 12) & 0x3f];
- *p++ = ascii64[(l >> 6) & 0x3f];
- *p++ = ascii64[l & 0x3f];
-
+ *q++ = ascii64[(l >> 18) & 0x3f]; /* bits 7..2 of r0 */
+ *q++ = ascii64[(l >> 12) & 0x3f]; /* bits 1..2 of r0 and 31..28 of r1 */
+ *q++ = ascii64[(l >> 6) & 0x3f]; /* bits 27..22 of r1 */
+ *q++ = ascii64[l & 0x3f]; /* bits 21..16 of r1 */
l = r1 << 2;
- *p++ = ascii64[(l >> 12) & 0x3f];
- *p++ = ascii64[(l >> 6) & 0x3f];
- *p++ = ascii64[l & 0x3f];
- *p = 0;
+ *q++ = ascii64[(l >> 12) & 0x3f]; /* bits 15..10 of r1 */
+ *q++ = ascii64[(l >> 6) & 0x3f]; /* bits 9..4 of r1 */
+ *q++ = ascii64[l & 0x3f]; /* bits 3..0 of r1 + 00 */
+ *q = 0;
+}
+#else
+ /* Each call takes low-order 24 bits and stores 4 chars */
+ /* bits 31..8 of r0 */
+ to64_msb_first(output + 2, (r0 >> 8));
+ /* bits 7..0 of r0 and 31..16 of r1 */
+ to64_msb_first(output + 6, (r0 << 16) | (r1 >> 16));
+ /* (bits 15..0 of r1 + 00) and NUL byte */
+ to64_msb_first(output + 10, (r1 << 8));
+#endif
return output;
}
diff --git a/release/src/router/busybox/libbb/pw_encrypt_md5.c b/release/src/router/busybox/libbb/pw_encrypt_md5.c
dissimilarity index 79%
index 8d0a516cf9..58964b5676 100644
--- a/release/src/router/busybox/libbb/pw_encrypt_md5.c
+++ b/release/src/router/busybox/libbb/pw_encrypt_md5.c
@@ -1,648 +1,161 @@
-/*
- * MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
- *
- * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
- * rights reserved.
- *
- * License to copy and use this software is granted provided that it
- * is identified as the "RSA Data Security, Inc. MD5 Message-Digest
- * Algorithm" in all material mentioning or referencing this software
- * or this function.
- *
- * License is also granted to make and use derivative works provided
- * that such works are identified as "derived from the RSA Data
- * Security, Inc. MD5 Message-Digest Algorithm" in all material
- * mentioning or referencing the derived work.
- *
- * RSA Data Security, Inc. makes no representations concerning either
- * the merchantability of this software or the suitability of this
- * software for any particular purpose. It is provided "as is"
- * without express or implied warranty of any kind.
- *
- * These notices must be retained in any copies of any part of this
- * documentation and/or software.
- *
- * $FreeBSD: src/lib/libmd/md5c.c,v 1.9.2.1 1999/08/29 14:57:12 peter Exp $
- *
- * This code is the same as the code published by RSA Inc. It has been
- * edited for clarity and style only.
- *
- * ----------------------------------------------------------------------------
- * The md5_crypt() function was taken from freeBSD's libcrypt and contains
- * this license:
- * "THE BEER-WARE LICENSE" (Revision 42):
- * wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
- *
- * $FreeBSD: src/lib/libcrypt/crypt.c,v 1.7.2.1 1999/08/29 14:56:33 peter Exp $
- *
- * ----------------------------------------------------------------------------
- * On April 19th, 2001 md5_crypt() was modified to make it reentrant
- * by Erik Andersen
- *
- *
- * June 28, 2001 Manuel Novoa III
- *
- * "Un-inlined" code using loops and static const tables in order to
- * reduce generated code size (on i386 from approx 4k to approx 2.5k).
- *
- * June 29, 2001 Manuel Novoa III
- *
- * Completely removed static PADDING array.
- *
- * Reintroduced the loop unrolling in MD5_Transform and added the
- * MD5_SIZE_OVER_SPEED option for configurability. Define below as:
- * 0 fully unrolled loops
- * 1 partially unrolled (4 ops per loop)
- * 2 no unrolling -- introduces the need to swap 4 variables (slow)
- * 3 no unrolling and all 4 loops merged into one with switch
- * in each loop (glacial)
- * On i386, sizes are roughly (-Os -fno-builtin):
- * 0: 3k 1: 2.5k 2: 2.2k 3: 2k
- *
- *
- * Since SuSv3 does not require crypt_r, modified again August 7, 2002
- * by Erik Andersen to remove reentrance stuff...
- */
-
-/*
- * Valid values are 1 (fastest/largest) to 3 (smallest/slowest).
- */
-#define MD5_SIZE_OVER_SPEED 3
-
-/**********************************************************************/
-
-/* MD5 context. */
-struct MD5Context {
- uint32_t state[4]; /* state (ABCD) */
- uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */
- unsigned char buffer[64]; /* input buffer */
-};
-
-static void __md5_Init(struct MD5Context *);
-static void __md5_Update(struct MD5Context *, const unsigned char *, unsigned int);
-static void __md5_Pad(struct MD5Context *);
-static void __md5_Final(unsigned char [16], struct MD5Context *);
-static void __md5_Transform(uint32_t [4], const unsigned char [64]);
-
-
-#define MD5_MAGIC_STR "$1$"
-#define MD5_MAGIC_LEN (sizeof(MD5_MAGIC_STR) - 1)
-static const unsigned char __md5__magic[] = MD5_MAGIC_STR;
-
-
-#ifdef i386
-#define __md5_Encode memcpy
-#define __md5_Decode memcpy
-#else /* i386 */
-
-/*
- * __md5_Encodes input (uint32_t) into output (unsigned char). Assumes len is
- * a multiple of 4.
- */
-static void
-__md5_Encode(unsigned char *output, uint32_t *input, unsigned int len)
-{
- unsigned int i, j;
-
- for (i = 0, j = 0; j < len; i++, j += 4) {
- output[j] = input[i];
- output[j+1] = (input[i] >> 8);
- output[j+2] = (input[i] >> 16);
- output[j+3] = (input[i] >> 24);
- }
-}
-
-/*
- * __md5_Decodes input (unsigned char) into output (uint32_t). Assumes len is
- * a multiple of 4.
- */
-static void
-__md5_Decode(uint32_t *output, const unsigned char *input, unsigned int len)
-{
- unsigned int i, j;
-
- for (i = 0, j = 0; j < len; i++, j += 4)
- output[i] = ((uint32_t)input[j]) | (((uint32_t)input[j+1]) << 8) |
- (((uint32_t)input[j+2]) << 16) | (((uint32_t)input[j+3]) << 24);
-}
-#endif /* i386 */
-
-/* F, G, H and I are basic MD5 functions. */
-#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
-#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-#define I(x, y, z) ((y) ^ ((x) | ~(z)))
-
-/* ROTATE_LEFT rotates x left n bits. */
-#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
-
-/*
- * FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
- * Rotation is separate from addition to prevent recomputation.
- */
-#define FF(a, b, c, d, x, s, ac) { \
- (a) += F ((b), (c), (d)) + (x) + (uint32_t)(ac); \
- (a) = ROTATE_LEFT((a), (s)); \
- (a) += (b); \
- }
-#define GG(a, b, c, d, x, s, ac) { \
- (a) += G ((b), (c), (d)) + (x) + (uint32_t)(ac); \
- (a) = ROTATE_LEFT((a), (s)); \
- (a) += (b); \
- }
-#define HH(a, b, c, d, x, s, ac) { \
- (a) += H ((b), (c), (d)) + (x) + (uint32_t)(ac); \
- (a) = ROTATE_LEFT((a), (s)); \
- (a) += (b); \
- }
-#define II(a, b, c, d, x, s, ac) { \
- (a) += I ((b), (c), (d)) + (x) + (uint32_t)(ac); \
- (a) = ROTATE_LEFT((a), (s)); \
- (a) += (b); \
- }
-
-/* MD5 initialization. Begins an MD5 operation, writing a new context. */
-static void __md5_Init(struct MD5Context *context)
-{
- context->count[0] = context->count[1] = 0;
-
- /* Load magic initialization constants. */
- context->state[0] = 0x67452301;
- context->state[1] = 0xefcdab89;
- context->state[2] = 0x98badcfe;
- context->state[3] = 0x10325476;
-}
-
-/*
- * MD5 block update operation. Continues an MD5 message-digest
- * operation, processing another message block, and updating the
- * context.
- */
-static void __md5_Update(struct MD5Context *context, const unsigned char *input, unsigned int inputLen)
-{
- unsigned int i, idx, partLen;
-
- /* Compute number of bytes mod 64 */
- idx = (context->count[0] >> 3) & 0x3F;
-
- /* Update number of bits */
- context->count[0] += (inputLen << 3);
- if (context->count[0] < (inputLen << 3))
- context->count[1]++;
- context->count[1] += (inputLen >> 29);
-
- partLen = 64 - idx;
-
- /* Transform as many times as possible. */
- if (inputLen >= partLen) {
- memcpy(&context->buffer[idx], input, partLen);
- __md5_Transform(context->state, context->buffer);
-
- for (i = partLen; i + 63 < inputLen; i += 64)
- __md5_Transform(context->state, &input[i]);
-
- idx = 0;
- } else
- i = 0;
-
- /* Buffer remaining input */
- memcpy(&context->buffer[idx], &input[i], inputLen - i);
-}
-
-/*
- * MD5 padding. Adds padding followed by original length.
- */
-static void __md5_Pad(struct MD5Context *context)
-{
- unsigned char bits[8];
- unsigned int idx, padLen;
- unsigned char PADDING[64];
-
- memset(PADDING, 0, sizeof(PADDING));
- PADDING[0] = 0x80;
-
- /* Save number of bits */
- __md5_Encode(bits, context->count, 8);
-
- /* Pad out to 56 mod 64. */
- idx = (context->count[0] >> 3) & 0x3f;
- padLen = (idx < 56) ? (56 - idx) : (120 - idx);
- __md5_Update(context, PADDING, padLen);
-
- /* Append length (before padding) */
- __md5_Update(context, bits, 8);
-}
-
-/*
- * MD5 finalization. Ends an MD5 message-digest operation, writing the
- * the message digest and zeroizing the context.
- */
-static void __md5_Final(unsigned char digest[16], struct MD5Context *context)
-{
- /* Do padding. */
- __md5_Pad(context);
-
- /* Store state in digest */
- __md5_Encode(digest, context->state, 16);
-
- /* Zeroize sensitive information. */
- memset(context, 0, sizeof(*context));
-}
-
-/* MD5 basic transformation. Transforms state based on block. */
-static void __md5_Transform(uint32_t state[4], const unsigned char block[64])
-{
- uint32_t a, b, c, d, x[16];
-#if MD5_SIZE_OVER_SPEED > 1
- uint32_t temp;
- const unsigned char *ps;
-
- static const unsigned char S[] = {
- 7, 12, 17, 22,
- 5, 9, 14, 20,
- 4, 11, 16, 23,
- 6, 10, 15, 21
- };
-#endif /* MD5_SIZE_OVER_SPEED > 1 */
-
-#if MD5_SIZE_OVER_SPEED > 0
- const uint32_t *pc;
- const unsigned char *pp;
- int i;
-
- static const uint32_t C[] = {
- /* 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 unsigned char P[] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 1 */
- 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 */
- };
-
-#endif /* MD5_SIZE_OVER_SPEED > 0 */
-
- __md5_Decode(x, block, 64);
-
- a = state[0]; b = state[1]; c = state[2]; d = state[3];
-
-#if MD5_SIZE_OVER_SPEED > 2
- pc = C; pp = P; ps = S - 4;
-
- for (i = 0; i < 64; i++) {
- if ((i & 0x0f) == 0) ps += 4;
- temp = a;
- switch (i>>4) {
- case 0:
- temp += F(b, c, d);
- break;
- case 1:
- temp += G(b, c, d);
- break;
- case 2:
- temp += H(b, c, d);
- break;
- case 3:
- temp += I(b, c, d);
- break;
- }
- temp += x[*pp++] + *pc++;
- temp = ROTATE_LEFT(temp, ps[i & 3]);
- temp += b;
- a = d; d = c; c = b; b = temp;
- }
-#elif MD5_SIZE_OVER_SPEED > 1
- pc = C; pp = P; ps = S;
-
- /* Round 1 */
- for (i = 0; i < 16; i++) {
- FF(a, b, c, d, x[*pp], ps[i & 0x3], *pc); pp++; pc++;
- temp = d; d = c; c = b; b = a; a = temp;
- }
-
- /* Round 2 */
- ps += 4;
- for (; i < 32; i++) {
- GG(a, b, c, d, x[*pp], ps[i & 0x3], *pc); pp++; pc++;
- temp = d; d = c; c = b; b = a; a = temp;
- }
- /* Round 3 */
- ps += 4;
- for (; i < 48; i++) {
- HH(a, b, c, d, x[*pp], ps[i & 0x3], *pc); pp++; pc++;
- temp = d; d = c; c = b; b = a; a = temp;
- }
-
- /* Round 4 */
- ps += 4;
- for (; i < 64; i++) {
- II(a, b, c, d, x[*pp], ps[i & 0x3], *pc); pp++; pc++;
- temp = d; d = c; c = b; b = a; a = temp;
- }
-#elif MD5_SIZE_OVER_SPEED > 0
- pc = C; pp = P;
-
- /* Round 1 */
- for (i = 0; i < 4; i++) {
- FF(a, b, c, d, x[*pp], 7, *pc); pp++; pc++;
- FF(d, a, b, c, x[*pp], 12, *pc); pp++; pc++;
- FF(c, d, a, b, x[*pp], 17, *pc); pp++; pc++;
- FF(b, c, d, a, x[*pp], 22, *pc); pp++; pc++;
- }
-
- /* Round 2 */
- for (i = 0; i < 4; i++) {
- GG(a, b, c, d, x[*pp], 5, *pc); pp++; pc++;
- GG(d, a, b, c, x[*pp], 9, *pc); pp++; pc++;
- GG(c, d, a, b, x[*pp], 14, *pc); pp++; pc++;
- GG(b, c, d, a, x[*pp], 20, *pc); pp++; pc++;
- }
- /* Round 3 */
- for (i = 0; i < 4; i++) {
- HH(a, b, c, d, x[*pp], 4, *pc); pp++; pc++;
- HH(d, a, b, c, x[*pp], 11, *pc); pp++; pc++;
- HH(c, d, a, b, x[*pp], 16, *pc); pp++; pc++;
- HH(b, c, d, a, x[*pp], 23, *pc); pp++; pc++;
- }
-
- /* Round 4 */
- for (i = 0; i < 4; i++) {
- II(a, b, c, d, x[*pp], 6, *pc); pp++; pc++;
- II(d, a, b, c, x[*pp], 10, *pc); pp++; pc++;
- II(c, d, a, b, x[*pp], 15, *pc); pp++; pc++;
- II(b, c, d, a, x[*pp], 21, *pc); pp++; pc++;
- }
-#else
- /* Round 1 */
-#define S11 7
-#define S12 12
-#define S13 17
-#define S14 22
- FF(a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
- FF(d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
- FF(c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
- FF(b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
- FF(a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
- FF(d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
- FF(c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
- FF(b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
- FF(a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
- FF(d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
- FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
- FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
- FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
- FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
- FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
- FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
-
- /* Round 2 */
-#define S21 5
-#define S22 9
-#define S23 14
-#define S24 20
- GG(a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
- GG(d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
- GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
- GG(b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
- GG(a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
- GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
- GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
- GG(b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
- GG(a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
- GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
- GG(c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
- GG(b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
- GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
- GG(d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
- GG(c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
- GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
-
- /* Round 3 */
-#define S31 4
-#define S32 11
-#define S33 16
-#define S34 23
- HH(a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
- HH(d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
- HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
- HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
- HH(a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
- HH(d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
- HH(c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
- HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
- HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
- HH(d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
- HH(c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
- HH(b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
- HH(a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
- HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
- HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
- HH(b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
-
- /* Round 4 */
-#define S41 6
-#define S42 10
-#define S43 15
-#define S44 21
- II(a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
- II(d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
- II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
- II(b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
- II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
- II(d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
- II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
- II(b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
- II(a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
- II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
- II(c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
- II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
- II(a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
- II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
- II(c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
- II(b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
-#endif
-
- state[0] += a;
- state[1] += b;
- state[2] += c;
- state[3] += d;
-
- /* Zeroize sensitive information. */
- memset(x, 0, sizeof(x));
-}
-
-
-static char*
-__md5_to64(char *s, unsigned v, int n)
-{
- while (--n >= 0) {
- *s++ = ascii64[v & 0x3f];
- v >>= 6;
- }
- return s;
-}
-
-/*
- * UNIX password
- *
- * Use MD5 for what it is best at...
- */
-#define MD5_OUT_BUFSIZE 36
-static char *
-NOINLINE
-md5_crypt(char passwd[MD5_OUT_BUFSIZE], const unsigned char *pw, const unsigned char *salt)
-{
- const unsigned char *sp, *ep;
- char *p;
- unsigned char final[17]; /* final[16] exists only to aid in looping */
- int sl, pl, i, pw_len;
- struct MD5Context ctx, ctx1;
-
- /* Refine the Salt first */
- sp = salt;
-
-// always true for bbox
-// /* If it starts with the magic string, then skip that */
-// if (!strncmp(sp, __md5__magic, MD5_MAGIC_LEN))
- sp += MD5_MAGIC_LEN;
-
- /* It stops at the first '$', max 8 chars */
- for (ep = sp; *ep && *ep != '$' && ep < (sp+8); ep++)
- continue;
-
- /* get the length of the true salt */
- sl = ep - sp;
-
- __md5_Init(&ctx);
-
- /* The password first, since that is what is most unknown */
- pw_len = strlen((char*)pw);
- __md5_Update(&ctx, pw, pw_len);
-
- /* Then our magic string */
- __md5_Update(&ctx, __md5__magic, MD5_MAGIC_LEN);
-
- /* Then the raw salt */
- __md5_Update(&ctx, sp, sl);
-
- /* Then just as many characters of the MD5(pw, salt, pw) */
- __md5_Init(&ctx1);
- __md5_Update(&ctx1, pw, pw_len);
- __md5_Update(&ctx1, sp, sl);
- __md5_Update(&ctx1, pw, pw_len);
- __md5_Final(final, &ctx1);
- for (pl = pw_len; pl > 0; pl -= 16)
- __md5_Update(&ctx, final, pl > 16 ? 16 : pl);
-
- /* Don't leave anything around in vm they could use. */
-//TODO: the above comment seems to be wrong. final is used later.
- memset(final, 0, sizeof(final));
-
- /* Then something really weird... */
- for (i = pw_len; i; i >>= 1) {
- __md5_Update(&ctx, ((i & 1) ? final : (const unsigned char *) pw), 1);
- }
-
- /* Now make the output string */
- passwd[0] = '$';
- passwd[1] = '1';
- passwd[2] = '$';
- strncpy(passwd + 3, (char*)sp, sl);
- passwd[sl + 3] = '$';
-
- __md5_Final(final, &ctx);
-
- /*
- * and now, just to make sure things don't run too fast
- * On a 60 Mhz Pentium this takes 34 msec, so you would
- * need 30 seconds to build a 1000 entry dictionary...
- */
- for (i = 0; i < 1000; i++) {
- __md5_Init(&ctx1);
- if (i & 1)
- __md5_Update(&ctx1, pw, pw_len);
- else
- __md5_Update(&ctx1, final, 16);
-
- if (i % 3)
- __md5_Update(&ctx1, sp, sl);
-
- if (i % 7)
- __md5_Update(&ctx1, pw, pw_len);
-
- if (i & 1)
- __md5_Update(&ctx1, final, 16);
- else
- __md5_Update(&ctx1, pw, pw_len);
- __md5_Final(final, &ctx1);
- }
-
- p = passwd + sl + 4; /* 12 bytes max (sl is up to 8 bytes) */
-
- /* Add 5*4+2 = 22 bytes of hash, + NUL byte. */
- final[16] = final[5];
- for (i = 0; i < 5; i++) {
- unsigned l = (final[i] << 16) | (final[i+6] << 8) | final[i+12];
- p = __md5_to64(p, l, 4);
- }
- p = __md5_to64(p, final[11], 2);
- *p = '\0';
-
- /* Don't leave anything around in vm they could use. */
- memset(final, 0, sizeof(final));
-
- return passwd;
-}
-
-#undef MD5_SIZE_OVER_SPEED
-#undef MD5_MAGIC_STR
-#undef MD5_MAGIC_LEN
-#undef __md5_Encode
-#undef __md5_Decode
-#undef F
-#undef G
-#undef H
-#undef I
-#undef ROTATE_LEFT
-#undef FF
-#undef GG
-#undef HH
-#undef II
-#undef S11
-#undef S12
-#undef S13
-#undef S14
-#undef S21
-#undef S22
-#undef S23
-#undef S24
-#undef S31
-#undef S32
-#undef S33
-#undef S34
-#undef S41
-#undef S42
-#undef S43
-#undef S44
+/*
+ * MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
+ *
+ * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ * rights reserved.
+ *
+ * License to copy and use this software is granted provided that it
+ * is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+ * Algorithm" in all material mentioning or referencing this software
+ * or this function.
+ *
+ * License is also granted to make and use derivative works provided
+ * that such works are identified as "derived from the RSA Data
+ * Security, Inc. MD5 Message-Digest Algorithm" in all material
+ * mentioning or referencing the derived work.
+ *
+ * RSA Data Security, Inc. makes no representations concerning either
+ * the merchantability of this software or the suitability of this
+ * software for any particular purpose. It is provided "as is"
+ * without express or implied warranty of any kind.
+ *
+ * These notices must be retained in any copies of any part of this
+ * documentation and/or software.
+ *
+ * $FreeBSD: src/lib/libmd/md5c.c,v 1.9.2.1 1999/08/29 14:57:12 peter Exp $
+ *
+ * This code is the same as the code published by RSA Inc. It has been
+ * edited for clarity and style only.
+ *
+ * ----------------------------------------------------------------------------
+ * The md5_crypt() function was taken from freeBSD's libcrypt and contains
+ * this license:
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * wrote this file. As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
+ *
+ * $FreeBSD: src/lib/libcrypt/crypt.c,v 1.7.2.1 1999/08/29 14:56:33 peter Exp $
+ *
+ * ----------------------------------------------------------------------------
+ * On April 19th, 2001 md5_crypt() was modified to make it reentrant
+ * by Erik Andersen
+ *
+ *
+ * June 28, 2001 Manuel Novoa III
+ *
+ * "Un-inlined" code using loops and static const tables in order to
+ * reduce generated code size (on i386 from approx 4k to approx 2.5k).
+ *
+ * June 29, 2001 Manuel Novoa III
+ *
+ * Completely removed static PADDING array.
+ *
+ * Reintroduced the loop unrolling in MD5_Transform and added the
+ * MD5_SIZE_OVER_SPEED option for configurability. Define below as:
+ * 0 fully unrolled loops
+ * 1 partially unrolled (4 ops per loop)
+ * 2 no unrolling -- introduces the need to swap 4 variables (slow)
+ * 3 no unrolling and all 4 loops merged into one with switch
+ * in each loop (glacial)
+ * On i386, sizes are roughly (-Os -fno-builtin):
+ * 0: 3k 1: 2.5k 2: 2.2k 3: 2k
+ *
+ * Since SuSv3 does not require crypt_r, modified again August 7, 2002
+ * by Erik Andersen to remove reentrance stuff...
+ */
+
+/*
+ * UNIX password
+ *
+ * Use MD5 for what it is best at...
+ */
+#define MD5_OUT_BUFSIZE 36
+static char *
+NOINLINE
+md5_crypt(char result[MD5_OUT_BUFSIZE], const unsigned char *pw, const unsigned char *salt)
+{
+ char *p;
+ unsigned char final[17]; /* final[16] exists only to aid in looping */
+ int sl, pl, i, pw_len;
+ md5_ctx_t ctx, ctx1;
+
+ /* NB: in busybox, "$1$" in salt is always present */
+
+ /* Refine the Salt first */
+
+ /* Get the length of the salt including "$1$" */
+ sl = 3;
+ while (salt[sl] && salt[sl] != '$' && sl < (3 + 8))
+ sl++;
+
+ /* Hash. the password first, since that is what is most unknown */
+ md5_begin(&ctx);
+ pw_len = strlen((char*)pw);
+ md5_hash(pw, pw_len, &ctx);
+
+ /* Then the salt including "$1$" */
+ md5_hash(salt, sl, &ctx);
+
+ /* Copy salt to result; skip "$1$" */
+ memcpy(result, salt, sl);
+ result[sl] = '$';
+ salt += 3;
+ sl -= 3;
+
+ /* Then just as many characters of the MD5(pw, salt, pw) */
+ md5_begin(&ctx1);
+ md5_hash(pw, pw_len, &ctx1);
+ md5_hash(salt, sl, &ctx1);
+ md5_hash(pw, pw_len, &ctx1);
+ md5_end(final, &ctx1);
+ for (pl = pw_len; pl > 0; pl -= 16)
+ md5_hash(final, pl > 16 ? 16 : pl, &ctx);
+
+ /* Then something really weird... */
+ memset(final, 0, sizeof(final));
+ for (i = pw_len; i; i >>= 1) {
+ md5_hash(((i & 1) ? final : (const unsigned char *) pw), 1, &ctx);
+ }
+ md5_end(final, &ctx);
+
+ /* And now, just to make sure things don't run too fast.
+ * On a 60 Mhz Pentium this takes 34 msec, so you would
+ * need 30 seconds to build a 1000 entry dictionary...
+ */
+ for (i = 0; i < 1000; i++) {
+ md5_begin(&ctx1);
+ if (i & 1)
+ md5_hash(pw, pw_len, &ctx1);
+ else
+ md5_hash(final, 16, &ctx1);
+
+ if (i % 3)
+ md5_hash(salt, sl, &ctx1);
+
+ if (i % 7)
+ md5_hash(pw, pw_len, &ctx1);
+
+ if (i & 1)
+ md5_hash(final, 16, &ctx1);
+ else
+ md5_hash(pw, pw_len, &ctx1);
+ md5_end(final, &ctx1);
+ }
+
+ p = result + sl + 4; /* 12 bytes max (sl is up to 8 bytes) */
+
+ /* Add 5*4+2 = 22 bytes of hash, + NUL byte. */
+ final[16] = final[5];
+ for (i = 0; i < 5; i++) {
+ unsigned l = (final[i] << 16) | (final[i+6] << 8) | final[i+12];
+ p = to64(p, l, 4);
+ }
+ p = to64(p, final[11], 2);
+ *p = '\0';
+
+ /* Don't leave anything around in vm they could use. */
+ memset(final, 0, sizeof(final));
+
+ return result;
+}
diff --git a/release/src/router/busybox/libbb/pw_encrypt_sha.c b/release/src/router/busybox/libbb/pw_encrypt_sha.c
new file mode 100644
index 0000000000..070e0d442c
--- /dev/null
+++ b/release/src/router/busybox/libbb/pw_encrypt_sha.c
@@ -0,0 +1,286 @@
+/* SHA256 and SHA512-based Unix crypt implementation.
+ * Released into the Public Domain by Ulrich Drepper .
+ */
+
+/* Prefix for optional rounds specification. */
+static const char str_rounds[] = "rounds=%u$";
+
+/* Maximum salt string length. */
+#define SALT_LEN_MAX 16
+/* Default number of rounds if not explicitly specified. */
+#define ROUNDS_DEFAULT 5000
+/* Minimum number of rounds. */
+#define ROUNDS_MIN 1000
+/* Maximum number of rounds. */
+#define ROUNDS_MAX 999999999
+
+static char *
+NOINLINE
+sha_crypt(/*const*/ char *key_data, /*const*/ char *salt_data)
+{
+ void (*sha_begin)(void *ctx) FAST_FUNC;
+ void (*sha_hash)(const void *buffer, size_t len, void *ctx) FAST_FUNC;
+ void (*sha_end)(void *resbuf, void *ctx) FAST_FUNC;
+ int _32or64;
+
+ char *result, *resptr;
+
+ /* btw, sha256 needs [32] and uint32_t only */
+ struct {
+ unsigned char alt_result[64];
+ unsigned char temp_result[64];
+ union {
+ sha256_ctx_t x;
+ sha512_ctx_t y;
+ } ctx;
+ union {
+ sha256_ctx_t x;
+ sha512_ctx_t y;
+ } alt_ctx;
+ } L __attribute__((__aligned__(__alignof__(uint64_t))));
+#define alt_result (L.alt_result )
+#define temp_result (L.temp_result)
+#define ctx (L.ctx )
+#define alt_ctx (L.alt_ctx )
+ unsigned salt_len;
+ unsigned key_len;
+ unsigned cnt;
+ unsigned rounds;
+ char *cp;
+ char is_sha512;
+
+ /* Analyze salt, construct already known part of result */
+ cnt = strlen(salt_data) + 1 + 43 + 1;
+ is_sha512 = salt_data[1];
+ if (is_sha512 == '6')
+ cnt += 43;
+ result = resptr = xzalloc(cnt); /* will provide NUL terminator */
+ *resptr++ = '$';
+ *resptr++ = is_sha512;
+ *resptr++ = '$';
+ rounds = ROUNDS_DEFAULT;
+ salt_data += 3;
+ if (strncmp(salt_data, str_rounds, 7) == 0) {
+ /* 7 == strlen("rounds=") */
+ char *endp;
+ cnt = bb_strtou(salt_data + 7, &endp, 10);
+ if (*endp == '$') {
+ salt_data = endp + 1;
+ rounds = cnt;
+ if (rounds < ROUNDS_MIN)
+ rounds = ROUNDS_MIN;
+ if (rounds > ROUNDS_MAX)
+ rounds = ROUNDS_MAX;
+ /* add "rounds=NNNNN$" to result */
+ resptr += sprintf(resptr, str_rounds, rounds);
+ }
+ }
+ salt_len = strchrnul(salt_data, '$') - salt_data;
+ if (salt_len > SALT_LEN_MAX)
+ salt_len = SALT_LEN_MAX;
+ /* xstrdup assures suitable alignment; also we will use it
+ as a scratch space later. */
+ salt_data = xstrndup(salt_data, salt_len);
+ /* add "salt$" to result */
+ strcpy(resptr, salt_data);
+ resptr += salt_len;
+ *resptr++ = '$';
+ /* key data doesn't need much processing */
+ key_len = strlen(key_data);
+ key_data = xstrdup(key_data);
+
+ /* Which flavor of SHAnnn ops to use? */
+ sha_begin = (void*)sha256_begin;
+ sha_hash = (void*)sha256_hash;
+ sha_end = (void*)sha256_end;
+ _32or64 = 32;
+ if (is_sha512 == '6') {
+ sha_begin = (void*)sha512_begin;
+ sha_hash = (void*)sha512_hash;
+ sha_end = (void*)sha512_end;
+ _32or64 = 64;
+ }
+
+ /* Add KEY, SALT. */
+ sha_begin(&ctx);
+ sha_hash(key_data, key_len, &ctx);
+ sha_hash(salt_data, salt_len, &ctx);
+
+ /* Compute alternate SHA sum with input KEY, SALT, and KEY.
+ The final result will be added to the first context. */
+ sha_begin(&alt_ctx);
+ sha_hash(key_data, key_len, &alt_ctx);
+ sha_hash(salt_data, salt_len, &alt_ctx);
+ sha_hash(key_data, key_len, &alt_ctx);
+ sha_end(alt_result, &alt_ctx);
+
+ /* Add result of this to the other context. */
+ /* Add for any character in the key one byte of the alternate sum. */
+ for (cnt = key_len; cnt > _32or64; cnt -= _32or64)
+ sha_hash(alt_result, _32or64, &ctx);
+ sha_hash(alt_result, cnt, &ctx);
+
+ /* Take the binary representation of the length of the key and for every
+ 1 add the alternate sum, for every 0 the key. */
+ for (cnt = key_len; cnt != 0; cnt >>= 1)
+ if ((cnt & 1) != 0)
+ sha_hash(alt_result, _32or64, &ctx);
+ else
+ sha_hash(key_data, key_len, &ctx);
+
+ /* Create intermediate result. */
+ sha_end(alt_result, &ctx);
+
+ /* Start computation of P byte sequence. */
+ /* For every character in the password add the entire password. */
+ sha_begin(&alt_ctx);
+ for (cnt = 0; cnt < key_len; ++cnt)
+ sha_hash(key_data, key_len, &alt_ctx);
+ sha_end(temp_result, &alt_ctx);
+
+ /* NB: past this point, raw key_data is not used anymore */
+
+ /* Create byte sequence P. */
+#define p_bytes key_data /* reuse the buffer as it is of the key_len size */
+ cp = p_bytes; /* was: ... = alloca(key_len); */
+ for (cnt = key_len; cnt >= _32or64; cnt -= _32or64) {
+ cp = memcpy(cp, temp_result, _32or64);
+ cp += _32or64;
+ }
+ memcpy(cp, temp_result, cnt);
+
+ /* Start computation of S byte sequence. */
+ /* For every character in the password add the entire password. */
+ sha_begin(&alt_ctx);
+ for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt)
+ sha_hash(salt_data, salt_len, &alt_ctx);
+ sha_end(temp_result, &alt_ctx);
+
+ /* NB: past this point, raw salt_data is not used anymore */
+
+ /* Create byte sequence S. */
+#define s_bytes salt_data /* reuse the buffer as it is of the salt_len size */
+ cp = s_bytes; /* was: ... = alloca(salt_len); */
+ for (cnt = salt_len; cnt >= _32or64; cnt -= _32or64) {
+ cp = memcpy(cp, temp_result, _32or64);
+ cp += _32or64;
+ }
+ memcpy(cp, temp_result, cnt);
+
+ /* Repeatedly run the collected hash value through SHA to burn
+ CPU cycles. */
+ for (cnt = 0; cnt < rounds; ++cnt) {
+ sha_begin(&ctx);
+
+ /* Add key or last result. */
+ if ((cnt & 1) != 0)
+ sha_hash(p_bytes, key_len, &ctx);
+ else
+ sha_hash(alt_result, _32or64, &ctx);
+ /* Add salt for numbers not divisible by 3. */
+ if (cnt % 3 != 0)
+ sha_hash(s_bytes, salt_len, &ctx);
+ /* Add key for numbers not divisible by 7. */
+ if (cnt % 7 != 0)
+ sha_hash(p_bytes, key_len, &ctx);
+ /* Add key or last result. */
+ if ((cnt & 1) != 0)
+ sha_hash(alt_result, _32or64, &ctx);
+ else
+ sha_hash(p_bytes, key_len, &ctx);
+
+ sha_end(alt_result, &ctx);
+ }
+
+ /* Append encrypted password to result buffer */
+//TODO: replace with something like
+// bb_uuencode(cp, src, length, bb_uuenc_tbl_XXXbase64);
+#define b64_from_24bit(B2, B1, B0, N) \
+do { \
+ unsigned w = ((B2) << 16) | ((B1) << 8) | (B0); \
+ resptr = to64(resptr, w, N); \
+} while (0)
+ if (is_sha512 == '5') {
+ unsigned i = 0;
+ while (1) {
+ unsigned j = i + 10;
+ unsigned k = i + 20;
+ if (j >= 30) j -= 30;
+ if (k >= 30) k -= 30;
+ b64_from_24bit(alt_result[i], alt_result[j], alt_result[k], 4);
+ if (k == 29)
+ break;
+ i = k + 1;
+ }
+ b64_from_24bit(0, alt_result[31], alt_result[30], 3);
+ /* was:
+ b64_from_24bit(alt_result[0], alt_result[10], alt_result[20], 4);
+ b64_from_24bit(alt_result[21], alt_result[1], alt_result[11], 4);
+ b64_from_24bit(alt_result[12], alt_result[22], alt_result[2], 4);
+ b64_from_24bit(alt_result[3], alt_result[13], alt_result[23], 4);
+ b64_from_24bit(alt_result[24], alt_result[4], alt_result[14], 4);
+ b64_from_24bit(alt_result[15], alt_result[25], alt_result[5], 4);
+ b64_from_24bit(alt_result[6], alt_result[16], alt_result[26], 4);
+ b64_from_24bit(alt_result[27], alt_result[7], alt_result[17], 4);
+ b64_from_24bit(alt_result[18], alt_result[28], alt_result[8], 4);
+ b64_from_24bit(alt_result[9], alt_result[19], alt_result[29], 4);
+ b64_from_24bit(0, alt_result[31], alt_result[30], 3);
+ */
+ } else {
+ unsigned i = 0;
+ while (1) {
+ unsigned j = i + 21;
+ unsigned k = i + 42;
+ if (j >= 63) j -= 63;
+ if (k >= 63) k -= 63;
+ b64_from_24bit(alt_result[i], alt_result[j], alt_result[k], 4);
+ if (j == 20)
+ break;
+ i = j + 1;
+ }
+ b64_from_24bit(0, 0, alt_result[63], 2);
+ /* was:
+ b64_from_24bit(alt_result[0], alt_result[21], alt_result[42], 4);
+ b64_from_24bit(alt_result[22], alt_result[43], alt_result[1], 4);
+ b64_from_24bit(alt_result[44], alt_result[2], alt_result[23], 4);
+ b64_from_24bit(alt_result[3], alt_result[24], alt_result[45], 4);
+ b64_from_24bit(alt_result[25], alt_result[46], alt_result[4], 4);
+ b64_from_24bit(alt_result[47], alt_result[5], alt_result[26], 4);
+ b64_from_24bit(alt_result[6], alt_result[27], alt_result[48], 4);
+ b64_from_24bit(alt_result[28], alt_result[49], alt_result[7], 4);
+ b64_from_24bit(alt_result[50], alt_result[8], alt_result[29], 4);
+ b64_from_24bit(alt_result[9], alt_result[30], alt_result[51], 4);
+ b64_from_24bit(alt_result[31], alt_result[52], alt_result[10], 4);
+ b64_from_24bit(alt_result[53], alt_result[11], alt_result[32], 4);
+ b64_from_24bit(alt_result[12], alt_result[33], alt_result[54], 4);
+ b64_from_24bit(alt_result[34], alt_result[55], alt_result[13], 4);
+ b64_from_24bit(alt_result[56], alt_result[14], alt_result[35], 4);
+ b64_from_24bit(alt_result[15], alt_result[36], alt_result[57], 4);
+ b64_from_24bit(alt_result[37], alt_result[58], alt_result[16], 4);
+ b64_from_24bit(alt_result[59], alt_result[17], alt_result[38], 4);
+ b64_from_24bit(alt_result[18], alt_result[39], alt_result[60], 4);
+ b64_from_24bit(alt_result[40], alt_result[61], alt_result[19], 4);
+ b64_from_24bit(alt_result[62], alt_result[20], alt_result[41], 4);
+ b64_from_24bit(0, 0, alt_result[63], 2);
+ */
+ }
+ /* *resptr = '\0'; - xzalloc did it */
+#undef b64_from_24bit
+
+ /* Clear the buffer for the intermediate result so that people
+ attaching to processes or reading core dumps cannot get any
+ information. */
+ memset(&L, 0, sizeof(L)); /* [alt]_ctx and XXX_result buffers */
+ memset(key_data, 0, key_len); /* also p_bytes */
+ memset(salt_data, 0, salt_len); /* also s_bytes */
+ free(key_data);
+ free(salt_data);
+#undef p_bytes
+#undef s_bytes
+
+ return result;
+#undef alt_result
+#undef temp_result
+#undef ctx
+#undef alt_ctx
+}
diff --git a/release/src/router/busybox/libbb/read.c b/release/src/router/busybox/libbb/read.c
index 815007c1e9..37503e84d3 100644
--- a/release/src/router/busybox/libbb/read.c
+++ b/release/src/router/busybox/libbb/read.c
@@ -141,7 +141,7 @@ char* FAST_FUNC xmalloc_reads(int fd, char *buf, size_t *maxsz_p)
{
char *p;
size_t sz = buf ? strlen(buf) : 0;
- size_t maxsz = maxsz_p ? *maxsz_p : MAXINT(size_t);
+ size_t maxsz = maxsz_p ? *maxsz_p : (INT_MAX - 4095);
goto jump_in;
while (sz < maxsz) {
@@ -198,7 +198,7 @@ void* FAST_FUNC xmalloc_read(int fd, size_t *maxsz_p)
size_t to_read;
struct stat st;
- to_read = maxsz_p ? *maxsz_p : MAXINT(ssize_t); /* max to read */
+ to_read = maxsz_p ? *maxsz_p : (INT_MAX - 4095); /* max to read */
/* Estimate file size */
st.st_size = 0; /* in case fstat fails, assume 0 */
@@ -262,7 +262,7 @@ void* FAST_FUNC xmalloc_open_read_close(const char *filename, size_t *maxsz_p)
len = lseek(fd, 0, SEEK_END) | 0x3ff; /* + up to 1k */
if (len != (off_t)-1) {
xlseek(fd, 0, SEEK_SET);
- size = maxsz_p ? *maxsz_p : INT_MAX;
+ size = maxsz_p ? *maxsz_p : (INT_MAX - 4095);
if (len < size)
size = len;
}
diff --git a/release/src/router/busybox/libbb/read_key.c b/release/src/router/busybox/libbb/read_key.c
new file mode 100644
index 0000000000..0f36d20b63
--- /dev/null
+++ b/release/src/router/busybox/libbb/read_key.c
@@ -0,0 +1,157 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Utility routines.
+ *
+ * Copyright (C) 2008 Rob Landley
+ * Copyright (C) 2008 Denys Vlasenko
+ *
+ * Licensed under GPL version 2, see file LICENSE in this tarball for details.
+ */
+#include "libbb.h"
+
+int FAST_FUNC read_key(int fd, smalluint *nbuffered, char *buffer)
+{
+ struct pollfd pfd;
+ const char *seq;
+ int n;
+ int c;
+
+ /* Known escape sequences for cursor and function keys */
+ static const char esccmds[] ALIGN1 = {
+ 'O','A' |0x80,KEYCODE_UP ,
+ 'O','B' |0x80,KEYCODE_DOWN ,
+ 'O','C' |0x80,KEYCODE_RIGHT ,
+ 'O','D' |0x80,KEYCODE_LEFT ,
+ 'O','H' |0x80,KEYCODE_HOME ,
+ 'O','F' |0x80,KEYCODE_END ,
+#if 0
+ 'O','P' |0x80,KEYCODE_FUN1 ,
+ /* [ESC] ESC O [2] P - [Alt-][Shift-]F1 */
+ /* Ctrl- seems to not affect sequences */
+ 'O','Q' |0x80,KEYCODE_FUN2 ,
+ 'O','R' |0x80,KEYCODE_FUN3 ,
+ 'O','S' |0x80,KEYCODE_FUN4 ,
+#endif
+ '[','A' |0x80,KEYCODE_UP ,
+ '[','B' |0x80,KEYCODE_DOWN ,
+ '[','C' |0x80,KEYCODE_RIGHT ,
+ '[','D' |0x80,KEYCODE_LEFT ,
+ '[','H' |0x80,KEYCODE_HOME , /* xterm */
+ /* [ESC] ESC [ [2] H - [Alt-][Shift-]Home */
+ '[','F' |0x80,KEYCODE_END , /* xterm */
+ '[','1','~' |0x80,KEYCODE_HOME , /* vt100? linux vt? or what? */
+ '[','2','~' |0x80,KEYCODE_INSERT ,
+ '[','3','~' |0x80,KEYCODE_DELETE ,
+ /* [ESC] ESC [ 3 [;2] ~ - [Alt-][Shift-]Delete */
+ '[','4','~' |0x80,KEYCODE_END , /* vt100? linux vt? or what? */
+ '[','5','~' |0x80,KEYCODE_PAGEUP ,
+ '[','6','~' |0x80,KEYCODE_PAGEDOWN,
+ '[','7','~' |0x80,KEYCODE_HOME , /* vt100? linux vt? or what? */
+ '[','8','~' |0x80,KEYCODE_END , /* vt100? linux vt? or what? */
+#if 0
+ '[','1','1','~'|0x80,KEYCODE_FUN1 ,
+ '[','1','2','~'|0x80,KEYCODE_FUN2 ,
+ '[','1','3','~'|0x80,KEYCODE_FUN3 ,
+ '[','1','4','~'|0x80,KEYCODE_FUN4 ,
+ '[','1','5','~'|0x80,KEYCODE_FUN5 ,
+ /* [ESC] ESC [ 1 5 [;2] ~ - [Alt-][Shift-]F5 */
+ '[','1','7','~'|0x80,KEYCODE_FUN6 ,
+ '[','1','8','~'|0x80,KEYCODE_FUN7 ,
+ '[','1','9','~'|0x80,KEYCODE_FUN8 ,
+ '[','2','0','~'|0x80,KEYCODE_FUN9 ,
+ '[','2','1','~'|0x80,KEYCODE_FUN10 ,
+ '[','2','3','~'|0x80,KEYCODE_FUN11 ,
+ '[','2','4','~'|0x80,KEYCODE_FUN12 ,
+#endif
+ 0
+ };
+
+ n = 0;
+ if (nbuffered)
+ n = *nbuffered;
+ if (n == 0) {
+ /* If no data, block waiting for input. If we read more
+ * than the minimal ESC sequence size, the "n=0" below
+ * would instead have to figure out how much to keep,
+ * resulting in larger code. */
+ n = safe_read(fd, buffer, 3);
+ if (n <= 0)
+ return -1;
+ }
+
+ /* Grab character to return from buffer */
+ c = (unsigned char)buffer[0];
+ n--;
+ if (n)
+ memmove(buffer, buffer + 1, n);
+
+ /* Only ESC starts ESC sequences */
+ if (c != 27)
+ goto ret;
+
+ /* Loop through known ESC sequences */
+ pfd.fd = fd;
+ pfd.events = POLLIN;
+ seq = esccmds;
+ while (*seq != '\0') {
+ /* n - position in sequence we did not read yet */
+ int i = 0; /* position in sequence to compare */
+
+ /* Loop through chars in this sequence */
+ while (1) {
+ /* So far escape sequence matched up to [i-1] */
+ if (n <= i) {
+ /* Need more chars, read another one if it wouldn't block.
+ * Note that escape sequences come in as a unit,
+ * so if we block for long it's not really an escape sequence.
+ * Timeout is needed to reconnect escape sequences
+ * split up by transmission over a serial console. */
+ if (safe_poll(&pfd, 1, 50) == 0) {
+ /* No more data!
+ * Array is sorted from shortest to longest,
+ * we can't match anything later in array,
+ * break out of both loops. */
+ goto ret;
+ }
+ errno = 0;
+ if (safe_read(fd, buffer + n, 1) <= 0) {
+ /* If EAGAIN, then fd is O_NONBLOCK and poll lied:
+ * in fact, there is no data. */
+ if (errno != EAGAIN)
+ c = -1; /* otherwise it's EOF/error */
+ goto ret;
+ }
+ n++;
+ }
+ if (buffer[i] != (seq[i] & 0x7f)) {
+ /* This seq doesn't match, go to next */
+ seq += i;
+ /* Forward to last char */
+ while (!(*seq & 0x80))
+ seq++;
+ /* Skip it and the keycode which follows */
+ seq += 2;
+ break;
+ }
+ if (seq[i] & 0x80) {
+ /* Entire seq matched */
+ c = (signed char)seq[i+1];
+ n = 0;
+ /* n -= i; memmove(...);
+ * would be more correct,
+ * but we never read ahead that much,
+ * and n == i here. */
+ goto ret;
+ }
+ i++;
+ }
+ }
+ /* We did not find matching sequence, it was a bare ESC.
+ * We possibly read and stored more input in buffer[]
+ * by now. */
+
+ ret:
+ if (nbuffered)
+ *nbuffered = n;
+ return c;
+}
diff --git a/release/src/router/busybox/libbb/rtc.c b/release/src/router/busybox/libbb/rtc.c
index 222d977ca6..51834f8f99 100644
--- a/release/src/router/busybox/libbb/rtc.c
+++ b/release/src/router/busybox/libbb/rtc.c
@@ -1,5 +1,7 @@
/*
* Common RTC functions
+ *
+ * Licensed under GPLv2, see file LICENSE in this tarball for details.
*/
#include "libbb.h"
diff --git a/release/src/router/busybox/libbb/selinux_common.c b/release/src/router/busybox/libbb/selinux_common.c
index 5fdbe9d587..275a761d29 100644
--- a/release/src/router/busybox/libbb/selinux_common.c
+++ b/release/src/router/busybox/libbb/selinux_common.c
@@ -3,6 +3,8 @@
* -- common SELinux utility functions
*
* Copyright 2007 KaiGai Kohei
+ *
+ * Licensed under GPLv2, see file LICENSE in this tarball for details.
*/
#include "libbb.h"
#include
diff --git a/release/src/router/busybox/libbb/sha1.c b/release/src/router/busybox/libbb/sha1.c
dissimilarity index 79%
index cc7edd8a79..9fa095e857 100644
--- a/release/src/router/busybox/libbb/sha1.c
+++ b/release/src/router/busybox/libbb/sha1.c
@@ -1,170 +1,465 @@
-/* vi: set sw=4 ts=4: */
-/*
- * Based on shasum from http://www.netsw.org/crypto/hash/
- * Majorly hacked up to use Dr Brian Gladman's sha1 code
- *
- * Copyright (C) 2002 Dr Brian Gladman , Worcester, UK.
- * Copyright (C) 2003 Glenn L. McGrath
- * Copyright (C) 2003 Erik Andersen
- *
- * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
- *
- * ---------------------------------------------------------------------------
- * Issue Date: 10/11/2002
- *
- * This is a byte oriented version of SHA1 that operates on arrays of bytes
- * stored in memory. It runs at 22 cycles per byte on a Pentium P4 processor
- */
-
-#include "libbb.h"
-
-#define SHA1_BLOCK_SIZE 64
-#define SHA1_DIGEST_SIZE 20
-#define SHA1_HASH_SIZE SHA1_DIGEST_SIZE
-#define SHA2_GOOD 0
-#define SHA2_BAD 1
-
-#define rotl32(x,n) (((x) << n) | ((x) >> (32 - n)))
-
-#define SHA1_MASK (SHA1_BLOCK_SIZE - 1)
-
-/* reverse byte order in 32-bit words */
-#define ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
-#define parity(x,y,z) ((x) ^ (y) ^ (z))
-#define maj(x,y,z) (((x) & (y)) | ((z) & ((x) | (y))))
-
-/* A normal version as set out in the FIPS. This version uses */
-/* partial loop unrolling and is optimised for the Pentium 4 */
-#define rnd(f,k) \
- do { \
- t = a; a = rotl32(a,5) + f(b,c,d) + e + k + w[i]; \
- e = d; d = c; c = rotl32(b, 30); b = t; \
- } while (0)
-
-static void sha1_compile(sha1_ctx_t *ctx)
-{
- uint32_t w[80], i, a, b, c, d, e, t;
-
- /* note that words are compiled from the buffer into 32-bit */
- /* words in big-endian order so an order reversal is needed */
- /* here on little endian machines */
- for (i = 0; i < SHA1_BLOCK_SIZE / 4; ++i)
- w[i] = htonl(ctx->wbuf[i]);
-
- for (i = SHA1_BLOCK_SIZE / 4; i < 80; ++i)
- w[i] = rotl32(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1);
-
- a = ctx->hash[0];
- b = ctx->hash[1];
- c = ctx->hash[2];
- d = ctx->hash[3];
- e = ctx->hash[4];
-
- for (i = 0; i < 20; ++i) {
- rnd(ch, 0x5a827999);
- }
-
- for (i = 20; i < 40; ++i) {
- rnd(parity, 0x6ed9eba1);
- }
-
- for (i = 40; i < 60; ++i) {
- rnd(maj, 0x8f1bbcdc);
- }
-
- for (i = 60; i < 80; ++i) {
- rnd(parity, 0xca62c1d6);
- }
-
- ctx->hash[0] += a;
- ctx->hash[1] += b;
- ctx->hash[2] += c;
- ctx->hash[3] += d;
- ctx->hash[4] += e;
-}
-
-void FAST_FUNC sha1_begin(sha1_ctx_t *ctx)
-{
- ctx->count[0] = ctx->count[1] = 0;
- ctx->hash[0] = 0x67452301;
- ctx->hash[1] = 0xefcdab89;
- ctx->hash[2] = 0x98badcfe;
- ctx->hash[3] = 0x10325476;
- ctx->hash[4] = 0xc3d2e1f0;
-}
-
-/* SHA1 hash data in an array of bytes into hash buffer and call the */
-/* hash_compile function as required. */
-void FAST_FUNC sha1_hash(const void *data, size_t length, sha1_ctx_t *ctx)
-{
- uint32_t pos = (uint32_t) (ctx->count[0] & SHA1_MASK);
- uint32_t freeb = SHA1_BLOCK_SIZE - pos;
- const unsigned char *sp = data;
-
- if ((ctx->count[0] += length) < length)
- ++(ctx->count[1]);
-
- while (length >= freeb) { /* tranfer whole blocks while possible */
- memcpy(((unsigned char *) ctx->wbuf) + pos, sp, freeb);
- sp += freeb;
- length -= freeb;
- freeb = SHA1_BLOCK_SIZE;
- pos = 0;
- sha1_compile(ctx);
- }
-
- memcpy(((unsigned char *) ctx->wbuf) + pos, sp, length);
-}
-
-void* FAST_FUNC sha1_end(void *resbuf, sha1_ctx_t *ctx)
-{
- /* SHA1 Final padding and digest calculation */
-#if BB_BIG_ENDIAN
- static uint32_t mask[4] = { 0x00000000, 0xff000000, 0xffff0000, 0xffffff00 };
- static uint32_t bits[4] = { 0x80000000, 0x00800000, 0x00008000, 0x00000080 };
-#else
- static uint32_t mask[4] = { 0x00000000, 0x000000ff, 0x0000ffff, 0x00ffffff };
- static uint32_t bits[4] = { 0x00000080, 0x00008000, 0x00800000, 0x80000000 };
-#endif
-
- uint8_t *hval = resbuf;
- uint32_t i, cnt = (uint32_t) (ctx->count[0] & SHA1_MASK);
-
- /* mask out the rest of any partial 32-bit word and then set */
- /* the next byte to 0x80. On big-endian machines any bytes in */
- /* the buffer will be at the top end of 32 bit words, on little */
- /* endian machines they will be at the bottom. Hence the AND */
- /* and OR masks above are reversed for little endian systems */
- ctx->wbuf[cnt >> 2] =
- (ctx->wbuf[cnt >> 2] & mask[cnt & 3]) | bits[cnt & 3];
-
- /* we need 9 or more empty positions, one for the padding byte */
- /* (above) and eight for the length count. If there is not */
- /* enough space pad and empty the buffer */
- if (cnt > SHA1_BLOCK_SIZE - 9) {
- if (cnt < 60)
- ctx->wbuf[15] = 0;
- sha1_compile(ctx);
- cnt = 0;
- } else /* compute a word index for the empty buffer positions */
- cnt = (cnt >> 2) + 1;
-
- while (cnt < 14) /* and zero pad all but last two positions */
- ctx->wbuf[cnt++] = 0;
-
- /* assemble the eight byte counter in the buffer in big-endian */
- /* format */
-
- ctx->wbuf[14] = htonl((ctx->count[1] << 3) | (ctx->count[0] >> 29));
- ctx->wbuf[15] = htonl(ctx->count[0] << 3);
-
- sha1_compile(ctx);
-
- /* extract the hash value as bytes in case the hash buffer is */
- /* misaligned for 32-bit words */
-
- for (i = 0; i < SHA1_DIGEST_SIZE; ++i)
- hval[i] = (unsigned char) (ctx->hash[i >> 2] >> 8 * (~i & 3));
-
- return resbuf;
-}
+/* vi: set sw=4 ts=4: */
+/*
+ * Based on shasum from http://www.netsw.org/crypto/hash/
+ * Majorly hacked up to use Dr Brian Gladman's sha1 code
+ *
+ * Copyright (C) 2002 Dr Brian Gladman , Worcester, UK.
+ * Copyright (C) 2003 Glenn L. McGrath
+ * Copyright (C) 2003 Erik Andersen
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ * ---------------------------------------------------------------------------
+ * Issue Date: 10/11/2002
+ *
+ * This is a byte oriented version of SHA1 that operates on arrays of bytes
+ * stored in memory. It runs at 22 cycles per byte on a Pentium P4 processor
+ *
+ * ---------------------------------------------------------------------------
+ *
+ * SHA256 and SHA512 parts are:
+ * Released into the Public Domain by Ulrich Drepper .
+ * Shrank by Denys Vlasenko.
+ *
+ * ---------------------------------------------------------------------------
+ *
+ * The best way to test random blocksizes is to go to coreutils/md5_sha1_sum.c
+ * and replace "4096" with something like "2000 + time(NULL) % 2097",
+ * then rebuild and compare "shaNNNsum bigfile" results.
+ */
+
+#include "libbb.h"
+
+#define rotl32(x,n) (((x) << (n)) | ((x) >> (32 - (n))))
+#define rotr32(x,n) (((x) >> (n)) | ((x) << (32 - (n))))
+/* for sha512: */
+#define rotr64(x,n) (((x) >> (n)) | ((x) << (64 - (n))))
+#if BB_LITTLE_ENDIAN
+static inline uint64_t hton64(uint64_t v)
+{
+ return (((uint64_t)htonl(v)) << 32) | htonl(v >> 32);
+}
+#else
+#define hton64(v) (v)
+#endif
+#define ntoh64(v) hton64(v)
+
+/* To check alignment gcc has an appropriate operator. Other
+ compilers don't. */
+#if defined(__GNUC__) && __GNUC__ >= 2
+# define UNALIGNED_P(p,type) (((uintptr_t) p) % __alignof__(type) != 0)
+#else
+# define UNALIGNED_P(p,type) (((uintptr_t) p) % sizeof(type) != 0)
+#endif
+
+
+static void FAST_FUNC sha1_process_block64(sha1_ctx_t *ctx)
+{
+ unsigned t;
+ uint32_t W[80], a, b, c, d, e;
+ const uint32_t *words = (uint32_t*) ctx->wbuffer;
+
+ for (t = 0; t < 16; ++t) {
+ W[t] = ntohl(*words);
+ words++;
+ }
+
+ for (/*t = 16*/; t < 80; ++t) {
+ uint32_t T = W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16];
+ W[t] = rotl32(T, 1);
+ }
+
+ a = ctx->hash[0];
+ b = ctx->hash[1];
+ c = ctx->hash[2];
+ d = ctx->hash[3];
+ e = ctx->hash[4];
+
+/* Reverse byte order in 32-bit words */
+#define ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
+#define parity(x,y,z) ((x) ^ (y) ^ (z))
+#define maj(x,y,z) (((x) & (y)) | ((z) & ((x) | (y))))
+/* A normal version as set out in the FIPS. This version uses */
+/* partial loop unrolling and is optimised for the Pentium 4 */
+#define rnd(f,k) \
+ do { \
+ uint32_t T = a; \
+ a = rotl32(a, 5) + f(b, c, d) + e + k + W[t]; \
+ e = d; \
+ d = c; \
+ c = rotl32(b, 30); \
+ b = T; \
+ } while (0)
+
+ for (t = 0; t < 20; ++t)
+ rnd(ch, 0x5a827999);
+
+ for (/*t = 20*/; t < 40; ++t)
+ rnd(parity, 0x6ed9eba1);
+
+ for (/*t = 40*/; t < 60; ++t)
+ rnd(maj, 0x8f1bbcdc);
+
+ for (/*t = 60*/; t < 80; ++t)
+ rnd(parity, 0xca62c1d6);
+#undef ch
+#undef parity
+#undef maj
+#undef rnd
+
+ ctx->hash[0] += a;
+ ctx->hash[1] += b;
+ ctx->hash[2] += c;
+ ctx->hash[3] += d;
+ ctx->hash[4] += e;
+}
+
+/* Constants for SHA512 from FIPS 180-2:4.2.3.
+ * SHA256 constants from FIPS 180-2:4.2.2
+ * are the most significant half of first 64 elements
+ * of the same array.
+ */
+static const uint64_t sha_K[80] = {
+ 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
+ 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
+ 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
+ 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
+ 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
+ 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+ 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
+ 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
+ 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+ 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
+ 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
+ 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+ 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
+ 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
+ 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
+ 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
+ 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
+ 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+ 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
+ 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
+ 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
+ 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
+ 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
+ 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+ 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
+ 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
+ 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+ 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
+ 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
+ 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+ 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
+ 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
+ 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, /* [64]+ are used for sha512 only */
+ 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
+ 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
+ 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+ 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
+ 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
+ 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
+ 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
+};
+
+static void FAST_FUNC sha256_process_block64(sha256_ctx_t *ctx)
+{
+ unsigned t;
+ uint32_t W[64], a, b, c, d, e, f, g, h;
+ const uint32_t *words = (uint32_t*) ctx->wbuffer;
+
+ /* Operators defined in FIPS 180-2:4.1.2. */
+#define Ch(x, y, z) ((x & y) ^ (~x & z))
+#define Maj(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
+#define S0(x) (rotr32(x, 2) ^ rotr32(x, 13) ^ rotr32(x, 22))
+#define S1(x) (rotr32(x, 6) ^ rotr32(x, 11) ^ rotr32(x, 25))
+#define R0(x) (rotr32(x, 7) ^ rotr32(x, 18) ^ (x >> 3))
+#define R1(x) (rotr32(x, 17) ^ rotr32(x, 19) ^ (x >> 10))
+
+ /* Compute the message schedule according to FIPS 180-2:6.2.2 step 2. */
+ for (t = 0; t < 16; ++t) {
+ W[t] = ntohl(*words);
+ words++;
+ }
+
+ for (/*t = 16*/; t < 64; ++t)
+ W[t] = R1(W[t - 2]) + W[t - 7] + R0(W[t - 15]) + W[t - 16];
+
+ a = ctx->hash[0];
+ b = ctx->hash[1];
+ c = ctx->hash[2];
+ d = ctx->hash[3];
+ e = ctx->hash[4];
+ f = ctx->hash[5];
+ g = ctx->hash[6];
+ h = ctx->hash[7];
+
+ /* The actual computation according to FIPS 180-2:6.2.2 step 3. */
+ for (t = 0; t < 64; ++t) {
+ /* Need to fetch upper half of sha_K[t]
+ * (I hope compiler is clever enough to just fetch
+ * upper half)
+ */
+ uint32_t K_t = sha_K[t] >> 32;
+ uint32_t T1 = h + S1(e) + Ch(e, f, g) + K_t + W[t];
+ uint32_t T2 = S0(a) + Maj(a, b, c);
+ h = g;
+ g = f;
+ f = e;
+ e = d + T1;
+ d = c;
+ c = b;
+ b = a;
+ a = T1 + T2;
+ }
+#undef Ch
+#undef Maj
+#undef S0
+#undef S1
+#undef R0
+#undef R1
+ /* Add the starting values of the context according to FIPS 180-2:6.2.2
+ step 4. */
+ ctx->hash[0] += a;
+ ctx->hash[1] += b;
+ ctx->hash[2] += c;
+ ctx->hash[3] += d;
+ ctx->hash[4] += e;
+ ctx->hash[5] += f;
+ ctx->hash[6] += g;
+ ctx->hash[7] += h;
+}
+
+static void FAST_FUNC sha512_process_block128(sha512_ctx_t *ctx)
+{
+ unsigned t;
+ uint64_t W[80];
+ /* On i386, having assignments here (not later as sha256 does)
+ * produces 99 bytes smaller code with gcc 4.3.1
+ */
+ uint64_t a = ctx->hash[0];
+ uint64_t b = ctx->hash[1];
+ uint64_t c = ctx->hash[2];
+ uint64_t d = ctx->hash[3];
+ uint64_t e = ctx->hash[4];
+ uint64_t f = ctx->hash[5];
+ uint64_t g = ctx->hash[6];
+ uint64_t h = ctx->hash[7];
+ const uint64_t *words = (uint64_t*) ctx->wbuffer;
+
+ /* Operators defined in FIPS 180-2:4.1.2. */
+#define Ch(x, y, z) ((x & y) ^ (~x & z))
+#define Maj(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
+#define S0(x) (rotr64(x, 28) ^ rotr64(x, 34) ^ rotr64(x, 39))
+#define S1(x) (rotr64(x, 14) ^ rotr64(x, 18) ^ rotr64(x, 41))
+#define R0(x) (rotr64(x, 1) ^ rotr64(x, 8) ^ (x >> 7))
+#define R1(x) (rotr64(x, 19) ^ rotr64(x, 61) ^ (x >> 6))
+
+ /* Compute the message schedule according to FIPS 180-2:6.3.2 step 2. */
+ for (t = 0; t < 16; ++t) {
+ W[t] = ntoh64(*words);
+ words++;
+ }
+ for (/*t = 16*/; t < 80; ++t)
+ W[t] = R1(W[t - 2]) + W[t - 7] + R0(W[t - 15]) + W[t - 16];
+
+ /* The actual computation according to FIPS 180-2:6.3.2 step 3. */
+ for (t = 0; t < 80; ++t) {
+ uint64_t T1 = h + S1(e) + Ch(e, f, g) + sha_K[t] + W[t];
+ uint64_t T2 = S0(a) + Maj(a, b, c);
+ h = g;
+ g = f;
+ f = e;
+ e = d + T1;
+ d = c;
+ c = b;
+ b = a;
+ a = T1 + T2;
+ }
+#undef Ch
+#undef Maj
+#undef S0
+#undef S1
+#undef R0
+#undef R1
+ /* Add the starting values of the context according to FIPS 180-2:6.3.2
+ step 4. */
+ ctx->hash[0] += a;
+ ctx->hash[1] += b;
+ ctx->hash[2] += c;
+ ctx->hash[3] += d;
+ ctx->hash[4] += e;
+ ctx->hash[5] += f;
+ ctx->hash[6] += g;
+ ctx->hash[7] += h;
+}
+
+
+void FAST_FUNC sha1_begin(sha1_ctx_t *ctx)
+{
+ ctx->hash[0] = 0x67452301;
+ ctx->hash[1] = 0xefcdab89;
+ ctx->hash[2] = 0x98badcfe;
+ ctx->hash[3] = 0x10325476;
+ ctx->hash[4] = 0xc3d2e1f0;
+ ctx->total64 = 0;
+ ctx->process_block = sha1_process_block64;
+}
+
+static const uint32_t init256[] = {
+ 0x6a09e667,
+ 0xbb67ae85,
+ 0x3c6ef372,
+ 0xa54ff53a,
+ 0x510e527f,
+ 0x9b05688c,
+ 0x1f83d9ab,
+ 0x5be0cd19
+};
+static const uint32_t init512_lo[] = {
+ 0xf3bcc908,
+ 0x84caa73b,
+ 0xfe94f82b,
+ 0x5f1d36f1,
+ 0xade682d1,
+ 0x2b3e6c1f,
+ 0xfb41bd6b,
+ 0x137e2179
+};
+
+/* Initialize structure containing state of computation.
+ (FIPS 180-2:5.3.2) */
+void FAST_FUNC sha256_begin(sha256_ctx_t *ctx)
+{
+ memcpy(ctx->hash, init256, sizeof(init256));
+ ctx->total64 = 0;
+ ctx->process_block = sha256_process_block64;
+}
+
+/* Initialize structure containing state of computation.
+ (FIPS 180-2:5.3.3) */
+void FAST_FUNC sha512_begin(sha512_ctx_t *ctx)
+{
+ int i;
+ for (i = 0; i < 8; i++)
+ ctx->hash[i] = ((uint64_t)(init256[i]) << 32) + init512_lo[i];
+ ctx->total64[0] = ctx->total64[1] = 0;
+}
+
+
+/* Used also for sha256 */
+void FAST_FUNC sha1_hash(const void *buffer, size_t len, sha1_ctx_t *ctx)
+{
+ unsigned in_buf = ctx->total64 & 63;
+ unsigned add = 64 - in_buf;
+
+ ctx->total64 += len;
+
+ while (len >= add) { /* transfer whole blocks while possible */
+ memcpy(ctx->wbuffer + in_buf, buffer, add);
+ buffer = (const char *)buffer + add;
+ len -= add;
+ add = 64;
+ in_buf = 0;
+ ctx->process_block(ctx);
+ }
+
+ memcpy(ctx->wbuffer + in_buf, buffer, len);
+}
+
+void FAST_FUNC sha512_hash(const void *buffer, size_t len, sha512_ctx_t *ctx)
+{
+ unsigned in_buf = ctx->total64[0] & 127;
+ unsigned add = 128 - in_buf;
+
+ /* First increment the byte count. FIPS 180-2 specifies the possible
+ length of the file up to 2^128 _bits_.
+ We compute the number of _bytes_ and convert to bits later. */
+ ctx->total64[0] += len;
+ if (ctx->total64[0] < len)
+ ctx->total64[1]++;
+
+ while (len >= add) { /* transfer whole blocks while possible */
+ memcpy(ctx->wbuffer + in_buf, buffer, add);
+ buffer = (const char *)buffer + add;
+ len -= add;
+ add = 128;
+ in_buf = 0;
+ sha512_process_block128(ctx);
+ }
+
+ memcpy(ctx->wbuffer + in_buf, buffer, len);
+}
+
+
+/* Used also for sha256 */
+void FAST_FUNC sha1_end(void *resbuf, sha1_ctx_t *ctx)
+{
+ unsigned i, pad, in_buf;
+
+ in_buf = ctx->total64 & 63;
+ /* Pad the buffer to the next 64-byte boundary with 0x80,0,0,0... */
+ ctx->wbuffer[in_buf++] = 0x80;
+
+ /* This loop iterates either once or twice, no more, no less */
+ while (1) {
+ pad = 64 - in_buf;
+ memset(ctx->wbuffer + in_buf, 0, pad);
+ in_buf = 0;
+ /* Do we have enough space for the length count? */
+ if (pad >= 8) {
+ /* Store the 64-bit counter of bits in the buffer in BE format */
+ uint64_t t = ctx->total64 << 3;
+ t = hton64(t);
+ /* wbuffer is suitably aligned for this */
+ *(uint64_t *) (&ctx->wbuffer[64 - 8]) = t;
+ }
+ ctx->process_block(ctx);
+ if (pad >= 8)
+ break;
+ }
+
+ in_buf = (ctx->process_block == sha1_process_block64) ? 5 : 8;
+ /* This way we do not impose alignment constraints on resbuf: */
+#if BB_LITTLE_ENDIAN
+ for (i = 0; i < in_buf; ++i)
+ ctx->hash[i] = htonl(ctx->hash[i]);
+#endif
+ memcpy(resbuf, ctx->hash, sizeof(ctx->hash[0]) * in_buf);
+}
+
+void FAST_FUNC sha512_end(void *resbuf, sha512_ctx_t *ctx)
+{
+ unsigned i, pad, in_buf;
+
+ in_buf = ctx->total64[0] & 127;
+ /* Pad the buffer to the next 128-byte boundary with 0x80,0,0,0...
+ * (FIPS 180-2:5.1.2)
+ */
+ ctx->wbuffer[in_buf++] = 0x80;
+
+ while (1) {
+ pad = 128 - in_buf;
+ memset(ctx->wbuffer + in_buf, 0, pad);
+ in_buf = 0;
+ if (pad >= 16) {
+ /* Store the 128-bit counter of bits in the buffer in BE format */
+ uint64_t t;
+ t = ctx->total64[0] << 3;
+ t = hton64(t);
+ *(uint64_t *) (&ctx->wbuffer[128 - 8]) = t;
+ t = (ctx->total64[1] << 3) | (ctx->total64[0] >> 61);
+ t = hton64(t);
+ *(uint64_t *) (&ctx->wbuffer[128 - 16]) = t;
+ }
+ sha512_process_block128(ctx);
+ if (pad >= 16)
+ break;
+ }
+
+#if BB_LITTLE_ENDIAN
+ for (i = 0; i < ARRAY_SIZE(ctx->hash); ++i)
+ ctx->hash[i] = hton64(ctx->hash[i]);
+#endif
+ memcpy(resbuf, ctx->hash, sizeof(ctx->hash));
+}
diff --git a/release/src/router/busybox/libbb/signals.c b/release/src/router/busybox/libbb/signals.c
index 959114679e..a528756fff 100644
--- a/release/src/router/busybox/libbb/signals.c
+++ b/release/src/router/busybox/libbb/signals.c
@@ -11,6 +11,14 @@
#include "libbb.h"
+/* All known arches use small ints for signals */
+smallint bb_got_signal;
+
+void record_signo(int signo)
+{
+ bb_got_signal = signo;
+}
+
/* Saves 2 bytes on x86! Oh my... */
int FAST_FUNC sigaction_set(int signum, const struct sigaction *act)
{
@@ -39,7 +47,7 @@ void FAST_FUNC bb_signals(int sigs, void (*f)(int))
}
}
-void FAST_FUNC bb_signals_recursive(int sigs, void (*f)(int))
+void FAST_FUNC bb_signals_recursive_norestart(int sigs, void (*f)(int))
{
int sig_no = 0;
int bit = 1;
diff --git a/release/src/router/busybox/libbb/speed_table.c b/release/src/router/busybox/libbb/speed_table.c
index 646f9146b7..05fe66c645 100644
--- a/release/src/router/busybox/libbb/speed_table.c
+++ b/release/src/router/busybox/libbb/speed_table.c
@@ -7,7 +7,6 @@
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
-#include
#include "libbb.h"
struct speed_map {
diff --git a/release/src/router/busybox/libbb/strrstr.c b/release/src/router/busybox/libbb/strrstr.c
index d5cd44b2a2..a803dd983f 100644
--- a/release/src/router/busybox/libbb/strrstr.c
+++ b/release/src/router/busybox/libbb/strrstr.c
@@ -2,7 +2,7 @@
/*
* Utility routines.
*
- * Copyright (C) 2008 Bernhard Fischer
+ * Copyright (C) 2008 Bernhard Reutner-Fischer
*
* Licensed under GPLv2 or later, see file License in this tarball for details.
*/
diff --git a/release/src/router/busybox/libbb/update_passwd.c b/release/src/router/busybox/libbb/update_passwd.c
index 88bc28ca93..35b89a5b40 100644
--- a/release/src/router/busybox/libbb/update_passwd.c
+++ b/release/src/router/busybox/libbb/update_passwd.c
@@ -7,8 +7,12 @@
* /etc/shadow) for a given user and password.
*
* Moved from loginutils/passwd.c by Alexander Shishkin
+ *
+ * Modified to be able to add or delete users, groups and users to/from groups
+ * by Tito Ragusa
+ *
+ * Licensed under GPLv2, see file LICENSE in this tarball for details.
*/
-
#include "libbb.h"
#if ENABLE_SELINUX
@@ -33,12 +37,44 @@ static void check_selinux_update_passwd(const char *username)
freecon(context);
}
#else
-#define check_selinux_update_passwd(username) ((void)0)
+# define check_selinux_update_passwd(username) ((void)0)
#endif
-int FAST_FUNC update_passwd(const char *filename, const char *username,
- const char *new_pw)
+/*
+ 1) add a user: update_passwd(FILE, USER, REMAINING_PWLINE, NULL)
+ only if CONFIG_ADDUSER=y and applet_name[0] == 'a' like in adduser
+
+ 2) add a group: update_passwd(FILE, GROUP, REMAINING_GRLINE, NULL)
+ only if CONFIG_ADDGROUP=y and applet_name[0] == 'a' like in addgroup
+
+ 3) add a user to a group: update_passwd(FILE, GROUP, NULL, MEMBER)
+ only if CONFIG_FEATURE_ADDUSER_TO_GROUP=y, applet_name[0] == 'a'
+ like in addgroup and member != NULL
+
+ 4) delete a user: update_passwd(FILE, USER, NULL, NULL)
+
+ 5) delete a group: update_passwd(FILE, GROUP, NULL, NULL)
+
+ 6) delete a user from a group: update_passwd(FILE, GROUP, NULL, MEMBER)
+ only if CONFIG_FEATURE_DEL_USER_FROM_GROUP=y and member != NULL
+
+ 7) change user's passord: update_passwd(FILE, USER, NEW_PASSWD, NULL)
+ only if CONFIG_PASSWD=y and applet_name[0] == 'p' like in passwd
+ or if CONFIG_CHPASSWD=y and applet_name[0] == 'c' like in chpasswd
+
+ This function does not validate the arguments fed to it
+ so the calling program should take care of that.
+
+ Returns number of lines changed, or -1 on error.
+*/
+int FAST_FUNC update_passwd(const char *filename,
+ const char *name,
+ const char *new_passwd,
+ const char *member)
{
+#if !(ENABLE_FEATURE_ADDUSER_TO_GROUP || ENABLE_FEATURE_DEL_USER_FROM_GROUP)
+#define member NULL
+#endif
struct stat sb;
struct flock lock;
FILE *old_fp;
@@ -49,22 +85,25 @@ int FAST_FUNC update_passwd(const char *filename, const char *username,
int old_fd;
int new_fd;
int i;
- int cnt = 0;
+ int changed_lines;
int ret = -1; /* failure */
filename = xmalloc_follow_symlinks(filename);
if (filename == NULL)
- return -1;
+ return ret;
- check_selinux_update_passwd(username);
+ check_selinux_update_passwd(name);
/* New passwd file, "/etc/passwd+" for now */
fnamesfx = xasprintf("%s+", filename);
sfx_char = &fnamesfx[strlen(fnamesfx)-1];
- username = xasprintf("%s:", username);
- user_len = strlen(username);
+ name = xasprintf("%s:", name);
+ user_len = strlen(name);
- old_fp = fopen(filename, "r+");
+ if (strstr(filename, "shadow"))
+ old_fp = fopen(filename, "r+");
+ else
+ old_fp = fopen_or_warn(filename, "r+");
if (!old_fp)
goto free_mem;
old_fd = fileno(old_fp);
@@ -80,7 +119,7 @@ int FAST_FUNC update_passwd(const char *filename, const char *username,
if (errno != EEXIST) break;
usleep(100000); /* 0.1 sec */
} while (--i);
- bb_perror_msg("cannot create '%s'", fnamesfx);
+ bb_perror_msg("can't create '%s'", fnamesfx);
goto close_old_fp;
created:
@@ -88,8 +127,10 @@ int FAST_FUNC update_passwd(const char *filename, const char *username,
fchmod(new_fd, sb.st_mode & 0777); /* ignore errors */
fchown(new_fd, sb.st_uid, sb.st_gid);
}
+ errno = 0;
new_fp = fdopen(new_fd, "w");
if (!new_fp) {
+ bb_perror_nomsg();
close(new_fd);
goto unlink_new;
}
@@ -100,7 +141,8 @@ int FAST_FUNC update_passwd(const char *filename, const char *username,
i = (unlink(fnamesfx) && errno != ENOENT);
/* Create backup as a hardlink to current */
if (i || link(filename, fnamesfx))
- bb_perror_msg("warning: cannot create backup copy '%s'", fnamesfx);
+ bb_perror_msg("warning: can't create backup copy '%s'",
+ fnamesfx);
*sfx_char = '+';
/* Lock the password file before updating */
@@ -109,38 +151,109 @@ int FAST_FUNC update_passwd(const char *filename, const char *username,
lock.l_start = 0;
lock.l_len = 0;
if (fcntl(old_fd, F_SETLK, &lock) < 0)
- bb_perror_msg("warning: cannot lock '%s'", filename);
+ bb_perror_msg("warning: can't lock '%s'", filename);
lock.l_type = F_UNLCK;
/* Read current password file, write updated /etc/passwd+ */
+ changed_lines = 0;
while (1) {
- char *line = xmalloc_fgets(old_fp);
- if (!line) break; /* EOF/error */
- if (strncmp(username, line, user_len) == 0) {
- /* we have a match with "username:"... */
- const char *cp = line + user_len;
- /* now cp -> old passwd, skip it: */
- cp = strchrnul(cp, ':');
- /* now cp -> ':' after old passwd or -> "" */
- fprintf(new_fp, "%s%s%s", username, new_pw, cp);
- cnt++;
+ char *cp, *line;
+
+ line = xmalloc_fgetline(old_fp);
+ if (!line) /* EOF/error */
+ break;
+ if (strncmp(name, line, user_len) != 0) {
+ fprintf(new_fp, "%s\n", line);
+ goto next;
+ }
+
+ /* We have a match with "name:"... */
+ cp = line + user_len; /* move past name: */
+
+#if ENABLE_FEATURE_ADDUSER_TO_GROUP || ENABLE_FEATURE_DEL_USER_FROM_GROUP
+ if (member) {
+ /* It's actually /etc/group+, not /etc/passwd+ */
+ if (ENABLE_FEATURE_ADDUSER_TO_GROUP
+ && applet_name[0] == 'a'
+ ) {
+ /* Add user to group */
+ fprintf(new_fp, "%s%s%s\n", line,
+ last_char_is(line, ':') ? "" : ",",
+ member);
+ changed_lines++;
+ } else if (ENABLE_FEATURE_DEL_USER_FROM_GROUP
+ /* && applet_name[0] == 'd' */
+ ) {
+ /* Delete user from group */
+ char *tmp;
+ const char *fmt = "%s";
+
+ /* find the start of the member list: last ':' */
+ cp = strrchr(line, ':');
+ /* cut it */
+ *cp++ = '\0';
+ /* write the cut line name:passwd:gid:
+ * or name:!:: */
+ fprintf(new_fp, "%s:", line);
+ /* parse the tokens of the member list */
+ tmp = cp;
+ while ((cp = strsep(&tmp, ",")) != NULL) {
+ if (strcmp(member, cp) != 0) {
+ fprintf(new_fp, fmt, cp);
+ fmt = ",%s";
+ } else {
+ /* found member, skip it */
+ changed_lines++;
+ }
+ }
+ fprintf(new_fp, "\n");
+ }
} else
- fputs(line, new_fp);
+#endif
+ if ((ENABLE_PASSWD && applet_name[0] == 'p')
+ || (ENABLE_CHPASSWD && applet_name[0] == 'c')
+ ) {
+ /* Change passwd */
+ cp = strchrnul(cp, ':'); /* move past old passwd */
+ /* name: + new_passwd + :rest of line */
+ fprintf(new_fp, "%s%s%s\n", name, new_passwd, cp);
+ changed_lines++;
+ } /* else delete user or group: skip the line */
+ next:
free(line);
}
+
+ if (changed_lines == 0) {
+#if ENABLE_FEATURE_DEL_USER_FROM_GROUP
+ if (member)
+ bb_error_msg("can't find %s in %s", member, filename);
+#endif
+ if ((ENABLE_ADDUSER || ENABLE_ADDGROUP)
+ && applet_name[0] == 'a' && !member
+ ) {
+ /* add user or group */
+ fprintf(new_fp, "%s%s\n", name, new_passwd);
+ changed_lines++;
+ }
+ }
+
fcntl(old_fd, F_SETLK, &lock);
/* We do want all of them to execute, thus | instead of || */
+ errno = 0;
if ((ferror(old_fp) | fflush(new_fp) | fsync(new_fd) | fclose(new_fp))
|| rename(fnamesfx, filename)
) {
/* At least one of those failed */
+ bb_perror_nomsg();
goto unlink_new;
}
- ret = cnt; /* whee, success! */
+ /* Success: ret >= 0 */
+ ret = changed_lines;
unlink_new:
- if (ret < 0) unlink(fnamesfx);
+ if (ret < 0)
+ unlink(fnamesfx);
close_old_fp:
fclose(old_fp);
@@ -148,6 +261,6 @@ int FAST_FUNC update_passwd(const char *filename, const char *username,
free_mem:
free(fnamesfx);
free((char *)filename);
- free((char *)username);
+ free((char *)name);
return ret;
}
diff --git a/release/src/router/busybox/libbb/vfork_daemon_rexec.c b/release/src/router/busybox/libbb/vfork_daemon_rexec.c
index 17b373cd1b..f64239a96c 100644
--- a/release/src/router/busybox/libbb/vfork_daemon_rexec.c
+++ b/release/src/router/busybox/libbb/vfork_daemon_rexec.c
@@ -66,9 +66,9 @@ pid_t FAST_FUNC xspawn(char **argv)
return pid;
}
-int FAST_FUNC safe_waitpid(int pid, int *wstat, int options)
+pid_t FAST_FUNC safe_waitpid(pid_t pid, int *wstat, int options)
{
- int r;
+ pid_t r;
do
r = waitpid(pid, wstat, options);
@@ -76,13 +76,13 @@ int FAST_FUNC safe_waitpid(int pid, int *wstat, int options)
return r;
}
-int FAST_FUNC wait_any_nohang(int *wstat)
+pid_t FAST_FUNC wait_any_nohang(int *wstat)
{
return safe_waitpid(-1, wstat, WNOHANG);
}
// Wait for the specified child PID to exit, returning child's error return.
-int FAST_FUNC wait4pid(int pid)
+int FAST_FUNC wait4pid(pid_t pid)
{
int status;
@@ -251,35 +251,33 @@ void FAST_FUNC re_exec(char **argv)
bb_perror_msg_and_die("exec %s", bb_busybox_exec_path);
}
-void FAST_FUNC forkexit_or_rexec(char **argv)
+pid_t FAST_FUNC fork_or_rexec(char **argv)
{
pid_t pid;
/* Maybe we are already re-execed and come here again? */
if (re_execed)
- return;
+ return 0; /* child */
pid = vfork();
if (pid < 0) /* wtf? */
bb_perror_msg_and_die("vfork");
if (pid) /* parent */
- exit(EXIT_SUCCESS);
+ return pid;
/* child - re-exec ourself */
re_exec(argv);
}
#else
/* Dance around (void)...*/
-#undef forkexit_or_rexec
-void FAST_FUNC forkexit_or_rexec(void)
+#undef fork_or_rexec
+pid_t FAST_FUNC fork_or_rexec(void)
{
pid_t pid;
pid = fork();
if (pid < 0) /* wtf? */
bb_perror_msg_and_die("fork");
- if (pid) /* parent */
- exit(EXIT_SUCCESS);
- /* child */
+ return pid;
}
-#define forkexit_or_rexec(argv) forkexit_or_rexec()
+#define fork_or_rexec(argv) fork_or_rexec()
#endif
/* Due to a #define in libbb.h on MMU systems we actually have 1 argument -
@@ -310,7 +308,8 @@ void FAST_FUNC bb_daemonize_or_rexec(int flags, char **argv)
fd = dup(fd); /* have 0,1,2 open at least to /dev/null */
if (!(flags & DAEMON_ONLY_SANITIZE)) {
- forkexit_or_rexec(argv);
+ if (fork_or_rexec(argv))
+ exit(EXIT_SUCCESS); /* parent */
/* if daemonizing, make sure we detach from stdio & ctty */
setsid();
dup2(fd, 0);
diff --git a/release/src/router/busybox/libbb/wfopen.c b/release/src/router/busybox/libbb/wfopen.c
index 4c84b3ba97..1cb871ef51 100644
--- a/release/src/router/busybox/libbb/wfopen.c
+++ b/release/src/router/busybox/libbb/wfopen.c
@@ -14,7 +14,7 @@ FILE* FAST_FUNC fopen_or_warn(const char *path, const char *mode)
FILE *fp = fopen(path, mode);
if (!fp) {
bb_simple_perror_msg(path);
- errno = 0;
+ //errno = 0; /* why? */
}
return fp;
}
diff --git a/release/src/router/busybox/libbb/write.c b/release/src/router/busybox/libbb/write.c
index e8a9eff866..116e4d1531 100644
--- a/release/src/router/busybox/libbb/write.c
+++ b/release/src/router/busybox/libbb/write.c
@@ -2,7 +2,7 @@
/*
* Utility routines.
*
- * Copyright (C) 2008 Bernhard Fischer
+ * Copyright (C) 2008 Bernhard Reutner-Fischer
*
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
@@ -10,11 +10,10 @@
#include "libbb.h"
/* Open file and write string str to it, close file.
- * Die on any open or write-error. */
+ * Die on any open or write error. */
void FAST_FUNC xopen_xwrite_close(const char* file, const char* str)
{
int fd = xopen(file, O_WRONLY);
-
- xwrite(fd, str, strlen(str));
+ xwrite_str(fd, str);
close(fd);
}
diff --git a/release/src/router/busybox/libbb/xatonum_template.c b/release/src/router/busybox/libbb/xatonum_template.c
index 2360ae88a3..5e0bb59e6b 100644
--- a/release/src/router/busybox/libbb/xatonum_template.c
+++ b/release/src/router/busybox/libbb/xatonum_template.c
@@ -1,4 +1,8 @@
/*
+ *
+ * Licensed under GPLv2, see file LICENSE in this tarball for details.
+ */
+/*
You need to define the following (example):
#define type long
diff --git a/release/src/router/busybox/libbb/xconnect.c b/release/src/router/busybox/libbb/xconnect.c
index d48c503399..f5d7983a43 100644
--- a/release/src/router/busybox/libbb/xconnect.c
+++ b/release/src/router/busybox/libbb/xconnect.c
@@ -4,9 +4,11 @@
*
* Connect to host at port using address resolution from getaddrinfo
*
+ * Licensed under GPLv2, see file LICENSE in this tarball for details.
*/
#include
+#include
#include "libbb.h"
void FAST_FUNC setsockopt_reuseaddr(int fd)
@@ -17,6 +19,35 @@ int FAST_FUNC setsockopt_broadcast(int fd)
{
return setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &const_int_1, sizeof(const_int_1));
}
+int FAST_FUNC setsockopt_bindtodevice(int fd, const char *iface)
+{
+ int r;
+ struct ifreq ifr;
+ strncpy_IFNAMSIZ(ifr.ifr_name, iface);
+ /* NB: passing (iface, strlen(iface) + 1) does not work!
+ * (maybe it works on _some_ kernels, but not on 2.6.26)
+ * Actually, ifr_name is at offset 0, and in practice
+ * just giving char[IFNAMSIZ] instead of struct ifreq works too.
+ * But just in case it's not true on some obscure arch... */
+ r = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr));
+ if (r)
+ bb_perror_msg("can't bind to interface %s", iface);
+ return r;
+}
+
+len_and_sockaddr* FAST_FUNC get_sock_lsa(int fd)
+{
+ len_and_sockaddr *lsa;
+ socklen_t len = 0;
+
+ /* Can be optimized to do only one getsockname() */
+ if (getsockname(fd, NULL, &len) != 0)
+ return NULL;
+ lsa = xzalloc(LSA_LEN_SIZE + len);
+ lsa->len = len;
+ getsockname(fd, &lsa->u.sa, &lsa->len);
+ return lsa;
+}
void FAST_FUNC xconnect(int s, const struct sockaddr *s_addr, socklen_t addrlen)
{
@@ -33,8 +64,9 @@ void FAST_FUNC xconnect(int s, const struct sockaddr *s_addr, socklen_t addrlen)
/* Return port number for a service.
* If "port" is a number use it as the port.
- * If "port" is a name it is looked up in /etc/services, if it isnt found return
- * default_port */
+ * If "port" is a name it is looked up in /etc/services,
+ * if it isnt found return default_port
+ */
unsigned FAST_FUNC bb_lookup_port(const char *port, const char *protocol, unsigned default_port)
{
unsigned port_nr = default_port;
@@ -135,7 +167,8 @@ USE_FEATURE_IPV6(sa_family_t af,)
/* Even uglier parsing of [xx]:nn */
host++;
cp = strchr(host, ']');
- if (!cp || cp[1] != ':') { /* Malformed: must have [xx]:nn */
+ if (!cp || (cp[1] != ':' && cp[1] != '\0')) {
+ /* Malformed: must be [xx]:nn or [xx] */
bb_error_msg("bad address '%s'", org_host);
if (ai_flags & DIE_ON_ERROR)
xfunc_die();
@@ -151,8 +184,11 @@ USE_FEATURE_IPV6(sa_family_t af,)
if (cp) { /* points to ":" or "]:" */
int sz = cp - host + 1;
host = safe_strncpy(alloca(sz), host, sz);
- if (ENABLE_FEATURE_IPV6 && *cp != ':')
+ if (ENABLE_FEATURE_IPV6 && *cp != ':') {
cp++; /* skip ']' */
+ if (*cp == '\0') /* [xx] without port */
+ goto skip;
+ }
cp++; /* skip ':' */
port = bb_strtou(cp, NULL, 10);
if (errno || (unsigned)port > 0xffff) {
@@ -161,6 +197,7 @@ USE_FEATURE_IPV6(sa_family_t af,)
xfunc_die();
return NULL;
}
+ skip: ;
}
memset(&hint, 0 , sizeof(hint));
diff --git a/release/src/router/busybox/libbb/xfuncs.c b/release/src/router/busybox/libbb/xfuncs.c
index 8ef305ba08..a86efc2981 100644
--- a/release/src/router/busybox/libbb/xfuncs.c
+++ b/release/src/router/busybox/libbb/xfuncs.c
@@ -40,6 +40,14 @@ int FAST_FUNC close_on_exec_on(int fd)
return fcntl(fd, F_SETFD, FD_CLOEXEC);
}
+char* FAST_FUNC strncpy_IFNAMSIZ(char *dst, const char *src)
+{
+#ifndef IFNAMSIZ
+ enum { IFNAMSIZ = 16 };
+#endif
+ return strncpy(dst, src, IFNAMSIZ);
+}
+
/* Convert unsigned long long value into compact 4-char
* representation. Examples: "1234", "1.2k", " 27M", "123T"
* String is not terminated (buf[4] is untouched) */
@@ -260,6 +268,17 @@ off_t FAST_FUNC fdlength(int fd)
}
#endif
+char* FAST_FUNC xmalloc_ttyname(int fd)
+{
+ char *buf = xzalloc(128);
+ int r = ttyname_r(fd, buf, 127);
+ if (r) {
+ free(buf);
+ buf = NULL;
+ }
+ return buf;
+}
+
/* It is perfectly ok to pass in a NULL for either width or for
* height, in which case that value will not be set. */
int FAST_FUNC get_terminal_width_height(int fd, unsigned *width, unsigned *height)
@@ -289,3 +308,8 @@ int FAST_FUNC get_terminal_width_height(int fd, unsigned *width, unsigned *heigh
return ret;
}
+
+int FAST_FUNC tcsetattr_stdin_TCSANOW(const struct termios *tp)
+{
+ return tcsetattr(STDIN_FILENO, TCSANOW, tp);
+}
diff --git a/release/src/router/busybox/libbb/xfuncs_printf.c b/release/src/router/busybox/libbb/xfuncs_printf.c
index 108e14043f..6d0fa6e8d7 100644
--- a/release/src/router/busybox/libbb/xfuncs_printf.c
+++ b/release/src/router/busybox/libbb/xfuncs_printf.c
@@ -208,6 +208,10 @@ void FAST_FUNC xwrite(int fd, const void *buf, size_t count)
bb_error_msg_and_die("short write");
}
}
+void FAST_FUNC xwrite_str(int fd, const char *str)
+{
+ xwrite(fd, str, strlen(str));
+}
// Die with an error message if we can't lseek to the right spot.
off_t FAST_FUNC xlseek(int fd, off_t offset, int whence)
@@ -333,6 +337,29 @@ void FAST_FUNC xsetenv(const char *key, const char *value)
bb_error_msg_and_die(bb_msg_memory_exhausted);
}
+/* Handles "VAR=VAL" strings, even those which are part of environ
+ * _right now_
+ */
+void FAST_FUNC bb_unsetenv(const char *var)
+{
+ char *tp = strchr(var, '=');
+
+ if (!tp) {
+ unsetenv(var);
+ return;
+ }
+
+ /* In case var was putenv'ed, we can't replace '='
+ * with NUL and unsetenv(var) - it won't work,
+ * env is modified by the replacement, unsetenv
+ * sees "VAR" instead of "VAR=VAL" and does not remove it!
+ * horror :( */
+ tp = xstrndup(var, tp - var);
+ unsetenv(tp);
+ free(tp);
+}
+
+
// Die with an error message if we can't set gid. (Because resource limits may
// limit this user to a given number of processes, and if that fills up the
// setgid() will fail and we'll _still_be_root_, which is bad.)
@@ -417,7 +444,7 @@ void FAST_FUNC xlisten(int s, int backlog)
/* Die with an error message if sendto failed.
* Return bytes sent otherwise */
-ssize_t FAST_FUNC xsendto(int s, const void *buf, size_t len, const struct sockaddr *to,
+ssize_t FAST_FUNC xsendto(int s, const void *buf, size_t len, const struct sockaddr *to,
socklen_t tolen)
{
ssize_t ret = sendto(s, buf, len, 0, to, tolen);
diff --git a/release/src/router/busybox/libbb/xgetcwd.c b/release/src/router/busybox/libbb/xgetcwd.c
index eefe1d6600..10febe32d4 100644
--- a/release/src/router/busybox/libbb/xgetcwd.c
+++ b/release/src/router/busybox/libbb/xgetcwd.c
@@ -5,7 +5,9 @@
* Written by David MacKenzie .
*
* Special function for busybox written by Vladimir Oleynik
-*/
+ *
+ * Licensed under GPLv2, see file LICENSE in this tarball for details.
+ */
#include "libbb.h"
diff --git a/release/src/router/busybox/libbb/xreadlink.c b/release/src/router/busybox/libbb/xreadlink.c
index 2cfc5751ca..8d232f16b6 100644
--- a/release/src/router/busybox/libbb/xreadlink.c
+++ b/release/src/router/busybox/libbb/xreadlink.c
@@ -1,7 +1,9 @@
/* vi: set sw=4 ts=4: */
/*
- * xreadlink.c - safe implementation of readlink.
- * Returns a NULL on failure...
+ * xreadlink.c - safe implementation of readlink.
+ * Returns a NULL on failure...
+ *
+ * Licensed under GPLv2, see file LICENSE in this tarball for details.
*/
#include "libbb.h"
@@ -89,7 +91,11 @@ char* FAST_FUNC xmalloc_readlink_or_warn(const char *path)
char *buf = xmalloc_readlink(path);
if (!buf) {
/* EINVAL => "file: Invalid argument" => puzzled user */
- bb_error_msg("%s: cannot read link (not a symlink?)", path);
+ const char *errmsg = "not a symlink";
+ int err = errno;
+ if (err != EINVAL)
+ errmsg = strerror(err);
+ bb_error_msg("%s: cannot read link: %s", path, errmsg);
}
return buf;
}
diff --git a/release/src/router/busybox/libpwdgrp/pwd_grp.c b/release/src/router/busybox/libpwdgrp/pwd_grp.c
index 2065190849..56bfcbe913 100644
--- a/release/src/router/busybox/libpwdgrp/pwd_grp.c
+++ b/release/src/router/busybox/libpwdgrp/pwd_grp.c
@@ -396,6 +396,7 @@ struct spwd *getspnam(const char *name)
}
#endif
+#ifdef THIS_ONE_IS_UNUSED
/* This one doesn't use static buffers */
int getpw(uid_t uid, char *buf)
{
@@ -419,6 +420,7 @@ int getpw(uid_t uid, char *buf)
return -1;
}
+#endif
/**********************************************************************/
@@ -620,43 +622,63 @@ struct spwd *sgetspent(const char *string)
}
#endif
-int initgroups(const char *user, gid_t gid)
+static gid_t *getgrouplist_internal(int *ngroups_ptr, const char *user, gid_t gid)
{
FILE *grfile;
gid_t *group_list;
- int num_groups, rv;
- char **m;
+ int ngroups;
struct group group;
char buff[PWD_BUFFER_SIZE];
- rv = -1;
- grfile = fopen_for_read(_PATH_GROUP);
- if (grfile != NULL) {
-
- /* We alloc space for 8 gids at a time. */
- group_list = xmalloc(8 * sizeof(gid_t *));
- *group_list = gid;
- num_groups = 1;
+ /* We alloc space for 8 gids at a time. */
+ group_list = xmalloc(8 * sizeof(group_list[0]));
+ group_list[0] = gid;
+ ngroups = 1;
+ grfile = fopen_for_read(_PATH_GROUP);
+ if (grfile) {
while (!bb__pgsreader(bb__parsegrent, &group, buff, sizeof(buff), grfile)) {
+ char **m;
assert(group.gr_mem); /* Must have at least a NULL terminator. */
- if (group.gr_gid != gid) {
- for (m = group.gr_mem; *m; m++) {
- if (!strcmp(*m, user)) {
- group_list = xrealloc_vector(group_list, 3, num_groups);
- group_list[num_groups++] = group.gr_gid;
- break;
- }
- }
+ if (group.gr_gid == gid)
+ continue;
+ for (m = group.gr_mem; *m; m++) {
+ if (strcmp(*m, user) != 0)
+ continue;
+ group_list = xrealloc_vector(group_list, 3, ngroups);
+ group_list[ngroups++] = group.gr_gid;
+ break;
}
}
-
- rv = setgroups(num_groups, group_list);
- free(group_list);
fclose(grfile);
}
+ *ngroups_ptr = ngroups;
+ return group_list;
+}
- return rv;
+int initgroups(const char *user, gid_t gid)
+{
+ int ngroups;
+ gid_t *group_list = getgrouplist_internal(&ngroups, user, gid);
+
+ ngroups = setgroups(ngroups, group_list);
+ free(group_list);
+ return ngroups;
+}
+
+int getgrouplist(const char *user, gid_t gid, gid_t *groups, int *ngroups)
+{
+ int ngroups_old = *ngroups;
+ gid_t *group_list = getgrouplist_internal(ngroups, user, gid);
+
+ if (*ngroups <= ngroups_old) {
+ ngroups_old = *ngroups;
+ memcpy(groups, group_list, ngroups_old * sizeof(groups[0]));
+ } else {
+ ngroups_old = -1;
+ }
+ free(group_list);
+ return ngroups_old;
}
int putpwent(const struct passwd *__restrict p, FILE *__restrict f)
diff --git a/release/src/router/busybox/libpwdgrp/uidgid_get.c b/release/src/router/busybox/libpwdgrp/uidgid_get.c
index ebc7fc58c4..92290bfdb6 100644
--- a/release/src/router/busybox/libpwdgrp/uidgid_get.c
+++ b/release/src/router/busybox/libpwdgrp/uidgid_get.c
@@ -87,15 +87,12 @@ void FAST_FUNC xget_uidgid(struct bb_uidgid_t *u, const char *ug)
* ":group" sets gid only
* "user:" sets uid and gid (to user's primary group id)
* "user:group" sets uid and gid
- * ('unset' uid or gid is actually set to -1)
+ * ('unset' uid or gid retains the value it has on entry)
*/
void FAST_FUNC parse_chown_usergroup_or_die(struct bb_uidgid_t *u, char *user_group)
{
char *group;
- u->uid = -1;
- u->gid = -1;
-
/* Check if there is a group name */
group = strchr(user_group, '.'); /* deprecated? */
if (!group)
diff --git a/release/src/router/busybox/loginutils/Config.in b/release/src/router/busybox/loginutils/Config.in
index aca85a1ba6..ddd0c80151 100644
--- a/release/src/router/busybox/loginutils/Config.in
+++ b/release/src/router/busybox/loginutils/Config.in
@@ -58,7 +58,7 @@ config USE_BB_SHADOW
password servers and whatnot.
config USE_BB_CRYPT
- bool "Use internal DES and MD5 crypt functions"
+ bool "Use internal crypt functions"
default y
help
Busybox has internal DES and MD5 crypt functions.
@@ -79,6 +79,18 @@ config USE_BB_CRYPT
In static build, it makes code _smaller_ by about 1.2k,
and likely many kilobytes less of bss.
+config USE_BB_CRYPT_SHA
+ bool "Enable SHA256/512 crypt functions"
+ default n
+ depends on USE_BB_CRYPT
+ help
+ Enable this if you have passwords starting with "$5$" or "$6$"
+ in your /etc/passwd or /etc/shadow files. These passwords
+ are hashed using SHA256 and SHA512 algorithms. Support for them
+ was added to glibc in 2008.
+ With this option off, login will fail password check for any
+ user which has password encrypted with these algorithms.
+
config ADDGROUP
bool "addgroup"
default n
@@ -230,15 +242,16 @@ config CRYPTPW
bool "cryptpw"
default n
help
- Applet for crypting a string.
+ Encrypts the given password with the crypt(3) libc function
+ using the given salt. Debian has this utility under mkpasswd
+ name. Busybox provides mkpasswd as an alias for cryptpw.
config CHPASSWD
- bool "chpasswd"
- default n
- help
- chpasswd reads a file of user name and password pairs from
- standard input and uses this information to update a group of
- existing users.
+ bool "chpasswd"
+ default n
+ help
+ Reads a file of user name and password pairs from standard input
+ and uses this information to update a group of existing users.
config SU
bool "su"
diff --git a/release/src/router/busybox/loginutils/addgroup.c b/release/src/router/busybox/loginutils/addgroup.c
index 89414d7381..5a0cf3ffff 100644
--- a/release/src/router/busybox/loginutils/addgroup.c
+++ b/release/src/router/busybox/loginutils/addgroup.c
@@ -9,7 +9,6 @@
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*
*/
-
#include "libbb.h"
static void xgroup_study(struct group *g)
@@ -45,8 +44,8 @@ static void xgroup_study(struct group *g)
/* append a new user to the passwd file */
static void new_group(char *group, gid_t gid)
{
- FILE *file;
struct group gr;
+ char *p;
/* make sure gid and group haven't already been allocated */
gr.gr_gid = gid;
@@ -54,67 +53,17 @@ static void new_group(char *group, gid_t gid)
xgroup_study(&gr);
/* add entry to group */
- file = xfopen(bb_path_group_file, "a");
- /* group:passwd:gid:userlist */
- fprintf(file, "%s:x:%u:\n", group, (unsigned)gr.gr_gid);
+ p = xasprintf("x:%u:", gr.gr_gid);
+ if (update_passwd(bb_path_group_file, group, p, NULL) < 0)
+ exit(EXIT_FAILURE);
if (ENABLE_FEATURE_CLEAN_UP)
- fclose(file);
+ free(p);
#if ENABLE_FEATURE_SHADOWPASSWDS
- file = fopen_or_warn(bb_path_gshadow_file, "a");
- if (file) {
- fprintf(file, "%s:!::\n", group);
- if (ENABLE_FEATURE_CLEAN_UP)
- fclose(file);
- }
+ /* Ignore errors: if file is missing we suppose admin doesn't want it */
+ update_passwd(bb_path_gshadow_file, group, "!::", NULL);
#endif
}
-#if ENABLE_FEATURE_ADDUSER_TO_GROUP
-static void add_user_to_group(char **args,
- const char *path,
- FILE* FAST_FUNC (*fopen_func)(const char *fileName, const char *mode))
-{
- char *line;
- int len = strlen(args[1]);
- llist_t *plist = NULL;
- FILE *group_file;
-
- group_file = fopen_func(path, "r");
-
- if (!group_file) return;
-
- while ((line = xmalloc_fgetline(group_file)) != NULL) {
- /* Find the group */
- if (!strncmp(line, args[1], len)
- && line[len] == ':'
- ) {
- /* Add the new user */
- line = xasprintf("%s%s%s", line,
- last_char_is(line, ':') ? "" : ",",
- args[0]);
- }
- llist_add_to_end(&plist, line);
- }
-
- if (ENABLE_FEATURE_CLEAN_UP) {
- fclose(group_file);
- group_file = fopen_func(path, "w");
- while ((line = llist_pop(&plist))) {
- if (group_file)
- fprintf(group_file, "%s\n", line);
- free(line);
- }
- if (group_file)
- fclose(group_file);
- } else {
- group_file = fopen_func(path, "w");
- if (group_file)
- while ((line = llist_pop(&plist)))
- fprintf(group_file, "%s\n", line);
- }
-}
-#endif
-
/*
* addgroup will take a login_name as its first parameter.
*
@@ -158,19 +107,20 @@ int addgroup_main(int argc UNUSED_PARAM, char **argv)
/* check if group and user exist */
xuname2uid(argv[0]); /* unknown user: exit */
- xgroup2gid(argv[1]); /* unknown group: exit */
+ gr = xgetgrnam(argv[1]); /* unknown group: exit */
/* check if user is already in this group */
- gr = getgrnam(argv[1]);
for (; *(gr->gr_mem) != NULL; (gr->gr_mem)++) {
if (!strcmp(argv[0], *(gr->gr_mem))) {
/* user is already in group: do nothing */
return EXIT_SUCCESS;
}
}
- add_user_to_group(argv, bb_path_group_file, xfopen);
-#if ENABLE_FEATURE_SHADOWPASSWDS
- add_user_to_group(argv, bb_path_gshadow_file, fopen_or_warn);
-#endif
+ if (update_passwd(bb_path_group_file, argv[1], NULL, argv[0]) < 0) {
+ return EXIT_FAILURE;
+ }
+# if ENABLE_FEATURE_SHADOWPASSWDS
+ update_passwd(bb_path_gshadow_file, argv[1], NULL, argv[0]);
+# endif
} else
#endif /* ENABLE_FEATURE_ADDUSER_TO_GROUP */
{
diff --git a/release/src/router/busybox/loginutils/adduser.c b/release/src/router/busybox/loginutils/adduser.c
index 3154806b61..8a5d902e6b 100644
--- a/release/src/router/busybox/loginutils/adduser.c
+++ b/release/src/router/busybox/loginutils/adduser.c
@@ -7,14 +7,12 @@
*
* Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
*/
-
#include "libbb.h"
#define OPT_DONT_SET_PASS (1 << 4)
#define OPT_SYSTEM_ACCOUNT (1 << 5)
#define OPT_DONT_MAKE_HOME (1 << 6)
-
/* remix */
/* recoded such that the uid may be passed in *p */
static void passwd_study(struct passwd *p)
@@ -33,18 +31,17 @@ static void passwd_study(struct passwd *p)
}
/* check for a free uid (and maybe gid) */
- while (getpwuid(p->pw_uid) || (!p->pw_gid && getgrgid(p->pw_uid)))
+ while (getpwuid(p->pw_uid) || (p->pw_gid == (gid_t)-1 && getgrgid(p->pw_uid))) {
p->pw_uid++;
+ if (p->pw_uid > max)
+ bb_error_msg_and_die("no free uids left");
+ }
- if (!p->pw_gid) {
- /* new gid = uid */
- p->pw_gid = p->pw_uid;
+ if (p->pw_gid == (gid_t)-1) {
+ p->pw_gid = p->pw_uid; /* new gid = uid */
if (getgrnam(p->pw_name))
bb_error_msg_and_die("group name '%s' is in use", p->pw_name);
}
-
- if (p->pw_uid > max)
- bb_error_msg_and_die("no free uids left");
}
static void addgroup_wrapper(struct passwd *p)
@@ -89,7 +86,7 @@ int adduser_main(int argc UNUSED_PARAM, char **argv)
{
struct passwd pw;
const char *usegroup = NULL;
- FILE *file;
+ char *p;
#if ENABLE_FEATURE_ADDUSER_LONG_OPTIONS
applet_long_options = adduser_longopts;
@@ -117,35 +114,24 @@ int adduser_main(int argc UNUSED_PARAM, char **argv)
pw.pw_dir = xasprintf("/home/%s", argv[0]);
}
pw.pw_passwd = (char *)"x";
- pw.pw_gid = usegroup ? xgroup2gid(usegroup) : 0; /* exits on failure */
+ pw.pw_gid = usegroup ? xgroup2gid(usegroup) : -1; /* exits on failure */
/* make sure everything is kosher and setup uid && maybe gid */
passwd_study(&pw);
- /* add to passwd */
- file = xfopen(bb_path_passwd_file, "a");
- //fseek(file, 0, SEEK_END); /* paranoia, "a" should ensure that anyway */
- if (putpwent(&pw, file) != 0) {
- bb_perror_nomsg_and_die();
+ p = xasprintf("x:%u:%u:%s:%s:%s", pw.pw_uid, pw.pw_gid, pw.pw_gecos, pw.pw_dir, pw.pw_shell);
+ if (update_passwd(bb_path_passwd_file, pw.pw_name, p, NULL) < 0) {
+ return EXIT_FAILURE;
}
- /* do fclose even if !ENABLE_FEATURE_CLEAN_UP.
- * We will exec passwd, files must be flushed & closed before that! */
- fclose(file);
+ if (ENABLE_FEATURE_CLEAN_UP)
+ free(p);
#if ENABLE_FEATURE_SHADOWPASSWDS
- /* add to shadow if necessary */
- file = fopen_or_warn(bb_path_shadow_file, "a");
- if (file) {
- //fseek(file, 0, SEEK_END);
- fprintf(file, "%s:!:%u:0:99999:7:::\n",
- pw.pw_name, /* username */
- (unsigned)(time(NULL) / 86400) /* sp->sp_lstchg */
- /*0,*/ /* sp->sp_min */
- /*99999,*/ /* sp->sp_max */
- /*7*/ /* sp->sp_warn */
- );
- fclose(file);
- }
+ p = xasprintf("!:%u:0:99999:7:::", (unsigned)(time(NULL) / 86400)); /* sp->sp_lstchg */
+ /* ignore errors: if file is missing we suppose admin doesn't want it */
+ update_passwd(bb_path_shadow_file, pw.pw_name, p, NULL);
+ if (ENABLE_FEATURE_CLEAN_UP)
+ free(p);
#endif
/* add to group */
@@ -154,7 +140,7 @@ int adduser_main(int argc UNUSED_PARAM, char **argv)
if (!usegroup)
addgroup_wrapper(&pw);
- /* Clear the umask for this process so it doesn't
+ /* clear the umask for this process so it doesn't
* screw up the permissions on the mkdir and chown. */
umask(0);
if (!(option_mask32 & OPT_DONT_MAKE_HOME)) {
diff --git a/release/src/router/busybox/loginutils/chpasswd.c b/release/src/router/busybox/loginutils/chpasswd.c
index c83d1dad78..4bffbe83f1 100644
--- a/release/src/router/busybox/loginutils/chpasswd.c
+++ b/release/src/router/busybox/loginutils/chpasswd.c
@@ -5,7 +5,6 @@
* Written for SLIND (from passwd.c) by Alexander Shishkin
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
-
#include "libbb.h"
#if ENABLE_GETOPT_LONG
@@ -53,10 +52,10 @@ int chpasswd_main(int argc UNUSED_PARAM, char **argv)
/* This is rather complex: if user is not found in /etc/shadow,
* we try to find & change his passwd in /etc/passwd */
#if ENABLE_FEATURE_SHADOWPASSWDS
- rc = update_passwd(bb_path_shadow_file, name, pass);
+ rc = update_passwd(bb_path_shadow_file, name, pass, NULL);
if (rc == 0) /* no lines updated, no errors detected */
#endif
- rc = update_passwd(bb_path_passwd_file, name, pass);
+ rc = update_passwd(bb_path_passwd_file, name, pass, NULL);
/* LOGMODE_BOTH logs to syslog also */
logmode = LOGMODE_BOTH;
if (rc < 0)
diff --git a/release/src/router/busybox/loginutils/cryptpw.c b/release/src/router/busybox/loginutils/cryptpw.c
dissimilarity index 76%
index db5d95920a..47212e18a0 100644
--- a/release/src/router/busybox/loginutils/cryptpw.c
+++ b/release/src/router/busybox/loginutils/cryptpw.c
@@ -1,58 +1,117 @@
-/* vi: set sw=4 ts=4: */
-/*
- * cryptpw.c
- *
- * Cooked from passwd.c by Thomas Lundquist
- */
-
-#include "libbb.h"
-
-#define TESTING 0
-
-/*
-set TESTING to 1 and pipe some file through this script
-if you played with bbox's crypt implementation.
-
-while read line; do
- n=`./busybox cryptpw -a des -- "$line"`
- o=`./busybox_org cryptpw -a des -- "$line"`
- test "$n" != "$o" && {
- echo n="$n"
- echo o="$o"
- exit
- }
- n=`./busybox cryptpw -- "$line"`
- o=`./busybox_org cryptpw -- "$line"`
- test "$n" != "$o" && {
- echo n="$n"
- echo o="$o"
- exit
- }
-done
- */
-
-int cryptpw_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int cryptpw_main(int argc UNUSED_PARAM, char **argv)
-{
- char salt[sizeof("$N$XXXXXXXX")];
- char *opt_a;
-
- if (!getopt32(argv, "a:", &opt_a) || opt_a[0] != 'd') {
- salt[0] = '$';
- salt[1] = '1';
- salt[2] = '$';
- crypt_make_salt(salt + 3, 4, 0); /* md5 */
-#if TESTING
- strcpy(salt + 3, "ajg./bcf");
-#endif
- } else {
- crypt_make_salt(salt, 1, 0); /* des */
-#if TESTING
- strcpy(salt, "a.");
-#endif
- }
-
- puts(pw_encrypt(argv[optind] ? argv[optind] : xmalloc_fgetline(stdin), salt, 1));
-
- return 0;
-}
+/* vi: set sw=4 ts=4: */
+/*
+ * cryptpw.c - output a crypt(3)ed password to stdout.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ *
+ * Cooked from passwd.c by Thomas Lundquist
+ * mkpasswd compatible options added by Bernhard Reutner-Fischer
+ *
+ * Licensed under GPLv2, see file LICENSE in this tarball for details.
+ */
+
+#include "libbb.h"
+
+/* Debian has 'mkpasswd' utility, manpage says:
+
+NAME
+ mkpasswd - Overfeatured front end to crypt(3)
+SYNOPSIS
+ mkpasswd PASSWORD SALT
+...
+OPTIONS
+-S, --salt=STRING
+ Use the STRING as salt. It must not contain prefixes such as
+ $1$.
+-R, --rounds=NUMBER
+ Use NUMBER rounds. This argument is ignored if the method
+ choosen does not support variable rounds. For the OpenBSD Blowfish
+ method this is the logarithm of the number of rounds.
+-m, --method=TYPE
+ Compute the password using the TYPE method. If TYPE is 'help'
+ then the available methods are printed.
+-P, --password-fd=NUM
+ Read the password from file descriptor NUM instead of using getpass(3).
+ If the file descriptor is not connected to a tty then
+ no other message than the hashed password is printed on stdout.
+-s, --stdin
+ Like --password-fd=0.
+ENVIRONMENT
+ $MKPASSWD_OPTIONS
+ A list of options which will be evaluated before the ones
+ specified on the command line.
+BUGS
+ This programs suffers of a bad case of featuritis.
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Very true...
+
+cryptpw was in bbox before this gem, so we retain it, and alias mkpasswd
+to cryptpw. -a option (alias for -m) came from cryptpw.
+*/
+
+int cryptpw_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int cryptpw_main(int argc UNUSED_PARAM, char **argv)
+{
+ /* $N$ + sha_salt_16_bytes + NUL */
+ char salt[3 + 16 + 1];
+ char *salt_ptr;
+ const char *opt_m, *opt_S;
+ int len;
+ int fd;
+
+#if ENABLE_GETOPT_LONG
+ static const char mkpasswd_longopts[] ALIGN1 =
+ "stdin\0" No_argument "s"
+ "password-fd\0" Required_argument "P"
+ "salt\0" Required_argument "S"
+ "method\0" Required_argument "m"
+ ;
+ applet_long_options = mkpasswd_longopts;
+#endif
+ fd = STDIN_FILENO;
+ opt_m = "d";
+ opt_S = NULL;
+ /* at most two non-option arguments; -P NUM */
+ opt_complementary = "?2:P+";
+ getopt32(argv, "sP:S:m:a:", &fd, &opt_S, &opt_m, &opt_m);
+ argv += optind;
+
+ /* have no idea how to handle -s... */
+
+ if (argv[0] && !opt_S)
+ opt_S = argv[1];
+
+ len = 2/2;
+ salt_ptr = salt;
+ if (opt_m[0] != 'd') { /* not des */
+ len = 8/2; /* so far assuming md5 */
+ *salt_ptr++ = '$';
+ *salt_ptr++ = '1';
+ *salt_ptr++ = '$';
+#if !ENABLE_USE_BB_CRYPT || ENABLE_USE_BB_CRYPT_SHA
+ if (opt_m[0] == 's') { /* sha */
+ salt[1] = '5' + (strcmp(opt_m, "sha512") == 0);
+ len = 16/2;
+ }
+#endif
+ }
+ if (opt_S)
+ safe_strncpy(salt_ptr, opt_S, sizeof(salt) - 3);
+ else
+ crypt_make_salt(salt_ptr, len, 0);
+
+ xmove_fd(fd, STDIN_FILENO);
+
+ puts(pw_encrypt(
+ argv[0] ? argv[0] : (
+ /* Only mkpasswd, and only from tty, prompts.
+ * Otherwise it is a plain read. */
+ (isatty(STDIN_FILENO) && applet_name[0] == 'm')
+ ? bb_ask_stdin("Password: ")
+ : xmalloc_fgetline(stdin)
+ ),
+ salt, 1));
+
+ return EXIT_SUCCESS;
+}
diff --git a/release/src/router/busybox/loginutils/deluser.c b/release/src/router/busybox/loginutils/deluser.c
dissimilarity index 85%
index 56253712e1..293e324b06 100644
--- a/release/src/router/busybox/loginutils/deluser.c
+++ b/release/src/router/busybox/loginutils/deluser.c
@@ -1,125 +1,56 @@
-/* vi: set sw=4 ts=4: */
-/*
- * deluser/delgroup implementation for busybox
- *
- * Copyright (C) 1999 by Lineo, inc. and John Beppu
- * Copyright (C) 1999,2000,2001 by John Beppu
- * Copyright (C) 2007 by Tito Ragusa
- *
- * Licensed under GPL version 2, see file LICENSE in this tarball for details.
- *
- */
-
-#include "libbb.h"
-
-/* Status */
-#define STATUS_OK 0
-#define NAME_NOT_FOUND 1
-#define MEMBER_NOT_FOUND 2
-
-static void del_line_matching(char **args,
- const char *filename,
- FILE* FAST_FUNC (*fopen_func)(const char *fileName, const char *mode))
-{
- FILE *passwd;
- smallint error = NAME_NOT_FOUND;
- char *name = (ENABLE_FEATURE_DEL_USER_FROM_GROUP && args[2]) ? args[2] : args[1];
- char *line, *del;
- char *new = xzalloc(1);
-
- passwd = fopen_func(filename, "r");
- if (passwd) {
- while ((line = xmalloc_fgets(passwd))) {
- int len = strlen(name);
-
- if (strncmp(line, name, len) == 0
- && line[len] == ':'
- ) {
- error = STATUS_OK;
- if (ENABLE_FEATURE_DEL_USER_FROM_GROUP) {
- struct group *gr;
- char *p;
- if (args[2]
- /* There were two args on commandline */
- && (gr = getgrnam(name))
- /* The group was not deleted in the meanwhile */
- && (p = strrchr(line, ':'))
- /* We can find a pointer to the last ':' */
- ) {
- error = MEMBER_NOT_FOUND;
- /* Move past ':' (worst case to '\0') and cut the line */
- p[1] = '\0';
- /* Reuse p */
- for (p = xzalloc(1); *gr->gr_mem != NULL; gr->gr_mem++) {
- /* Add all the other group members */
- if (strcmp(args[1], *gr->gr_mem) != 0) {
- del = p;
- p = xasprintf("%s%s%s", p, p[0] ? "," : "", *gr->gr_mem);
- free(del);
- } else
- error = STATUS_OK;
- }
- /* Recompose the line */
- line = xasprintf("%s%s\n", line, p);
- if (ENABLE_FEATURE_CLEAN_UP) free(p);
- } else
- goto skip;
- }
- }
- del = new;
- new = xasprintf("%s%s", new, line);
- free(del);
- skip:
- free(line);
- }
-
- if (ENABLE_FEATURE_CLEAN_UP) fclose(passwd);
-
- if (error) {
- if (ENABLE_FEATURE_DEL_USER_FROM_GROUP && error == MEMBER_NOT_FOUND) {
- /* Set the correct values for error message */
- filename = name;
- name = args[1];
- }
- bb_error_msg("can't find %s in %s", name, filename);
- } else {
- passwd = fopen_func(filename, "w");
- if (passwd) {
- fputs(new, passwd);
- if (ENABLE_FEATURE_CLEAN_UP) fclose(passwd);
- }
- }
- }
- free(new);
-}
-
-int deluser_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int deluser_main(int argc, char **argv)
-{
- if (argc == 2
- || (ENABLE_FEATURE_DEL_USER_FROM_GROUP
- && (applet_name[3] == 'g' && argc == 3))
- ) {
- if (geteuid())
- bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
-
- if ((ENABLE_FEATURE_DEL_USER_FROM_GROUP && argc != 3)
- || ENABLE_DELUSER
- || (ENABLE_DELGROUP && ENABLE_DESKTOP)
- ) {
- if (ENABLE_DELUSER
- && (!ENABLE_DELGROUP || applet_name[3] == 'u')
- ) {
- del_line_matching(argv, bb_path_passwd_file, xfopen);
- if (ENABLE_FEATURE_SHADOWPASSWDS)
- del_line_matching(argv, bb_path_shadow_file, fopen_or_warn);
- } else if (ENABLE_DESKTOP && ENABLE_DELGROUP && getpwnam(argv[1]))
- bb_error_msg_and_die("can't remove primary group of user %s", argv[1]);
- }
- del_line_matching(argv, bb_path_group_file, xfopen);
- if (ENABLE_FEATURE_SHADOWPASSWDS)
- del_line_matching(argv, bb_path_gshadow_file, fopen_or_warn);
- return EXIT_SUCCESS;
- } else
- bb_show_usage();
-}
+/* vi: set sw=4 ts=4: */
+/*
+ * deluser/delgroup implementation for busybox
+ *
+ * Copyright (C) 1999 by Lineo, inc. and John Beppu
+ * Copyright (C) 1999,2000,2001 by John Beppu
+ * Copyright (C) 2007 by Tito Ragusa
+ *
+ * Licensed under GPL version 2, see file LICENSE in this tarball for details.
+ *
+ */
+#include "libbb.h"
+
+static int del_line_matching(char **args, const char *filename)
+{
+ if (ENABLE_FEATURE_DEL_USER_FROM_GROUP && args[2]) {
+ return update_passwd(filename, args[2], NULL, args[1]);
+ }
+ return update_passwd(filename, args[1], NULL, NULL);
+}
+
+int deluser_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int deluser_main(int argc, char **argv)
+{
+ if (argc != 2
+ && (!ENABLE_FEATURE_DEL_USER_FROM_GROUP
+ || (applet_name[3] != 'g' || argc != 3))
+ ) {
+ bb_show_usage();
+ }
+
+ if (geteuid())
+ bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
+
+ if ((ENABLE_FEATURE_DEL_USER_FROM_GROUP && argc != 3)
+ || ENABLE_DELUSER
+ || (ENABLE_DELGROUP && ENABLE_DESKTOP)
+ ) {
+ if (ENABLE_DELUSER
+ && (!ENABLE_DELGROUP || applet_name[3] == 'u')
+ ) {
+ if (del_line_matching(argv, bb_path_passwd_file) < 0)
+ return EXIT_FAILURE;
+ if (ENABLE_FEATURE_SHADOWPASSWDS) {
+ del_line_matching(argv, bb_path_shadow_file);
+ }
+ } else if (ENABLE_DESKTOP && ENABLE_DELGROUP && getpwnam(argv[1]))
+ bb_error_msg_and_die("can't remove primary group of user %s", argv[1]);
+ }
+ if (del_line_matching(argv, bb_path_group_file) < 0)
+ return EXIT_FAILURE;
+ if (ENABLE_FEATURE_SHADOWPASSWDS) {
+ del_line_matching(argv, bb_path_gshadow_file);
+ }
+ return EXIT_SUCCESS;
+}
diff --git a/release/src/router/busybox/loginutils/getty.c b/release/src/router/busybox/loginutils/getty.c
index 358a45c7cd..24a182ff40 100644
--- a/release/src/router/busybox/loginutils/getty.c
+++ b/release/src/router/busybox/loginutils/getty.c
@@ -19,7 +19,7 @@
#include
#if ENABLE_FEATURE_UTMP
-#include
+#include /* updwtmp() */
#endif
/*
@@ -28,10 +28,6 @@
*/
#ifdef LOGIN_PROCESS /* defined in System V utmp.h */
#include
-#include
-#if ENABLE_FEATURE_WTMP
-extern void updwtmp(const char *filename, const struct utmp *ut);
-#endif
#else /* if !sysV style, wtmp/utmp code is off */
#undef ENABLE_FEATURE_UTMP
#undef ENABLE_FEATURE_WTMP
@@ -167,8 +163,9 @@ static void parse_speeds(struct options *op, char *arg)
debug("entered parse_speeds\n");
while ((cp = strsep(&arg, ",")) != NULL) {
op->speeds[op->numspeed] = bcode(cp);
- if (op->speeds[op->numspeed] <= 0)
+ if (op->speeds[op->numspeed] < 0)
bb_error_msg_and_die("bad speed: %s", cp);
+ /* note: arg "0" turns into speed B0 */
op->numspeed++;
if (op->numspeed > MAX_SPEED)
bb_error_msg_and_die("too many alternate speeds");
@@ -274,6 +271,7 @@ static void open_tty(const char *tty)
/* termios_init - initialize termios settings */
static void termios_init(struct termios *tp, int speed, struct options *op)
{
+ speed_t ispeed, ospeed;
/*
* Initial termios settings: 8-bit characters, raw-mode, blocking i/o.
* Special characters are set after we have read the login name; all
@@ -282,12 +280,20 @@ static void termios_init(struct termios *tp, int speed, struct options *op)
*/
#ifdef __linux__
/* flush input and output queues, important for modems! */
- ioctl(0, TCFLSH, TCIOFLUSH);
+ ioctl(0, TCFLSH, TCIOFLUSH); /* tcflush(0, TCIOFLUSH)? - same */
#endif
-
- tp->c_cflag = CS8 | HUPCL | CREAD | speed;
+ ispeed = ospeed = speed;
+ if (speed == B0) {
+ /* Speed was specified as "0" on command line.
+ * Just leave it unchanged */
+ ispeed = cfgetispeed(tp);
+ ospeed = cfgetospeed(tp);
+ }
+ tp->c_cflag = CS8 | HUPCL | CREAD;
if (op->flags & F_LOCAL)
tp->c_cflag |= CLOCAL;
+ cfsetispeed(tp, ispeed);
+ cfsetospeed(tp, ospeed);
tp->c_iflag = tp->c_lflag = tp->c_line = 0;
tp->c_oflag = OPOST | ONLCR;
@@ -300,7 +306,7 @@ static void termios_init(struct termios *tp, int speed, struct options *op)
tp->c_cflag |= CRTSCTS;
#endif
- ioctl(0, TCSETS, tp);
+ tcsetattr_stdin_TCSANOW(tp);
debug("term_io 2\n");
}
@@ -337,7 +343,7 @@ static void auto_baud(char *buf, unsigned size_buf, struct termios *tp)
tp->c_iflag |= ISTRIP; /* enable 8th-bit stripping */
vmin = tp->c_cc[VMIN];
tp->c_cc[VMIN] = 0; /* don't block if queue empty */
- ioctl(0, TCSETS, tp);
+ tcsetattr_stdin_TCSANOW(tp);
/*
* Wait for a while, then read everything the modem has said so far and
@@ -362,7 +368,7 @@ static void auto_baud(char *buf, unsigned size_buf, struct termios *tp)
/* Restore terminal settings. Errors will be dealt with later on. */
tp->c_iflag = iflag;
tp->c_cc[VMIN] = vmin;
- ioctl(0, TCSETS, tp);
+ tcsetattr_stdin_TCSANOW(tp);
}
/* do_prompt - show login prompt, optionally preceded by /etc/issue contents */
@@ -407,7 +413,7 @@ static char *get_logname(char *logname, unsigned size_logname,
/* Flush pending input (esp. after parsing or switching the baud rate). */
sleep(1);
- ioctl(0, TCFLSH, TCIFLUSH);
+ ioctl(0, TCFLSH, TCIFLUSH); /* tcflush(0, TCIOFLUSH)? - same */
/* Prompt for and read a login name. */
logname[0] = '\0';
@@ -477,7 +483,7 @@ static char *get_logname(char *logname, unsigned size_logname,
case CTL('D'):
exit(EXIT_SUCCESS);
default:
- if (!isascii(ascval) || !isprint(ascval)) {
+ if (!isprint(ascval)) {
/* ignore garbage characters */
} else if ((int)(bp - logname) >= size_logname - 1) {
bb_error_msg_and_die("%s: input overrun", op->tty);
@@ -555,12 +561,13 @@ static void termios_final(struct options *op, struct termios *tp, struct chardat
}
#endif
/* Optionally enable hardware flow control */
-#ifdef CRTSCTS
+#ifdef CRTSCTS
if (op->flags & F_RTSCTS)
tp->c_cflag |= CRTSCTS;
#endif
/* Finally, make the new settings effective */
+ /* It's tcsetattr_stdin_TCSANOW() + error check */
ioctl_or_perror_and_die(0, TCSETS, tp, "%s: TCSETS", op->tty);
}
@@ -692,6 +699,7 @@ int getty_main(int argc UNUSED_PARAM, char **argv)
* by patching the SunOS kernel variable "zsadtrlow" to a larger value;
* 5 seconds seems to be a good value.
*/
+ /* tcgetattr() + error check */
ioctl_or_perror_and_die(0, TCGETS, &termios, "%s: TCGETS", options.tty);
#ifdef __linux__
@@ -715,6 +723,7 @@ int getty_main(int argc UNUSED_PARAM, char **argv)
/* Write the modem init string and DON'T flush the buffers */
if (options.flags & F_INITSTRING) {
debug("writing init string\n");
+ /* todo: use xwrite_str? */
full_write(STDOUT_FILENO, options.initstring, strlen(options.initstring));
}
@@ -754,9 +763,9 @@ int getty_main(int argc UNUSED_PARAM, char **argv)
break;
/* we are here only if options.numspeed > 1 */
baud_index = (baud_index + 1) % options.numspeed;
- termios.c_cflag &= ~CBAUD;
- termios.c_cflag |= options.speeds[baud_index];
- ioctl(0, TCSETS, &termios);
+ cfsetispeed(&termios, options.speeds[baud_index]);
+ cfsetospeed(&termios, options.speeds[baud_index]);
+ tcsetattr_stdin_TCSANOW(&termios);
}
}
diff --git a/release/src/router/busybox/loginutils/login.c b/release/src/router/busybox/loginutils/login.c
index 8732b99f1e..d57d529c03 100644
--- a/release/src/router/busybox/loginutils/login.c
+++ b/release/src/router/busybox/loginutils/login.c
@@ -52,7 +52,7 @@ static char* short_tty;
* command line flags.
*/
-static void read_or_build_utent(struct utmp *utptr, int picky)
+static void read_or_build_utent(struct utmp *utptr, int run_by_root)
{
struct utmp *ut;
pid_t pid = getpid();
@@ -60,30 +60,33 @@ static void read_or_build_utent(struct utmp *utptr, int picky)
setutent();
/* First, try to find a valid utmp entry for this process. */
- while ((ut = getutent()))
- if (ut->ut_pid == pid && ut->ut_line[0] && ut->ut_id[0] &&
- (ut->ut_type == LOGIN_PROCESS || ut->ut_type == USER_PROCESS))
- break;
+ /* If there is one, just use it. */
+ while ((ut = getutent()) != NULL)
+ if (ut->ut_pid == pid && ut->ut_line[0] && ut->ut_id[0]
+ && (ut->ut_type == LOGIN_PROCESS || ut->ut_type == USER_PROCESS)
+ ) {
+ *utptr = *ut; /* struct copy */
+ if (run_by_root) /* why only for root? */
+ memset(utptr->ut_host, 0, sizeof(utptr->ut_host));
+ return;
+ }
- /* If there is one, just use it, otherwise create a new one. */
- if (ut) {
- *utptr = *ut;
- } else {
- if (picky)
- bb_error_msg_and_die("no utmp entry found");
-
- memset(utptr, 0, sizeof(*utptr));
- utptr->ut_type = LOGIN_PROCESS;
- utptr->ut_pid = pid;
- strncpy(utptr->ut_line, short_tty, sizeof(utptr->ut_line));
- /* This one is only 4 chars wide. Try to fit something
- * remotely meaningful by skipping "tty"... */
- strncpy(utptr->ut_id, short_tty + 3, sizeof(utptr->ut_id));
- strncpy(utptr->ut_user, "LOGIN", sizeof(utptr->ut_user));
- utptr->ut_tv.tv_sec = time(NULL);
- }
- if (!picky) /* root login */
- memset(utptr->ut_host, 0, sizeof(utptr->ut_host));
+// Why? Do we require non-root to exec login from another
+// former login process (e.g. login shell)? Some login's have
+// login shells as children, so it won't work...
+// if (!run_by_root)
+// bb_error_msg_and_die("no utmp entry found");
+
+ /* Otherwise create a new one. */
+ memset(utptr, 0, sizeof(*utptr));
+ utptr->ut_type = LOGIN_PROCESS;
+ utptr->ut_pid = pid;
+ strncpy(utptr->ut_line, short_tty, sizeof(utptr->ut_line));
+ /* This one is only 4 chars wide. Try to fit something
+ * remotely meaningful by skipping "tty"... */
+ strncpy(utptr->ut_id, short_tty + 3, sizeof(utptr->ut_id));
+ strncpy(utptr->ut_user, "LOGIN", sizeof(utptr->ut_user));
+ utptr->ut_tv.tv_sec = time(NULL);
}
/*
@@ -109,7 +112,7 @@ static void write_utent(struct utmp *utptr, const char *username)
#endif
}
#else /* !ENABLE_FEATURE_UTMP */
-#define read_or_build_utent(utptr, picky) ((void)0)
+#define read_or_build_utent(utptr, run_by_root) ((void)0)
#define write_utent(utptr, username) ((void)0)
#endif /* !ENABLE_FEATURE_UTMP */
@@ -118,18 +121,25 @@ static void die_if_nologin(void)
{
FILE *fp;
int c;
+ int empty = 1;
- if (access("/etc/nologin", F_OK))
+ fp = fopen_for_read("/etc/nologin");
+ if (!fp) /* assuming it does not exist */
return;
- fp = fopen_for_read("/etc/nologin");
- if (fp) {
- while ((c = getc(fp)) != EOF)
- bb_putchar((c=='\n') ? '\r' : c);
- fflush(stdout);
- fclose(fp);
- } else
+ while ((c = getc(fp)) != EOF) {
+ if (c == '\n')
+ bb_putchar('\r');
+ bb_putchar(c);
+ empty = 0;
+ }
+ if (empty)
puts("\r\nSystem closed for routine maintenance\r");
+
+ fclose(fp);
+ fflush(NULL);
+ /* Users say that they do need this prior to exit: */
+ tcdrain(STDOUT_FILENO);
exit(EXIT_FAILURE);
}
#else
@@ -155,6 +165,56 @@ static int check_securetty(void)
static ALWAYS_INLINE int check_securetty(void) { return 1; }
#endif
+#if ENABLE_SELINUX
+static void initselinux(char *username, char *full_tty,
+ security_context_t *user_sid)
+{
+ security_context_t old_tty_sid, new_tty_sid;
+
+ if (!is_selinux_enabled())
+ return;
+
+ if (get_default_context(username, NULL, user_sid)) {
+ bb_error_msg_and_die("cannot get SID for %s", username);
+ }
+ if (getfilecon(full_tty, &old_tty_sid) < 0) {
+ bb_perror_msg_and_die("getfilecon(%s) failed", full_tty);
+ }
+ if (security_compute_relabel(*user_sid, old_tty_sid,
+ SECCLASS_CHR_FILE, &new_tty_sid) != 0) {
+ bb_perror_msg_and_die("security_change_sid(%s) failed", full_tty);
+ }
+ if (setfilecon(full_tty, new_tty_sid) != 0) {
+ bb_perror_msg_and_die("chsid(%s, %s) failed", full_tty, new_tty_sid);
+ }
+}
+#endif
+
+#if ENABLE_LOGIN_SCRIPTS
+static void run_login_script(struct passwd *pw, char *full_tty)
+{
+ char *t_argv[2];
+
+ t_argv[0] = getenv("LOGIN_PRE_SUID_SCRIPT");
+ if (t_argv[0]) {
+ t_argv[1] = NULL;
+ xsetenv("LOGIN_TTY", full_tty);
+ xsetenv("LOGIN_USER", pw->pw_name);
+ xsetenv("LOGIN_UID", utoa(pw->pw_uid));
+ xsetenv("LOGIN_GID", utoa(pw->pw_gid));
+ xsetenv("LOGIN_SHELL", pw->pw_shell);
+ spawn_and_wait(t_argv); /* NOMMU-friendly */
+ unsetenv("LOGIN_TTY");
+ unsetenv("LOGIN_USER");
+ unsetenv("LOGIN_UID");
+ unsetenv("LOGIN_GID");
+ unsetenv("LOGIN_SHELL");
+ }
+}
+#else
+void run_login_script(struct passwd *pw, char *full_tty);
+#endif
+
static void get_username_or_die(char *buf, int size_buf)
{
int c, cntdown;
@@ -218,13 +278,13 @@ int login_main(int argc UNUSED_PARAM, char **argv)
char *fromhost;
char username[USERNAME_SIZE];
const char *tmp;
- int amroot;
+ int run_by_root;
unsigned opt;
int count = 0;
struct passwd *pw;
char *opt_host = opt_host; /* for compiler */
char *opt_user = opt_user; /* for compiler */
- char full_tty[TTYNAME_SIZE];
+ char *full_tty;
USE_SELINUX(security_context_t user_sid = NULL;)
USE_FEATURE_UTMP(struct utmp utent;)
#if ENABLE_PAM
@@ -236,13 +296,13 @@ int login_main(int argc UNUSED_PARAM, char **argv)
char pwdbuf[256];
#endif
- short_tty = full_tty;
username[0] = '\0';
signal(SIGALRM, alarm_handler);
alarm(TIMEOUT);
- /* More of suid paranoia if called by non-root */
- amroot = !sanitize_env_if_suid(); /* Clear dangerous stuff, set PATH */
+ /* More of suid paranoia if called by non-root: */
+ /* Clear dangerous stuff, set PATH */
+ run_by_root = !sanitize_env_if_suid();
/* Mandatory paranoia for suid applet:
* ensure that fd# 0,1,2 are opened (at least to /dev/null)
@@ -252,7 +312,7 @@ int login_main(int argc UNUSED_PARAM, char **argv)
opt = getopt32(argv, "f:h:p", &opt_user, &opt_host);
if (opt & LOGIN_OPT_f) {
- if (!amroot)
+ if (!run_by_root)
bb_error_msg_and_die("-f is for root only");
safe_strncpy(username, opt_user, sizeof(username));
}
@@ -261,30 +321,28 @@ int login_main(int argc UNUSED_PARAM, char **argv)
safe_strncpy(username, argv[0], sizeof(username));
/* Let's find out and memorize our tty */
- if (!isatty(0) || !isatty(1) || !isatty(2))
+ if (!isatty(STDIN_FILENO) || !isatty(STDOUT_FILENO) || !isatty(STDERR_FILENO))
return EXIT_FAILURE; /* Must be a terminal */
- safe_strncpy(full_tty, "UNKNOWN", sizeof(full_tty));
- tmp = ttyname(0);
- if (tmp) {
- safe_strncpy(full_tty, tmp, sizeof(full_tty));
- if (strncmp(full_tty, "/dev/", 5) == 0)
- short_tty = full_tty + 5;
- }
+ full_tty = xmalloc_ttyname(STDIN_FILENO);
+ if (!full_tty)
+ full_tty = xstrdup("UNKNOWN");
+ short_tty = full_tty;
+ if (strncmp(full_tty, "/dev/", 5) == 0)
+ short_tty += 5;
- read_or_build_utent(&utent, !amroot);
+ read_or_build_utent(&utent, run_by_root);
if (opt & LOGIN_OPT_h) {
- USE_FEATURE_UTMP(
- safe_strncpy(utent.ut_host, opt_host, sizeof(utent.ut_host));
- )
+ USE_FEATURE_UTMP(safe_strncpy(utent.ut_host, opt_host, sizeof(utent.ut_host));)
fromhost = xasprintf(" on '%s' from '%s'", short_tty, opt_host);
- } else
+ } else {
fromhost = xasprintf(" on '%s'", short_tty);
+ }
/* Was breaking "login " from shell command line: */
/*bb_setpgrp();*/
- openlog(applet_name, LOG_PID | LOG_CONS | LOG_NOWAIT, LOG_AUTH);
+ openlog(applet_name, LOG_PID | LOG_CONS, LOG_AUTH);
while (1) {
/* flush away any type-ahead (as getty does) */
@@ -389,62 +447,26 @@ int login_main(int argc UNUSED_PARAM, char **argv)
return EXIT_FAILURE;
}
username[0] = '\0';
- }
+ } /* while (1) */
alarm(0);
- if (!amroot)
+ /* We can ignore /etc/nologin if we are logging in as root,
+ * it doesn't matter whether we are run by root or not */
+ if (pw->pw_uid != 0)
die_if_nologin();
write_utent(&utent, username);
-#if ENABLE_SELINUX
- if (is_selinux_enabled()) {
- security_context_t old_tty_sid, new_tty_sid;
+ USE_SELINUX(initselinux(username, full_tty, &user_sid));
- if (get_default_context(username, NULL, &user_sid)) {
- bb_error_msg_and_die("cannot get SID for %s",
- username);
- }
- if (getfilecon(full_tty, &old_tty_sid) < 0) {
- bb_perror_msg_and_die("getfilecon(%s) failed",
- full_tty);
- }
- if (security_compute_relabel(user_sid, old_tty_sid,
- SECCLASS_CHR_FILE, &new_tty_sid) != 0) {
- bb_perror_msg_and_die("security_change_sid(%s) failed",
- full_tty);
- }
- if (setfilecon(full_tty, new_tty_sid) != 0) {
- bb_perror_msg_and_die("chsid(%s, %s) failed",
- full_tty, new_tty_sid);
- }
- }
-#endif
/* Try these, but don't complain if they fail.
* _f_chown is safe wrt race t=ttyname(0);...;chown(t); */
fchown(0, pw->pw_uid, pw->pw_gid);
fchmod(0, 0600);
/* We trust environment only if we run by root */
- if (ENABLE_LOGIN_SCRIPTS && amroot) {
- char *t_argv[2];
-
- t_argv[0] = getenv("LOGIN_PRE_SUID_SCRIPT");
- if (t_argv[0]) {
- t_argv[1] = NULL;
- xsetenv("LOGIN_TTY", full_tty);
- xsetenv("LOGIN_USER", pw->pw_name);
- xsetenv("LOGIN_UID", utoa(pw->pw_uid));
- xsetenv("LOGIN_GID", utoa(pw->pw_gid));
- xsetenv("LOGIN_SHELL", pw->pw_shell);
- spawn_and_wait(t_argv); /* NOMMU-friendly */
- unsetenv("LOGIN_TTY" );
- unsetenv("LOGIN_USER" );
- unsetenv("LOGIN_UID" );
- unsetenv("LOGIN_GID" );
- unsetenv("LOGIN_SHELL");
- }
- }
+ if (ENABLE_LOGIN_SCRIPTS && run_by_root)
+ run_login_script(pw, full_tty);
change_identity(pw);
tmp = pw->pw_shell;
@@ -457,11 +479,10 @@ int login_main(int argc UNUSED_PARAM, char **argv)
if (pw->pw_uid == 0)
syslog(LOG_INFO, "root login%s", fromhost);
-#if ENABLE_SELINUX
+
/* well, a simple setexeccon() here would do the job as well,
* but let's play the game for now */
- set_current_security_context(user_sid);
-#endif
+ USE_SELINUX(set_current_security_context(user_sid);)
// util-linux login also does:
// /* start new session */
@@ -472,14 +493,16 @@ int login_main(int argc UNUSED_PARAM, char **argv)
// bb_setpgrp();
// If this stuff is really needed, add it and explain why!
- /* set signals to defaults */
- signal(SIGALRM, SIG_DFL);
+ /* Set signals to defaults */
+ /* Non-ignored signals revert to SIG_DFL on exec anyway */
+ /*signal(SIGALRM, SIG_DFL);*/
+
/* Is this correct? This way user can ctrl-c out of /etc/profile,
* potentially creating security breach (tested with bash 3.0).
* But without this, bash 3.0 will not enable ctrl-c either.
* Maybe bash is buggy?
* Need to find out what standards say about /bin/login -
- * should it leave SIGINT etc enabled or disabled? */
+ * should we leave SIGINT etc enabled or disabled? */
signal(SIGINT, SIG_DFL);
/* Exec login shell with no additional parameters */
diff --git a/release/src/router/busybox/loginutils/passwd.c b/release/src/router/busybox/loginutils/passwd.c
index 99fb76ecae..7b93713b9c 100644
--- a/release/src/router/busybox/loginutils/passwd.c
+++ b/release/src/router/busybox/loginutils/passwd.c
@@ -2,7 +2,6 @@
/*
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
-
#include "libbb.h"
#include
@@ -22,7 +21,7 @@ static char* new_password(const struct passwd *pw, uid_t myuid, int algo)
if (myuid && pw->pw_passwd[0]) {
char *encrypted;
- orig = bb_askpass(0, "Old password:"); /* returns ptr to static */
+ orig = bb_ask_stdin("Old password:"); /* returns ptr to static */
if (!orig)
goto err_ret;
encrypted = pw_encrypt(orig, pw->pw_passwd, 1); /* returns malloced str */
@@ -35,16 +34,16 @@ static char* new_password(const struct passwd *pw, uid_t myuid, int algo)
}
if (ENABLE_FEATURE_CLEAN_UP) free(encrypted);
}
- orig = xstrdup(orig); /* or else bb_askpass() will destroy it */
- newp = bb_askpass(0, "New password:"); /* returns ptr to static */
+ orig = xstrdup(orig); /* or else bb_ask_stdin() will destroy it */
+ newp = bb_ask_stdin("New password:"); /* returns ptr to static */
if (!newp)
goto err_ret;
- newp = xstrdup(newp); /* we are going to bb_askpass() again, so save it */
+ newp = xstrdup(newp); /* we are going to bb_ask_stdin() again, so save it */
if (ENABLE_FEATURE_PASSWD_WEAK_CHECK
&& obscure(orig, newp, pw) && myuid)
goto err_ret; /* non-root is not allowed to have weak passwd */
- cp = bb_askpass(0, "Retype password:");
+ cp = bb_ask_stdin("Retype password:");
if (!cp)
goto err_ret;
if (strcmp(cp, newp)) {
@@ -100,7 +99,7 @@ int passwd_main(int argc UNUSED_PARAM, char **argv)
#endif
logmode = LOGMODE_BOTH;
- openlog(applet_name, LOG_NOWAIT, LOG_AUTH);
+ openlog(applet_name, 0, LOG_AUTH);
opt = getopt32(argv, "a:lud", &opt_a);
//argc -= optind;
argv += optind;
@@ -115,12 +114,10 @@ int passwd_main(int argc UNUSED_PARAM, char **argv)
bb_show_usage();
/* Will complain and die if username not found */
- myname = xstrdup(bb_getpwuid(NULL, -1, myuid));
+ myname = xstrdup(xuid2uname(myuid));
name = argv[0] ? argv[0] : myname;
- pw = getpwnam(name);
- if (!pw)
- bb_error_msg_and_die("unknown user %s", name);
+ pw = xgetpwnam(name);
if (myuid && pw->pw_uid != myuid) {
/* LOGMODE_BOTH */
bb_error_msg_and_die("%s can't change password for %s", myname, name);
@@ -183,12 +180,12 @@ int passwd_main(int argc UNUSED_PARAM, char **argv)
#if ENABLE_FEATURE_SHADOWPASSWDS
filename = bb_path_shadow_file;
- rc = update_passwd(bb_path_shadow_file, name, newp);
+ rc = update_passwd(bb_path_shadow_file, name, newp, NULL);
if (rc == 0) /* no lines updated, no errors detected */
#endif
{
filename = bb_path_passwd_file;
- rc = update_passwd(bb_path_passwd_file, name, newp);
+ rc = update_passwd(bb_path_passwd_file, name, newp, NULL);
}
/* LOGMODE_BOTH */
if (rc < 0)
diff --git a/release/src/router/busybox/loginutils/su.c b/release/src/router/busybox/loginutils/su.c
index 61039d823f..de8c18d25e 100644
--- a/release/src/router/busybox/loginutils/su.c
+++ b/release/src/router/busybox/loginutils/su.c
@@ -44,13 +44,11 @@ int su_main(int argc UNUSED_PARAM, char **argv)
But getlogin can fail -- usually due to lack of utmp entry.
in this case resort to getpwuid. */
old_user = xstrdup(USE_FEATURE_UTMP(getlogin() ? : ) (pw = getpwuid(cur_uid)) ? pw->pw_name : "");
- tty = ttyname(2) ? : "none";
+ tty = xmalloc_ttyname(2) ? : "none";
openlog(applet_name, 0, LOG_AUTH);
}
- pw = getpwnam(opt_username);
- if (!pw)
- bb_error_msg_and_die("unknown id: %s", opt_username);
+ pw = xgetpwnam(opt_username);
/* Make sure pw->pw_shell is non-NULL. It may be NULL when NEW_USER
is a username that is retrieved via NIS (YP), but that doesn't have
diff --git a/release/src/router/busybox/loginutils/sulogin.c b/release/src/router/busybox/loginutils/sulogin.c
index bfd42569ab..4ffefe933b 100644
--- a/release/src/router/busybox/loginutils/sulogin.c
+++ b/release/src/router/busybox/loginutils/sulogin.c
@@ -32,11 +32,12 @@ int sulogin_main(int argc UNUSED_PARAM, char **argv)
opt_complementary = "t+"; /* -t N */
getopt32(argv, "t:", &timeout);
+ argv += optind;
- if (argv[optind]) {
+ if (argv[0]) {
close(0);
close(1);
- dup(xopen(argv[optind], O_RDWR));
+ dup(xopen(argv[0], O_RDWR));
close(2);
dup(0);
}
@@ -50,7 +51,7 @@ int sulogin_main(int argc UNUSED_PARAM, char **argv)
/* Clear dangerous stuff, set PATH */
sanitize_env_if_suid();
-// bb_askpass() already handles this
+// bb_ask() already handles this
// signal(SIGALRM, catchalarm);
pwd = getpwuid(0);
@@ -76,7 +77,7 @@ int sulogin_main(int argc UNUSED_PARAM, char **argv)
int r;
/* cp points to a static buffer that is zeroed every time */
- cp = bb_askpass(timeout,
+ cp = bb_ask(STDIN_FILENO, timeout,
"Give root password for system maintenance\n"
"(or type Control-D for normal startup):");
diff --git a/release/src/router/busybox/loginutils/vlock.c b/release/src/router/busybox/loginutils/vlock.c
index 42ef447326..85f489c228 100644
--- a/release/src/router/busybox/loginutils/vlock.c
+++ b/release/src/router/busybox/loginutils/vlock.c
@@ -38,14 +38,9 @@ int vlock_main(int argc UNUSED_PARAM, char **argv)
struct termios term;
struct termios oterm;
struct vt_mode ovtm;
- uid_t uid;
struct passwd *pw;
-/* XXX: xgetpwuid */
- uid = getuid();
- pw = getpwuid(uid);
- if (pw == NULL)
- bb_error_msg_and_die("unknown uid %d", (int)uid);
+ pw = xgetpwuid(getuid());
opt_complementary = "=0"; /* no params! */
getopt32(argv, "a");
@@ -87,7 +82,7 @@ int vlock_main(int argc UNUSED_PARAM, char **argv)
term.c_iflag |= IGNBRK;
term.c_lflag &= ~ISIG;
term.c_lflag &= ~(ECHO | ECHOCTL);
- tcsetattr(STDIN_FILENO, TCSANOW, &term);
+ tcsetattr_stdin_TCSANOW(&term);
do {
printf("Virtual console%s locked by %s.\n",
@@ -101,6 +96,6 @@ int vlock_main(int argc UNUSED_PARAM, char **argv)
} while (1);
ioctl(STDIN_FILENO, VT_SETMODE, &ovtm);
- tcsetattr(STDIN_FILENO, TCSANOW, &oterm);
+ tcsetattr_stdin_TCSANOW(&oterm);
fflush_stdout_and_exit(EXIT_SUCCESS);
}
diff --git a/release/src/router/busybox/mailutils/Config.in b/release/src/router/busybox/mailutils/Config.in
new file mode 100644
index 0000000000..519d562ae6
--- /dev/null
+++ b/release/src/router/busybox/mailutils/Config.in
@@ -0,0 +1,53 @@
+menu "Mail Utilities"
+
+config MAKEMIME
+ bool "makemime"
+ default n
+ help
+ Create MIME-formatted messages.
+
+config FEATURE_MIME_CHARSET
+ string "Default charset"
+ default "us-ascii"
+ depends on MAKEMIME || REFORMIME || SENDMAIL
+ help
+ Default charset of the message.
+
+config POPMAILDIR
+ bool "popmaildir"
+ default n
+ help
+ Simple yet powerful POP3 mail popper. Delivers content
+ of remote mailboxes to local Maildir.
+
+config FEATURE_POPMAILDIR_DELIVERY
+ bool "Allow message filters and custom delivery program"
+ default n
+ depends on POPMAILDIR
+ help
+ Allow to use a custom program to filter the content
+ of the message before actual delivery (-F "prog [args...]").
+ Allow to use a custom program for message actual delivery
+ (-M "prog [args...]").
+
+config REFORMIME
+ bool "reformime"
+ default n
+ help
+ Parse MIME-formatted messages.
+
+config FEATURE_REFORMIME_COMPAT
+ bool "Accept and ignore options other than -x and -X"
+ default y
+ depends on REFORMIME
+ help
+ Accept (for compatibility only) and ignore options
+ other than -x and -X.
+
+config SENDMAIL
+ bool "sendmail"
+ default n
+ help
+ Barebones sendmail.
+
+endmenu
diff --git a/release/src/router/busybox/mailutils/Kbuild b/release/src/router/busybox/mailutils/Kbuild
new file mode 100644
index 0000000000..871e879810
--- /dev/null
+++ b/release/src/router/busybox/mailutils/Kbuild
@@ -0,0 +1,11 @@
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+lib-y:=
+lib-$(CONFIG_MAKEMIME) += mime.o mail.o
+lib-$(CONFIG_POPMAILDIR) += popmaildir.o mail.o
+lib-$(CONFIG_REFORMIME) += mime.o mail.o
+lib-$(CONFIG_SENDMAIL) += sendmail.o mail.o
diff --git a/release/src/router/busybox/mailutils/mail.c b/release/src/router/busybox/mailutils/mail.c
new file mode 100644
index 0000000000..68883ff42c
--- /dev/null
+++ b/release/src/router/busybox/mailutils/mail.c
@@ -0,0 +1,248 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * helper routines
+ *
+ * Copyright (C) 2008 by Vladimir Dronnikov
+ *
+ * Licensed under GPLv2, see file LICENSE in this tarball for details.
+ */
+#include "libbb.h"
+#include "mail.h"
+
+static void kill_helper(void)
+{
+ if (G.helper_pid > 0) {
+ kill(G.helper_pid, SIGTERM);
+ G.helper_pid = 0;
+ }
+}
+
+// generic signal handler
+static void signal_handler(int signo)
+{
+#define err signo
+ if (SIGALRM == signo) {
+ kill_helper();
+ bb_error_msg_and_die("timed out");
+ }
+
+ // SIGCHLD. reap zombies
+ if (safe_waitpid(G.helper_pid, &err, WNOHANG) > 0) {
+ if (WIFSIGNALED(err))
+ bb_error_msg_and_die("helper killed by signal %u", WTERMSIG(err));
+ if (WIFEXITED(err)) {
+ G.helper_pid = 0;
+ if (WEXITSTATUS(err))
+ bb_error_msg_and_die("helper exited (%u)", WEXITSTATUS(err));
+ }
+ }
+#undef err
+}
+
+void FAST_FUNC launch_helper(const char **argv)
+{
+ // setup vanilla unidirectional pipes interchange
+ int i;
+ int pipes[4];
+
+ xpipe(pipes);
+ xpipe(pipes + 2);
+
+ // NB: handler must be installed before vfork
+ bb_signals(0
+ + (1 << SIGCHLD)
+ + (1 << SIGALRM)
+ , signal_handler);
+
+ G.helper_pid = vfork();
+ if (G.helper_pid < 0)
+ bb_perror_msg_and_die("vfork");
+
+ i = (!G.helper_pid) * 2; // for parent:0, for child:2
+ close(pipes[i + 1]); // 1 or 3 - closing one write end
+ close(pipes[2 - i]); // 2 or 0 - closing one read end
+ xmove_fd(pipes[i], STDIN_FILENO); // 0 or 2 - using other read end
+ xmove_fd(pipes[3 - i], STDOUT_FILENO); // 3 or 1 - other write end
+
+ if (!G.helper_pid) {
+ // child: try to execute connection helper
+ // NB: SIGCHLD & SIGALRM revert to SIG_DFL on exec
+ BB_EXECVP(*argv, (char **)argv);
+ _exit(127);
+ }
+
+ // parent
+ // check whether child is alive
+ //redundant:signal_handler(SIGCHLD);
+ // child seems OK -> parent goes on
+ atexit(kill_helper);
+}
+
+const FAST_FUNC char *command(const char *fmt, const char *param)
+{
+ const char *msg = fmt;
+ if (timeout)
+ alarm(timeout);
+ if (msg) {
+ msg = xasprintf(fmt, param);
+ printf("%s\r\n", msg);
+ }
+ fflush(stdout);
+ return msg;
+}
+
+// NB: parse_url can modify url[] (despite const), but only if '@' is there
+/*
+static char FAST_FUNC *parse_url(char *url, char **user, char **pass)
+{
+ // parse [user[:pass]@]host
+ // return host
+ char *s = strchr(url, '@');
+ *user = *pass = NULL;
+ if (s) {
+ *s++ = '\0';
+ *user = url;
+ url = s;
+ s = strchr(*user, ':');
+ if (s) {
+ *s++ = '\0';
+ *pass = s;
+ }
+ }
+ return url;
+}
+*/
+
+void FAST_FUNC encode_base64(char *fname, const char *text, const char *eol)
+{
+ enum {
+ SRC_BUF_SIZE = 45, /* This *MUST* be a multiple of 3 */
+ DST_BUF_SIZE = 4 * ((SRC_BUF_SIZE + 2) / 3),
+ };
+
+#define src_buf text
+ FILE *fp = fp;
+ ssize_t len = len;
+ char dst_buf[DST_BUF_SIZE + 1];
+
+ if (fname) {
+ fp = (NOT_LONE_DASH(fname)) ? xfopen_for_read(fname) : (FILE *)text;
+ src_buf = bb_common_bufsiz1;
+ // N.B. strlen(NULL) segfaults!
+ } else if (text) {
+ // though we do not call uuencode(NULL, NULL) explicitly
+ // still we do not want to break things suddenly
+ len = strlen(text);
+ } else
+ return;
+
+ while (1) {
+ size_t size;
+ if (fname) {
+ size = fread((char *)src_buf, 1, SRC_BUF_SIZE, fp);
+ if ((ssize_t)size < 0)
+ bb_perror_msg_and_die(bb_msg_read_error);
+ } else {
+ size = len;
+ if (len > SRC_BUF_SIZE)
+ size = SRC_BUF_SIZE;
+ }
+ if (!size)
+ break;
+ // encode the buffer we just read in
+ bb_uuencode(dst_buf, src_buf, size, bb_uuenc_tbl_base64);
+ if (fname) {
+ printf("%s\n", eol);
+ } else {
+ src_buf += size;
+ len -= size;
+ }
+ fwrite(dst_buf, 1, 4 * ((size + 2) / 3), stdout);
+ }
+ if (fname && NOT_LONE_DASH(fname))
+ fclose(fp);
+#undef src_buf
+}
+
+void FAST_FUNC decode_base64(FILE *src_stream, FILE *dst_stream)
+{
+ int term_count = 1;
+
+ while (1) {
+ char translated[4];
+ int count = 0;
+
+ while (count < 4) {
+ char *table_ptr;
+ int ch;
+
+ /* Get next _valid_ character.
+ * global vector bb_uuenc_tbl_base64[] contains this string:
+ * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n"
+ */
+ do {
+ ch = fgetc(src_stream);
+ if (ch == EOF) {
+ bb_error_msg_and_die(bb_msg_read_error);
+ }
+ // - means end of MIME section
+ if ('-' == ch) {
+ // push it back
+ ungetc(ch, src_stream);
+ return;
+ }
+ table_ptr = strchr(bb_uuenc_tbl_base64, ch);
+ } while (table_ptr == NULL);
+
+ /* Convert encoded character to decimal */
+ ch = table_ptr - bb_uuenc_tbl_base64;
+
+ if (*table_ptr == '=') {
+ if (term_count == 0) {
+ translated[count] = '\0';
+ break;
+ }
+ term_count++;
+ } else if (*table_ptr == '\n') {
+ /* Check for terminating line */
+ if (term_count == 5) {
+ return;
+ }
+ term_count = 1;
+ continue;
+ } else {
+ translated[count] = ch;
+ count++;
+ term_count = 0;
+ }
+ }
+
+ /* Merge 6 bit chars to 8 bit */
+ if (count > 1) {
+ fputc(translated[0] << 2 | translated[1] >> 4, dst_stream);
+ }
+ if (count > 2) {
+ fputc(translated[1] << 4 | translated[2] >> 2, dst_stream);
+ }
+ if (count > 3) {
+ fputc(translated[2] << 6 | translated[3], dst_stream);
+ }
+ }
+}
+
+
+/*
+ * get username and password from a file descriptor
+ */
+void FAST_FUNC get_cred_or_die(int fd)
+{
+ if (isatty(fd)) {
+ G.user = xstrdup(bb_ask(fd, /* timeout: */ 0, "User: "));
+ G.pass = xstrdup(bb_ask(fd, /* timeout: */ 0, "Password: "));
+ } else {
+ G.user = xmalloc_reads(fd, /* pfx: */ NULL, /* maxsize: */ NULL);
+ G.pass = xmalloc_reads(fd, /* pfx: */ NULL, /* maxsize: */ NULL);
+ }
+ if (!G.user || !*G.user || !G.pass)
+ bb_error_msg_and_die("no username or password");
+}
diff --git a/release/src/router/busybox/mailutils/mail.h b/release/src/router/busybox/mailutils/mail.h
new file mode 100644
index 0000000000..bb747c4c52
--- /dev/null
+++ b/release/src/router/busybox/mailutils/mail.h
@@ -0,0 +1,35 @@
+
+struct globals {
+ pid_t helper_pid;
+ unsigned timeout;
+ unsigned opts;
+ char *user;
+ char *pass;
+ FILE *fp0; // initial stdin
+ char *opt_charset;
+ char *content_type;
+};
+
+#define G (*ptr_to_globals)
+#define timeout (G.timeout )
+#define opts (G.opts )
+//#define user (G.user )
+//#define pass (G.pass )
+//#define fp0 (G.fp0 )
+//#define opt_charset (G.opt_charset)
+//#define content_type (G.content_type)
+#define INIT_G() do { \
+ SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
+ G.opt_charset = (char *)CONFIG_FEATURE_MIME_CHARSET; \
+ G.content_type = (char *)"text/plain"; \
+} while (0)
+
+//char FAST_FUNC *parse_url(char *url, char **user, char **pass);
+
+void FAST_FUNC launch_helper(const char **argv);
+void FAST_FUNC get_cred_or_die(int fd);
+
+const FAST_FUNC char *command(const char *fmt, const char *param);
+
+void FAST_FUNC encode_base64(char *fname, const char *text, const char *eol);
+void FAST_FUNC decode_base64(FILE *src_stream, FILE *dst_stream);
diff --git a/release/src/router/busybox/mailutils/mime.c b/release/src/router/busybox/mailutils/mime.c
new file mode 100644
index 0000000000..bda727b7c8
--- /dev/null
+++ b/release/src/router/busybox/mailutils/mime.c
@@ -0,0 +1,354 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * makemime: create MIME-encoded message
+ * reformime: parse MIME-encoded message
+ *
+ * Copyright (C) 2008 by Vladimir Dronnikov
+ *
+ * Licensed under GPLv2, see file LICENSE in this tarball for details.
+ */
+#include "libbb.h"
+#include "mail.h"
+
+/*
+ makemime -c type [-o file] [-e encoding] [-C charset] [-N name] \
+ [-a "Header: Contents"] file
+ -m [ type ] [-o file] [-e encoding] [-a "Header: Contents"] file
+ -j [-o file] file1 file2
+ @file
+
+ file: filename - read or write from filename
+ - - read or write from stdin or stdout
+ &n - read or write from file descriptor n
+ \( opts \) - read from child process, that generates [ opts ]
+
+Options:
+
+ -c type - create a new MIME section from "file" with this
+ Content-Type: (default is application/octet-stream).
+ -C charset - MIME charset of a new text/plain section.
+ -N name - MIME content name of the new mime section.
+ -m [ type ] - create a multipart mime section from "file" of this
+ Content-Type: (default is multipart/mixed).
+ -e encoding - use the given encoding (7bit, 8bit, quoted-printable,
+ or base64), instead of guessing. Omit "-e" and use
+ -c auto to set Content-Type: to text/plain or
+ application/octet-stream based on picked encoding.
+ -j file1 file2 - join mime section file2 to multipart section file1.
+ -o file - write ther result to file, instead of stdout (not
+ allowed in child processes).
+ -a header - prepend an additional header to the output.
+
+ @file - read all of the above options from file, one option or
+ value on each line.
+*/
+
+int makemime_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int makemime_main(int argc UNUSED_PARAM, char **argv)
+{
+ llist_t *opt_headers = NULL, *l;
+ const char *opt_output;
+#define boundary opt_output
+
+ enum {
+ OPT_c = 1 << 0, // Content-Type:
+ OPT_e = 1 << 1, // Content-Transfer-Encoding. Ignored. Assumed base64
+ OPT_o = 1 << 2, // output to
+ OPT_C = 1 << 3, // charset
+ OPT_N = 1 << 4, // COMPAT
+ OPT_a = 1 << 5, // additional headers
+ OPT_m = 1 << 6, // COMPAT
+ OPT_j = 1 << 7, // COMPAT
+ };
+
+ INIT_G();
+
+ // parse options
+ opt_complementary = "a::";
+ opts = getopt32(argv,
+ "c:e:o:C:N:a:m:j:",
+ &G.content_type, NULL, &opt_output, &G.opt_charset, NULL, &opt_headers, NULL, NULL
+ );
+ //argc -= optind;
+ argv += optind;
+
+ // respect -o output
+ if (opts & OPT_o)
+ freopen(opt_output, "w", stdout);
+
+ // no files given on command line? -> use stdin
+ if (!*argv)
+ *--argv = (char *)"-";
+
+ // put additional headers
+ for (l = opt_headers; l; l = l->link)
+ puts(l->data);
+
+ // make a random string -- it will delimit message parts
+ srand(monotonic_us());
+ boundary = xasprintf("%d-%d-%d", rand(), rand(), rand());
+
+ // put multipart header
+ printf(
+ "Mime-Version: 1.0\n"
+ "Content-Type: multipart/mixed; boundary=\"%s\"\n"
+ , boundary
+ );
+
+ // put attachments
+ while (*argv) {
+ printf(
+ "\n--%s\n"
+ "Content-Type: %s; charset=%s\n"
+ "Content-Disposition: inline; filename=\"%s\"\n"
+ "Content-Transfer-Encoding: base64\n"
+ , boundary
+ , G.content_type
+ , G.opt_charset
+ , bb_get_last_path_component_strip(*argv)
+ );
+ encode_base64(*argv++, (const char *)stdin, "");
+ }
+
+ // put multipart footer
+ printf("\n--%s--\n" "\n", boundary);
+
+ return EXIT_SUCCESS;
+#undef boundary
+}
+
+static const char *find_token(const char *const string_array[], const char *key, const char *defvalue)
+{
+ const char *r = NULL;
+ for (int i = 0; string_array[i] != 0; i++) {
+ if (strcasecmp(string_array[i], key) == 0) {
+ r = (char *)string_array[i+1];
+ break;
+ }
+ }
+ return (r) ? r : defvalue;
+}
+
+static const char *xfind_token(const char *const string_array[], const char *key)
+{
+ const char *r = find_token(string_array, key, NULL);
+ if (r)
+ return r;
+ bb_error_msg_and_die("header: %s", key);
+}
+
+enum {
+ OPT_x = 1 << 0,
+ OPT_X = 1 << 1,
+#if ENABLE_FEATURE_REFORMIME_COMPAT
+ OPT_d = 1 << 2,
+ OPT_e = 1 << 3,
+ OPT_i = 1 << 4,
+ OPT_s = 1 << 5,
+ OPT_r = 1 << 6,
+ OPT_c = 1 << 7,
+ OPT_m = 1 << 8,
+ OPT_h = 1 << 9,
+ OPT_o = 1 << 10,
+ OPT_O = 1 << 11,
+#endif
+};
+
+static int parse(const char *boundary, char **argv)
+{
+ char *line, *s, *p;
+ const char *type;
+ int boundary_len = strlen(boundary);
+ const char *delims = " ;\"\t\r\n";
+ const char *uniq;
+ int ntokens;
+ const char *tokens[32]; // 32 is enough
+
+ // prepare unique string pattern
+ uniq = xasprintf("%%llu.%u.%s", (unsigned)getpid(), safe_gethostname());
+
+//bb_info_msg("PARSE[%s]", terminator);
+
+ while ((line = xmalloc_fgets_str(stdin, "\r\n\r\n")) != NULL) {
+
+ // seek to start of MIME section
+ // N.B. to avoid false positives let us seek to the _last_ occurance
+ p = NULL;
+ s = line;
+ while ((s=strcasestr(s, "Content-Type:")) != NULL)
+ p = s++;
+ if (!p)
+ goto next;
+//bb_info_msg("L[%s]", p);
+
+ // split to tokens
+ // TODO: strip of comments which are of form: (comment-text)
+ ntokens = 0;
+ tokens[ntokens] = NULL;
+ for (s = strtok(p, delims); s; s = strtok(NULL, delims)) {
+ tokens[ntokens] = s;
+ if (ntokens < ARRAY_SIZE(tokens) - 1)
+ ntokens++;
+//bb_info_msg("L[%d][%s]", ntokens, s);
+ }
+ tokens[ntokens] = NULL;
+//bb_info_msg("N[%d]", ntokens);
+
+ // analyse tokens
+ type = find_token(tokens, "Content-Type:", "text/plain");
+//bb_info_msg("T[%s]", type);
+ if (0 == strncasecmp(type, "multipart/", 10)) {
+ if (0 == strcasecmp(type+10, "mixed")) {
+ parse(xfind_token(tokens, "boundary="), argv);
+ } else
+ bb_error_msg_and_die("no support of content type '%s'", type);
+ } else {
+ pid_t pid = pid;
+ int rc;
+ FILE *fp;
+ // fetch charset
+ const char *charset = find_token(tokens, "charset=", CONFIG_FEATURE_MIME_CHARSET);
+ // fetch encoding
+ const char *encoding = find_token(tokens, "Content-Transfer-Encoding:", "7bit");
+ // compose target filename
+ char *filename = (char *)find_token(tokens, "filename=", NULL);
+ if (!filename)
+ filename = xasprintf(uniq, monotonic_us());
+ else
+ filename = bb_get_last_path_component_strip(xstrdup(filename));
+
+ // start external helper, if any
+ if (opts & OPT_X) {
+ int fd[2];
+ xpipe(fd);
+ pid = vfork();
+ if (0 == pid) {
+ // child reads from fd[0]
+ xdup2(fd[0], STDIN_FILENO);
+ close(fd[0]); close(fd[1]);
+ xsetenv("CONTENT_TYPE", type);
+ xsetenv("CHARSET", charset);
+ xsetenv("ENCODING", encoding);
+ xsetenv("FILENAME", filename);
+ BB_EXECVP(*argv, argv);
+ _exit(EXIT_FAILURE);
+ }
+ // parent dumps to fd[1]
+ close(fd[0]);
+ fp = fdopen(fd[1], "w");
+ signal(SIGPIPE, SIG_IGN); // ignore EPIPE
+ // or create a file for dump
+ } else {
+ char *fname = xasprintf("%s%s", *argv, filename);
+ fp = xfopen_for_write(fname);
+ free(fname);
+ }
+
+ // housekeeping
+ free(filename);
+
+ // dump to fp
+ if (0 == strcasecmp(encoding, "base64")) {
+ decode_base64(stdin, fp);
+ } else if (0 != strcasecmp(encoding, "7bit")
+ && 0 != strcasecmp(encoding, "8bit")) {
+ // quoted-printable, binary, user-defined are unsupported so far
+ bb_error_msg_and_die("no support of encoding '%s'", encoding);
+ } else {
+ // N.B. we have written redundant \n. so truncate the file
+ // The following weird 2-tacts reading technique is due to
+ // we have to not write extra \n at the end of the file
+ // In case of -x option we could truncate the resulting file as
+ // fseek(fp, -1, SEEK_END);
+ // if (ftruncate(fileno(fp), ftell(fp)))
+ // bb_perror_msg("ftruncate");
+ // But in case of -X we have to be much more careful. There is
+ // no means to truncate what we already have sent to the helper.
+ p = xmalloc_fgets_str(stdin, "\r\n");
+ while (p) {
+ if ((s = xmalloc_fgets_str(stdin, "\r\n")) == NULL)
+ break;
+ if ('-' == s[0] && '-' == s[1]
+ && 0 == strncmp(s+2, boundary, boundary_len))
+ break;
+ fputs(p, fp);
+ p = s;
+ }
+
+/*
+ while ((s = xmalloc_fgetline_str(stdin, "\r\n")) != NULL) {
+ if ('-' == s[0] && '-' == s[1]
+ && 0 == strncmp(s+2, boundary, boundary_len))
+ break;
+ fprintf(fp, "%s\n", s);
+ }
+ // N.B. we have written redundant \n. so truncate the file
+ fseek(fp, -1, SEEK_END);
+ if (ftruncate(fileno(fp), ftell(fp)))
+ bb_perror_msg("ftruncate");
+*/
+ }
+ fclose(fp);
+
+ // finalize helper
+ if (opts & OPT_X) {
+ signal(SIGPIPE, SIG_DFL);
+ // exit if helper exited >0
+ rc = wait4pid(pid);
+ if (rc)
+ return rc+20;
+ }
+
+ // check multipart finalized
+ if (s && '-' == s[2+boundary_len] && '-' == s[2+boundary_len+1]) {
+ free(line);
+ break;
+ }
+ }
+ next:
+ free(line);
+ }
+
+//bb_info_msg("ENDPARSE[%s]", boundary);
+
+ return EXIT_SUCCESS;
+}
+
+/*
+Usage: reformime [options]
+ -d - parse a delivery status notification.
+ -e - extract contents of MIME section.
+ -x - extract MIME section to a file.
+ -X - pipe MIME section to a program.
+ -i - show MIME info.
+ -s n.n.n.n - specify MIME section.
+ -r - rewrite message, filling in missing MIME headers.
+ -r7 - also convert 8bit/raw encoding to quoted-printable, if possible.
+ -r8 - also convert quoted-printable encoding to 8bit, if possible.
+ -c charset - default charset for rewriting, -o, and -O.
+ -m [file] [file]... - create a MIME message digest.
+ -h "header" - decode RFC 2047-encoded header.
+ -o "header" - encode unstructured header using RFC 2047.
+ -O "header" - encode address list header using RFC 2047.
+*/
+
+int reformime_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int reformime_main(int argc UNUSED_PARAM, char **argv)
+{
+ const char *opt_prefix = "";
+
+ INIT_G();
+
+ // parse options
+ // N.B. only -x and -X are supported so far
+ opt_complementary = "x--X:X--x" USE_FEATURE_REFORMIME_COMPAT(":m::");
+ opts = getopt32(argv,
+ "x:X" USE_FEATURE_REFORMIME_COMPAT("deis:r:c:m:h:o:O:"),
+ &opt_prefix
+ USE_FEATURE_REFORMIME_COMPAT(, NULL, NULL, &G.opt_charset, NULL, NULL, NULL, NULL)
+ );
+ //argc -= optind;
+ argv += optind;
+
+ return parse("", (opts & OPT_X) ? argv : (char **)&opt_prefix);
+}
diff --git a/release/src/router/busybox/mailutils/popmaildir.c b/release/src/router/busybox/mailutils/popmaildir.c
new file mode 100644
index 0000000000..1a72b87c58
--- /dev/null
+++ b/release/src/router/busybox/mailutils/popmaildir.c
@@ -0,0 +1,235 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * popmaildir: a simple yet powerful POP3 client
+ * Delivers contents of remote mailboxes to local Maildir
+ *
+ * Inspired by original utility by Nikola Vladov
+ *
+ * Copyright (C) 2008 by Vladimir Dronnikov
+ *
+ * Licensed under GPLv2, see file LICENSE in this tarball for details.
+ */
+#include "libbb.h"
+#include "mail.h"
+
+static void pop3_checkr(const char *fmt, const char *param, char **ret)
+{
+ const char *msg = command(fmt, param);
+ char *answer = xmalloc_fgetline(stdin);
+ if (answer && '+' == answer[0]) {
+ if (timeout)
+ alarm(0);
+ if (ret) {
+ // skip "+OK "
+ memmove(answer, answer + 4, strlen(answer) - 4);
+ *ret = answer;
+ } else
+ free(answer);
+ return;
+ }
+ bb_error_msg_and_die("%s failed: %s", msg, answer);
+}
+
+static void pop3_check(const char *fmt, const char *param)
+{
+ pop3_checkr(fmt, param, NULL);
+}
+
+int popmaildir_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int popmaildir_main(int argc UNUSED_PARAM, char **argv)
+{
+ char *buf;
+ unsigned nmsg;
+ char *hostname;
+ pid_t pid;
+ const char *retr;
+#if ENABLE_FEATURE_POPMAILDIR_DELIVERY
+ const char *delivery;
+#endif
+ unsigned opt_nlines = 0;
+
+ enum {
+ OPT_b = 1 << 0, // -b binary mode. Ignored
+ OPT_d = 1 << 1, // -d,-dd,-ddd debug. Ignored
+ OPT_m = 1 << 2, // -m show used memory. Ignored
+ OPT_V = 1 << 3, // -V version. Ignored
+ OPT_c = 1 << 4, // -c use tcpclient. Ignored
+ OPT_a = 1 << 5, // -a use APOP protocol
+ OPT_s = 1 << 6, // -s skip authorization
+ OPT_T = 1 << 7, // -T get messages with TOP instead with RETR
+ OPT_k = 1 << 8, // -k keep retrieved messages on the server
+ OPT_t = 1 << 9, // -t90 set timeout to 90 sec
+ OPT_R = 1 << 10, // -R20000 remove old messages on the server >= 20000 bytes (requires -k). Ignored
+ OPT_Z = 1 << 11, // -Z11-23 remove messages from 11 to 23 (dangerous). Ignored
+ OPT_L = 1 << 12, // -L50000 not retrieve new messages >= 50000 bytes. Ignored
+ OPT_H = 1 << 13, // -H30 type first 30 lines of a message; (-L12000 -H30). Ignored
+ OPT_M = 1 << 14, // -M\"program arg1 arg2 ...\"; deliver by program. Treated like -F
+ OPT_F = 1 << 15, // -F\"program arg1 arg2 ...\"; filter by program. Treated like -M
+ };
+
+ // init global variables
+ INIT_G();
+
+ // parse options
+ opt_complementary = "-1:dd:t+:R+:L+:H+";
+ opts = getopt32(argv,
+ "bdmVcasTkt:" "R:Z:L:H:" USE_FEATURE_POPMAILDIR_DELIVERY("M:F:"),
+ &timeout, NULL, NULL, NULL, &opt_nlines
+ USE_FEATURE_POPMAILDIR_DELIVERY(, &delivery, &delivery) // we treat -M and -F the same
+ );
+ //argc -= optind;
+ argv += optind;
+
+ // get auth info
+ if (!(opts & OPT_s))
+ get_cred_or_die(STDIN_FILENO);
+
+ // goto maildir
+ xchdir(*argv++);
+
+ // launch connect helper, if any
+ if (*argv)
+ launch_helper((const char **)argv);
+
+ // get server greeting
+ pop3_checkr(NULL, NULL, &buf);
+
+ // authenticate (if no -s given)
+ if (!(opts & OPT_s)) {
+ // server supports APOP and we want it?
+ if ('<' == buf[0] && (opts & OPT_a)) {
+ union { // save a bit of stack
+ md5_ctx_t ctx;
+ char hex[16 * 2 + 1];
+ } md5;
+ uint32_t res[16 / 4];
+
+ char *s = strchr(buf, '>');
+ if (s)
+ s[1] = '\0';
+ // get md5 sum of "password" string
+ md5_begin(&md5.ctx);
+ md5_hash(buf, strlen(buf), &md5.ctx);
+ md5_hash(G.pass, strlen(G.pass), &md5.ctx);
+ md5_end(res, &md5.ctx);
+ *bin2hex(md5.hex, (char*)res, 16) = '\0';
+ // APOP
+ s = xasprintf("%s %s", G.user, md5.hex);
+ pop3_check("APOP %s", s);
+ free(s);
+ free(buf);
+ // server ignores APOP -> use simple text authentication
+ } else {
+ // USER
+ pop3_check("USER %s", G.user);
+ // PASS
+ pop3_check("PASS %s", G.pass);
+ }
+ }
+
+ // get mailbox statistics
+ pop3_checkr("STAT", NULL, &buf);
+
+ // prepare message filename suffix
+ hostname = safe_gethostname();
+ pid = getpid();
+
+ // get messages counter
+ // NOTE: we don't use xatou(buf) since buf is "nmsg nbytes"
+ // we only need nmsg and atoi is just exactly what we need
+ // if atoi fails to convert buf into number it returns 0
+ // in this case the following loop simply will not be executed
+ nmsg = atoi(buf);
+ free(buf);
+
+ // loop through messages
+ retr = (opts & OPT_T) ? xasprintf("TOP %%u %u", opt_nlines) : "RETR %u";
+ for (; nmsg; nmsg--) {
+
+ char *filename;
+ char *target;
+ char *answer;
+ FILE *fp;
+#if ENABLE_FEATURE_POPMAILDIR_DELIVERY
+ int rc;
+#endif
+ // generate unique filename
+ filename = xasprintf("tmp/%llu.%u.%s",
+ monotonic_us(), (unsigned)pid, hostname);
+
+ // retrieve message in ./tmp/ unless filter is specified
+ pop3_check(retr, (const char *)(ptrdiff_t)nmsg);
+
+#if ENABLE_FEATURE_POPMAILDIR_DELIVERY
+ // delivery helper ordered? -> setup pipe
+ if (opts & (OPT_F|OPT_M)) {
+ // helper will have $FILENAME set to filename
+ xsetenv("FILENAME", filename);
+ fp = popen(delivery, "w");
+ unsetenv("FILENAME");
+ if (!fp) {
+ bb_perror_msg("delivery helper");
+ break;
+ }
+ } else
+#endif
+ // create and open file filename
+ fp = xfopen_for_write(filename);
+
+ // copy stdin to fp (either filename or delivery helper)
+ while ((answer = xmalloc_fgets_str(stdin, "\r\n")) != NULL) {
+ char *s = answer;
+ if ('.' == answer[0]) {
+ if ('.' == answer[1])
+ s++;
+ else if ('\r' == answer[1] && '\n' == answer[2] && '\0' == answer[3])
+ break;
+ }
+ //*strchrnul(s, '\r') = '\n';
+ fputs(s, fp);
+ free(answer);
+ }
+
+#if ENABLE_FEATURE_POPMAILDIR_DELIVERY
+ // analyse delivery status
+ if (opts & (OPT_F|OPT_M)) {
+ rc = pclose(fp);
+ if (99 == rc) // 99 means bail out
+ break;
+// if (rc) // !0 means skip to the next message
+ goto skip;
+// // 0 means continue
+ } else {
+ // close filename
+ fclose(fp);
+ }
+#endif
+
+ // delete message from server
+ if (!(opts & OPT_k))
+ pop3_check("DELE %u", (const char*)(ptrdiff_t)nmsg);
+
+ // atomically move message to ./new/
+ target = xstrdup(filename);
+ strncpy(target, "new", 3);
+ // ... or just stop receiving on failure
+ if (rename_or_warn(filename, target))
+ break;
+ free(target);
+
+#if ENABLE_FEATURE_POPMAILDIR_DELIVERY
+ skip:
+#endif
+ free(filename);
+ }
+
+ // Bye
+ pop3_check("QUIT", NULL);
+
+ if (ENABLE_FEATURE_CLEAN_UP) {
+ free(G.user);
+ free(G.pass);
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/release/src/router/busybox/mailutils/sendmail.c b/release/src/router/busybox/mailutils/sendmail.c
new file mode 100644
index 0000000000..7e57a94cf3
--- /dev/null
+++ b/release/src/router/busybox/mailutils/sendmail.c
@@ -0,0 +1,259 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * bare bones sendmail
+ *
+ * Copyright (C) 2008 by Vladimir Dronnikov
+ *
+ * Licensed under GPLv2, see file LICENSE in this tarball for details.
+ */
+#include "libbb.h"
+#include "mail.h"
+
+static int smtp_checkp(const char *fmt, const char *param, int code)
+{
+ char *answer;
+ const char *msg = command(fmt, param);
+ // read stdin
+ // if the string has a form \d\d\d- -- read next string. E.g. EHLO response
+ // parse first bytes to a number
+ // if code = -1 then just return this number
+ // if code != -1 then checks whether the number equals the code
+ // if not equal -> die saying msg
+ while ((answer = xmalloc_fgetline(stdin)) != NULL)
+ if (strlen(answer) <= 3 || '-' != answer[3])
+ break;
+ if (answer) {
+ int n = atoi(answer);
+ if (timeout)
+ alarm(0);
+ free(answer);
+ if (-1 == code || n == code)
+ return n;
+ }
+ bb_error_msg_and_die("%s failed", msg);
+}
+
+static int smtp_check(const char *fmt, int code)
+{
+ return smtp_checkp(fmt, NULL, code);
+}
+
+// strip argument of bad chars
+static char *sane_address(char *str)
+{
+ char *s = str;
+ char *p = s;
+ while (*s) {
+ if (isalnum(*s) || '_' == *s || '-' == *s || '.' == *s || '@' == *s) {
+ *p++ = *s;
+ }
+ s++;
+ }
+ *p = '\0';
+ return str;
+}
+
+static void rcptto(const char *s)
+{
+ smtp_checkp("RCPT TO:<%s>", s, 250);
+}
+
+int sendmail_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int sendmail_main(int argc UNUSED_PARAM, char **argv)
+{
+ char *opt_connect = opt_connect;
+ char *opt_from;
+ char *s;
+ llist_t *list = NULL;
+ char *domain = sane_address(safe_getdomainname());
+ int code;
+
+ enum {
+ //--- standard options
+ OPT_t = 1 << 0, // read message for recipients, append them to those on cmdline
+ OPT_f = 1 << 1, // sender address
+ OPT_o = 1 << 2, // various options. -oi IMPLIED! others are IGNORED!
+ //--- BB specific options
+ OPT_w = 1 << 3, // network timeout
+ OPT_H = 1 << 4, // use external connection helper
+ OPT_S = 1 << 5, // specify connection string
+ OPT_a = 1 << 6, // authentication tokens
+ };
+
+ // init global variables
+ INIT_G();
+
+ // save initial stdin since body is piped!
+ xdup2(STDIN_FILENO, 3);
+ G.fp0 = fdopen(3, "r");
+
+ // parse options
+ // -f is required. -H and -S are mutually exclusive
+ opt_complementary = "f:w+:H--S:S--H:a::";
+ // N.B. since -H and -S are mutually exclusive they do not interfere in opt_connect
+ // -a is for ssmtp (http://downloads.openwrt.org/people/nico/man/man8/ssmtp.8.html) compatibility,
+ // it is still under development.
+ opts = getopt32(argv, "tf:o:w:H:S:a::", &opt_from, NULL, &timeout, &opt_connect, &opt_connect, &list);
+ //argc -= optind;
+ argv += optind;
+
+ // process -a[upm] options
+ if ((opts & OPT_a) && !list)
+ bb_show_usage();
+ while (list) {
+ char *a = (char *) llist_pop(&list);
+ if ('u' == a[0])
+ G.user = xstrdup(a+1);
+ if ('p' == a[0])
+ G.pass = xstrdup(a+1);
+ // N.B. we support only AUTH LOGIN so far
+ //if ('m' == a[0])
+ // G.method = xstrdup(a+1);
+ }
+ // N.B. list == NULL here
+ //bb_info_msg("OPT[%x] AU[%s], AP[%s], AM[%s], ARGV[%s]", opts, au, ap, am, *argv);
+
+ // connect to server
+
+ // connection helper ordered? ->
+ if (opts & OPT_H) {
+ const char *args[] = { "sh", "-c", opt_connect, NULL };
+ // plug it in
+ launch_helper(args);
+ // vanilla connection
+ } else {
+ int fd;
+ // host[:port] not explicitly specified? -> use $SMTPHOST
+ // no $SMTPHOST ? -> use localhost
+ if (!(opts & OPT_S)) {
+ opt_connect = getenv("SMTPHOST");
+ if (!opt_connect)
+ opt_connect = (char *)"127.0.0.1";
+ }
+ // do connect
+ fd = create_and_connect_stream_or_die(opt_connect, 25);
+ // and make ourselves a simple IO filter
+ xmove_fd(fd, STDIN_FILENO);
+ xdup2(STDIN_FILENO, STDOUT_FILENO);
+ }
+ // N.B. from now we know nothing about network :)
+
+ // wait for initial server OK
+ // N.B. if we used openssl the initial 220 answer is already swallowed during openssl TLS init procedure
+ // so we need to kick the server to see whether we are ok
+ code = smtp_check("NOOP", -1);
+ // 220 on plain connection, 250 on openssl-helped TLS session
+ if (220 == code)
+ smtp_check(NULL, 250); // reread the code to stay in sync
+ else if (250 != code)
+ bb_error_msg_and_die("INIT failed");
+
+ // we should start with modern EHLO
+ if (250 != smtp_checkp("EHLO %s", domain, -1)) {
+ smtp_checkp("HELO %s", domain, 250);
+ }
+ if (ENABLE_FEATURE_CLEAN_UP)
+ free(domain);
+
+ // perform authentication
+ if (opts & OPT_a) {
+ smtp_check("AUTH LOGIN", 334);
+ // we must read credentials unless they are given via -a[up] options
+ if (!G.user || !G.pass)
+ get_cred_or_die(4);
+ encode_base64(NULL, G.user, NULL);
+ smtp_check("", 334);
+ encode_base64(NULL, G.pass, NULL);
+ smtp_check("", 235);
+ }
+
+ // set sender
+ // N.B. we have here a very loosely defined algotythm
+ // since sendmail historically offers no means to specify secrets on cmdline.
+ // 1) server can require no authentication ->
+ // we must just provide a (possibly fake) reply address.
+ // 2) server can require AUTH ->
+ // we must provide valid username and password along with a (possibly fake) reply address.
+ // For the sake of security username and password are to be read either from console or from a secured file.
+ // Since reading from console may defeat usability, the solution is either to read from a predefined
+ // file descriptor (e.g. 4), or again from a secured file.
+
+ // got no sender address? -> use system username as a resort
+ // N.B. we marked -f as required option!
+ //if (!G.user) {
+ // // N.B. IMHO getenv("USER") can be way easily spoofed!
+ // G.user = xuid2uname(getuid());
+ // opt_from = xasprintf("%s@%s", G.user, domain);
+ //}
+ //if (ENABLE_FEATURE_CLEAN_UP)
+ // free(domain);
+ smtp_checkp("MAIL FROM:<%s>", opt_from, 250);
+
+ // process message
+
+ // read recipients from message and add them to those given on cmdline.
+ // this means we scan stdin for To:, Cc:, Bcc: lines until an empty line
+ // and then use the rest of stdin as message body
+ code = 0; // set "analyze headers" mode
+ while ((s = xmalloc_fgetline(G.fp0)) != NULL) {
+ // put message lines doubling leading dots
+ if (code) {
+ // escape leading dots
+ // N.B. this feature is implied even if no -i (-oi) switch given
+ // N.B. we need to escape the leading dot regardless of
+ // whether it is single or not character on the line
+ if ('.' == s[0] /*&& '\0' == s[1] */)
+ printf(".");
+ // dump read line
+ printf("%s\r\n", s);
+ free(s);
+ continue;
+ }
+
+ // analyze headers
+ // To: or Cc: headers add recipients
+ if (0 == strncasecmp("To: ", s, 4) || 0 == strncasecmp("Bcc: " + 1, s, 4)) {
+ rcptto(sane_address(s+4));
+// goto addh;
+ llist_add_to_end(&list, s);
+ // Bcc: header adds blind copy (hidden) recipient
+ } else if (0 == strncasecmp("Bcc: ", s, 5)) {
+ rcptto(sane_address(s+5));
+ free(s);
+ // N.B. Bcc: vanishes from headers!
+ // other headers go verbatim
+ } else if (s[0]) {
+// addh:
+ llist_add_to_end(&list, s);
+ // the empty line stops analyzing headers
+ } else {
+ free(s);
+ // put recipients specified on cmdline
+ while (*argv) {
+ s = sane_address(*argv);
+ rcptto(s);
+ llist_add_to_end(&list, xasprintf("To: %s", s));
+ argv++;
+ }
+ // enter "put message" mode
+ smtp_check("DATA", 354);
+ // dump the headers
+ while (list) {
+ printf("%s\r\n", (char *) llist_pop(&list));
+ }
+ printf("%s\r\n" + 2); // quirk for format string to be reused
+ // stop analyzing headers
+ code++;
+ }
+ }
+
+ // finalize the message
+ smtp_check(".", 250);
+ // ... and say goodbye
+ smtp_check("QUIT", 221);
+ // cleanup
+ if (ENABLE_FEATURE_CLEAN_UP)
+ fclose(G.fp0);
+
+ return EXIT_SUCCESS;
+}
diff --git a/release/src/router/busybox/miscutils/Config.in b/release/src/router/busybox/miscutils/Config.in
index 0c80ae6e9b..7feaf4a879 100644
--- a/release/src/router/busybox/miscutils/Config.in
+++ b/release/src/router/busybox/miscutils/Config.in
@@ -107,7 +107,7 @@ config CROND
# Run daily cron jobs at 4:40 every day:
40 4 * * * /etc/cron/daily > /dev/null 2>&1
-config DEBUG_CROND_OPTION
+config FEATURE_CROND_D
bool "Support option -d to redirect output to stderr"
depends on CROND
default n
@@ -121,6 +121,13 @@ config FEATURE_CROND_CALL_SENDMAIL
help
Support calling /usr/sbin/sendmail for send cmd outputs.
+config FEATURE_CROND_DIR
+ string "crond spool directory"
+ default "/var/spool/cron"
+ depends on CROND || CRONTAB
+ help
+ Location of crond spool.
+
config CRONTAB
bool "crontab"
default n
@@ -138,12 +145,23 @@ config DC
Dc is a reverse-polish desk calculator which supports unlimited
precision arithmetic.
+config FEATURE_DC_LIBM
+ bool "Enable power and exp functions (requires libm)"
+ default n
+ depends on DC
+ help
+ Enable power and exp functions.
+ NOTE: This will require libm to be present for linking.
+
config DEVFSD
bool "devfsd (obsolete)"
default n
select FEATURE_SYSLOG
help
- This is deprecated, and will be removed at the end of 2008.
+ This is deprecated and should NOT be used anymore.
+ Use linux >= 2.6 (optionally with hotplug) and mdev instead!
+ See docs/mdev.txt for detailed instructions on how to use mdev
+ instead.
Provides compatibility with old device names on a devfs systems.
You should set it to true if you have devfs enabled.
@@ -152,7 +170,7 @@ config DEVFSD
"PERMISSIONS", "EXECUTE", "COPY", "IGNORE",
"MKOLDCOMPAT", "MKNEWCOMPAT","RMOLDCOMPAT", "RMNEWCOMPAT".
- But only if they are written UPPERCASE!!!!!!!!
+ But only if they are written UPPERCASE!!!!!!!!
config DEVFSD_MODLOAD
bool "Adds support for MODLOAD keyword in devsfd.conf"
@@ -182,12 +200,21 @@ config FEATURE_DEVFS
bool "Use devfs names for all devices (obsolete)"
default n
help
- This is obsolete and will be going away at the end of 2008..
+ This is obsolete and should NOT be used anymore.
+ Use linux >= 2.6 (optionally with hotplug) and mdev instead!
- This tells busybox to look for names like /dev/loop/0 instead of
+ For legacy systems -- if there is no way around devfsd -- this
+ tells busybox to look for names like /dev/loop/0 instead of
/dev/loop0. If your /dev directory has normal names instead of
devfs names, you don't want this.
+config DEVMEM
+ bool "devmem"
+ default n
+ help
+ devmem is a small program that reads and writes from physical
+ memory using /dev/mem.
+
config EJECT
bool "eject"
default n
@@ -223,6 +250,20 @@ config FBSPLASH
"NN" (ASCII decimal number) - percentage to show on progress bar
"exit" - well you guessed it
+config FLASH_ERASEALL
+ bool "flash_eraseall"
+ default n
+ help
+ The flash_eraseall binary from mtd-utils as of git head c4c6a59eb.
+ This utility is used to erase the whole MTD device.
+
+config IONICE
+ bool "ionice"
+ default n
+ help
+ Set/set program io scheduling class and priority
+ Requires kernel >= 2.6.13
+
config INOTIFYD
bool "inotifyd"
default n
@@ -285,14 +326,6 @@ config FEATURE_LESS_FLAGS
The -M flag enables a more sophisticated status line.
The -m flag enables a simpler status line with a percentage.
-config FEATURE_LESS_FLAGCS
- bool "Enable flag changes"
- default n
- depends on LESS
- help
- This enables the ability to change command-line flags within
- less itself.
-
config FEATURE_LESS_MARKS
bool "Enable marks"
default n
@@ -307,6 +340,28 @@ config FEATURE_LESS_REGEXP
help
Enable regular expressions, allowing complex file searches.
+config FEATURE_LESS_WINCH
+ bool "Enable automatic resizing on window size changes"
+ default n
+ depends on LESS
+ help
+ Makes less track window size changes.
+
+config FEATURE_LESS_DASHCMD
+ bool "Enable flag changes ('-' command)"
+ default n
+ depends on LESS
+ help
+ This enables the ability to change command-line flags within
+ less itself ('-' keyboard command).
+
+config FEATURE_LESS_LINENUMS
+ bool "Enable dynamic switching of line numbers"
+ default n
+ depends on FEATURE_LESS_DASHCMD
+ help
+ Enable "-N" command.
+
config HDPARM
bool "hdparm"
default n
@@ -359,12 +414,11 @@ config FEATURE_HDPARM_HDIO_TRISTATE_HWIF
stuff, so you should probably say N.
config FEATURE_HDPARM_HDIO_GETSET_DMA
- bool "Get/set using_dma flag (DANGEROUS)"
+ bool "Get/set using_dma flag"
default n
depends on HDPARM
help
Enables the 'hdparm -d' option to get/set using_dma flag.
- This is dangerous stuff, so you should probably say N.
config MAKEDEVS
bool "makedevs"
@@ -500,6 +554,13 @@ config TIME
When the command finishes, time writes a message to standard output
giving timing statistics about this program run.
+config TIMEOUT
+ bool "timeout"
+ default n
+ help
+ Runs a program and watches it. If it does not terminate in
+ specified number of seconds, it is sent a signal.
+
config TTYSIZE
bool "ttysize"
default n
diff --git a/release/src/router/busybox/miscutils/Kbuild b/release/src/router/busybox/miscutils/Kbuild
index c12b12d423..23d7d8d497 100644
--- a/release/src/router/busybox/miscutils/Kbuild
+++ b/release/src/router/busybox/miscutils/Kbuild
@@ -13,8 +13,11 @@ lib-$(CONFIG_CROND) += crond.o
lib-$(CONFIG_CRONTAB) += crontab.o
lib-$(CONFIG_DC) += dc.o
lib-$(CONFIG_DEVFSD) += devfsd.o
+lib-$(CONFIG_DEVMEM) += devmem.o
lib-$(CONFIG_EJECT) += eject.o
lib-$(CONFIG_FBSPLASH) += fbsplash.o
+lib-$(CONFIG_FLASH_ERASEALL) += flash_eraseall.o
+lib-$(CONFIG_IONICE) += ionice.o
lib-$(CONFIG_HDPARM) += hdparm.o
lib-$(CONFIG_INOTIFYD) += inotifyd.o
lib-$(CONFIG_FEATURE_LAST_SMALL)+= last.o
@@ -33,5 +36,6 @@ lib-$(CONFIG_SETSID) += setsid.o
lib-$(CONFIG_STRINGS) += strings.o
lib-$(CONFIG_TASKSET) += taskset.o
lib-$(CONFIG_TIME) += time.o
+lib-$(CONFIG_TIMEOUT) += timeout.o
lib-$(CONFIG_TTYSIZE) += ttysize.o
lib-$(CONFIG_WATCHDOG) += watchdog.o
diff --git a/release/src/router/busybox/miscutils/chat.c b/release/src/router/busybox/miscutils/chat.c
index d550c7c90a..3ffd7b228f 100644
--- a/release/src/router/busybox/miscutils/chat.c
+++ b/release/src/router/busybox/miscutils/chat.c
@@ -9,16 +9,6 @@
*/
#include "libbb.h"
-/*
-#define ENABLE_FEATURE_CHAT_NOFAIL 1 // +126 bytes
-#define ENABLE_FEATURE_CHAT_TTY_HIFI 0 // + 70 bytes
-#define ENABLE_FEATURE_CHAT_IMPLICIT_CR 1 // + 44 bytes
-#define ENABLE_FEATURE_CHAT_SEND_ESCAPES 0 // +103 bytes
-#define ENABLE_FEATURE_CHAT_VAR_ABORT_LEN 0 // + 70 bytes
-#define ENABLE_FEATURE_CHAT_CLR_ABORT 0 // +113 bytes
-#define ENABLE_FEATURE_CHAT_SWALLOW_OPTS 0 // + 23 bytes
-*/
-
// default timeout: 45 sec
#define DEFAULT_CHAT_TIMEOUT 45*1000
// max length of "abort string",
@@ -37,8 +27,7 @@ enum {
};
// exit code
-// N.B> 10 bytes for volatile. Why all these signals?!
-static /*volatile*/ smallint exitcode;
+#define exitcode bb_got_signal
// trap for critical signals
static void signal_handler(UNUSED_PARAM int signo)
@@ -101,13 +90,10 @@ static size_t unescape(char *s, int *nocr)
return p - start;
}
-
int chat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int chat_main(int argc UNUSED_PARAM, char **argv)
{
-// should we dump device output? to what fd? by default no.
-// this can be controlled later via ECHO {ON|OFF} chat directive
-// int echo_fd;
+ int record_fd = -1;
bool echo = 0;
// collection of device replies which cause unconditional termination
llist_t *aborts = NULL;
@@ -132,6 +118,7 @@ int chat_main(int argc UNUSED_PARAM, char **argv)
DIR_TIMEOUT,
DIR_ECHO,
DIR_SAY,
+ DIR_RECORD,
};
// make x* functions fail with correct exitcode
@@ -166,14 +153,14 @@ int chat_main(int argc UNUSED_PARAM, char **argv)
#if ENABLE_FEATURE_CHAT_CLR_ABORT
"CLR_ABORT\0"
#endif
- "TIMEOUT\0" "ECHO\0" "SAY\0"
+ "TIMEOUT\0" "ECHO\0" "SAY\0" "RECORD\0"
, *argv
);
if (key >= 0) {
// cache directive value
char *arg = *++argv;
- // ON -> 1, anything else -> 0
- bool onoff = !strcmp("ON", arg);
+ // OFF -> 0, anything else -> 1
+ bool onoff = (0 != strcmp("OFF", arg));
// process directive
if (DIR_HANGUP == key) {
// turn SIGHUP on/off
@@ -217,14 +204,20 @@ int chat_main(int argc UNUSED_PARAM, char **argv)
timeout = DEFAULT_CHAT_TIMEOUT;
} else if (DIR_ECHO == key) {
// turn echo on/off
- // N.B. echo means dumping output
- // from stdin (device) to stderr
+ // N.B. echo means dumping device input/output to stderr
echo = onoff;
-//TODO? echo_fd = onoff * STDERR_FILENO;
-//TODO? echo_fd = xopen(arg, O_WRONLY|O_CREAT|O_TRUNC);
+ } else if (DIR_RECORD == key) {
+ // turn record on/off
+ // N.B. record means dumping device input to a file
+ // close previous record_fd
+ if (record_fd > 0)
+ close(record_fd);
+ // N.B. do we have to die here on open error?
+ record_fd = (onoff) ? xopen(arg, O_WRONLY|O_CREAT|O_TRUNC) : -1;
} else if (DIR_SAY == key) {
// just print argument verbatim
- fprintf(stderr, arg);
+ // TODO: should we use full_write() to avoid unistd/stdio conflict?
+ bb_error_msg("%s", arg);
}
// next, please!
argv++;
@@ -288,12 +281,18 @@ int chat_main(int argc UNUSED_PARAM, char **argv)
// read next char from device
if (safe_read(STDIN_FILENO, buf+buf_len, 1) > 0) {
- // dump device output if ECHO ON or RECORD fname
-//TODO? if (echo_fd > 0) {
-//TODO? full_write(echo_fd, buf+buf_len, 1);
-//TODO? }
- if (echo > 0)
+ // dump device input if RECORD fname
+ if (record_fd > 0) {
+ full_write(record_fd, buf+buf_len, 1);
+ }
+ // dump device input if ECHO ON
+ if (echo > 0) {
+// if (buf[buf_len] < ' ') {
+// full_write(STDERR_FILENO, "^", 1);
+// buf[buf_len] += '@';
+// }
full_write(STDERR_FILENO, buf+buf_len, 1);
+ }
buf_len++;
// move input frame if we've reached higher bound
if (buf_len > COMMON_BUFSIZE) {
@@ -320,7 +319,7 @@ int chat_main(int argc UNUSED_PARAM, char **argv)
if (delta >= 0 && !memcmp(buf+delta, expect, expect_len))
goto expect_done;
#undef buf
- }
+ } /* while (have data) */
// device timed out or unexpected reply received
exitcode = ERR_TIMEOUT;
@@ -365,21 +364,18 @@ int chat_main(int argc UNUSED_PARAM, char **argv)
trim(++buf);
buf = loaded = xmalloc_xopen_read_close(buf, NULL);
}
-
// expand escape sequences in command
len = unescape(buf, &nocr);
// send command
-#if ENABLE_FEATURE_CHAT_SEND_ESCAPES
+ alarm(timeout);
pfd.fd = STDOUT_FILENO;
pfd.events = POLLOUT;
while (len && !exitcode
- && poll(&pfd, 1, timeout) > 0
+ && poll(&pfd, 1, -1) > 0
&& (pfd.revents & POLLOUT)
) {
- // ugly! ugly! ugly!
- // gotta send char by char to achieve this!
- // Brrr...
+#if ENABLE_FEATURE_CHAT_SEND_ESCAPES
// "\\d" means 1 sec delay, "\\p" means 0.01 sec delay
// "\\K" means send BREAK
char c = *buf;
@@ -389,31 +385,28 @@ int chat_main(int argc UNUSED_PARAM, char **argv)
sleep(1);
len--;
continue;
- } else if ('p' == c) {
+ }
+ if ('p' == c) {
usleep(10000);
len--;
continue;
- } else if ('K' == c) {
+ }
+ if ('K' == c) {
tcsendbreak(STDOUT_FILENO, 0);
len--;
continue;
- } else {
- buf--;
}
+ buf--;
}
- if (safe_write(STDOUT_FILENO, buf, 1) > 0) {
- len--;
- buf++;
- } else
+ if (safe_write(STDOUT_FILENO, buf, 1) != 1)
break;
- }
+ len--;
+ buf++;
#else
-// if (len) {
- alarm(timeout);
len -= full_write(STDOUT_FILENO, buf, len);
- alarm(0);
-// }
#endif
+ } /* while (can write) */
+ alarm(0);
// report I/O error if there still exists at least one non-sent char
if (len)
@@ -427,14 +420,12 @@ int chat_main(int argc UNUSED_PARAM, char **argv)
else if (!nocr)
xwrite(STDOUT_FILENO, "\r", 1);
#endif
-
// bail out unless we sent command successfully
if (exitcode)
break;
-
- }
+ } /* if (*argv) */
}
- }
+ } /* while (*argv) */
#if ENABLE_FEATURE_CHAT_TTY_HIFI
tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio0);
diff --git a/release/src/router/busybox/miscutils/chrt.c b/release/src/router/busybox/miscutils/chrt.c
index 23ef58c4d2..cc5660be7b 100644
--- a/release/src/router/busybox/miscutils/chrt.c
+++ b/release/src/router/busybox/miscutils/chrt.c
@@ -1,7 +1,7 @@
/* vi: set sw=4 ts=4: */
/*
* chrt - manipulate real-time attributes of a process
- * Copyright (c) 2006-2007 Bernhard Fischer
+ * Copyright (c) 2006-2007 Bernhard Reutner-Fischer
*
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
diff --git a/release/src/router/busybox/miscutils/crond.c b/release/src/router/busybox/miscutils/crond.c
index 2f0bf6ea8e..804fe0b292 100644
--- a/release/src/router/busybox/miscutils/crond.c
+++ b/release/src/router/busybox/miscutils/crond.c
@@ -23,12 +23,8 @@
#endif
-#ifndef CRONTABS
-#define CRONTABS "/var/spool/cron/crontabs"
-#endif
-#ifndef TMPDIR
-#define TMPDIR "/var/spool/cron"
-#endif
+#define TMPDIR CONFIG_FEATURE_CROND_DIR
+#define CRONTABS CONFIG_FEATURE_CROND_DIR "/crontabs"
#ifndef SENDMAIL
#define SENDMAIL "sendmail"
#endif
@@ -59,7 +55,7 @@ typedef struct CronLine {
#if ENABLE_FEATURE_CROND_CALL_SENDMAIL
int cl_MailPos; /* 'empty file' size */
smallint cl_MailFlag; /* running pid is for mail */
- char *cl_MailTo; /* whom to mail results */
+ char *cl_MailTo; /* whom to mail results */
#endif
/* ordered by size, not in natural order. makes code smaller: */
char cl_Dow[7]; /* 0-6, beginning sunday */
@@ -80,9 +76,9 @@ enum {
OPT_b = (1 << 3),
OPT_S = (1 << 4),
OPT_c = (1 << 5),
- OPT_d = (1 << 6) * ENABLE_DEBUG_CROND_OPTION,
+ OPT_d = (1 << 6) * ENABLE_FEATURE_CROND_D,
};
-#if ENABLE_DEBUG_CROND_OPTION
+#if ENABLE_FEATURE_CROND_D
#define DebugOpt (option_mask32 & OPT_d)
#else
#define DebugOpt 0
@@ -146,7 +142,7 @@ static void crondlog(const char *ctl, ...)
/* Syslog mode: all to syslog (logmode = LOGMODE_SYSLOG), */
if (!DebugOpt && LogFile) {
/* Otherwise (log to file): we reopen log file at every write: */
- int logfd = open3_or_warn(LogFile, O_WRONLY | O_CREAT | O_APPEND, 0600);
+ int logfd = open3_or_warn(LogFile, O_WRONLY | O_CREAT | O_APPEND, 0666);
if (logfd >= 0)
xmove_fd(logfd, STDERR_FILENO);
}
@@ -166,11 +162,11 @@ int crond_main(int argc UNUSED_PARAM, char **argv)
INIT_G();
/* "-b after -f is ignored", and so on for every pair a-b */
- opt_complementary = "f-b:b-f:S-L:L-S" USE_DEBUG_CROND_OPTION(":d-l")
+ opt_complementary = "f-b:b-f:S-L:L-S" USE_FEATURE_CROND_D(":d-l")
":l+:d+"; /* -l and -d have numeric param */
- opt = getopt32(argv, "l:L:fbSc:" USE_DEBUG_CROND_OPTION("d:"),
+ opt = getopt32(argv, "l:L:fbSc:" USE_FEATURE_CROND_D("d:"),
&LogLevel, &LogFile, &CDir
- USE_DEBUG_CROND_OPTION(,&LogLevel));
+ USE_FEATURE_CROND_D(,&LogLevel));
/* both -d N and -l N set the same variable: LogLevel */
if (!(opt & OPT_f)) {
@@ -187,7 +183,7 @@ int crond_main(int argc UNUSED_PARAM, char **argv)
xchdir(CDir);
//signal(SIGHUP, SIG_IGN); /* ? original crond dies on HUP... */
- setenv("SHELL", DEFAULT_SHELL, 1); /* once, for all future children */
+ xsetenv("SHELL", DEFAULT_SHELL); /* once, for all future children */
crondlog(LVL9 "crond (busybox "BB_VER") started, log level %d", LogLevel);
SynchronizeDir();
@@ -252,14 +248,12 @@ int crond_main(int argc UNUSED_PARAM, char **argv)
/* We set environment *before* vfork (because we want to use vfork),
* so we cannot use setenv() - repeated calls to setenv() may leak memory!
* Using putenv(), and freeing memory after unsetenv() won't leak */
-static void safe_setenv4(char **pvar_val, const char *var, const char *val /*, int len*/)
+static void safe_setenv(char **pvar_val, const char *var, const char *val)
{
- const int len = 4; /* both var names are 4 char long */
char *var_val = *pvar_val;
if (var_val) {
- var_val[len] = '\0'; /* nuke '=' */
- unsetenv(var_val);
+ bb_unsetenv(var_val);
free(var_val);
}
*pvar_val = xasprintf("%s=%s", var, val);
@@ -270,13 +264,13 @@ static void safe_setenv4(char **pvar_val, const char *var, const char *val /*, i
static void SetEnv(struct passwd *pas)
{
#if SETENV_LEAKS
- safe_setenv4(&env_var_user, "USER", pas->pw_name);
- safe_setenv4(&env_var_home, "HOME", pas->pw_dir);
+ safe_setenv(&env_var_user, "USER", pas->pw_name);
+ safe_setenv(&env_var_home, "HOME", pas->pw_dir);
/* if we want to set user's shell instead: */
- /*safe_setenv(env_var_user, "SHELL", pas->pw_shell, 5);*/
+ /*safe_setenv(env_var_user, "SHELL", pas->pw_shell);*/
#else
- setenv("USER", pas->pw_name, 1);
- setenv("HOME", pas->pw_dir, 1);
+ xsetenv("USER", pas->pw_name);
+ xsetenv("HOME", pas->pw_dir);
#endif
/* currently, we use constant one: */
/*setenv("SHELL", DEFAULT_SHELL, 1); - done earlier */
@@ -779,7 +773,9 @@ ForkJob(const char *user, CronLine *line, int mailFd,
xmove_fd(mailFd, mail_filename ? 1 : 0);
dup2(1, 2);
}
- execlp(prog, prog, cmd, arg, NULL);
+ /* crond 3.0pl1-100 puts tasks in separate process groups */
+ bb_setpgrp();
+ execlp(prog, prog, cmd, arg, (char *) NULL);
crondlog(ERR20 "can't exec, user %s cmd %s %s %s", user, prog, cmd, arg);
if (mail_filename) {
fdprintf(1, "Exec failed: %s -c %s\n", prog, arg);
@@ -914,7 +910,9 @@ static void RunJob(const char *user, CronLine *line)
if (DebugOpt) {
crondlog(LVL5 "child running %s", DEFAULT_SHELL);
}
- execl(DEFAULT_SHELL, DEFAULT_SHELL, "-c", line->cl_Shell, NULL);
+ /* crond 3.0pl1-100 puts tasks in separate process groups */
+ bb_setpgrp();
+ execl(DEFAULT_SHELL, DEFAULT_SHELL, "-c", line->cl_Shell, (char *) NULL);
crondlog(ERR20 "can't exec, user %s cmd %s %s %s", user,
DEFAULT_SHELL, "-c", line->cl_Shell);
_exit(EXIT_SUCCESS);
diff --git a/release/src/router/busybox/miscutils/crontab.c b/release/src/router/busybox/miscutils/crontab.c
index 01656cc6e7..34b80ea37a 100644
--- a/release/src/router/busybox/miscutils/crontab.c
+++ b/release/src/router/busybox/miscutils/crontab.c
@@ -12,18 +12,16 @@
#include "libbb.h"
-#ifndef CRONTABS
-#define CRONTABS "/var/spool/cron/crontabs"
-#endif
+#define CRONTABS CONFIG_FEATURE_CROND_DIR "/crontabs"
#ifndef CRONUPDATE
#define CRONUPDATE "cron.update"
#endif
static void change_user(const struct passwd *pas)
{
- setenv("USER", pas->pw_name, 1);
- setenv("HOME", pas->pw_dir, 1);
- setenv("SHELL", DEFAULT_SHELL, 1);
+ xsetenv("USER", pas->pw_name);
+ xsetenv("HOME", pas->pw_dir);
+ xsetenv("SHELL", DEFAULT_SHELL);
/* initgroups, setgid, setuid */
change_identity(pas);
@@ -126,15 +124,9 @@ int crontab_main(int argc UNUSED_PARAM, char **argv)
}
if (opt_ler & OPT_u) {
- pas = getpwnam(user_name);
- if (!pas)
- bb_error_msg_and_die("user %s is not known", user_name);
+ pas = xgetpwnam(user_name);
} else {
-/* XXX: xgetpwuid */
- uid_t my_uid = getuid();
- pas = getpwuid(my_uid);
- if (!pas)
- bb_perror_msg_and_die("unknown uid %d", (int)my_uid);
+ pas = xgetpwuid(getuid());
}
#define user_name DONT_USE_ME_BEYOND_THIS_POINT
diff --git a/release/src/router/busybox/miscutils/dc.c b/release/src/router/busybox/miscutils/dc.c
index 47ec060c80..ff2bc3bcef 100644
--- a/release/src/router/busybox/miscutils/dc.c
+++ b/release/src/router/busybox/miscutils/dc.c
@@ -19,7 +19,9 @@ enum { STACK_SIZE = (COMMON_BUFSIZE - offsetof(struct globals, stack)) / sizeof(
#define pointer (G.pointer )
#define base (G.base )
#define stack (G.stack )
-#define INIT_G() do { } while (0)
+#define INIT_G() do { \
+ base = 10; \
+} while (0)
static void push(double a)
@@ -53,12 +55,14 @@ static void mul(void)
push(pop() * pop());
}
+#if ENABLE_FEATURE_DC_LIBM
static void power(void)
{
double topower = pop();
push(pow(pop(), topower));
}
+#endif
static void divide(void)
{
@@ -96,19 +100,45 @@ static void not(void)
static void set_output_base(void)
{
- base = (unsigned)pop();
- if ((base != 10) && (base != 16)) {
- bb_error_msg("error, base %d is not supported", base);
+ static const char bases[] ALIGN1 = { 2, 8, 10, 16, 0 };
+ unsigned b = (unsigned)pop();
+
+ base = *strchrnul(bases, b);
+ if (base == 0) {
+ bb_error_msg("error, base %u is not supported", b);
base = 10;
}
}
static void print_base(double print)
{
- if (base == 16)
- printf("%x\n", (unsigned)print);
- else
+ unsigned x, i;
+
+ if (base == 10) {
printf("%g\n", print);
+ return;
+ }
+
+ x = (unsigned)print;
+ switch (base) {
+ case 16:
+ printf("%x\n", x);
+ break;
+ case 8:
+ printf("%o\n", x);
+ break;
+ default: /* base 2 */
+ i = (unsigned)INT_MAX + 1;
+ do {
+ if (x & i) break;
+ i >>= 1;
+ } while (i > 1);
+ do {
+ bb_putchar('1' - !(x & i));
+ i >>= 1;
+ } while (i);
+ bb_putchar('\n');
+ }
}
static void print_stack_no_pop(void)
@@ -137,9 +167,11 @@ static const struct op operators[] = {
{"mul", mul},
{"/", divide},
{"div", divide},
+#if ENABLE_FEATURE_DC_LIBM
{"**", power},
{"exp", power},
{"pow", power},
+#endif
{"%", mod},
{"mod", mod},
{"and", and},
diff --git a/release/src/router/busybox/miscutils/devmem.c b/release/src/router/busybox/miscutils/devmem.c
new file mode 100644
index 0000000000..e13dedc0a5
--- /dev/null
+++ b/release/src/router/busybox/miscutils/devmem.c
@@ -0,0 +1,128 @@
+/*
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ * Copyright (C) 2000, Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl)
+ * Copyright (C) 2008, BusyBox Team. -solar 4/26/08
+ */
+
+#include "libbb.h"
+
+int devmem_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int devmem_main(int argc UNUSED_PARAM, char **argv)
+{
+ void *map_base, *virt_addr;
+ uint64_t read_result;
+ uint64_t writeval = writeval; /* for compiler */
+ off_t target;
+ unsigned page_size = getpagesize();
+ int fd;
+ int width = 8 * sizeof(int);
+
+ /* devmem ADDRESS [WIDTH [VALUE]] */
+// TODO: options?
+// -r: read and output only the value in hex, with 0x prefix
+// -w: write only, no reads before or after, and no output
+// or make this behavior default?
+// Let's try this and see how users react.
+
+ /* ADDRESS */
+ if (!argv[1])
+ bb_show_usage();
+ errno = 0;
+ target = bb_strtoull(argv[1], NULL, 0); /* allows hex, oct etc */
+
+ /* WIDTH */
+ if (argv[2]) {
+ if (isdigit(argv[2][0]) || argv[2][1])
+ width = xatou(argv[2]);
+ else {
+ static const char bhwl[] ALIGN1 = "bhwl";
+ static const uint8_t sizes[] ALIGN1 = {
+ 8 * sizeof(char),
+ 8 * sizeof(short),
+ 8 * sizeof(int),
+ 8 * sizeof(long),
+ 0 /* bad */
+ };
+ width = strchrnul(bhwl, (argv[2][0] | 0x20)) - bhwl;
+ width = sizes[width];
+ }
+ /* VALUE */
+ if (argv[3])
+ writeval = bb_strtoull(argv[3], NULL, 0);
+ } else { /* argv[2] == NULL */
+ /* make argv[3] to be a valid thing to use */
+ argv--;
+ }
+ if (errno)
+ bb_show_usage(); /* bb_strtouXX failed */
+
+ fd = xopen("/dev/mem", argv[3] ? (O_RDWR | O_SYNC) : (O_RDONLY | O_SYNC));
+ map_base = mmap(NULL,
+ page_size * 2 /* in case value spans page */,
+ argv[3] ? (PROT_READ | PROT_WRITE) : PROT_READ,
+ MAP_SHARED,
+ fd,
+ target & ~(off_t)(page_size - 1));
+ if (map_base == MAP_FAILED)
+ bb_perror_msg_and_die("mmap");
+
+// printf("Memory mapped at address %p.\n", map_base);
+
+ virt_addr = (char*)map_base + (target & (page_size - 1));
+
+ if (!argv[3]) {
+ switch (width) {
+ case 8:
+ read_result = *(volatile uint8_t*)virt_addr;
+ break;
+ case 16:
+ read_result = *(volatile uint16_t*)virt_addr;
+ break;
+ case 32:
+ read_result = *(volatile uint32_t*)virt_addr;
+ break;
+ case 64:
+ read_result = *(volatile uint64_t*)virt_addr;
+ break;
+ default:
+ bb_error_msg_and_die("bad width");
+ }
+// printf("Value at address 0x%"OFF_FMT"X (%p): 0x%llX\n",
+// target, virt_addr,
+// (unsigned long long)read_result);
+ /* Zero-padded output shows the width of access just done */
+ printf("0x%0*llX\n", (width >> 2), (unsigned long long)read_result);
+ } else {
+ switch (width) {
+ case 8:
+ *(volatile uint8_t*)virt_addr = writeval;
+// read_result = *(volatile uint8_t*)virt_addr;
+ break;
+ case 16:
+ *(volatile uint16_t*)virt_addr = writeval;
+// read_result = *(volatile uint16_t*)virt_addr;
+ break;
+ case 32:
+ *(volatile uint32_t*)virt_addr = writeval;
+// read_result = *(volatile uint32_t*)virt_addr;
+ break;
+ case 64:
+ *(volatile uint64_t*)virt_addr = writeval;
+// read_result = *(volatile uint64_t*)virt_addr;
+ break;
+ default:
+ bb_error_msg_and_die("bad width");
+ }
+// printf("Written 0x%llX; readback 0x%llX\n",
+// (unsigned long long)writeval,
+// (unsigned long long)read_result);
+ }
+
+ if (ENABLE_FEATURE_CLEAN_UP) {
+ if (munmap(map_base, page_size * 2) == -1)
+ bb_perror_msg_and_die("munmap");
+ close(fd);
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/release/src/router/busybox/miscutils/fbsplash.c b/release/src/router/busybox/miscutils/fbsplash.c
index f8289c3d11..ec0f092dcb 100644
--- a/release/src/router/busybox/miscutils/fbsplash.c
+++ b/release/src/router/busybox/miscutils/fbsplash.c
@@ -1,7 +1,6 @@
/* vi: set sw=4 ts=4: */
/*
- * Copyright (C) 2008 Michele Sanges ,
- *
+ * Copyright (C) 2008 Michele Sanges
*
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*
@@ -88,7 +87,7 @@ static void fb_open(const char *strfb_device)
* BYTES_PER_PIXEL /*(G.scr_var.bits_per_pixel / 8)*/ ,
PROT_WRITE, MAP_SHARED, fbfd, 0);
if (G.addr == MAP_FAILED)
- bb_perror_msg_and_die("can't mmap %s", strfb_device);
+ bb_perror_msg_and_die("mmap");
close(fbfd);
}
@@ -122,7 +121,7 @@ static void fb_drawrectangle(void)
// vertical lines
ptr1 = (DATA*)(G.addr + (G.nbar_posy * G.scr_var.xres + G.nbar_posx) * BYTES_PER_PIXEL);
ptr2 = (DATA*)(G.addr + (G.nbar_posy * G.scr_var.xres + G.nbar_posx + G.nbar_width - 1) * BYTES_PER_PIXEL);
- cnt = G.nbar_posy + G.nbar_height - 1 - G.nbar_posy;
+ cnt = G.nbar_height - 1 /* HUH?! G.nbar_posy + G.nbar_height - 1 - G.nbar_posy*/;
do {
*ptr1 = thispix; ptr1 += G.scr_var.xres;
*ptr2 = thispix; ptr2 += G.scr_var.xres;
@@ -217,36 +216,50 @@ static void fb_drawprogressbar(unsigned percent)
*/
static void fb_drawimage(void)
{
- char head[256];
- char s[80];
+ char *head, *ptr;
FILE *theme_file;
unsigned char *pixline;
unsigned i, j, width, height, line_size;
- memset(head, 0, sizeof(head));
theme_file = xfopen_stdin(G.image_filename);
-
- // parse ppm header
+ head = xmalloc(256);
+
+ /* parse ppm header
+ * - A ppm image’s magic number is the two characters "P6".
+ * - Whitespace (blanks, TABs, CRs, LFs).
+ * - A width, formatted as ASCII characters in decimal.
+ * - Whitespace.
+ * - A height, again in ASCII decimal.
+ * - Whitespace.
+ * - The maximum color value (Maxval), again in ASCII decimal. Must be
+ * less than 65536.
+ * - Newline or other single whitespace character.
+ * - A raster of Width * Height pixels in triplets of rgb
+ * in pure binary by 1 (or not implemented 2) bytes.
+ */
while (1) {
- if (fgets(s, sizeof(s), theme_file) == NULL)
- bb_error_msg_and_die("bad PPM file '%s'", G.image_filename);
-
- if (s[0] == '#')
- continue;
-
- if (strlen(head) + strlen(s) >= sizeof(head))
- bb_error_msg_and_die("bad PPM file '%s'", G.image_filename);
-
- strcat(head, s);
- if (head[0] != 'P' || head[1] != '6')
+ if (fgets(head, 256, theme_file) == NULL
+ /* do not overrun the buffer */
+ || strlen(bb_common_bufsiz1) >= sizeof(bb_common_bufsiz1) - 256)
bb_error_msg_and_die("bad PPM file '%s'", G.image_filename);
+ ptr = memchr(skip_whitespace(head), '#', 256);
+ if (ptr != NULL)
+ *ptr = 0; /* ignore comments */
+ strcat(bb_common_bufsiz1, head);
// width, height, max_color_val
- if (sscanf(head, "P6 %u %u %u", &width, &height, &i) == 3)
+ if (sscanf(bb_common_bufsiz1, "P6 %u %u %u", &width, &height, &i) == 3
+ && i <= 255)
break;
-// TODO: i must be <= 255!
+ /* If we do not find a signature throughout the whole file then
+ we will diagnose this via EOF on read in the head of the loop. */
}
+ if (ENABLE_FEATURE_CLEAN_UP)
+ free(head);
+ if (width != G.scr_var.xres || height != G.scr_var.yres)
+ bb_error_msg_and_die("PPM %dx%d does not match screen %dx%d",
+ width, height, G.scr_var.xres, G.scr_var.yres);
line_size = width*3;
if (width > G.scr_var.xres)
width = G.scr_var.xres;
@@ -269,7 +282,8 @@ static void fb_drawimage(void)
pixel += 3;
}
}
- free(pixline);
+ if (ENABLE_FEATURE_CLEAN_UP)
+ free(pixline);
fclose(theme_file);
}
@@ -295,7 +309,7 @@ static void init(const char *cfg_filename)
unsigned val = xatoi_u(token[1]);
int i = index_in_strings(param_names, token[0]);
if (i < 0)
- bb_error_msg_and_die("syntax error: '%s'", token[0]);
+ bb_error_msg_and_die("syntax error: %s", token[0]);
if (i >= 0 && i < 7)
G.ns[i] = val;
#if DEBUG
diff --git a/release/src/router/busybox/miscutils/flash_eraseall.c b/release/src/router/busybox/miscutils/flash_eraseall.c
new file mode 100644
index 0000000000..3e0c06ffd8
--- /dev/null
+++ b/release/src/router/busybox/miscutils/flash_eraseall.c
@@ -0,0 +1,194 @@
+/* vi: set sw=4 ts=4: */
+/* eraseall.c -- erase the whole of a MTD device
+ *
+ * Ported to busybox from mtd-utils.
+ *
+ * Copyright (C) 2000 Arcom Control System Ltd
+ *
+ * Renamed to flash_eraseall.c
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "libbb.h"
+#include
+#include
+
+#define OPTION_J (1 << 0)
+#define OPTION_Q (1 << 1)
+#define IS_NAND (1 << 2)
+#define BBTEST (1 << 3)
+
+struct globals {
+ /* This is used in the cpu_to_je/je_to_cpu macros in jffs2_user.h */
+ int tgt_endian;
+};
+#define G (*(struct globals*)&bb_common_bufsiz1)
+#define target_endian (G.tgt_endian)
+#define INIT_G() do { \
+ target_endian = __BYTE_ORDER; \
+} while (0)
+
+static uint32_t crc32(uint32_t val, const void *ss, int len,
+ uint32_t *crc32_table)
+{
+ const unsigned char *s = ss;
+ while (--len >= 0)
+ val = crc32_table[(val ^ *s++) & 0xff] ^ (val >> 8);
+ return val;
+}
+
+static void show_progress(mtd_info_t *meminfo, erase_info_t *erase)
+{
+ printf("\rErasing %d Kibyte @ %x -- %2llu %% complete.",
+ (unsigned)meminfo->erasesize / 1024, erase->start,
+ (unsigned long long) erase->start * 100 / meminfo->size);
+ fflush(stdout);
+}
+
+int flash_eraseall_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int flash_eraseall_main(int argc UNUSED_PARAM, char **argv)
+{
+ struct jffs2_unknown_node cleanmarker;
+ mtd_info_t meminfo;
+ int fd, clmpos, clmlen;
+ erase_info_t erase;
+ struct stat st;
+ unsigned int flags;
+ char *mtd_name;
+
+ INIT_G();
+ opt_complementary = "=1";
+ flags = BBTEST | getopt32(argv, "jq");
+
+ mtd_name = argv[optind];
+ xstat(mtd_name, &st);
+ if (!S_ISCHR(st.st_mode))
+ bb_error_msg_and_die("%s: not a char device", mtd_name);
+
+ fd = xopen(mtd_name, O_RDWR);
+
+ xioctl(fd, MEMGETINFO, &meminfo);
+ erase.length = meminfo.erasesize;
+ if (meminfo.type == MTD_NANDFLASH)
+ flags |= IS_NAND;
+
+ clmpos = 0;
+ clmlen = 8;
+ if (flags & OPTION_J) {
+ uint32_t *crc32_table;
+
+ crc32_table = crc32_filltable(NULL, 0);
+
+ cleanmarker.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
+ cleanmarker.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER);
+ if (!(flags & IS_NAND))
+ cleanmarker.totlen = cpu_to_je32(sizeof(struct jffs2_unknown_node));
+ else {
+ struct nand_oobinfo oobinfo;
+
+ xioctl(fd, MEMGETOOBSEL, &oobinfo);
+
+ /* Check for autoplacement */
+ if (oobinfo.useecc == MTD_NANDECC_AUTOPLACE) {
+ /* Get the position of the free bytes */
+ clmpos = oobinfo.oobfree[0][0];
+ clmlen = oobinfo.oobfree[0][1];
+ if (clmlen > 8)
+ clmlen = 8;
+ if (clmlen == 0)
+ bb_error_msg_and_die("Autoplacement selected and no empty space in oob");
+ } else {
+ /* Legacy mode */
+ switch (meminfo.oobsize) {
+ case 8:
+ clmpos = 6;
+ clmlen = 2;
+ break;
+ case 16:
+ clmpos = 8;
+ /*clmlen = 8;*/
+ break;
+ case 64:
+ clmpos = 16;
+ /*clmlen = 8;*/
+ break;
+ }
+ }
+ cleanmarker.totlen = cpu_to_je32(8);
+ }
+
+ cleanmarker.hdr_crc = cpu_to_je32(crc32(0, &cleanmarker, sizeof(struct jffs2_unknown_node) - 4,
+ crc32_table));
+ }
+
+ /* Don't want to destroy progress indicator by bb_error_msg's */
+ applet_name = xasprintf("\n%s: %s", applet_name, mtd_name);
+
+ for (erase.start = 0; erase.start < meminfo.size;
+ erase.start += meminfo.erasesize) {
+ if (flags & BBTEST) {
+ int ret;
+ loff_t offset = erase.start;
+
+ ret = ioctl(fd, MEMGETBADBLOCK, &offset);
+ if (ret > 0) {
+ if (!(flags & OPTION_Q))
+ bb_info_msg("\nSkipping bad block at 0x%08x", erase.start);
+ continue;
+ }
+ if (ret < 0) {
+ /* Black block table is not available on certain flash
+ * types e.g. NOR
+ */
+ if (errno == EOPNOTSUPP) {
+ flags &= ~BBTEST;
+ if (flags & IS_NAND)
+ bb_error_msg_and_die("bad block check not available");
+ } else {
+ bb_perror_msg_and_die("MEMGETBADBLOCK error");
+ }
+ }
+ }
+
+ if (!(flags & OPTION_Q))
+ show_progress(&meminfo, &erase);
+
+ xioctl(fd, MEMERASE, &erase);
+
+ /* format for JFFS2 ? */
+ if (!(flags & OPTION_J))
+ continue;
+
+ /* write cleanmarker */
+ if (flags & IS_NAND) {
+ struct mtd_oob_buf oob;
+
+ oob.ptr = (unsigned char *) &cleanmarker;
+ oob.start = erase.start + clmpos;
+ oob.length = clmlen;
+ xioctl(fd, MEMWRITEOOB, &oob);
+ } else {
+ xlseek(fd, erase.start, SEEK_SET);
+ /* if (lseek(fd, erase.start, SEEK_SET) < 0) {
+ bb_perror_msg("MTD %s failure", "seek");
+ continue;
+ } */
+ xwrite(fd, &cleanmarker, sizeof(cleanmarker));
+ /* if (write(fd, &cleanmarker, sizeof(cleanmarker)) != sizeof(cleanmarker)) {
+ bb_perror_msg("MTD %s failure", "write");
+ continue;
+ } */
+ }
+ if (!(flags & OPTION_Q))
+ printf(" Cleanmarker written at %x.", erase.start);
+ }
+ if (!(flags & OPTION_Q)) {
+ show_progress(&meminfo, &erase);
+ bb_putchar('\n');
+ }
+
+ if (ENABLE_FEATURE_CLEAN_UP)
+ close(fd);
+ return EXIT_SUCCESS;
+}
diff --git a/release/src/router/busybox/miscutils/hdparm.c b/release/src/router/busybox/miscutils/hdparm.c
index b75da16ece..de5d68a043 100644
--- a/release/src/router/busybox/miscutils/hdparm.c
+++ b/release/src/router/busybox/miscutils/hdparm.c
@@ -59,7 +59,7 @@
#define ADV_PIO_MODES 64 /* advanced PIO modes supported */
/* multiword DMA xfer cycle time: */
#define DMA_TIME_MIN 65 /* - minimum */
-#define DMA_TIME_NORM 66 /* - manufacturer's recommended */
+#define DMA_TIME_NORM 66 /* - manufacturer's recommended */
/* minimum PIO xfer cycle time: */
#define PIO_NO_FLOW 67 /* - without flow control */
#define PIO_FLOW 68 /* - with IORDY flow control */
@@ -82,7 +82,7 @@
#define ENH_ERASE_TIME 90 /* - enhanced */
#define ADV_PWR 91 /* current advanced power management level
in low byte, 0x40 in high byte. */
-#define PSWD_CODE 92 /* master password revision code */
+#define PSWD_CODE 92 /* master password revision code */
#define HWRST_RSLT 93 /* hardware reset result */
#define ACOUSTIC 94 /* acoustic mgmt values ( >= ATA-6) */
#define LBA_LSB 100 /* LBA: maximum. Currently only 48 */
@@ -1759,7 +1759,7 @@ static void process_dev(char *devname)
}
}
if (get_unmask) {
- if(!ioctl_or_warn(fd, HDIO_GET_UNMASKINTR, &parm))
+ if (!ioctl_or_warn(fd, HDIO_GET_UNMASKINTR, &parm))
print_value_on_off("unmaskirq", parm);
}
@@ -1777,25 +1777,25 @@ static void process_dev(char *devname)
#endif
#ifdef HDIO_GET_QDMA
if (get_dma_q) {
- if(!ioctl_or_warn(fd, HDIO_GET_QDMA, &parm))
+ if (!ioctl_or_warn(fd, HDIO_GET_QDMA, &parm))
print_value_on_off("queue_depth", parm);
}
#endif
if (get_keep) {
- if(!ioctl_or_warn(fd, HDIO_GET_KEEPSETTINGS, &parm))
+ if (!ioctl_or_warn(fd, HDIO_GET_KEEPSETTINGS, &parm))
print_value_on_off("keepsettings", parm);
}
if (get_nowerr) {
- if(!ioctl_or_warn(fd, HDIO_GET_NOWERR, &parm))
+ if (!ioctl_or_warn(fd, HDIO_GET_NOWERR, &parm))
print_value_on_off("nowerr", parm);
}
if (get_readonly) {
- if(!ioctl_or_warn(fd, BLKROGET, &parm))
+ if (!ioctl_or_warn(fd, BLKROGET, &parm))
print_value_on_off("readonly", parm);
}
if (get_readahead) {
- if(!ioctl_or_warn(fd, BLKRAGET, &parm))
+ if (!ioctl_or_warn(fd, BLKRAGET, &parm))
print_value_on_off("readahead", parm);
}
if (get_geom) {
diff --git a/release/src/router/busybox/miscutils/inotifyd.c b/release/src/router/busybox/miscutils/inotifyd.c
index 2a1a153489..d6b5d246bc 100644
--- a/release/src/router/busybox/miscutils/inotifyd.c
+++ b/release/src/router/busybox/miscutils/inotifyd.c
@@ -28,14 +28,7 @@
*/
#include "libbb.h"
-#include
-
-static volatile smallint signalled;
-
-static void signal_handler(int signo)
-{
- signalled = signo;
-}
+#include
static const char mask_names[] ALIGN1 =
"a" // 0x00000001 File was accessed
@@ -50,73 +43,96 @@ static const char mask_names[] ALIGN1 =
"d" // 0x00000200 Subfile was deleted
"D" // 0x00000400 Self was deleted
"M" // 0x00000800 Self was moved
+ "\0" // 0x00001000 (unused)
+ // Kernel events, always reported:
+ "u" // 0x00002000 Backing fs was unmounted
+ "o" // 0x00004000 Event queued overflowed
+ "x" // 0x00008000 File is no longer watched (usually deleted)
;
-
-extern int inotify_init(void);
-extern int inotify_add_watch(int fd, const char *path, uint32_t mask);
+enum {
+ MASK_BITS = sizeof(mask_names) - 1
+};
int inotifyd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int inotifyd_main(int argc UNUSED_PARAM, char **argv)
+int inotifyd_main(int argc, char **argv)
{
- unsigned mask = IN_ALL_EVENTS; // assume we want all events
+ int n;
+ unsigned mask;
struct pollfd pfd;
- char **watched = ++argv; // watched name list
- const char *args[] = { *argv, NULL, NULL, NULL, NULL };
+ char **watches; // names of files being watched
+ const char *args[5];
// sanity check: agent and at least one watch must be given
- if (!argv[1])
+ if (!argv[1] || !argv[2])
bb_show_usage();
+ argv++;
+ // inotify_add_watch will number watched files
+ // starting from 1, thus watches[0] is unimportant,
+ // and 1st file name is watches[1].
+ watches = argv;
+ args[0] = *argv;
+ args[4] = NULL;
+ argc -= 2; // number of files we watch
+
// open inotify
pfd.fd = inotify_init();
if (pfd.fd < 0)
bb_perror_msg_and_die("no kernel support");
- // setup watched
+ // setup watches
while (*++argv) {
char *path = *argv;
char *masks = strchr(path, ':');
- int wd; // watch descriptor
+
+ mask = 0x0fff; // assuming we want all non-kernel events
// if mask is specified ->
if (masks) {
*masks = '\0'; // split path and mask
// convert mask names to mask bitset
mask = 0;
while (*++masks) {
- int i = strchr(mask_names, *masks) - mask_names;
- if (i >= 0) {
- mask |= (1 << i);
- }
+ const char *found;
+ found = memchr(mask_names, *masks, MASK_BITS);
+ if (found)
+ mask |= (1 << (found - mask_names));
}
}
// add watch
- wd = inotify_add_watch(pfd.fd, path, mask);
- if (wd < 0) {
+ n = inotify_add_watch(pfd.fd, path, mask);
+ if (n < 0)
bb_perror_msg_and_die("add watch (%s) failed", path);
-// } else {
-// bb_error_msg("added %d [%s]:%4X", wd, path, mask);
- }
+ //bb_error_msg("added %d [%s]:%4X", n, path, mask);
}
// setup signals
- bb_signals(0
- + (1 << SIGHUP)
- + (1 << SIGINT)
- + (1 << SIGTERM)
- + (1 << SIGPIPE)
- , signal_handler);
+ bb_signals(BB_FATAL_SIGS, record_signo);
// do watch
-
-// pfd.fd = fd;
pfd.events = POLLIN;
-
- while (!signalled && poll(&pfd, 1, -1) > 0) {
- ssize_t len;
+ while (1) {
+ int len;
void *buf;
struct inotify_event *ie;
+ again:
+ if (bb_got_signal)
+ break;
+ n = poll(&pfd, 1, -1);
+ // Signal interrupted us?
+ if (n < 0 && errno == EINTR)
+ goto again;
+ // Under Linux, above if() is not necessary.
+ // Non-fatal signals, e.g. SIGCHLD, when set to SIG_DFL,
+ // are not interrupting poll().
+ // Thus we can just break if n <= 0 (see below),
+ // because EINTR will happen only on SIGTERM et al.
+ // But this might be not true under other Unixes,
+ // and is generally way too subtle to depend on.
+ if (n <= 0) // strange error?
+ break;
// read out all pending events
+ // (NB: len must be int, not ssize_t or long!)
xioctl(pfd.fd, FIONREAD, &len);
#define eventbuf bb_common_bufsiz1
ie = buf = (len <= sizeof(eventbuf)) ? eventbuf : xmalloc(len);
@@ -124,21 +140,29 @@ int inotifyd_main(int argc UNUSED_PARAM, char **argv)
// process events. N.B. events may vary in length
while (len > 0) {
int i;
- char events[12];
- char *s = events;
- unsigned m = ie->mask;
-
- for (i = 0; i < 12; ++i, m >>= 1) {
- if (m & 1) {
- *s++ = mask_names[i];
+ // cache relevant events mask
+ unsigned m = ie->mask & ((1 << MASK_BITS) - 1);
+ if (m) {
+ char events[MASK_BITS + 1];
+ char *s = events;
+ for (i = 0; i < MASK_BITS; ++i, m >>= 1) {
+ if ((m & 1) && (mask_names[i] != '\0'))
+ *s++ = mask_names[i];
+ }
+ *s = '\0';
+// bb_error_msg("exec %s %08X\t%s\t%s\t%s", args[0],
+// ie->mask, events, watches[ie->wd], ie->len ? ie->name : "");
+ args[1] = events;
+ args[2] = watches[ie->wd];
+ args[3] = ie->len ? ie->name : NULL;
+ wait4pid(xspawn((char **)args));
+ // we are done if all files got final x event
+ if (ie->mask & 0x8000) {
+ if (--argc <= 0)
+ goto done;
+ inotify_rm_watch(pfd.fd, ie->wd);
}
}
- *s = '\0';
-// bb_error_msg("exec %s %08X\t%s\t%s\t%s", agent, ie->mask, events, watched[ie->wd], ie->len ? ie->name : "");
- args[1] = events;
- args[2] = watched[ie->wd];
- args[3] = ie->len ? ie->name : NULL;
- xspawn((char **)args);
// next event
i = sizeof(struct inotify_event) + ie->len;
len -= i;
@@ -146,7 +170,7 @@ int inotifyd_main(int argc UNUSED_PARAM, char **argv)
}
if (eventbuf != buf)
free(buf);
- }
-
- return EXIT_SUCCESS;
+ } // while (1)
+ done:
+ return bb_got_signal;
}
diff --git a/release/src/router/busybox/miscutils/ionice.c b/release/src/router/busybox/miscutils/ionice.c
new file mode 100644
index 0000000000..361c141b82
--- /dev/null
+++ b/release/src/router/busybox/miscutils/ionice.c
@@ -0,0 +1,99 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * ionice implementation for busybox based on linux-utils-ng 2.14
+ *
+ * Copyright (C) 2008 by
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include
+#include
+#include "libbb.h"
+
+static int ioprio_set(int which, int who, int ioprio)
+{
+ return syscall(SYS_ioprio_set, which, who, ioprio);
+}
+
+static int ioprio_get(int which, int who)
+{
+ return syscall(SYS_ioprio_get, which, who);
+}
+
+enum {
+ IOPRIO_WHO_PROCESS = 1,
+ IOPRIO_WHO_PGRP,
+ IOPRIO_WHO_USER
+};
+
+enum {
+ IOPRIO_CLASS_NONE,
+ IOPRIO_CLASS_RT,
+ IOPRIO_CLASS_BE,
+ IOPRIO_CLASS_IDLE
+};
+
+static const char to_prio[] = "none\0realtime\0best-effort\0idle";
+
+#define IOPRIO_CLASS_SHIFT 13
+
+int ionice_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int ionice_main(int argc UNUSED_PARAM, char **argv)
+{
+ /* Defaults */
+ int ioclass = 0;
+ int pri = 0;
+ int pid = 0; /* affect own porcess */
+ int opt;
+ enum {
+ OPT_n = 1,
+ OPT_c = 2,
+ OPT_p = 4,
+ };
+
+ /* Numeric params */
+ opt_complementary = "n+:c+:p+";
+ /* '+': stop at first non-option */
+ opt = getopt32(argv, "+n:c:p:", &pri, &ioclass, &pid);
+ argv += optind;
+
+ if (opt & OPT_c) {
+ if (ioclass > 3)
+ bb_error_msg_and_die("bad class %d", ioclass);
+// Do we need this (compat?)?
+// if (ioclass == IOPRIO_CLASS_NONE)
+// ioclass = IOPRIO_CLASS_BE;
+// if (ioclass == IOPRIO_CLASS_IDLE) {
+// //if (opt & OPT_n)
+// // bb_error_msg("ignoring priority for idle class");
+// pri = 7;
+// }
+ }
+
+ if (!(opt & (OPT_n|OPT_c))) {
+ if (!(opt & OPT_p) && *argv)
+ pid = xatoi_u(*argv);
+
+ pri = ioprio_get(IOPRIO_WHO_PROCESS, pid);
+ if (pri == -1)
+ bb_perror_msg_and_die("ioprio_%cet", 'g');
+
+ ioclass = (pri >> IOPRIO_CLASS_SHIFT) & 0x3;
+ pri &= 0xff;
+ printf((ioclass == IOPRIO_CLASS_IDLE) ? "%s\n" : "%s: prio %d\n",
+ nth_string(to_prio, ioclass), pri);
+ } else {
+//printf("pri=%d class=%d val=%x\n",
+//pri, ioclass, pri | (ioclass << IOPRIO_CLASS_SHIFT));
+ pri |= (ioclass << IOPRIO_CLASS_SHIFT);
+ if (ioprio_set(IOPRIO_WHO_PROCESS, pid, pri) == -1)
+ bb_perror_msg_and_die("ioprio_%cet", 's');
+ if (*argv) {
+ BB_EXECVP(*argv, argv);
+ bb_simple_perror_msg_and_die(*argv);
+ }
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/release/src/router/busybox/miscutils/less.c b/release/src/router/busybox/miscutils/less.c
index 530a40a8c8..27855bbe8b 100644
--- a/release/src/router/busybox/miscutils/less.c
+++ b/release/src/router/busybox/miscutils/less.c
@@ -28,10 +28,6 @@
#include "xregex.h"
#endif
-/* FIXME: currently doesn't work right */
-#undef ENABLE_FEATURE_LESS_FLAGCS
-#define ENABLE_FEATURE_LESS_FLAGCS 0
-
/* The escape codes for highlighted and normal text */
#define HIGHLIGHT "\033[7m"
#define NORMAL "\033[0m"
@@ -40,45 +36,22 @@
/* The escape code to clear to end of line */
#define CLEAR_2_EOL "\033[K"
-/* These are the escape sequences corresponding to special keys */
enum {
- REAL_KEY_UP = 'A',
- REAL_KEY_DOWN = 'B',
- REAL_KEY_RIGHT = 'C',
- REAL_KEY_LEFT = 'D',
- REAL_PAGE_UP = '5',
- REAL_PAGE_DOWN = '6',
- REAL_KEY_HOME = '7', // vt100? linux vt? or what?
- REAL_KEY_END = '8',
- REAL_KEY_HOME_ALT = '1', // ESC [1~ (vt100? linux vt? or what?)
- REAL_KEY_END_ALT = '4', // ESC [4~
- REAL_KEY_HOME_XTERM = 'H',
- REAL_KEY_END_XTERM = 'F',
-
-/* These are the special codes assigned by this program to the special keys */
- KEY_UP = 20,
- KEY_DOWN = 21,
- KEY_RIGHT = 22,
- KEY_LEFT = 23,
- PAGE_UP = 24,
- PAGE_DOWN = 25,
- KEY_HOME = 26,
- KEY_END = 27,
-
/* Absolute max of lines eaten */
MAXLINES = CONFIG_FEATURE_LESS_MAXLINES,
-
/* This many "after the end" lines we will show (at max) */
TILDES = 1,
};
/* Command line options */
enum {
- FLAG_E = 1,
+ FLAG_E = 1 << 0,
FLAG_M = 1 << 1,
FLAG_m = 1 << 2,
FLAG_N = 1 << 3,
FLAG_TILDE = 1 << 4,
+ FLAG_I = 1 << 5,
+ FLAG_S = (1 << 6) * ENABLE_FEATURE_LESS_DASHCMD,
/* hijack command line options variable for internal state vars */
LESS_STATE_MATCH_BACKWARDS = 1 << 15,
};
@@ -92,11 +65,14 @@ struct globals {
int kbd_fd; /* fd to get input from */
int less_gets_pos;
/* last position in last line, taking into account tabs */
- size_t linepos;
- unsigned max_displayed_line;
+ size_t last_line_pos;
unsigned max_fline;
unsigned max_lineno; /* this one tracks linewrap */
+ unsigned max_displayed_line;
unsigned width;
+#if ENABLE_FEATURE_LESS_WINCH
+ unsigned winch_counter;
+#endif
ssize_t eof_error; /* eof if 0, error if < 0 */
ssize_t readpos;
ssize_t readeof; /* must be signed */
@@ -120,17 +96,22 @@ struct globals {
smallint pattern_valid;
#endif
smallint terminated;
+ smalluint kbd_input_size;
struct termios term_orig, term_less;
+ char kbd_input[KEYCODE_BUFFER_SIZE];
};
#define G (*ptr_to_globals)
#define cur_fline (G.cur_fline )
#define kbd_fd (G.kbd_fd )
#define less_gets_pos (G.less_gets_pos )
-#define linepos (G.linepos )
-#define max_displayed_line (G.max_displayed_line)
+#define last_line_pos (G.last_line_pos )
#define max_fline (G.max_fline )
#define max_lineno (G.max_lineno )
+#define max_displayed_line (G.max_displayed_line)
#define width (G.width )
+#define winch_counter (G.winch_counter )
+/* This one is 100% not cached by compiler on read access */
+#define WINCH_COUNTER (*(volatile unsigned *)&winch_counter)
#define eof_error (G.eof_error )
#define readpos (G.readpos )
#define readeof (G.readeof )
@@ -154,6 +135,8 @@ struct globals {
#define terminated (G.terminated )
#define term_orig (G.term_orig )
#define term_less (G.term_less )
+#define kbd_input_size (G.kbd_input_size )
+#define kbd_input (G.kbd_input )
#define INIT_G() do { \
SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
less_gets_pos = -1; \
@@ -165,6 +148,14 @@ struct globals {
USE_FEATURE_LESS_REGEXP(wanted_match = -1;) \
} while (0)
+/* flines[] are lines read from stdin, each in malloc'ed buffer.
+ * Line numbers are stored as uint32_t prepended to each line.
+ * Pointer is adjusted so that flines[i] points directly past
+ * line number. Accesor: */
+#define MEMPTR(p) ((char*)(p) - 4)
+#define LINENO(p) (*(uint32_t*)((p) - 4))
+
+
/* Reset terminal input to normal */
static void set_tty_cooked(void)
{
@@ -205,6 +196,92 @@ static void less_exit(int code)
exit(code);
}
+#if (ENABLE_FEATURE_LESS_DASHCMD && ENABLE_FEATURE_LESS_LINENUMS) \
+ || ENABLE_FEATURE_LESS_WINCH
+static void re_wrap(void)
+{
+ int w = width;
+ int new_line_pos;
+ int src_idx;
+ int dst_idx;
+ int new_cur_fline = 0;
+ uint32_t lineno;
+ char linebuf[w + 1];
+ const char **old_flines = flines;
+ const char *s;
+ char **new_flines = NULL;
+ char *d;
+
+ if (option_mask32 & FLAG_N)
+ w -= 8;
+
+ src_idx = 0;
+ dst_idx = 0;
+ s = old_flines[0];
+ lineno = LINENO(s);
+ d = linebuf;
+ new_line_pos = 0;
+ while (1) {
+ *d = *s;
+ if (*d != '\0') {
+ new_line_pos++;
+ if (*d == '\t') /* tab */
+ new_line_pos += 7;
+ s++;
+ d++;
+ if (new_line_pos >= w) {
+ int sz;
+ /* new line is full, create next one */
+ *d = '\0';
+ next_new:
+ sz = (d - linebuf) + 1; /* + 1: NUL */
+ d = ((char*)xmalloc(sz + 4)) + 4;
+ LINENO(d) = lineno;
+ memcpy(d, linebuf, sz);
+ new_flines = xrealloc_vector(new_flines, 8, dst_idx);
+ new_flines[dst_idx] = d;
+ dst_idx++;
+ if (new_line_pos < w) {
+ /* if we came here thru "goto next_new" */
+ if (src_idx > max_fline)
+ break;
+ lineno = LINENO(s);
+ }
+ d = linebuf;
+ new_line_pos = 0;
+ }
+ continue;
+ }
+ /* *d == NUL: old line ended, go to next old one */
+ free(MEMPTR(old_flines[src_idx]));
+ /* btw, convert cur_fline... */
+ if (cur_fline == src_idx)
+ new_cur_fline = dst_idx;
+ src_idx++;
+ /* no more lines? finish last new line (and exit the loop) */
+ if (src_idx > max_fline)
+ goto next_new;
+ s = old_flines[src_idx];
+ if (lineno != LINENO(s)) {
+ /* this is not a continuation line!
+ * create next _new_ line too */
+ goto next_new;
+ }
+ }
+
+ free(old_flines);
+ flines = (const char **)new_flines;
+
+ max_fline = dst_idx - 1;
+ last_line_pos = new_line_pos;
+ cur_fline = new_cur_fline;
+ /* max_lineno is screen-size independent */
+#if ENABLE_FEATURE_LESS_REGEXP
+ pattern_valid = 0;
+#endif
+}
+#endif
+
#if ENABLE_FEATURE_LESS_REGEXP
static void fill_match_lines(unsigned pos);
#else
@@ -230,7 +307,7 @@ static void fill_match_lines(unsigned pos);
* on line wrap, only on "real" new lines.
* readbuf[0..readeof-1] - small preliminary buffer.
* readbuf[readpos] - next character to add to current line.
- * linepos - screen line position of next char to be read
+ * last_line_pos - screen line position of next char to be read
* (takes into account tabs and backspaces)
* eof_error - < 0 error, == 0 EOF, > 0 not EOF/error
*/
@@ -251,18 +328,16 @@ static void read_lines(void)
USE_FEATURE_LESS_REGEXP(again0:)
- p = current_line = xmalloc(w);
+ p = current_line = ((char*)xmalloc(w + 4)) + 4;
max_fline += last_terminated;
if (!last_terminated) {
const char *cp = flines[max_fline];
- if (option_mask32 & FLAG_N)
- cp += 8;
- strcpy(current_line, cp);
+ strcpy(p, cp);
p += strlen(current_line);
- free((char*)flines[max_fline]);
- /* linepos is still valid from previous read_lines() */
+ free(MEMPTR(flines[max_fline]));
+ /* last_line_pos is still valid from previous read_lines() */
} else {
- linepos = 0;
+ last_line_pos = 0;
}
while (1) { /* read lines until we reach cur_fline or wanted_match */
@@ -284,28 +359,28 @@ static void read_lines(void)
/* backspace? [needed for manpages] */
/* is (a) insane and */
/* (b) harder to do correctly, so we refuse to do it */
- if (c == '\x8' && linepos && p[-1] != '\t') {
+ if (c == '\x8' && last_line_pos && p[-1] != '\t') {
readpos++; /* eat it */
- linepos--;
+ last_line_pos--;
/* was buggy (p could end up <= current_line)... */
*--p = '\0';
continue;
}
{
- size_t new_linepos = linepos + 1;
+ size_t new_last_line_pos = last_line_pos + 1;
if (c == '\t') {
- new_linepos += 7;
- new_linepos &= (~7);
+ new_last_line_pos += 7;
+ new_last_line_pos &= (~7);
}
- if ((int)new_linepos >= w)
+ if ((int)new_last_line_pos >= w)
break;
- linepos = new_linepos;
+ last_line_pos = new_last_line_pos;
}
/* ok, we will eat this char */
readpos++;
if (c == '\n') {
terminated = 1;
- linepos = 0;
+ last_line_pos = 0;
break;
}
/* NUL is substituted by '\n'! */
@@ -323,22 +398,21 @@ static void read_lines(void)
reached_eof:
last_terminated = terminated;
flines = xrealloc_vector(flines, 8, max_fline);
- if (option_mask32 & FLAG_N) {
- /* Width of 7 preserves tab spacing in the text */
- flines[max_fline] = xasprintf(
- (max_lineno <= 9999999) ? "%7u %s" : "%07u %s",
- max_lineno % 10000000, current_line);
- free(current_line);
- if (terminated)
- max_lineno++;
- } else {
- flines[max_fline] = xrealloc(current_line, strlen(current_line) + 1);
- }
+
+ flines[max_fline] = (char*)xrealloc(MEMPTR(current_line), strlen(current_line) + 1 + 4) + 4;
+ LINENO(flines[max_fline]) = max_lineno;
+ if (terminated)
+ max_lineno++;
+
if (max_fline >= MAXLINES) {
eof_error = 0; /* Pretend we saw EOF */
break;
}
- if (max_fline > cur_fline + max_displayed_line) {
+ if (!(option_mask32 & FLAG_S)
+ ? (max_fline > cur_fline + max_displayed_line)
+ : (max_fline >= cur_fline
+ && max_lineno > LINENO(flines[cur_fline]) + max_displayed_line)
+ ) {
#if !ENABLE_FEATURE_LESS_REGEXP
break;
#else
@@ -379,9 +453,9 @@ static void read_lines(void)
#endif
}
max_fline++;
- current_line = xmalloc(w);
+ current_line = ((char*)xmalloc(w + 4)) + 4;
p = current_line;
- linepos = 0;
+ last_line_pos = 0;
} /* end of "read lines until we reach cur_fline" loop */
fill_match_lines(old_max_fline);
#if ENABLE_FEATURE_LESS_REGEXP
@@ -486,6 +560,30 @@ static const char ctrlconv[] ALIGN1 =
"\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x40\x4b\x4c\x4d\x4e\x4f"
"\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f";
+static void lineno_str(char *nbuf9, const char *line)
+{
+ nbuf9[0] = '\0';
+ if (option_mask32 & FLAG_N) {
+ const char *fmt;
+ unsigned n;
+
+ if (line == empty_line_marker) {
+ memset(nbuf9, ' ', 8);
+ nbuf9[8] = '\0';
+ return;
+ }
+ /* Width of 7 preserves tab spacing in the text */
+ fmt = "%7u ";
+ n = LINENO(line) + 1;
+ if (n > 9999999) {
+ n %= 10000000;
+ fmt = "%07u ";
+ }
+ sprintf(nbuf9, fmt, n);
+ }
+}
+
+
#if ENABLE_FEATURE_LESS_REGEXP
static void print_found(const char *line)
{
@@ -495,6 +593,7 @@ static void print_found(const char *line)
regmatch_t match_structs;
char buf[width];
+ char nbuf9[9];
const char *str = line;
char *p = buf;
size_t n;
@@ -531,7 +630,8 @@ static void print_found(const char *line)
match_structs.rm_so, str,
match_structs.rm_eo - match_structs.rm_so,
str + match_structs.rm_so);
- free(growline); growline = new;
+ free(growline);
+ growline = new;
str += match_structs.rm_eo;
line += match_structs.rm_eo;
eflags = REG_NOTBOL;
@@ -543,11 +643,12 @@ static void print_found(const char *line)
match_status = 1;
}
+ lineno_str(nbuf9, line);
if (!growline) {
- printf(CLEAR_2_EOL"%s\n", str);
+ printf(CLEAR_2_EOL"%s%s\n", nbuf9, str);
return;
}
- printf(CLEAR_2_EOL"%s%s\n", growline, str);
+ printf(CLEAR_2_EOL"%s%s%s\n", nbuf9, growline, str);
free(growline);
}
#else
@@ -557,10 +658,13 @@ void print_found(const char *line);
static void print_ascii(const char *str)
{
char buf[width];
+ char nbuf9[9];
char *p;
size_t n;
- printf(CLEAR_2_EOL);
+ lineno_str(nbuf9, str);
+ printf(CLEAR_2_EOL"%s", nbuf9);
+
while (*str) {
n = strcspn(str, controls);
if (n) {
@@ -604,9 +708,32 @@ static void buffer_print(void)
static void buffer_fill_and_print(void)
{
unsigned i;
+#if ENABLE_FEATURE_LESS_DASHCMD
+ int fpos = cur_fline;
+
+ if (option_mask32 & FLAG_S) {
+ /* Go back to the beginning of this line */
+ while (fpos && LINENO(flines[fpos]) == LINENO(flines[fpos-1]))
+ fpos--;
+ }
+
+ i = 0;
+ while (i <= max_displayed_line && fpos <= max_fline) {
+ int lineno = LINENO(flines[fpos]);
+ buffer[i] = flines[fpos];
+ i++;
+ do {
+ fpos++;
+ } while ((fpos <= max_fline)
+ && (option_mask32 & FLAG_S)
+ && lineno == LINENO(flines[fpos])
+ );
+ }
+#else
for (i = 0; i <= max_displayed_line && cur_fline + i <= max_fline; i++) {
buffer[i] = flines[cur_fline + i];
}
+#endif
for (; i <= max_displayed_line; i++) {
buffer[i] = empty_line_marker;
}
@@ -647,9 +774,7 @@ static void buffer_line(int linenum)
static void open_file_and_read_lines(void)
{
if (filename) {
- int fd = xopen(filename, O_RDONLY);
- dup2(fd, 0);
- if (fd) close(fd);
+ xmove_fd(xopen(filename, O_RDONLY), STDIN_FILENO);
} else {
/* "less" with no arguments in argv[] */
/* For status line only */
@@ -657,7 +782,7 @@ static void open_file_and_read_lines(void)
}
readpos = 0;
readeof = 0;
- linepos = 0;
+ last_line_pos = 0;
terminated = 1;
read_lines();
}
@@ -669,7 +794,7 @@ static void reinitialize(void)
if (flines) {
for (i = 0; i <= max_fline; i++)
- free((void*)(flines[i]));
+ free(MEMPTR(flines[i]));
free(flines);
flines = NULL;
}
@@ -681,9 +806,9 @@ static void reinitialize(void)
buffer_fill_and_print();
}
-static ssize_t getch_nowait(char* input, int sz)
+static ssize_t getch_nowait(void)
{
- ssize_t rd;
+ int rd;
struct pollfd pfd[2];
pfd[0].fd = STDIN_FILENO;
@@ -699,25 +824,49 @@ static ssize_t getch_nowait(char* input, int sz)
* (switch fd into O_NONBLOCK'ed mode to avoid it)
*/
rd = 1;
- if (max_fline <= cur_fline + max_displayed_line
- && eof_error > 0 /* did NOT reach eof yet */
+ /* Are we interested in stdin? */
+//TODO: reuse code for determining this
+ if (!(option_mask32 & FLAG_S)
+ ? !(max_fline > cur_fline + max_displayed_line)
+ : !(max_fline >= cur_fline
+ && max_lineno > LINENO(flines[cur_fline]) + max_displayed_line)
) {
- /* We are interested in stdin */
- rd = 0;
+ if (eof_error > 0) /* did NOT reach eof yet */
+ rd = 0; /* yes, we are interested in stdin */
}
- /* position cursor if line input is done */
+ /* Position cursor if line input is done */
if (less_gets_pos >= 0)
move_cursor(max_displayed_line + 2, less_gets_pos + 1);
fflush(stdout);
- safe_poll(pfd + rd, 2 - rd, -1);
- input[0] = '\0';
- rd = safe_read(kbd_fd, input, sz); /* NB: kbd_fd is in O_NONBLOCK mode */
- if (rd < 0 && errno == EAGAIN) {
- /* No keyboard input -> we have input on stdin! */
- read_lines();
- buffer_fill_and_print();
- goto again;
+ if (kbd_input_size == 0) {
+#if ENABLE_FEATURE_LESS_WINCH
+ while (1) {
+ int r;
+ /* NB: SIGWINCH interrupts poll() */
+ r = poll(pfd + rd, 2 - rd, -1);
+ if (/*r < 0 && errno == EINTR &&*/ winch_counter)
+ return '\\'; /* anything which has no defined function */
+ if (r) break;
+ }
+#else
+ safe_poll(pfd + rd, 2 - rd, -1);
+#endif
+ }
+
+ /* We have kbd_fd in O_NONBLOCK mode, read inside read_key()
+ * would not block even if there is no input available */
+ rd = read_key(kbd_fd, &kbd_input_size, kbd_input);
+ if (rd == -1) {
+ if (errno == EAGAIN) {
+ /* No keyboard input available. Since poll() did return,
+ * we should have input on stdin */
+ read_lines();
+ buffer_fill_and_print();
+ goto again;
+ }
+ /* EOF/error (ssh session got killed etc) */
+ less_exit(0);
}
set_tty_cooked();
return rd;
@@ -728,51 +877,29 @@ static ssize_t getch_nowait(char* input, int sz)
* special return codes. Note that this function works best with raw input. */
static int less_getch(int pos)
{
- unsigned char input[16];
- unsigned i;
+ int i;
again:
less_gets_pos = pos;
- memset(input, 0, sizeof(input));
- getch_nowait((char *)input, sizeof(input));
+ i = getch_nowait();
less_gets_pos = -1;
- /* Detect escape sequences (i.e. arrow keys) and handle
- * them accordingly */
- if (input[0] == '\033' && input[1] == '[') {
- i = input[2] - REAL_KEY_UP;
- if (i < 4)
- return 20 + i;
- i = input[2] - REAL_PAGE_UP;
- if (i < 4)
- return 24 + i;
- if (input[2] == REAL_KEY_HOME_XTERM)
- return KEY_HOME;
- if (input[2] == REAL_KEY_HOME_ALT)
- return KEY_HOME;
- if (input[2] == REAL_KEY_END_XTERM)
- return KEY_END;
- if (input[2] == REAL_KEY_END_ALT)
- return KEY_END;
- return 0;
- }
- /* Reject almost all control chars */
- i = input[0];
- if (i < ' ' && i != 0x0d && i != 8)
+ /* Discard Ctrl-something chars */
+ if (i >= 0 && i < ' ' && i != 0x0d && i != 8)
goto again;
return i;
}
static char* less_gets(int sz)
{
- char c;
+ int c;
unsigned i = 0;
char *result = xzalloc(1);
while (1) {
c = '\0';
less_gets_pos = sz + i;
- getch_nowait(&c, 1);
+ c = getch_nowait();
if (c == 0x0d) {
result[i] = '\0';
less_gets_pos = -1;
@@ -784,7 +911,7 @@ static char* less_gets(int sz)
printf("\x8 \x8");
i--;
}
- if (c < ' ')
+ if (c < ' ') /* filters out KEYCODE_xxx too (<0) */
continue;
if (i >= width - sz - 1)
continue; /* len limit */
@@ -965,7 +1092,8 @@ static void regex_process(void)
}
/* Compile the regex and check for errors */
- err = regcomp_or_errmsg(&pattern, uncomp_regex, 0);
+ err = regcomp_or_errmsg(&pattern, uncomp_regex,
+ (option_mask32 & FLAG_I) ? REG_ICASE : 0);
free(uncomp_regex);
if (err) {
print_statusline(err);
@@ -995,8 +1123,8 @@ static void number_process(int first_digit)
{
unsigned i;
int num;
+ int keypress;
char num_input[sizeof(int)*4]; /* more than enough */
- char keypress;
num_input[0] = first_digit;
@@ -1007,15 +1135,14 @@ static void number_process(int first_digit)
/* Receive input until a letter is given */
i = 1;
while (i < sizeof(num_input)-1) {
- num_input[i] = less_getch(i + 1);
- if (!num_input[i] || !isdigit(num_input[i]))
+ keypress = less_getch(i + 1);
+ if ((unsigned)keypress > 255 || !isdigit(num_input[i]))
break;
- bb_putchar(num_input[i]);
+ num_input[i] = keypress;
+ bb_putchar(keypress);
i++;
}
- /* Take the final letter out of the digits string */
- keypress = num_input[i];
num_input[i] = '\0';
num = bb_strtou(num_input, NULL, 10);
/* on format error, num == -1 */
@@ -1026,10 +1153,10 @@ static void number_process(int first_digit)
/* We now know the number and the letter entered, so we process them */
switch (keypress) {
- case KEY_DOWN: case 'z': case 'd': case 'e': case ' ': case '\015':
+ case KEYCODE_DOWN: case 'z': case 'd': case 'e': case ' ': case '\015':
buffer_down(num);
break;
- case KEY_UP: case 'b': case 'w': case 'y': case 'u':
+ case KEYCODE_UP: case 'b': case 'w': case 'y': case 'u':
buffer_up(num);
break;
case 'g': case '<': case 'G': case '>':
@@ -1059,7 +1186,7 @@ static void number_process(int first_digit)
}
}
-#if ENABLE_FEATURE_LESS_FLAGCS
+#if ENABLE_FEATURE_LESS_DASHCMD
static void flag_change(void)
{
int keypress;
@@ -1081,9 +1208,21 @@ static void flag_change(void)
case '~':
option_mask32 ^= FLAG_TILDE;
break;
+ case 'S':
+ option_mask32 ^= FLAG_S;
+ buffer_fill_and_print();
+ break;
+#if ENABLE_FEATURE_LESS_LINENUMS
+ case 'N':
+ option_mask32 ^= FLAG_N;
+ re_wrap();
+ buffer_fill_and_print();
+ break;
+#endif
}
}
+#ifdef BLOAT
static void show_flag_status(void)
{
int keypress;
@@ -1119,6 +1258,8 @@ static void show_flag_status(void)
}
#endif
+#endif /* ENABLE_FEATURE_LESS_DASHCMD */
+
static void save_input_to_file(void)
{
const char *msg = "";
@@ -1246,16 +1387,16 @@ static void match_left_bracket(char bracket)
static void keypress_process(int keypress)
{
switch (keypress) {
- case KEY_DOWN: case 'e': case 'j': case 0x0d:
+ case KEYCODE_DOWN: case 'e': case 'j': case 0x0d:
buffer_down(1);
break;
- case KEY_UP: case 'y': case 'k':
+ case KEYCODE_UP: case 'y': case 'k':
buffer_up(1);
break;
- case PAGE_DOWN: case ' ': case 'z': case 'f':
+ case KEYCODE_PAGEDOWN: case ' ': case 'z': case 'f':
buffer_down(max_displayed_line + 1);
break;
- case PAGE_UP: case 'w': case 'b':
+ case KEYCODE_PAGEUP: case 'w': case 'b':
buffer_up(max_displayed_line + 1);
break;
case 'd':
@@ -1264,10 +1405,10 @@ static void keypress_process(int keypress)
case 'u':
buffer_up((max_displayed_line + 1) / 2);
break;
- case KEY_HOME: case 'g': case 'p': case '<': case '%':
+ case KEYCODE_HOME: case 'g': case 'p': case '<': case '%':
buffer_line(0);
break;
- case KEY_END: case 'G': case '>':
+ case KEYCODE_END: case 'G': case '>':
cur_fline = MAXLINES;
read_lines();
buffer_line(cur_fline);
@@ -1318,15 +1459,17 @@ static void keypress_process(int keypress)
regex_process();
break;
#endif
-#if ENABLE_FEATURE_LESS_FLAGCS
+#if ENABLE_FEATURE_LESS_DASHCMD
case '-':
flag_change();
buffer_print();
break;
+#ifdef BLOAT
case '_':
show_flag_status();
break;
#endif
+#endif
#if ENABLE_FEATURE_LESS_BRACKETS
case '{': case '(': case '[':
match_right_bracket(keypress);
@@ -1349,6 +1492,13 @@ static void sig_catcher(int sig)
less_exit(- sig);
}
+#if ENABLE_FEATURE_LESS_WINCH
+static void sigwinch_handler(int sig UNUSED_PARAM)
+{
+ winch_counter++;
+}
+#endif
+
int less_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int less_main(int argc, char **argv)
{
@@ -1359,7 +1509,7 @@ int less_main(int argc, char **argv)
/* TODO: -x: do not interpret backspace, -xx: tab also */
/* -xxx: newline also */
/* -w N: assume width N (-xxx -w 32: hex viewer of sorts) */
- getopt32(argv, "EMmN~");
+ getopt32(argv, "EMmN~I" USE_FEATURE_LESS_DASHCMD("S"));
argc -= optind;
argv += optind;
num_files = argc;
@@ -1369,10 +1519,6 @@ int less_main(int argc, char **argv)
* is not a tty and turns into cat. This makes sense. */
if (!isatty(STDOUT_FILENO))
return bb_cat(argv);
- kbd_fd = open(CURRENT_TTY, O_RDONLY);
- if (kbd_fd < 0)
- return bb_cat(argv);
- ndelay_on(kbd_fd);
if (!num_files) {
if (isatty(STDIN_FILENO)) {
@@ -1380,19 +1526,18 @@ int less_main(int argc, char **argv)
bb_error_msg("missing filename");
bb_show_usage();
}
- } else
+ } else {
filename = xstrdup(files[0]);
+ }
- get_terminal_width_height(kbd_fd, &width, &max_displayed_line);
- /* 20: two tabstops + 4 */
- if (width < 20 || max_displayed_line < 3)
- return bb_cat(argv);
- max_displayed_line -= 2;
-
- buffer = xmalloc((max_displayed_line+1) * sizeof(char *));
if (option_mask32 & FLAG_TILDE)
empty_line_marker = "";
+ kbd_fd = open(CURRENT_TTY, O_RDONLY);
+ if (kbd_fd < 0)
+ return bb_cat(argv);
+ ndelay_on(kbd_fd);
+
tcgetattr(kbd_fd, &term_orig);
term_less = term_orig;
term_less.c_lflag &= ~(ICANON | ECHO);
@@ -1401,12 +1546,254 @@ int less_main(int argc, char **argv)
term_less.c_cc[VMIN] = 1;
term_less.c_cc[VTIME] = 0;
+ get_terminal_width_height(kbd_fd, &width, &max_displayed_line);
+ /* 20: two tabstops + 4 */
+ if (width < 20 || max_displayed_line < 3)
+ return bb_cat(argv);
+ max_displayed_line -= 2;
+
/* We want to restore term_orig on exit */
bb_signals(BB_FATAL_SIGS, sig_catcher);
+#if ENABLE_FEATURE_LESS_WINCH
+ signal(SIGWINCH, sigwinch_handler);
+#endif
+ buffer = xmalloc((max_displayed_line+1) * sizeof(char *));
reinitialize();
while (1) {
+#if ENABLE_FEATURE_LESS_WINCH
+ while (WINCH_COUNTER) {
+ again:
+ winch_counter--;
+ get_terminal_width_height(kbd_fd, &width, &max_displayed_line);
+ /* 20: two tabstops + 4 */
+ if (width < 20)
+ width = 20;
+ if (max_displayed_line < 3)
+ max_displayed_line = 3;
+ max_displayed_line -= 2;
+ free(buffer);
+ buffer = xmalloc((max_displayed_line+1) * sizeof(char *));
+ /* Avoid re-wrap and/or redraw if we already know
+ * we need to do it again. These ops are expensive */
+ if (WINCH_COUNTER)
+ goto again;
+ re_wrap();
+ if (WINCH_COUNTER)
+ goto again;
+ buffer_fill_and_print();
+ /* This took some time. Loop back and check,
+ * were there another SIGWINCH? */
+ }
+#endif
keypress = less_getch(-1); /* -1: do not position cursor */
keypress_process(keypress);
}
}
+
+/*
+Help text of less version 418 is below.
+If you are implementing something, keeping
+key and/or command line switch compatibility is a good idea:
+
+
+ SUMMARY OF LESS COMMANDS
+
+ Commands marked with * may be preceded by a number, N.
+ Notes in parentheses indicate the behavior if N is given.
+ h H Display this help.
+ q :q Q :Q ZZ Exit.
+ ---------------------------------------------------------------------------
+ MOVING
+ e ^E j ^N CR * Forward one line (or N lines).
+ y ^Y k ^K ^P * Backward one line (or N lines).
+ f ^F ^V SPACE * Forward one window (or N lines).
+ b ^B ESC-v * Backward one window (or N lines).
+ z * Forward one window (and set window to N).
+ w * Backward one window (and set window to N).
+ ESC-SPACE * Forward one window, but don't stop at end-of-file.
+ d ^D * Forward one half-window (and set half-window to N).
+ u ^U * Backward one half-window (and set half-window to N).
+ ESC-) RightArrow * Left one half screen width (or N positions).
+ ESC-( LeftArrow * Right one half screen width (or N positions).
+ F Forward forever; like "tail -f".
+ r ^R ^L Repaint screen.
+ R Repaint screen, discarding buffered input.
+ ---------------------------------------------------
+ Default "window" is the screen height.
+ Default "half-window" is half of the screen height.
+ ---------------------------------------------------------------------------
+ SEARCHING
+ /pattern * Search forward for (N-th) matching line.
+ ?pattern * Search backward for (N-th) matching line.
+ n * Repeat previous search (for N-th occurrence).
+ N * Repeat previous search in reverse direction.
+ ESC-n * Repeat previous search, spanning files.
+ ESC-N * Repeat previous search, reverse dir. & spanning files.
+ ESC-u Undo (toggle) search highlighting.
+ ---------------------------------------------------
+ Search patterns may be modified by one or more of:
+ ^N or ! Search for NON-matching lines.
+ ^E or * Search multiple files (pass thru END OF FILE).
+ ^F or @ Start search at FIRST file (for /) or last file (for ?).
+ ^K Highlight matches, but don't move (KEEP position).
+ ^R Don't use REGULAR EXPRESSIONS.
+ ---------------------------------------------------------------------------
+ JUMPING
+ g < ESC-< * Go to first line in file (or line N).
+ G > ESC-> * Go to last line in file (or line N).
+ p % * Go to beginning of file (or N percent into file).
+ t * Go to the (N-th) next tag.
+ T * Go to the (N-th) previous tag.
+ { ( [ * Find close bracket } ) ].
+ } ) ] * Find open bracket { ( [.
+ ESC-^F * Find close bracket .
+ ESC-^B * Find open bracket
+ ---------------------------------------------------
+ Each "find close bracket" command goes forward to the close bracket
+ matching the (N-th) open bracket in the top line.
+ Each "find open bracket" command goes backward to the open bracket
+ matching the (N-th) close bracket in the bottom line.
+ m Mark the current position with .
+ ' Go to a previously marked position.
+ '' Go to the previous position.
+ ^X^X Same as '.
+ ---------------------------------------------------
+ A mark is any upper-case or lower-case letter.
+ Certain marks are predefined:
+ ^ means beginning of the file
+ $ means end of the file
+ ---------------------------------------------------------------------------
+ CHANGING FILES
+ :e [file] Examine a new file.
+ ^X^V Same as :e.
+ :n * Examine the (N-th) next file from the command line.
+ :p * Examine the (N-th) previous file from the command line.
+ :x * Examine the first (or N-th) file from the command line.
+ :d Delete the current file from the command line list.
+ = ^G :f Print current file name.
+ ---------------------------------------------------------------------------
+ MISCELLANEOUS COMMANDS
+ - Toggle a command line option [see OPTIONS below].
+ -- Toggle a command line option, by name.
+ _ Display the setting of a command line option.
+ __ Display the setting of an option, by name.
+ +cmd Execute the less cmd each time a new file is examined.
+ !command Execute the shell command with $SHELL.
+ |Xcommand Pipe file between current pos & mark X to shell command.
+ v Edit the current file with $VISUAL or $EDITOR.
+ V Print version number of "less".
+ ---------------------------------------------------------------------------
+ OPTIONS
+ Most options may be changed either on the command line,
+ or from within less by using the - or -- command.
+ Options may be given in one of two forms: either a single
+ character preceded by a -, or a name preceeded by --.
+ -? ........ --help
+ Display help (from command line).
+ -a ........ --search-skip-screen
+ Forward search skips current screen.
+ -b [N] .... --buffers=[N]
+ Number of buffers.
+ -B ........ --auto-buffers
+ Don't automatically allocate buffers for pipes.
+ -c ........ --clear-screen
+ Repaint by clearing rather than scrolling.
+ -d ........ --dumb
+ Dumb terminal.
+ -D [xn.n] . --color=xn.n
+ Set screen colors. (MS-DOS only)
+ -e -E .... --quit-at-eof --QUIT-AT-EOF
+ Quit at end of file.
+ -f ........ --force
+ Force open non-regular files.
+ -F ........ --quit-if-one-screen
+ Quit if entire file fits on first screen.
+ -g ........ --hilite-search
+ Highlight only last match for searches.
+ -G ........ --HILITE-SEARCH
+ Don't highlight any matches for searches.
+ -h [N] .... --max-back-scroll=[N]
+ Backward scroll limit.
+ -i ........ --ignore-case
+ Ignore case in searches that do not contain uppercase.
+ -I ........ --IGNORE-CASE
+ Ignore case in all searches.
+ -j [N] .... --jump-target=[N]
+ Screen position of target lines.
+ -J ........ --status-column
+ Display a status column at left edge of screen.
+ -k [file] . --lesskey-file=[file]
+ Use a lesskey file.
+ -L ........ --no-lessopen
+ Ignore the LESSOPEN environment variable.
+ -m -M .... --long-prompt --LONG-PROMPT
+ Set prompt style.
+ -n -N .... --line-numbers --LINE-NUMBERS
+ Don't use line numbers.
+ -o [file] . --log-file=[file]
+ Copy to log file (standard input only).
+ -O [file] . --LOG-FILE=[file]
+ Copy to log file (unconditionally overwrite).
+ -p [pattern] --pattern=[pattern]
+ Start at pattern (from command line).
+ -P [prompt] --prompt=[prompt]
+ Define new prompt.
+ -q -Q .... --quiet --QUIET --silent --SILENT
+ Quiet the terminal bell.
+ -r -R .... --raw-control-chars --RAW-CONTROL-CHARS
+ Output "raw" control characters.
+ -s ........ --squeeze-blank-lines
+ Squeeze multiple blank lines.
+ -S ........ --chop-long-lines
+ Chop long lines.
+ -t [tag] .. --tag=[tag]
+ Find a tag.
+ -T [tagsfile] --tag-file=[tagsfile]
+ Use an alternate tags file.
+ -u -U .... --underline-special --UNDERLINE-SPECIAL
+ Change handling of backspaces.
+ -V ........ --version
+ Display the version number of "less".
+ -w ........ --hilite-unread
+ Highlight first new line after forward-screen.
+ -W ........ --HILITE-UNREAD
+ Highlight first new line after any forward movement.
+ -x [N[,...]] --tabs=[N[,...]]
+ Set tab stops.
+ -X ........ --no-init
+ Don't use termcap init/deinit strings.
+ --no-keypad
+ Don't use termcap keypad init/deinit strings.
+ -y [N] .... --max-forw-scroll=[N]
+ Forward scroll limit.
+ -z [N] .... --window=[N]
+ Set size of window.
+ -" [c[c]] . --quotes=[c[c]]
+ Set shell quote characters.
+ -~ ........ --tilde
+ Don't display tildes after end of file.
+ -# [N] .... --shift=[N]
+ Horizontal scroll amount (0 = one half screen width)
+
+ ---------------------------------------------------------------------------
+ LINE EDITING
+ These keys can be used to edit text being entered
+ on the "command line" at the bottom of the screen.
+ RightArrow ESC-l Move cursor right one character.
+ LeftArrow ESC-h Move cursor left one character.
+ CNTL-RightArrow ESC-RightArrow ESC-w Move cursor right one word.
+ CNTL-LeftArrow ESC-LeftArrow ESC-b Move cursor left one word.
+ HOME ESC-0 Move cursor to start of line.
+ END ESC-$ Move cursor to end of line.
+ BACKSPACE Delete char to left of cursor.
+ DELETE ESC-x Delete char under cursor.
+ CNTL-BACKSPACE ESC-BACKSPACE Delete word to left of cursor.
+ CNTL-DELETE ESC-DELETE ESC-X Delete word under cursor.
+ CNTL-U ESC (MS-DOS only) Delete entire line.
+ UpArrow ESC-k Retrieve previous command line.
+ DownArrow ESC-j Retrieve next command line.
+ TAB Complete filename & cycle.
+ SHIFT-TAB ESC-TAB Complete filename & reverse cycle.
+ CNTL-L Complete filename, list all.
+*/
diff --git a/release/src/router/busybox/miscutils/man.c b/release/src/router/busybox/miscutils/man.c
index e6824ebc86..672ddb1c8e 100644
--- a/release/src/router/busybox/miscutils/man.c
+++ b/release/src/router/busybox/miscutils/man.c
@@ -168,10 +168,12 @@ int man_main(int argc UNUSED_PARAM, char **argv)
sec_list = xstrdup("1:2:3:4:5:6:7:8:9");
/* Last valid man_path_list[] is [0x10] */
- man_path_list = xzalloc(0x11 * sizeof(man_path_list[0]));
count_mp = 0;
- man_path_list[0] = xstrdup(getenv("MANPATH"));
- if (man_path_list[0])
+ man_path_list = xzalloc(0x11 * sizeof(man_path_list[0]));
+ man_path_list[0] = getenv("MANPATH");
+ if (!man_path_list[0]) /* default, may be overridden by /etc/man.conf */
+ man_path_list[0] = (char*)"/usr/man";
+ else
count_mp++;
pager = getenv("MANPAGER");
if (!pager) {
@@ -181,16 +183,40 @@ int man_main(int argc UNUSED_PARAM, char **argv)
}
/* Parse man.conf */
- parser = config_open("/etc/man.conf");
+ parser = config_open2("/etc/man.conf", fopen_for_read);
while (config_read(parser, token, 2, 0, "# \t", PARSE_NORMAL)) {
if (!token[1])
continue;
if (strcmp("MANPATH", token[0]) == 0) {
- man_path_list = xrealloc_vector(man_path_list, 4, count_mp);
- man_path_list[count_mp] = xstrdup(token[1]);
- count_mp++;
- /* man_path_list is NULL terminated */
- /*man_path_list[count_mp] = NULL; - xrealloc_vector did it */
+ char *path = token[1];
+ while (*path) {
+ char *next_path;
+ char **path_element;
+
+ next_path = strchr(path, ':');
+ if (next_path) {
+ *next_path = '\0';
+ if (next_path++ == path) /* "::"? */
+ goto next;
+ }
+ /* Do we already have path? */
+ path_element = man_path_list;
+ while (*path_element) {
+ if (strcmp(*path_element, path) == 0)
+ goto skip;
+ path_element++;
+ }
+ man_path_list = xrealloc_vector(man_path_list, 4, count_mp);
+ man_path_list[count_mp] = xstrdup(path);
+ count_mp++;
+ /* man_path_list is NULL terminated */
+ /*man_path_list[count_mp] = NULL; - xrealloc_vector did it */
+ skip:
+ if (!next_path)
+ break;
+ next:
+ path = next_path;
+ }
}
if (strcmp("MANSECT", token[0]) == 0) {
free(sec_list);
@@ -210,41 +236,34 @@ int man_main(int argc UNUSED_PARAM, char **argv)
}
while ((cur_path = man_path_list[cur_mp++]) != NULL) {
/* for each MANPATH */
- do { /* for each MANPATH item */
- char *next_path = strchrnul(cur_path, ':');
- int path_len = next_path - cur_path;
- cur_sect = sec_list;
- do { /* for each section */
- char *next_sect = strchrnul(cur_sect, ':');
- int sect_len = next_sect - cur_sect;
- char *man_filename;
- int cat0man1 = 0;
-
- /* Search for cat, then man page */
- while (cat0man1 < 2) {
- int found_here;
- man_filename = xasprintf("%.*s/%s%.*s/%s.%.*s" Z_SUFFIX,
- path_len, cur_path,
- "cat\0man" + (cat0man1 * 4),
- sect_len, cur_sect,
- *argv,
- sect_len, cur_sect);
- found_here = show_manpage(pager, man_filename, cat0man1, 0);
- found |= found_here;
- cat0man1 += found_here + 1;
- free(man_filename);
- }
-
- if (found && !(opt & OPT_a))
- goto next_arg;
- cur_sect = next_sect;
- while (*cur_sect == ':')
- cur_sect++;
- } while (*cur_sect);
- cur_path = next_path;
- while (*cur_path == ':')
- cur_path++;
- } while (*cur_path);
+ cur_sect = sec_list;
+ do { /* for each section */
+ char *next_sect = strchrnul(cur_sect, ':');
+ int sect_len = next_sect - cur_sect;
+ char *man_filename;
+ int cat0man1 = 0;
+
+ /* Search for cat, then man page */
+ while (cat0man1 < 2) {
+ int found_here;
+ man_filename = xasprintf("%s/%s%.*s/%s.%.*s" Z_SUFFIX,
+ cur_path,
+ "cat\0man" + (cat0man1 * 4),
+ sect_len, cur_sect,
+ *argv,
+ sect_len, cur_sect);
+ found_here = show_manpage(pager, man_filename, cat0man1, 0);
+ found |= found_here;
+ cat0man1 += found_here + 1;
+ free(man_filename);
+ }
+
+ if (found && !(opt & OPT_a))
+ goto next_arg;
+ cur_sect = next_sect;
+ while (*cur_sect == ':')
+ cur_sect++;
+ } while (*cur_sect);
}
check_found:
if (!found) {
diff --git a/release/src/router/busybox/miscutils/microcom.c b/release/src/router/busybox/miscutils/microcom.c
index ac3e5514f3..a322197b83 100644
--- a/release/src/router/busybox/miscutils/microcom.c
+++ b/release/src/router/busybox/miscutils/microcom.c
@@ -9,14 +9,6 @@
*/
#include "libbb.h"
-/* All known arches use small ints for signals */
-static volatile smallint signalled;
-
-static void signal_handler(int signo)
-{
- signalled = signo;
-}
-
// set raw tty mode
static void xget1(int fd, struct termios *t, struct termios *oldt)
{
@@ -91,10 +83,10 @@ int microcom_main(int argc UNUSED_PARAM, char **argv)
+ (1 << SIGINT)
+ (1 << SIGTERM)
+ (1 << SIGPIPE)
- , signal_handler);
+ , record_signo);
// error exit code if we fail to open the device
- signalled = 1;
+ bb_got_signal = 1;
// open device
sfd = open_or_warn(argv[0], O_RDWR | O_NOCTTY | O_NONBLOCK);
@@ -123,9 +115,9 @@ int microcom_main(int argc UNUSED_PARAM, char **argv)
pfd[1].fd = STDIN_FILENO;
pfd[1].events = POLLIN;
- signalled = 0;
+ bb_got_signal = 0;
nfd = 2;
- while (!signalled && safe_poll(pfd, nfd, timeout) > 0) {
+ while (!bb_got_signal && safe_poll(pfd, nfd, timeout) > 0) {
if (nfd > 1 && pfd[1].revents) {
char c;
// read from stdin -> write to device
@@ -159,7 +151,7 @@ skip_write: ;
full_write(STDOUT_FILENO, iobuf, len);
else {
// EOF/error -> bail out
- signalled = SIGHUP;
+ bb_got_signal = SIGHUP;
break;
}
}
@@ -175,5 +167,5 @@ done:
if (device_lock_file)
unlink(device_lock_file);
- return signalled;
+ return bb_got_signal;
}
diff --git a/release/src/router/busybox/miscutils/mountpoint.c b/release/src/router/busybox/miscutils/mountpoint.c
dissimilarity index 71%
index 5647e4c5b2..b541ce28c3 100644
--- a/release/src/router/busybox/miscutils/mountpoint.c
+++ b/release/src/router/busybox/miscutils/mountpoint.c
@@ -1,66 +1,72 @@
-/* vi: set sw=4 ts=4: */
-/*
- * mountpoint implementation for busybox
- *
- * Copyright (C) 2005 Bernhard Fischer
- *
- * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
- *
- * Based on sysvinit's mountpoint
- */
-
-#include "libbb.h"
-
-int mountpoint_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int mountpoint_main(int argc, char **argv)
-{
- struct stat st;
- char *arg;
- int opt = getopt32(argv, "qdx");
-#define OPT_q (1)
-#define OPT_d (2)
-#define OPT_x (4)
-
- if (optind != argc - 1)
- bb_show_usage();
-
- arg = argv[optind];
-
- if ( (opt & OPT_x && stat(arg, &st) == 0) || (lstat(arg, &st) == 0) ) {
- if (opt & OPT_x) {
- if (S_ISBLK(st.st_mode)) {
- printf("%u:%u\n", major(st.st_rdev),
- minor(st.st_rdev));
- return EXIT_SUCCESS;
- } else {
- if (opt & OPT_q)
- bb_putchar('\n');
- else
- bb_error_msg("%s: not a block device", arg);
- }
- return EXIT_FAILURE;
- } else
- if (S_ISDIR(st.st_mode)) {
- dev_t st_dev = st.st_dev;
- ino_t st_ino = st.st_ino;
- char *p = xasprintf("%s/..", arg);
-
- if (stat(p, &st) == 0) {
- int ret = (st_dev != st.st_dev) ||
- (st_dev == st.st_dev && st_ino == st.st_ino);
- if (opt & OPT_d)
- printf("%u:%u\n", major(st_dev), minor(st_dev));
- else if (!(opt & OPT_q))
- printf("%s is %sa mountpoint\n", arg, ret?"":"not ");
- return !ret;
- }
- } else {
- if (!(opt & OPT_q))
- bb_error_msg("%s: not a directory", arg);
- return EXIT_FAILURE;
- }
- }
- if (!(opt & OPT_q))
- bb_simple_perror_msg(arg);
- return EXIT_FAILURE;
-}
+/* vi: set sw=4 ts=4: */
+/*
+ * mountpoint implementation for busybox
+ *
+ * Copyright (C) 2005 Bernhard Reutner-Fischer
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ *
+ * Based on sysvinit's mountpoint
+ */
+
+#include "libbb.h"
+
+int mountpoint_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int mountpoint_main(int argc UNUSED_PARAM, char **argv)
+{
+ struct stat st;
+ const char *msg;
+ char *arg;
+ int rc, opt;
+
+ opt_complementary = "=1"; /* must have one argument */
+ opt = getopt32(argv, "qdxn");
+#define OPT_q (1)
+#define OPT_d (2)
+#define OPT_x (4)
+#define OPT_n (8)
+ arg = argv[optind];
+ msg = "%s";
+
+ rc = (opt & OPT_x) ? stat(arg, &st) : lstat(arg, &st);
+ if (rc != 0)
+ goto err;
+
+ if (opt & OPT_x) {
+ if (S_ISBLK(st.st_mode)) {
+ printf("%u:%u\n", major(st.st_rdev),
+ minor(st.st_rdev));
+ return EXIT_SUCCESS;
+ }
+ errno = 0; /* make perror_msg work as error_msg */
+ msg = "%s: not a block device";
+ goto err;
+ }
+
+ errno = ENOTDIR;
+ if (S_ISDIR(st.st_mode)) {
+ dev_t st_dev = st.st_dev;
+ ino_t st_ino = st.st_ino;
+ char *p = xasprintf("%s/..", arg);
+
+ if (stat(p, &st) == 0) {
+ //int is_mnt = (st_dev != st.st_dev) || (st_dev == st.st_dev && st_ino == st.st_ino);
+ int is_not_mnt = (st_dev == st.st_dev) && (st_ino != st.st_ino);
+
+ if (opt & OPT_d)
+ printf("%u:%u\n", major(st_dev), minor(st_dev));
+ if (opt & OPT_n)
+ printf("%s %s\n", find_block_device(arg), arg);
+ if (!(opt & (OPT_q | OPT_d | OPT_n)))
+ printf("%s is %sa mountpoint\n", arg, is_not_mnt ? "not " : "");
+ return is_not_mnt;
+ }
+ arg = p;
+ /* else: stat had set errno, just fall through */
+ }
+
+ err:
+ if (!(opt & OPT_q))
+ bb_perror_msg(msg, arg);
+ return EXIT_FAILURE;
+}
diff --git a/release/src/router/busybox/miscutils/raidautorun.c b/release/src/router/busybox/miscutils/raidautorun.c
index 2766245dba..a2a852bbf2 100644
--- a/release/src/router/busybox/miscutils/raidautorun.c
+++ b/release/src/router/busybox/miscutils/raidautorun.c
@@ -2,7 +2,7 @@
/*
* raidautorun implementation for busybox
*
- * Copyright (C) 2006 Bernhard Fischer
+ * Copyright (C) 2006 Bernhard Reutner-Fischer
*
* Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
*
diff --git a/release/src/router/busybox/miscutils/runlevel.c b/release/src/router/busybox/miscutils/runlevel.c
index 04064ee73d..6e10d9cbb1 100644
--- a/release/src/router/busybox/miscutils/runlevel.c
+++ b/release/src/router/busybox/miscutils/runlevel.c
@@ -9,7 +9,7 @@
*
* Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
*
- * initially busyboxified by Bernhard Fischer
+ * initially busyboxified by Bernhard Reutner-Fischer
*/
#include
diff --git a/release/src/router/busybox/miscutils/setsid.c b/release/src/router/busybox/miscutils/setsid.c
index 127adf6f28..d7de1f1497 100644
--- a/release/src/router/busybox/miscutils/setsid.c
+++ b/release/src/router/busybox/miscutils/setsid.c
@@ -26,7 +26,8 @@ int setsid_main(int argc UNUSED_PARAM, char **argv)
* Otherwise our PID serves as PGID of some existing process group
* and cannot be used as PGID of a new process group. */
if (getpgrp() == getpid())
- forkexit_or_rexec(argv);
+ if (fork_or_rexec(argv))
+ exit(EXIT_SUCCESS); /* parent */
setsid(); /* no error possible */
diff --git a/release/src/router/busybox/miscutils/strings.c b/release/src/router/busybox/miscutils/strings.c
index 3e02b53afd..fea9edbed5 100644
--- a/release/src/router/busybox/miscutils/strings.c
+++ b/release/src/router/busybox/miscutils/strings.c
@@ -2,7 +2,7 @@
/*
* strings implementation for busybox
*
- * Copyright Tito Ragusa
+ * Copyright 2003 Tito Ragusa
*
* Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
*/
@@ -18,7 +18,6 @@ int strings_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int strings_main(int argc UNUSED_PARAM, char **argv)
{
int n, c, status = EXIT_SUCCESS;
- unsigned opt;
unsigned count;
off_t offset;
FILE *file;
@@ -26,7 +25,7 @@ int strings_main(int argc UNUSED_PARAM, char **argv)
const char *fmt = "%s: ";
const char *n_arg = "4";
- opt = getopt32(argv, "afon:", &n_arg);
+ getopt32(argv, "afon:", &n_arg);
/* -a is our default behaviour */
/*argc -= optind;*/
argv += optind;
@@ -56,10 +55,10 @@ int strings_main(int argc UNUSED_PARAM, char **argv)
} else {
string[count] = c;
if (count == n) {
- if (opt & PRINT_NAME) {
+ if (option_mask32 & PRINT_NAME) {
printf(fmt, *argv);
}
- if (opt & PRINT_OFFSET) {
+ if (option_mask32 & PRINT_OFFSET) {
printf("%7"OFF_FMT"o ", offset - n);
}
fputs(string, stdout);
diff --git a/release/src/router/busybox/miscutils/taskset.c b/release/src/router/busybox/miscutils/taskset.c
index b43d42e905..a0bbf0aa19 100644
--- a/release/src/router/busybox/miscutils/taskset.c
+++ b/release/src/router/busybox/miscutils/taskset.c
@@ -1,7 +1,7 @@
/* vi: set sw=4 ts=4: */
/*
* taskset - retrieve or set a processes' CPU affinity
- * Copyright (c) 2006 Bernhard Fischer
+ * Copyright (c) 2006 Bernhard Reutner-Fischer
*
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
diff --git a/release/src/router/busybox/miscutils/time.c b/release/src/router/busybox/miscutils/time.c
index dbc92d12ff..30298fe324 100644
--- a/release/src/router/busybox/miscutils/time.c
+++ b/release/src/router/busybox/miscutils/time.c
@@ -89,7 +89,7 @@ static void printargv(char *const *argv)
This is funky since the pagesize could be less than 1K.
Note: Some machines express getrusage statistics in terms of K,
others in terms of pages. */
-static unsigned long ptok(unsigned pagesize, unsigned long pages)
+static unsigned long ptok(const unsigned pagesize, const unsigned long pages)
{
unsigned long tmp;
@@ -303,7 +303,7 @@ static void summarize(const char *fmt, char **command, resource_t *resp)
printf("%lu", ptok(pagesize, (UL) resp->ru.ru_ixrss) / cpu_ticks);
break;
case 'Z': /* Page size. */
- printf("%u", getpagesize());
+ printf("%u", pagesize);
break;
case 'c': /* Involuntary context switches. */
printf("%lu", resp->ru.ru_nivcsw);
diff --git a/release/src/router/busybox/miscutils/timeout.c b/release/src/router/busybox/miscutils/timeout.c
new file mode 100644
index 0000000000..83ae56e69e
--- /dev/null
+++ b/release/src/router/busybox/miscutils/timeout.c
@@ -0,0 +1,115 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * COPYING NOTES
+ *
+ * timeout.c -- a timeout handler for shell commands
+ *
+ * Copyright (C) 2005-6, Roberto A. Foglietta
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * REVISION NOTES:
+ * released 17-11-2005 by Roberto A. Foglietta
+ * talarm 04-12-2005 by Roberto A. Foglietta
+ * modified 05-12-2005 by Roberto A. Foglietta
+ * sizerdct 06-12-2005 by Roberto A. Foglietta
+ * splitszf 12-05-2006 by Roberto A. Foglietta
+ * rewrite 14-11-2008 vda
+ */
+
+#include "libbb.h"
+
+int timeout_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int timeout_main(int argc UNUSED_PARAM, char **argv)
+{
+ int signo;
+ int status;
+ int parent = 0;
+ int timeout = 10;
+ pid_t pid;
+#if !BB_MMU
+ char *sv1, *sv2;
+#endif
+ const char *opt_s = "TERM";
+
+ /* -p option is not documented, it is needed to support NOMMU. */
+
+ /* -t SECONDS; -p PARENT_PID */
+ opt_complementary = "t+" USE_FOR_NOMMU(":p+");
+ /* '+': stop at first non-option */
+ getopt32(argv, "+s:t:" USE_FOR_NOMMU("p:"), &opt_s, &timeout, &parent);
+ /*argv += optind; - no, wait for bb_daemonize_or_rexec! */
+ signo = get_signum(opt_s);
+ if (signo < 0)
+ bb_error_msg_and_die("unknown signal '%s'", opt_s);
+
+ /* We want to create a grandchild which will watch
+ * and kill the grandparent. Other methods:
+ * making parent watch child disrupts parent<->child link
+ * (example: "tcpsvd 0.0.0.0 1234 timeout service_prog" -
+ * it's better if service_prog is a child of tcpsvd!),
+ * making child watch parent results in programs having
+ * unexpected children. */
+
+ if (parent) /* we were re-execed, already grandchild */
+ goto grandchild;
+ if (!argv[optind]) /* no PROG? */
+ bb_show_usage();
+
+#if !BB_MMU
+ sv1 = argv[optind];
+ sv2 = argv[optind + 1];
+#endif
+ pid = vfork();
+ if (pid < 0)
+ bb_perror_msg_and_die("vfork");
+ if (pid == 0) {
+ /* Child: spawn grandchild and exit */
+ parent = getppid();
+#if !BB_MMU
+ argv[optind] = xasprintf("-p%u", parent);
+ argv[optind + 1] = NULL;
+#endif
+ /* NB: exits with nonzero on error: */
+ bb_daemonize_or_rexec(0, argv);
+ /* Here we are grandchild. Sleep, then kill grandparent */
+ grandchild:
+ /* Just sleep(NUGE_NUM); kill(parent) may kill wrong process! */
+ while (1) {
+ sleep(1);
+ if (--timeout <= 0)
+ break;
+ if (kill(parent, 0)) {
+ /* process is gone */
+ return EXIT_SUCCESS;
+ }
+ }
+ kill(parent, signo);
+ return EXIT_SUCCESS;
+ }
+
+ /* Parent */
+ wait(&status); /* wait for child to die */
+ /* Did intermediate [v]fork or exec fail? */
+ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
+ return EXIT_FAILURE;
+ /* Ok, exec a program as requested */
+ argv += optind;
+#if !BB_MMU
+ argv[0] = sv1;
+ argv[1] = sv2;
+#endif
+ BB_EXECVP(argv[0], argv);
+ bb_perror_msg_and_die("exec '%s'", argv[0]);
+}
diff --git a/release/src/router/busybox/miscutils/watchdog.c b/release/src/router/busybox/miscutils/watchdog.c
index 9b1a110eac..f85138e119 100644
--- a/release/src/router/busybox/miscutils/watchdog.c
+++ b/release/src/router/busybox/miscutils/watchdog.c
@@ -3,15 +3,19 @@
* Mini watchdog implementation for busybox
*
* Copyright (C) 2003 Paul Mundt
- * Copyright (C) 2006 Bernhard Fischer
+ * Copyright (C) 2006 Bernhard Reutner-Fischer
+ * Copyright (C) 2008 Darius Augulis
*
* Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
*/
#include "libbb.h"
+#include "linux/types.h" /* for __u32 */
+#include "linux/watchdog.h"
-#define OPT_FOREGROUND 0x01
-#define OPT_TIMER 0x02
+#define OPT_FOREGROUND (1 << 0)
+#define OPT_STIMER (1 << 1)
+#define OPT_HTIMER (1 << 2)
static void watchdog_shutdown(int sig UNUSED_PARAM)
{
@@ -26,46 +30,56 @@ static void watchdog_shutdown(int sig UNUSED_PARAM)
int watchdog_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int watchdog_main(int argc, char **argv)
{
- unsigned opts;
- unsigned timer_duration = 30000; /* Userspace timer duration, in milliseconds */
- char *t_arg;
+ static const struct suffix_mult suffixes[] = {
+ { "ms", 1 },
+ { "", 1000 },
+ { }
+ };
- opt_complementary = "=1"; /* must have 1 argument */
- opts = getopt32(argv, "Ft:", &t_arg);
+ unsigned opts;
+ unsigned stimer_duration; /* how often to restart */
+ unsigned htimer_duration = 60000; /* reboots after N ms if not restarted */
+ char *st_arg;
+ char *ht_arg;
- if (opts & OPT_TIMER) {
- static const struct suffix_mult suffixes[] = {
- { "ms", 1 },
- { "", 1000 },
- { }
- };
- timer_duration = xatou_sfx(t_arg, suffixes);
- }
+ opt_complementary = "=1"; /* must have exactly 1 argument */
+ opts = getopt32(argv, "Ft:T:", &st_arg, &ht_arg);
- if (!(opts & OPT_FOREGROUND)) {
- bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv);
- }
+ if (opts & OPT_HTIMER)
+ htimer_duration = xatou_sfx(ht_arg, suffixes);
+ stimer_duration = htimer_duration / 2;
+ if (opts & OPT_STIMER)
+ stimer_duration = xatou_sfx(st_arg, suffixes);
bb_signals(BB_FATAL_SIGS, watchdog_shutdown);
/* Use known fd # - avoid needing global 'int fd' */
xmove_fd(xopen(argv[argc - 1], O_WRONLY), 3);
-// TODO?
-// if (!(opts & OPT_TIMER)) {
-// if (ioctl(fd, WDIOC_GETTIMEOUT, &timer_duration) == 0)
-// timer_duration *= 500;
-// else
-// timer_duration = 30000;
-// }
+ /* WDIOC_SETTIMEOUT takes seconds, not milliseconds */
+ htimer_duration = htimer_duration / 1000;
+#ifndef WDIOC_SETTIMEOUT
+#error WDIOC_SETTIMEOUT is not defined, cannot compile watchdog applet
+#else
+ ioctl_or_warn(3, WDIOC_SETTIMEOUT, &htimer_duration);
+#endif
+#if 0
+ ioctl_or_warn(3, WDIOC_GETTIMEOUT, &htimer_duration);
+ printf("watchdog: SW timer is %dms, HW timer is %dms\n",
+ stimer_duration, htimer_duration * 1000);
+#endif
+
+ if (!(opts & OPT_FOREGROUND)) {
+ bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv);
+ }
while (1) {
/*
- * Make sure we clear the counter before sleeping, as the counter value
- * is undefined at this point -- PFM
+ * Make sure we clear the counter before sleeping,
+ * as the counter value is undefined at this point -- PFM
*/
write(3, "", 1); /* write zero byte */
- usleep(timer_duration * 1000L);
+ usleep(stimer_duration * 1000L);
}
return EXIT_SUCCESS; /* - not reached, but gcc 4.2.1 is too dumb! */
}
diff --git a/release/src/router/busybox/modutils/Config.in b/release/src/router/busybox/modutils/Config.in
index a430fcac33..ef8d9692a3 100644
--- a/release/src/router/busybox/modutils/Config.in
+++ b/release/src/router/busybox/modutils/Config.in
@@ -44,7 +44,6 @@ config FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE
depends on MODPROBE_SMALL
help
Allow insmod and modprobe take module options from command line.
- N.B. Very bloaty.
config FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED
bool "Skip loading of already loaded modules"
@@ -52,50 +51,81 @@ config FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED
depends on MODPROBE_SMALL
help
Check if the module is already loaded.
- N.B. It's racy.
-config DEPMOD
- bool "depmod"
+config INSMOD
+ bool "insmod"
default n
depends on !MODPROBE_SMALL
help
- depmod generates modules.dep (FIXME: elaborate)
+ insmod is used to load specified modules in the running kernel.
-config FEATURE_DEPMOD_PRUNE_FANCY
- bool "Fancy dependency pruning"
+config RMMOD
+ bool "rmmod"
default n
- depends on DEPMOD
+ depends on !MODPROBE_SMALL
help
- By default modules.dep contains all dependencies as listed by
- the modules.
- If you enable this option then we remove implied modules from
- the dependencies.
- This makes depmod somewhat bigger but generates a smaller
- modules.dep file.
+ rmmod is used to unload specified modules from the kernel.
- If unsure, say N.
+config LSMOD
+ bool "lsmod"
+ default n
+ depends on !MODPROBE_SMALL
+ help
+ lsmod is used to display a list of loaded modules.
-config FEATURE_DEPMOD_ALIAS
- bool "Alias support"
+config FEATURE_LSMOD_PRETTY_2_6_OUTPUT
+ bool "Pretty output"
default n
- depends on DEPMOD
+ depends on LSMOD
help
- By default modules.dep does not contain alias information.
- Enable this to emit aliases of the form:
+ This option makes output format of lsmod adjusted to
+ the format of module-init-tools for Linux kernel 2.6.
+ Increases size somewhat.
- alias pcmcia:m*c*f03fn*pfn*pa*pb*pc*pd* parport_cs
+config MODPROBE
+ bool "modprobe"
+ default n
+ depends on !MODPROBE_SMALL
+ help
+ Handle the loading of modules, and their dependencies on a high
+ level.
-config INSMOD
- bool "insmod"
+config FEATURE_MODPROBE_BLACKLIST
+ bool
+ prompt "Blacklist support"
+ default n
+ depends on MODPROBE
+ help
+ Say 'y' here to enable support for the 'blacklist' command in
+ modprobe.conf. This prevents the alias resolver to resolve
+ blacklisted modules. This is useful if you want to prevent your
+ hardware autodetection scripts to load modules like evdev, frame
+ buffer drivers etc.
+
+config DEPMOD
+ bool "depmod"
default n
depends on !MODPROBE_SMALL
help
- insmod is used to load specified modules in the running kernel.
+ depmod generates modules.dep (and potentially modules.alias
+ and modules.symbols) that contain dependency information
+ for modprobe.
+
+comment "Options common to multiple modutils"
+
+config FEATURE_2_4_MODULES
+ bool "Support version 2.2/2.4 Linux kernels"
+ default n
+ depends on INSMOD || RMMOD || LSMOD
+ help
+ Support module loading for 2.2.x and 2.4.x Linux kernels.
+ This increases size considerably. Say N unless you plan
+ to run ancient kernels.
config FEATURE_INSMOD_VERSION_CHECKING
- bool "Module version checking"
+ bool "Enable module version checking"
default n
- depends on INSMOD && FEATURE_2_4_MODULES
+ depends on FEATURE_2_4_MODULES && (INSMOD || MODPROBE)
help
Support checking of versions for modules. This is used to
ensure that the kernel and module are made for each other.
@@ -103,18 +133,18 @@ config FEATURE_INSMOD_VERSION_CHECKING
config FEATURE_INSMOD_KSYMOOPS_SYMBOLS
bool "Add module symbols to kernel symbol table"
default n
- depends on INSMOD && FEATURE_2_4_MODULES
+ depends on FEATURE_2_4_MODULES && (INSMOD || MODPROBE)
help
By adding module symbols to the kernel symbol table, Oops messages
occuring within kernel modules can be properly debugged. By enabling
this feature, module symbols will always be added to the kernel symbol
- table for properly debugging support. If you are not interested in
+ table for proper debugging support. If you are not interested in
Oops messages from kernel modules, say N.
config FEATURE_INSMOD_LOADINKMEM
bool "In kernel memory optimization (uClinux only)"
default n
- depends on INSMOD && FEATURE_2_4_MODULES
+ depends on FEATURE_2_4_MODULES && (INSMOD || MODPROBE)
help
This is a special uClinux only memory optimization that lets insmod
load the specified kernel module directly into kernel space, reducing
@@ -122,9 +152,9 @@ config FEATURE_INSMOD_LOADINKMEM
being loaded into memory.
config FEATURE_INSMOD_LOAD_MAP
- bool "Enable load map (-m) option"
+ bool "Enable insmod load map (-m) option"
default n
- depends on INSMOD && ( FEATURE_2_4_MODULES || FEATURE_2_6_MODULES )
+ depends on FEATURE_2_4_MODULES && INSMOD
help
Enabling this, one would be able to get a load map
output on stdout. This makes kernel module debugging
@@ -135,138 +165,63 @@ config FEATURE_INSMOD_LOAD_MAP
config FEATURE_INSMOD_LOAD_MAP_FULL
bool "Symbols in load map"
default y
- depends on FEATURE_INSMOD_LOAD_MAP
+ depends on FEATURE_INSMOD_LOAD_MAP && !MODPROBE_SMALL
help
Without this option, -m will only output section
load map. With this option, -m will also output
symbols load map.
-config RMMOD
- bool "rmmod"
- default n
- depends on !MODPROBE_SMALL
- help
- rmmod is used to unload specified modules from the kernel.
-
-config LSMOD
- bool "lsmod"
- default n
- depends on !MODPROBE_SMALL
- help
- lsmod is used to display a list of loaded modules.
-
-config FEATURE_LSMOD_PRETTY_2_6_OUTPUT
- bool "Pretty output for 2.6.x Linux kernels"
- default n
- depends on LSMOD
- help
- This option makes output format of lsmod adjusted to
- the format of module-init-tools for Linux kernel 2.6.
-
-config MODPROBE
- bool "modprobe"
- default n
- depends on !MODPROBE_SMALL
- help
- Handle the loading of modules, and their dependencies on a high
- level.
-
- Note that in the state, modprobe does not understand multiple
- module options from the configuration file. See option below.
-
-config FEATURE_MODPROBE_MULTIPLE_OPTIONS
- bool
- prompt "Multiple options parsing"
- default y
- depends on MODPROBE
- help
- Allow modprobe to understand more than one option to pass to
- modules.
-
- This is a WIP, while waiting for a common argument parsing
- common amongst all BB applets (shell, modprobe, etc...) and
- adds around 600 bytes on x86, 700 bytes on ARM. The code is
- biggish and uggly, but just works.
-
- Saying Y here is not a bad idea if you're not that short
- on storage capacity.
-
-config FEATURE_MODPROBE_FANCY_ALIAS
- bool
- prompt "Fancy alias parsing"
- default y
- depends on MODPROBE && FEATURE_2_6_MODULES
- help
- Say 'y' here to enable parsing of aliases with underscore/dash
- mismatch between module name and file name, along with bus-specific
- aliases (such as pci:... or usb:... aliases).
-
-config FEATURE_MODPROBE_BLACKLIST
- bool
- prompt "Blacklist support"
- default n
- depends on MODPROBE && FEATURE_2_6_MODULES
- help
- Say 'y' here to enable support for the 'blacklist' command in
- modprobe.conf. This prevents the alias resolver to resolve
- blacklisted modules. This is useful if you want to prevent your
- hardware autodetection scripts to load modules like evdev, frame
- buffer drivers etc.
-
-comment "Options common to multiple modutils"
- depends on INSMOD || RMMOD || MODPROBE || LSMOD || DEPMOD
-
config FEATURE_CHECK_TAINTED_MODULE
- # Simulate indentation
bool "Support tainted module checking with new kernels"
default y
- depends on INSMOD || LSMOD
+ depends on (LSMOD || FEATURE_2_4_MODULES) && !MODPROBE_SMALL
help
Support checking for tainted modules. These are usually binary
only modules that will make the linux-kernel list ignore your
support request.
This option is required to support GPLONLY modules.
-config FEATURE_2_4_MODULES
- # Simulate indentation
- bool "Support version 2.2.x to 2.4.x Linux kernels"
+config FEATURE_MODUTILS_ALIAS
+ bool "Support for module.aliases file"
default y
- depends on INSMOD || RMMOD || MODPROBE
+ depends on DEPMOD || MODPROBE
help
- Support module loading for 2.2.x and 2.4.x Linux kernels.
+ Generate and parse modules.alias containing aliases for bus
+ identifiers:
+ alias pcmcia:m*c*f03fn*pfn*pa*pb*pc*pd* parport_cs
- Note:
- This is automatically enabled if 2.6 modules are not enabled.
+ and aliases for logical modules names e.g.:
+ alias padlock_aes aes
+ alias aes_i586 aes
+ alias aes_generic aes
-config FEATURE_2_6_MODULES
- # Simulate indentation
- bool "Support version 2.6.x Linux kernels"
+ Say Y if unsure.
+
+config FEATURE_MODUTILS_SYMBOLS
+ bool "Support for module.symbols file"
default y
- depends on INSMOD || RMMOD || MODPROBE
+ depends on DEPMOD || MODPROBE
help
- Support module loading for newer 2.6.x Linux kernels.
+ Generate and parse modules.symbols containing aliases for
+ symbol_request() kernel calls, such as:
+ alias symbol:usb_sg_init usbcore
+
+ Say Y if unsure.
config DEFAULT_MODULES_DIR
- # Simulate indentation
string "Default directory containing modules"
default "/lib/modules"
- depends on INSMOD || RMMOD || MODPROBE || MODPROBE_SMALL || DEPMOD
+ depends on DEPMOD || MODPROBE || MODPROBE_SMALL
help
Directory that contains kernel modules.
Defaults to "/lib/modules"
config DEFAULT_DEPMOD_FILE
- # Simulate indentation
string "Default name of modules.dep"
default "modules.dep"
- depends on INSMOD || RMMOD || MODPROBE || MODPROBE_SMALL || DEPMOD
+ depends on DEPMOD || MODPROBE || MODPROBE_SMALL
help
Filename that contains kernel modules dependencies.
Defaults to "modules.dep"
-config FEATURE_QUERY_MODULE_INTERFACE
- bool
- default y
- depends on FEATURE_2_4_MODULES && !FEATURE_2_6_MODULES
-
endmenu
diff --git a/release/src/router/busybox/modutils/Kbuild b/release/src/router/busybox/modutils/Kbuild
dissimilarity index 61%
index 828070114e..31f7cbf93a 100644
--- a/release/src/router/busybox/modutils/Kbuild
+++ b/release/src/router/busybox/modutils/Kbuild
@@ -1,13 +1,14 @@
-# Makefile for busybox
-#
-# Copyright (C) 1999-2005 by Erik Andersen
-#
-# Licensed under the GPL v2, see the file LICENSE in this tarball.
-
-lib-y:=
-lib-$(CONFIG_DEPMOD) += depmod.o
-lib-$(CONFIG_INSMOD) += insmod.o
-lib-$(CONFIG_LSMOD) += lsmod.o
-lib-$(CONFIG_MODPROBE) += modprobe.o
-lib-$(CONFIG_MODPROBE_SMALL) += modprobe-small.o
-lib-$(CONFIG_RMMOD) += rmmod.o
+# Makefile for busybox
+#
+# Copyright (C) 1999-2005 by Erik Andersen
+#
+# Licensed under the GPL v2, see the file LICENSE in this tarball.
+
+lib-y:=
+lib-$(CONFIG_MODPROBE_SMALL) += modprobe-small.o
+lib-$(CONFIG_DEPMOD) += depmod.o modutils.o
+lib-$(CONFIG_INSMOD) += insmod.o modutils.o
+lib-$(CONFIG_LSMOD) += lsmod.o modutils.o
+lib-$(CONFIG_MODPROBE) += modprobe.o modutils.o
+lib-$(CONFIG_RMMOD) += rmmod.o modutils.o
+lib-$(CONFIG_FEATURE_2_4_MODULES) += modutils-24.o
diff --git a/release/src/router/busybox/modutils/depmod.c b/release/src/router/busybox/modutils/depmod.c
dissimilarity index 87%
index b6a914eb05..405ba9e2a0 100644
--- a/release/src/router/busybox/modutils/depmod.c
+++ b/release/src/router/busybox/modutils/depmod.c
@@ -1,288 +1,232 @@
-/* vi: set sw=4 ts=4: */
-/*
- * depmod - generate modules.dep
- * Copyright (c) 2008 Bernhard Fischer
- *
- * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
- */
-
-#undef _GNU_SOURCE
-#define _GNU_SOURCE
-#include
-#include /* uname() */
-/*
- * Theory of operation:
- * - iterate over all modules and record their full path
- * - iterate over all modules looking for "depends=" entries
- * for each depends, look through our list of full paths and emit if found
- */
-
-typedef struct dep_lst_t {
- char *name;
- llist_t *dependencies;
- llist_t *aliases;
- struct dep_lst_t *next;
-} dep_lst_t;
-
-struct globals {
- dep_lst_t *lst; /* modules without their corresponding extension */
-};
-#define G (*(struct globals*)&bb_common_bufsiz1)
-/* We have to zero it out because of NOEXEC */
-#define INIT_G() memset(&G, 0, sizeof(G))
-
-static char* find_keyword(void *the_module, size_t len, const char * const word)
-{
- char *ptr = the_module;
- do {
- /* search for the first char in word */
- ptr = memchr(ptr, *word, len - (ptr - (char*)the_module));
- if (ptr == NULL) /* no occurance left, done */
- return NULL;
- if (!strncmp(ptr, word, strlen(word))) {
- ptr += strlen(word);
- break;
- }
- ++ptr;
- } while (1);
- return ptr;
-}
-static int FAST_FUNC fileAction(const char *fname, struct stat *sb,
- void UNUSED_PARAM *data, int UNUSED_PARAM depth)
-{
- size_t len = sb->st_size;
- void *the_module;
- char *ptr;
- int fd;
- char *depends, *deps;
- dep_lst_t *this;
-
- if (strrstr(fname, ".ko") == NULL) /* not a module */
- goto skip;
-
-/*XXX: FIXME: does not handle compressed modules!
- * There should be a function that looks at the extension and sets up
- * open_transformer for us.
- */
- fd = xopen(fname, O_RDONLY);
- the_module = mmap(NULL, len, PROT_READ, MAP_SHARED
-#if defined MAP_POPULATE
- |MAP_POPULATE
-#endif
- , fd, 0);
- close(fd);
- if (the_module == MAP_FAILED)
- bb_perror_msg_and_die("mmap");
-
- this = xzalloc(sizeof(dep_lst_t));
- this->name = xstrdup(fname);
- this->next = G.lst;
- G.lst = this;
-//bb_info_msg("fname='%s'", fname);
- ptr = find_keyword(the_module, len, "depends=");
- if (!*ptr)
- goto d_none;
- deps = depends = xstrdup(ptr);
-//bb_info_msg(" depends='%s'", depends);
- while (deps) {
- ptr = strsep(&deps, ",");
-//bb_info_msg("[%s] -> '%s'", fname, (char*)ptr);
- llist_add_to_end(&this->dependencies, xstrdup(ptr));
- }
- free(depends);
- d_none:
- if (ENABLE_FEATURE_DEPMOD_ALIAS)
- {
- size_t pos = 0;
- do {
- ptr = find_keyword(the_module + pos, len - pos, "alias=");
- if (ptr) {
-//bb_info_msg("[%s] alias '%s'", fname, (char*)ptr);
- llist_add_to_end(&this->aliases, xstrdup(ptr));
- } else
- break;
- pos = (ptr - (char*)the_module);
- } while (1);
- }
- munmap(the_module, sb->st_size);
- skip:
- return TRUE;
-}
-
-int depmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int depmod_main(int argc UNUSED_PARAM, char **argv)
-{
- int ret;
- size_t moddir_base_len = 0; /* length of the "-b basedir" */
- char *moddir_base = NULL, *moddir, *system_map, *chp;
- FILE *filedes = stdout;
- enum {
- ARG_a = (1<<0), /* All modules, ignore mods in argv */
- ARG_A = (1<<1), /* Only emit .ko that are newer than modules.dep file */
- ARG_b = (1<<2), /* not /lib/modules/$(uname -r)/ but this base-dir */
- ARG_e = (1<<3), /* with -F, print unresolved symbols */
- ARG_F = (1<<4), /* System.map that contains the symbols */
- ARG_n = (1<<5) /* dry-run, print to stdout only */
- };
- INIT_G();
-
- getopt32(argv, "aAb:eF:n", &moddir_base, &system_map);
- argv += optind;
-
- /* If a version is provided, then that kernel version’s module directory
- * is used, rather than the current kernel version (as returned by
- * "uname -r"). */
- if (*argv && (sscanf(*argv, "%d.%d.%d", &ret, &ret, &ret) == 3)) {
- moddir = concat_path_file(CONFIG_DEFAULT_MODULES_DIR, *argv++);
- } else {
- struct utsname uts;
- if (uname(&uts) < 0)
- bb_simple_perror_msg_and_die("uname");
- moddir = concat_path_file(CONFIG_DEFAULT_MODULES_DIR, uts.release);
- }
- /* If no modules are given on the command-line, -a is on per default. */
- option_mask32 |= *argv == NULL;
-
- if (option_mask32 & ARG_b) {
- moddir_base_len = strlen(moddir_base) + 1;
- xchdir(moddir_base);
- }
-
- if (!(option_mask32 & ARG_n)) { /* --dry-run */
- chp = concat_path_file(moddir, CONFIG_DEFAULT_DEPMOD_FILE);
- filedes = xfopen_for_write(chp);
- if (ENABLE_FEATURE_CLEAN_UP)
- free(chp);
- }
- ret = EXIT_SUCCESS;
- do {
- chp = option_mask32 & ARG_a ? moddir : (*argv + moddir_base_len);
-
- if (!recursive_action(chp,
- ACTION_RECURSE, /* flags */
- fileAction, /* file action */
- NULL, /* dir action */
- NULL, /* user data */
- 0)) { /* depth */
- ret = EXIT_FAILURE;
- }
- } while (!(option_mask32 & ARG_a) && *++argv);
-
- {
- dep_lst_t *mods = G.lst;
-
- /* Fixup the module names in the depends list */
- while (mods) {
- llist_t *deps = NULL, *old_deps = mods->dependencies;
-
- while (old_deps) {
- dep_lst_t *all = G.lst;
- char *longname = NULL;
- char *shortname = llist_pop(&old_deps);
-
- while (all) {
- char *nam =
- xstrdup(bb_get_last_path_component_nostrip(all->name));
- char *tmp = strrstr(nam, ".ko");
-
- *tmp = '\0';
- if (!strcmp(nam, shortname)) {
- if (ENABLE_FEATURE_CLEAN_UP)
- free(nam);
- longname = all->name;
- break;
- }
- free(nam);
- all = all->next;
- }
- llist_add_to_end(&deps, longname);
- }
- mods->dependencies = deps;
- mods = mods->next;
- }
-
-#if ENABLE_FEATURE_DEPMOD_PRUNE_FANCY
- /* modprobe allegedly wants dependencies without duplicates, i.e.
- * mod1: mod2 mod3
- * mod2: mod3
- * mod3:
- * implies that mod1 directly depends on mod2 and _not_ mod3 as mod3 is
- * already implicitely pulled in via mod2. This leaves us with:
- * mod1: mod2
- * mod2: mod3
- * mod3:
- */
- mods = G.lst;
- while (mods) {
- llist_t *deps = mods->dependencies;
- while (deps) {
- dep_lst_t *all = G.lst;
- while (all) {
- if (!strcmp(all->name, deps->data)) {
- llist_t *implied = all->dependencies;
- while (implied) {
- /* XXX:FIXME: erm, it would be nicer to just
- * llist_unlink(&mods->dependencies, implied) */
- llist_t *prune = mods->dependencies;
- while (prune) {
- if (!strcmp(implied->data, prune->data))
- break;
- prune = prune->link;
- }
-//if (prune) bb_info_msg("[%s] '%s' implies '%s', removing", mods->name, all->name, implied->data);
- llist_unlink(&mods->dependencies, prune);
- implied = implied->link;
- }
- }
- all = all->next;
- }
- deps = deps->link;
- }
- mods = mods->next;
- }
-#endif
-
- mods = G.lst;
- /* Finally print them. */
- while (mods) {
- fprintf(filedes, "%s:", mods->name);
- /* If we did not resolve all modules, then it's likely that we just did
- * not see the names of all prerequisites (which will be NULL in this
- * case). */
- while (mods->dependencies) {
- char *the_dep = llist_pop(&mods->dependencies);
- if (the_dep)
- fprintf(filedes, " %s", the_dep);
- }
- fprintf(filedes, "\n");
- if (ENABLE_FEATURE_DEPMOD_ALIAS)
- {
- char *shortname =
- xstrdup(bb_get_last_path_component_nostrip(mods->name));
- char *tmp = strrstr(shortname, ".ko");
-
- *tmp = '\0';
-
- while (mods->aliases) {
- fprintf(filedes, "alias %s %s\n",
- (char*)llist_pop(&mods->aliases),
- shortname);
- }
- free(shortname);
- }
- mods = mods->next;
- }
- }
-
- if (ENABLE_FEATURE_CLEAN_UP) {
- fclose_if_not_stdin(filedes);
- free(moddir);
- while (G.lst) {
- dep_lst_t *old = G.lst;
- G.lst = G.lst->next;
- free(old->name);
- free(old);
- }
- }
- return ret;
-}
+/* vi: set sw=4 ts=4: */
+/*
+ * depmod - generate modules.dep
+ * Copyright (c) 2008 Bernhard Reutner-Fischer
+ * Copyrihgt (c) 2008 Timo Teras
+ * Copyright (c) 2008 Vladimir Dronnikov
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#undef _GNU_SOURCE
+#define _GNU_SOURCE
+#include
+#include /* uname() */
+#include "modutils.h"
+
+/*
+ * Theory of operation:
+ * - iterate over all modules and record their full path
+ * - iterate over all modules looking for "depends=" entries
+ * for each depends, look through our list of full paths and emit if found
+ */
+
+typedef struct module_info {
+ struct module_info *next;
+ char *name, *modname;
+ llist_t *dependencies;
+ llist_t *aliases;
+ llist_t *symbols;
+ struct module_info *dnext, *dprev;
+} module_info;
+
+enum {
+ ARG_a = (1<<0), /* All modules, ignore mods in argv */
+ ARG_A = (1<<1), /* Only emit .ko that are newer than modules.dep file */
+ ARG_b = (1<<2), /* base directory when modules are in staging area */
+ ARG_e = (1<<3), /* with -F, print unresolved symbols */
+ ARG_F = (1<<4), /* System.map that contains the symbols */
+ ARG_n = (1<<5), /* dry-run, print to stdout only */
+ ARG_r = (1<<6) /* Compat dummy. Linux Makefile uses it */
+};
+
+static int FAST_FUNC parse_module(const char *fname, struct stat *sb,
+ void *data, int UNUSED_PARAM depth)
+{
+ module_info **first = (module_info **) data;
+ char *image, *ptr;
+ module_info *info;
+ size_t len = sb->st_size;
+
+ if (strrstr(fname, ".ko") == NULL)
+ return TRUE;
+
+ image = xmalloc_open_zipped_read_close(fname, &len);
+ info = xzalloc(sizeof(module_info));
+
+ info->next = *first;
+ *first = info;
+
+ info->dnext = info->dprev = info;
+ info->name = xasprintf("/%s", fname);
+ info->modname = filename2modname(fname, NULL);
+ for (ptr = image; ptr < image + len - 10; ptr++) {
+ if (strncmp(ptr, "depends=", 8) == 0) {
+ char *u;
+
+ ptr += 8;
+ for (u = ptr; *u; u++)
+ if (*u == '-')
+ *u = '_';
+ ptr += string_to_llist(ptr, &info->dependencies, ",");
+ } else if (ENABLE_FEATURE_MODUTILS_ALIAS &&
+ strncmp(ptr, "alias=", 6) == 0) {
+ llist_add_to(&info->aliases, xstrdup(ptr + 6));
+ ptr += strlen(ptr);
+ } else if (ENABLE_FEATURE_MODUTILS_SYMBOLS &&
+ strncmp(ptr, "__ksymtab_", 10) == 0) {
+ ptr += 10;
+ if (strncmp(ptr, "gpl", 3) == 0 ||
+ strcmp(ptr, "strings") == 0)
+ continue;
+ llist_add_to(&info->symbols, xstrdup(ptr));
+ ptr += strlen(ptr);
+ }
+ }
+ free(image);
+
+ return TRUE;
+}
+
+static module_info *find_module(module_info *modules, const char *modname)
+{
+ module_info *m;
+
+ for (m = modules; m != NULL; m = m->next)
+ if (strcmp(m->modname, modname) == 0)
+ return m;
+ return NULL;
+}
+
+static void order_dep_list(module_info *modules, module_info *start,
+ llist_t *add)
+{
+ module_info *m;
+ llist_t *n;
+
+ for (n = add; n != NULL; n = n->link) {
+ m = find_module(modules, n->data);
+ if (m == NULL)
+ continue;
+
+ /* unlink current entry */
+ m->dnext->dprev = m->dprev;
+ m->dprev->dnext = m->dnext;
+
+ /* and add it to tail */
+ m->dnext = start;
+ m->dprev = start->dprev;
+ start->dprev->dnext = m;
+ start->dprev = m;
+
+ /* recurse */
+ order_dep_list(modules, start, m->dependencies);
+ }
+}
+
+static void xfreopen_write(const char *file, FILE *f)
+{
+ if (freopen(file, "w", f) == NULL)
+ bb_perror_msg_and_die("can't open '%s'", file);
+}
+
+int depmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int depmod_main(int argc UNUSED_PARAM, char **argv)
+{
+ module_info *modules = NULL, *m, *dep;
+ const char *moddir_base = "/";
+ char *moddir, *version;
+ struct utsname uts;
+ int tmp;
+
+ getopt32(argv, "aAb:eF:nr", &moddir_base, NULL);
+ argv += optind;
+
+ /* goto modules location */
+ xchdir(moddir_base);
+
+ /* If a version is provided, then that kernel version's module directory
+ * is used, rather than the current kernel version (as returned by
+ * "uname -r"). */
+ if (*argv && sscanf(*argv, "%d.%d.%d", &tmp, &tmp, &tmp) == 3) {
+ version = *argv++;
+ } else {
+ uname(&uts);
+ version = uts.release;
+ }
+ moddir = concat_path_file(&CONFIG_DEFAULT_MODULES_DIR[1], version);
+
+ /* Scan modules */
+ if (*argv) {
+ char *modfile;
+ struct stat sb;
+ do {
+ modfile = concat_path_file(moddir, *argv);
+ xstat(modfile, &sb);
+ parse_module(modfile, &sb, &modules, 0);
+ free(modfile);
+ } while (*(++argv));
+ } else {
+ recursive_action(moddir, ACTION_RECURSE,
+ parse_module, NULL, &modules, 0);
+ }
+
+ /* Prepare for writing out the dep files */
+ xchdir(moddir);
+ if (ENABLE_FEATURE_CLEAN_UP)
+ free(moddir);
+
+ /* Generate dependency and alias files */
+ if (!(option_mask32 & ARG_n))
+ xfreopen_write(CONFIG_DEFAULT_DEPMOD_FILE, stdout);
+ for (m = modules; m != NULL; m = m->next) {
+ printf("%s:", m->name);
+
+ order_dep_list(modules, m, m->dependencies);
+ while (m->dnext != m) {
+ dep = m->dnext;
+ printf(" %s", dep->name);
+
+ /* unlink current entry */
+ dep->dnext->dprev = dep->dprev;
+ dep->dprev->dnext = dep->dnext;
+ dep->dnext = dep->dprev = dep;
+ }
+ bb_putchar('\n');
+ }
+
+#if ENABLE_FEATURE_MODUTILS_ALIAS
+ if (!(option_mask32 & ARG_n))
+ xfreopen_write("modules.alias", stdout);
+ for (m = modules; m != NULL; m = m->next) {
+ while (m->aliases) {
+ printf("alias %s %s\n",
+ (char*)llist_pop(&m->aliases),
+ m->modname);
+ }
+ }
+#endif
+#if ENABLE_FEATURE_MODUTILS_SYMBOLS
+ if (!(option_mask32 & ARG_n))
+ xfreopen_write("modules.symbols", stdout);
+ for (m = modules; m != NULL; m = m->next) {
+ while (m->symbols) {
+ printf("alias symbol:%s %s\n",
+ (char*)llist_pop(&m->symbols),
+ m->modname);
+ }
+ }
+#endif
+
+ if (ENABLE_FEATURE_CLEAN_UP) {
+ while (modules) {
+ module_info *old = modules;
+ modules = modules->next;
+ free(old->name);
+ free(old->modname);
+ free(old);
+ }
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/release/src/router/busybox/modutils/insmod.c b/release/src/router/busybox/modutils/insmod.c
dissimilarity index 99%
index 80dbfd78ec..90ed87a72a 100644
--- a/release/src/router/busybox/modutils/insmod.c
+++ b/release/src/router/busybox/modutils/insmod.c
@@ -1,4287 +1,41 @@
-/* vi: set sw=4 ts=4: */
-/*
- * Mini insmod implementation for busybox
- *
- * This version of insmod supports ARM, CRIS, H8/300, x86, ia64, x86_64,
- * m68k, MIPS, PowerPC, S390, SH3/4/5, Sparc, v850e, and x86_64.
- *
- * Copyright (C) 1999-2004 by Erik Andersen
- * and Ron Alder
- *
- * Rodney Radford 17-Aug-2004.
- * Added x86_64 support.
- *
- * Miles Bader added NEC V850E support.
- *
- * 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.
- *
- * Yoshinori Sato 19-May-2004.
- * added Renesas H8/300 support.
- *
- * Paul Mundt 08-Aug-2003.
- * Integrated support for sh64 (SH-5), from preliminary modutils
- * patches from Benedict Gaster .
- * Currently limited to support for 32bit ABI.
- *
- * Magnus Damm 22-May-2002.
- * The plt and got code are now using the same structs.
- * Added generic linked list code to fully support PowerPC.
- * Replaced the mess in arch_apply_relocation() with architecture blocks.
- * The arch_create_got() function got cleaned up with architecture blocks.
- * These blocks should be easy maintain and sync with obj_xxx.c in modutils.
- *
- * 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 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
- *
- * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
- */
-
-#include "libbb.h"
-#include
-#include
-
-#if !ENABLE_FEATURE_2_4_MODULES && !ENABLE_FEATURE_2_6_MODULES
-#undef ENABLE_FEATURE_2_4_MODULES
-#define ENABLE_FEATURE_2_4_MODULES 1
-#endif
-
-/*
- * Big piece of 2.4-specific code
- */
-#if ENABLE_FEATURE_2_4_MODULES
-
-#if ENABLE_FEATURE_2_6_MODULES
-static int insmod_ng_main(int argc, char **argv);
-#endif
-
-#if ENABLE_FEATURE_INSMOD_LOADINKMEM
-#define LOADBITS 0
-#else
-#define LOADBITS 1
-#endif
-
-/* Alpha */
-#if defined(__alpha__)
-#define MATCH_MACHINE(x) (x == EM_ALPHA)
-#define SHT_RELM SHT_RELA
-#define Elf64_RelM Elf64_Rela
-#define ELFCLASSM ELFCLASS64
-#endif
-
-/* ARM support */
-#if defined(__arm__)
-#define MATCH_MACHINE(x) (x == EM_ARM)
-#define SHT_RELM SHT_REL
-#define Elf32_RelM Elf32_Rel
-#define ELFCLASSM ELFCLASS32
-#define USE_PLT_ENTRIES
-#define PLT_ENTRY_SIZE 8
-#define USE_GOT_ENTRIES
-#define GOT_ENTRY_SIZE 8
-#define USE_SINGLE
-#endif
-
-/* blackfin */
-#if defined(BFIN)
-#define MATCH_MACHINE(x) (x == EM_BLACKFIN)
-#define SHT_RELM SHT_RELA
-#define Elf32_RelM Elf32_Rela
-#define ELFCLASSM ELFCLASS32
-#endif
-
-/* CRIS */
-#if defined(__cris__)
-#define MATCH_MACHINE(x) (x == EM_CRIS)
-#define SHT_RELM SHT_RELA
-#define Elf32_RelM Elf32_Rela
-#define ELFCLASSM ELFCLASS32
-#ifndef EM_CRIS
-#define EM_CRIS 76
-#define R_CRIS_NONE 0
-#define R_CRIS_32 3
-#endif
-#endif
-
-/* H8/300 */
-#if defined(__H8300H__) || defined(__H8300S__)
-#define MATCH_MACHINE(x) (x == EM_H8_300)
-#define SHT_RELM SHT_RELA
-#define Elf32_RelM Elf32_Rela
-#define ELFCLASSM ELFCLASS32
-#define USE_SINGLE
-#define SYMBOL_PREFIX "_"
-#endif
-
-/* PA-RISC / HP-PA */
-#if defined(__hppa__)
-#define MATCH_MACHINE(x) (x == EM_PARISC)
-#define SHT_RELM SHT_RELA
-#if defined(__LP64__)
-#define Elf64_RelM Elf64_Rela
-#define ELFCLASSM ELFCLASS64
-#else
-#define Elf32_RelM Elf32_Rela
-#define ELFCLASSM ELFCLASS32
-#endif
-#endif
-
-/* x86 */
-#if defined(__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 ELFCLASSM ELFCLASS32
-#define USE_GOT_ENTRIES
-#define GOT_ENTRY_SIZE 4
-#define USE_SINGLE
-#endif
-
-/* IA64, aka Itanium */
-#if defined(__ia64__)
-#define MATCH_MACHINE(x) (x == EM_IA_64)
-#define SHT_RELM SHT_RELA
-#define Elf64_RelM Elf64_Rela
-#define ELFCLASSM ELFCLASS64
-#endif
-
-/* m68k */
-#if defined(__mc68000__)
-#define MATCH_MACHINE(x) (x == EM_68K)
-#define SHT_RELM SHT_RELA
-#define Elf32_RelM Elf32_Rela
-#define ELFCLASSM ELFCLASS32
-#define USE_GOT_ENTRIES
-#define GOT_ENTRY_SIZE 4
-#define USE_SINGLE
-#endif
-
-/* Microblaze */
-#if defined(__microblaze__)
-#define USE_SINGLE
-#include
-#define MATCH_MACHINE(x) (x == EM_XILINX_MICROBLAZE)
-#define SHT_RELM SHT_RELA
-#define Elf32_RelM Elf32_Rela
-#define ELFCLASSM ELFCLASS32
-#endif
-
-/* MIPS */
-#if defined(__mips__)
-#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
-#define SHT_RELM SHT_REL
-#define Elf32_RelM Elf32_Rel
-#define ELFCLASSM ELFCLASS32
-/* 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 ARCHDATAM "__dbe_table"
-#endif
-
-/* Nios II */
-#if defined(__nios2__)
-#define MATCH_MACHINE(x) (x == EM_ALTERA_NIOS2)
-#define SHT_RELM SHT_RELA
-#define Elf32_RelM Elf32_Rela
-#define ELFCLASSM ELFCLASS32
-#endif
-
-/* PowerPC */
-#if defined(__powerpc64__)
-#define MATCH_MACHINE(x) (x == EM_PPC64)
-#define SHT_RELM SHT_RELA
-#define Elf64_RelM Elf64_Rela
-#define ELFCLASSM ELFCLASS64
-#elif defined(__powerpc__)
-#define MATCH_MACHINE(x) (x == EM_PPC)
-#define SHT_RELM SHT_RELA
-#define Elf32_RelM Elf32_Rela
-#define ELFCLASSM ELFCLASS32
-#define USE_PLT_ENTRIES
-#define PLT_ENTRY_SIZE 16
-#define USE_PLT_LIST
-#define LIST_ARCHTYPE ElfW(Addr)
-#define USE_LIST
-#define ARCHDATAM "__ftr_fixup"
-#endif
-
-/* S390 */
-#if defined(__s390__)
-#define MATCH_MACHINE(x) (x == EM_S390)
-#define SHT_RELM SHT_RELA
-#define Elf32_RelM Elf32_Rela
-#define ELFCLASSM ELFCLASS32
-#define USE_PLT_ENTRIES
-#define PLT_ENTRY_SIZE 8
-#define USE_GOT_ENTRIES
-#define GOT_ENTRY_SIZE 8
-#define USE_SINGLE
-#endif
-
-/* SuperH */
-#if defined(__sh__)
-#define MATCH_MACHINE(x) (x == EM_SH)
-#define SHT_RELM SHT_RELA
-#define Elf32_RelM Elf32_Rela
-#define ELFCLASSM ELFCLASS32
-#define USE_GOT_ENTRIES
-#define GOT_ENTRY_SIZE 4
-#define USE_SINGLE
-/* the SH changes have only been tested in =little endian= mode */
-/* I'm not sure about big endian, so let's warn: */
-#if defined(__sh__) && BB_BIG_ENDIAN
-# error insmod.c may require changes for use on big endian SH
-#endif
-/* it may or may not work on the SH1/SH2... Error on those also */
-#if ((!(defined(__SH3__) || defined(__SH4__) || defined(__SH5__)))) && (defined(__sh__))
-#error insmod.c may require changes for SH1 or SH2 use
-#endif
-#endif
-
-/* Sparc */
-#if defined(__sparc__)
-#define MATCH_MACHINE(x) (x == EM_SPARC)
-#define SHT_RELM SHT_RELA
-#define Elf32_RelM Elf32_Rela
-#define ELFCLASSM ELFCLASS32
-#endif
-
-/* v850e */
-#if defined(__v850e__)
-#define MATCH_MACHINE(x) ((x) == EM_V850 || (x) == EM_CYGNUS_V850)
-#define SHT_RELM SHT_RELA
-#define Elf32_RelM Elf32_Rela
-#define ELFCLASSM ELFCLASS32
-#define USE_PLT_ENTRIES
-#define PLT_ENTRY_SIZE 8
-#define USE_SINGLE
-#ifndef EM_CYGNUS_V850 /* grumble */
-#define EM_CYGNUS_V850 0x9080
-#endif
-#define SYMBOL_PREFIX "_"
-#endif
-
-/* X86_64 */
-#if defined(__x86_64__)
-#define MATCH_MACHINE(x) (x == EM_X86_64)
-#define SHT_RELM SHT_RELA
-#define USE_GOT_ENTRIES
-#define GOT_ENTRY_SIZE 8
-#define USE_SINGLE
-#define Elf64_RelM Elf64_Rela
-#define ELFCLASSM ELFCLASS64
-#endif
-
-#ifndef SHT_RELM
-#error Sorry, but insmod.c does not yet support this architecture...
-#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
-
-/*======================================================================*/
-/* 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
-enum {
- tgt_sizeof_long = 8,
- tgt_sizeof_char_p = 8,
- 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;
- 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 */
-};
-
-#ifdef ARCHDATAM
-#define ARCHDATA_SEC_NAME ARCHDATAM
-#else
-#define ARCHDATA_SEC_NAME "__archdata"
-#endif
-#define KALLSYMS_SEC_NAME "__kallsyms"
-
-
-struct new_module_info {
- unsigned long addr;
- unsigned long size;
- unsigned long flags;
- long usecount;
-};
-
-/* Bits of module.flags. */
-enum {
- NEW_MOD_RUNNING = 1,
- NEW_MOD_DELETED = 2,
- NEW_MOD_AUTOCLEAN = 4,
- NEW_MOD_VISITED = 8,
- NEW_MOD_USED_ONCE = 16
-};
-
-int 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. */
-enum {
- QM_MODULES = 1,
- QM_DEPS = 2,
- QM_REFS = 3,
- QM_SYMBOLS = 4,
- 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 *module, unsigned int flags);
-
-
-#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
-
-/* The relocatable object is manipulated using elfin types. */
-
-#include
-#include
-
-#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 some ancient C libraries.... */
-#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
-
-#define ELF_ST_BIND(info) ELFW(ST_BIND)(info)
-#define ELF_ST_TYPE(info) ELFW(ST_TYPE)(info)
-#define ELF_ST_INFO(bind, type) ELFW(ST_INFO)(bind, type)
-#define ELF_R_TYPE(val) ELFW(R_TYPE)(val)
-#define ELF_R_SYM(val) ELFW(R_SYM)(val)
-
-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);
-
-#if ENABLE_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 void obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
- const char *string);
-
-static void obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
- struct obj_symbol *sym);
-
-static void 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 void arch_create_got(struct obj_file *f);
-#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
-static int obj_gpl_license(struct obj_file *f, const char **license);
-#endif /* FEATURE_CHECK_TAINTED_MODULE */
-#endif /* obj.h */
-//----------------------------------------------------------------------------
-//--------end of modutils obj.h
-//----------------------------------------------------------------------------
-
-
-/* SPFX is always a string, so it can be concatenated to string constants. */
-#ifdef SYMBOL_PREFIX
-#define SPFX SYMBOL_PREFIX
-#else
-#define SPFX ""
-#endif
-
-enum { STRVERSIONLEN = 64 };
-
-/*======================================================================*/
-
-#define OPTION_STR "sLo:fkvqx" USE_FEATURE_INSMOD_LOAD_MAP("m")
-enum {
- OPT_s = 0x1, // -s /* log to syslog */
- /* Not supported but kernel needs this for request_module(),
- as this calls: modprobe -k -s --
- so silently ignore this flag */
- OPT_L = 0x2, // -L /* Stub warning */
- /* 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. */
- OPT_o = 0x4, // -o /* name the output module */
- OPT_f = 0x8, // -f /* force loading */
- OPT_k = 0x10, // -k /* module loaded by kerneld, auto-cleanable */
- OPT_v = 0x20, // -v /* verbose output */
- OPT_q = 0x40, // -q /* silent */
- OPT_x = 0x80, // -x /* do not export externs */
- OPT_m = 0x100, // -m /* print module load map */
-};
-#define flag_force_load (option_mask32 & OPT_f)
-#define flag_autoclean (option_mask32 & OPT_k)
-#define flag_verbose (option_mask32 & OPT_v)
-#define flag_quiet (option_mask32 & OPT_q)
-#define flag_noexport (option_mask32 & OPT_x)
-#if ENABLE_FEATURE_INSMOD_LOAD_MAP
-#define flag_print_load_map (option_mask32 & OPT_m)
-#else
-#define flag_print_load_map 0
-#endif
-
-/*======================================================================*/
-
-#if defined(USE_LIST)
-
-struct arch_list_entry
-{
- struct arch_list_entry *next;
- LIST_ARCHTYPE addend;
- int offset;
- int inited : 1;
-};
-
-#endif
-
-#if defined(USE_SINGLE)
-
-struct arch_single_entry
-{
- int offset;
- int inited : 1;
- int allocated : 1;
-};
-
-#endif
-
-#if defined(__mips__)
-struct mips_hi16
-{
- struct mips_hi16 *next;
- ElfW(Addr) *addr;
- ElfW(Addr) value;
-};
-#endif
-
-struct arch_file {
- struct obj_file root;
-#if defined(USE_PLT_ENTRIES)
- struct obj_section *plt;
-#endif
-#if defined(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(USE_PLT_ENTRIES)
-#if defined(USE_PLT_LIST)
- struct arch_list_entry *pltent;
-#else
- struct arch_single_entry pltent;
-#endif
-#endif
-#if defined(USE_GOT_ENTRIES)
- struct arch_single_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;
-
-static char *m_filename;
-static char *m_fullName;
-
-
-/*======================================================================*/
-
-
-static int FAST_FUNC check_module_name_match(const char *filename,
- struct stat *statbuf UNUSED_PARAM,
- void *userdata, int depth UNUSED_PARAM)
-{
- char *fullname = (char *) userdata;
- char *tmp;
-
- if (fullname[0] == '\0')
- return FALSE;
-
- tmp = bb_get_last_path_component_nostrip(filename);
- if (strcmp(tmp, fullname) == 0) {
- /* Stop searching if we find a match */
- m_filename = xstrdup(filename);
- return FALSE;
- }
- return TRUE;
-}
-
-
-/*======================================================================*/
-
-static struct obj_file *arch_new_file(void)
-{
- struct arch_file *f;
- f = xzalloc(sizeof(*f));
- return &f->root; /* it's a first member */
-}
-
-static struct obj_section *arch_new_section(void)
-{
- return xzalloc(sizeof(struct obj_section));
-}
-
-static struct obj_symbol *arch_new_symbol(void)
-{
- struct arch_symbol *sym;
- sym = xzalloc(sizeof(*sym));
- 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)
-{
-#if defined(__arm__) || defined(__i386__) || defined(__mc68000__) \
- || defined(__sh__) || defined(__s390__) || defined(__x86_64__) \
- || defined(__powerpc__) || defined(__mips__)
- struct arch_file *ifile = (struct arch_file *) f;
-#endif
- enum obj_reloc ret = obj_reloc_ok;
- ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
-#if defined(__arm__) || defined(__H8300H__) || defined(__H8300S__) \
- || defined(__i386__) || defined(__mc68000__) || defined(__microblaze__) \
- || defined(__mips__) || defined(__nios2__) || defined(__powerpc__) \
- || defined(__s390__) || defined(__sh__) || defined(__x86_64__)
- ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
-#endif
-#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
- struct arch_symbol *isym = (struct arch_symbol *) sym;
-#endif
-#if defined(__arm__) || defined(__i386__) || defined(__mc68000__) \
- || defined(__sh__) || defined(__s390__)
-#if defined(USE_GOT_ENTRIES)
- ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
-#endif
-#endif
-#if defined(USE_PLT_ENTRIES)
- ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
- unsigned long *ip;
-# if defined(USE_PLT_LIST)
- struct arch_list_entry *pe;
-# else
- struct arch_single_entry *pe;
-# endif
-#endif
-
- switch (ELF_R_TYPE(rel->r_info)) {
-
-#if defined(__arm__)
-
- case R_ARM_NONE:
- break;
-
- case R_ARM_ABS32:
- *loc += v;
- break;
-
- case R_ARM_GOT32:
- goto bb_use_got;
-
- case R_ARM_GOTPC:
- /* relative reloc, always to _GLOBAL_OFFSET_TABLE_
- * (which is .got) similar to branch,
- * but is full 32 bits relative */
-
- *loc += got - dot;
- break;
-
- case R_ARM_PC24:
- case R_ARM_PLT32:
- goto bb_use_plt;
-
- case R_ARM_GOTOFF: /* address relative to the got */
- *loc += v - got;
- break;
-
-#elif defined(__cris__)
-
- case R_CRIS_NONE:
- break;
-
- case R_CRIS_32:
- /* CRIS keeps the relocation value in the r_addend field and
- * should not use whats in *loc at all
- */
- *loc = v;
- break;
-
-#elif defined(__H8300H__) || defined(__H8300S__)
-
- case R_H8_DIR24R8:
- loc = (ElfW(Addr) *)((ElfW(Addr))loc - 1);
- *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v);
- break;
- case R_H8_DIR24A8:
- *loc += v;
- break;
- case R_H8_DIR32:
- case R_H8_DIR32A16:
- *loc += v;
- break;
- case R_H8_PCREL16:
- v -= dot + 2;
- if ((ElfW(Sword))v > 0x7fff ||
- (ElfW(Sword))v < -(ElfW(Sword))0x8000)
- ret = obj_reloc_overflow;
- else
- *(unsigned short *)loc = v;
- break;
- case R_H8_PCREL8:
- v -= dot + 1;
- if ((ElfW(Sword))v > 0x7f ||
- (ElfW(Sword))v < -(ElfW(Sword))0x80)
- ret = obj_reloc_overflow;
- else
- *(unsigned char *)loc = v;
- break;
-
-#elif defined(__i386__)
-
- case R_386_NONE:
- break;
-
- case R_386_32:
- *loc += v;
- break;
-
- case R_386_PLT32:
- case R_386_PC32:
- case R_386_GOTOFF:
- *loc += v - dot;
- break;
-
- case R_386_GLOB_DAT:
- case R_386_JMP_SLOT:
- *loc = v;
- break;
-
- case R_386_RELATIVE:
- *loc += f->baseaddr;
- break;
-
- case R_386_GOTPC:
- *loc += got - dot;
- break;
-
- case R_386_GOT32:
- goto bb_use_got;
- break;
-
-#elif defined(__microblaze__)
- case R_MICROBLAZE_NONE:
- case R_MICROBLAZE_64_NONE:
- case R_MICROBLAZE_32_SYM_OP_SYM:
- case R_MICROBLAZE_32_PCREL:
- break;
-
- case R_MICROBLAZE_64_PCREL: {
- /* dot is the address of the current instruction.
- * v is the target symbol address.
- * So we need to extract the offset in the code,
- * adding v, then subtrating the current address
- * of this instruction.
- * Ex: "IMM 0xFFFE bralid 0x0000" = "bralid 0xFFFE0000"
- */
-
- /* Get split offset stored in code */
- unsigned int temp = (loc[0] & 0xFFFF) << 16 |
- (loc[1] & 0xFFFF);
-
- /* Adjust relative offset. -4 adjustment required
- * because dot points to the IMM insn, but branch
- * is computed relative to the branch instruction itself.
- */
- temp += v - dot - 4;
-
- /* Store back into code */
- loc[0] = (loc[0] & 0xFFFF0000) | temp >> 16;
- loc[1] = (loc[1] & 0xFFFF0000) | (temp & 0xFFFF);
-
- break;
- }
-
- case R_MICROBLAZE_32:
- *loc += v;
- break;
-
- case R_MICROBLAZE_64: {
- /* Get split pointer stored in code */
- unsigned int temp1 = (loc[0] & 0xFFFF) << 16 |
- (loc[1] & 0xFFFF);
-
- /* Add reloc offset */
- temp1+=v;
-
- /* Store back into code */
- loc[0] = (loc[0] & 0xFFFF0000) | temp1 >> 16;
- loc[1] = (loc[1] & 0xFFFF0000) | (temp1 & 0xFFFF);
-
- break;
- }
-
- case R_MICROBLAZE_32_PCREL_LO:
- case R_MICROBLAZE_32_LO:
- case R_MICROBLAZE_SRO32:
- case R_MICROBLAZE_SRW32:
- ret = obj_reloc_unhandled;
- break;
-
-#elif defined(__mc68000__)
-
- case R_68K_NONE:
- break;
-
- case R_68K_32:
- *loc += v;
- break;
-
- 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;
-
- case R_68K_PC8:
- v -= dot;
- if ((ElfW(Sword))v > 0x7f
- || (ElfW(Sword))v < -(ElfW(Sword))0x80
- ) {
- ret = obj_reloc_overflow;
- }
- *(char *)loc = v;
- break;
-
- case R_68K_PC16:
- v -= dot;
- if ((ElfW(Sword))v > 0x7fff
- || (ElfW(Sword))v < -(ElfW(Sword))0x8000
- ) {
- ret = obj_reloc_overflow;
- }
- *(short *)loc = v;
- break;
-
- case R_68K_PC32:
- *(int *)loc = v - dot;
- break;
-
- case R_68K_GLOB_DAT:
- case R_68K_JMP_SLOT:
- *loc = v;
- break;
-
- case R_68K_RELATIVE:
- *(int *)loc += f->baseaddr;
- break;
-
- case R_68K_GOT32:
- goto bb_use_got;
-
-# ifdef R_68K_GOTOFF
- case R_68K_GOTOFF:
- *loc += v - got;
- break;
-# endif
-
-#elif defined(__mips__)
-
- case R_MIPS_NONE:
- break;
-
- case R_MIPS_32:
- *loc += v;
- break;
-
- 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 = 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;
- ElfW(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;
-
- /* 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;
- }
-
-#elif defined(__nios2__)
-
- case R_NIOS2_NONE:
- break;
-
- case R_NIOS2_BFD_RELOC_32:
- *loc += v;
- break;
-
- case R_NIOS2_BFD_RELOC_16:
- if (v > 0xffff) {
- ret = obj_reloc_overflow;
- }
- *(short *)loc = v;
- break;
-
- case R_NIOS2_BFD_RELOC_8:
- if (v > 0xff) {
- ret = obj_reloc_overflow;
- }
- *(char *)loc = v;
- break;
-
- case R_NIOS2_S16:
- {
- Elf32_Addr word;
-
- if ((Elf32_Sword)v > 0x7fff
- || (Elf32_Sword)v < -(Elf32_Sword)0x8000
- ) {
- ret = obj_reloc_overflow;
- }
-
- word = *loc;
- *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
- (word & 0x3f);
- }
- break;
-
- case R_NIOS2_U16:
- {
- Elf32_Addr word;
-
- if (v > 0xffff) {
- ret = obj_reloc_overflow;
- }
-
- word = *loc;
- *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
- (word & 0x3f);
- }
- break;
-
- case R_NIOS2_PCREL16:
- {
- Elf32_Addr word;
-
- v -= dot + 4;
- if ((Elf32_Sword)v > 0x7fff
- || (Elf32_Sword)v < -(Elf32_Sword)0x8000
- ) {
- ret = obj_reloc_overflow;
- }
-
- word = *loc;
- *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
- }
- break;
-
- case R_NIOS2_GPREL:
- {
- Elf32_Addr word, gp;
- /* get _gp */
- gp = obj_symbol_final_value(f, obj_find_symbol(f, SPFX "_gp"));
- v -= gp;
- if ((Elf32_Sword)v > 0x7fff
- || (Elf32_Sword)v < -(Elf32_Sword)0x8000
- ) {
- ret = obj_reloc_overflow;
- }
-
- word = *loc;
- *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
- }
- break;
-
- case R_NIOS2_CALL26:
- if (v & 3)
- ret = obj_reloc_dangerous;
- if ((v >> 28) != (dot >> 28))
- ret = obj_reloc_overflow;
- *loc = (*loc & 0x3f) | ((v >> 2) << 6);
- break;
-
- case R_NIOS2_IMM5:
- {
- Elf32_Addr word;
-
- if (v > 0x1f) {
- ret = obj_reloc_overflow;
- }
-
- word = *loc & ~0x7c0;
- *loc = word | ((v & 0x1f) << 6);
- }
- break;
-
- case R_NIOS2_IMM6:
- {
- Elf32_Addr word;
-
- if (v > 0x3f) {
- ret = obj_reloc_overflow;
- }
-
- word = *loc & ~0xfc0;
- *loc = word | ((v & 0x3f) << 6);
- }
- break;
-
- case R_NIOS2_IMM8:
- {
- Elf32_Addr word;
-
- if (v > 0xff) {
- ret = obj_reloc_overflow;
- }
-
- word = *loc & ~0x3fc0;
- *loc = word | ((v & 0xff) << 6);
- }
- break;
-
- case R_NIOS2_HI16:
- {
- Elf32_Addr word;
-
- word = *loc;
- *loc = ((((word >> 22) << 16) | ((v >>16) & 0xffff)) << 6) |
- (word & 0x3f);
- }
- break;
-
- case R_NIOS2_LO16:
- {
- Elf32_Addr word;
-
- word = *loc;
- *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
- (word & 0x3f);
- }
- break;
-
- case R_NIOS2_HIADJ16:
- {
- Elf32_Addr word1, word2;
-
- word1 = *loc;
- word2 = ((v >> 16) + ((v >> 15) & 1)) & 0xffff;
- *loc = ((((word1 >> 22) << 16) | word2) << 6) |
- (word1 & 0x3f);
- }
- break;
-
-#elif defined(__powerpc64__)
- /* PPC64 needs a 2.6 kernel, 2.4 module relocation irrelevant */
-
-#elif 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;
-
- case R_PPC_REL24:
- goto bb_use_plt;
-
- case R_PPC_REL32:
- *loc = v - dot;
- break;
-
- case R_PPC_ADDR32:
- *loc = v;
- break;
-
-#elif defined(__s390__)
-
- case R_390_32:
- *(unsigned int *) loc += v;
- break;
- case R_390_16:
- *(unsigned short *) loc += v;
- break;
- case R_390_8:
- *(unsigned char *) loc += v;
- break;
-
- case R_390_PC32:
- *(unsigned int *) loc += v - dot;
- break;
- case R_390_PC16DBL:
- *(unsigned short *) loc += (v - dot) >> 1;
- break;
- case R_390_PC16:
- *(unsigned short *) loc += v - dot;
- break;
-
- case R_390_PLT32:
- case R_390_PLT16DBL:
- /* find the plt entry and initialize it. */
- pe = (struct arch_single_entry *) &isym->pltent;
- if (pe->inited == 0) {
- ip = (unsigned long *)(ifile->plt->contents + pe->offset);
- ip[0] = 0x0d105810; /* basr 1,0; lg 1,10(1); br 1 */
- ip[1] = 0x100607f1;
- if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
- ip[2] = v - 2;
- else
- ip[2] = v;
- pe->inited = 1;
- }
-
- /* Insert relative distance to target. */
- v = plt + pe->offset - dot;
- if (ELF_R_TYPE(rel->r_info) == R_390_PLT32)
- *(unsigned int *) loc = (unsigned int) v;
- else if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
- *(unsigned short *) loc = (unsigned short) ((v + 2) >> 1);
- break;
-
- case R_390_GLOB_DAT:
- case R_390_JMP_SLOT:
- *loc = v;
- break;
-
- case R_390_RELATIVE:
- *loc += f->baseaddr;
- break;
-
- case R_390_GOTPC:
- *(unsigned long *) loc += got - dot;
- break;
-
- case R_390_GOT12:
- case R_390_GOT16:
- case R_390_GOT32:
- if (!isym->gotent.inited)
- {
- isym->gotent.inited = 1;
- *(ElfW(Addr) *)(ifile->got->contents + isym->gotent.offset) = v;
- }
- if (ELF_R_TYPE(rel->r_info) == R_390_GOT12)
- *(unsigned short *) loc |= (*(unsigned short *) loc + isym->gotent.offset) & 0xfff;
- else if (ELF_R_TYPE(rel->r_info) == R_390_GOT16)
- *(unsigned short *) loc += isym->gotent.offset;
- else if (ELF_R_TYPE(rel->r_info) == R_390_GOT32)
- *(unsigned int *) loc += isym->gotent.offset;
- break;
-
-# ifndef R_390_GOTOFF32
-# define R_390_GOTOFF32 R_390_GOTOFF
-# endif
- case R_390_GOTOFF32:
- *loc += v - got;
- break;
-
-#elif defined(__sh__)
-
- case R_SH_NONE:
- break;
-
- case R_SH_DIR32:
- *loc += v;
- break;
-
- case R_SH_REL32:
- *loc += v - dot;
- break;
-
- case R_SH_PLT32:
- *loc = v - dot;
- break;
-
- case R_SH_GLOB_DAT:
- case R_SH_JMP_SLOT:
- *loc = v;
- break;
-
- case R_SH_RELATIVE:
- *loc = f->baseaddr + rel->r_addend;
- break;
-
- case R_SH_GOTPC:
- *loc = got - dot + rel->r_addend;
- break;
-
- case R_SH_GOT32:
- goto bb_use_got;
-
- case R_SH_GOTOFF:
- *loc = v - got;
- break;
-
-# if defined(__SH5__)
- case R_SH_IMM_MEDLOW16:
- case R_SH_IMM_LOW16:
- {
- ElfW(Addr) word;
-
- if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16)
- v >>= 16;
-
- /*
- * movi and shori have the format:
- *
- * | op | imm | reg | reserved |
- * 31..26 25..10 9.. 4 3 .. 0
- *
- * so we simply mask and or in imm.
- */
- word = *loc & ~0x3fffc00;
- word |= (v & 0xffff) << 10;
-
- *loc = word;
-
- break;
- }
-
- case R_SH_IMM_MEDLOW16_PCREL:
- case R_SH_IMM_LOW16_PCREL:
- {
- ElfW(Addr) word;
-
- word = *loc & ~0x3fffc00;
-
- v -= dot;
-
- if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16_PCREL)
- v >>= 16;
-
- word |= (v & 0xffff) << 10;
-
- *loc = word;
-
- break;
- }
-# endif /* __SH5__ */
-
-#elif defined(__v850e__)
-
- case R_V850_NONE:
- break;
-
- case R_V850_32:
- /* We write two shorts instead of a long because even
- 32-bit insns only need half-word alignment, but
- 32-bit data needs to be long-word aligned. */
- v += ((unsigned short *)loc)[0];
- v += ((unsigned short *)loc)[1] << 16;
- ((unsigned short *)loc)[0] = v & 0xffff;
- ((unsigned short *)loc)[1] = (v >> 16) & 0xffff;
- break;
-
- case R_V850_22_PCREL:
- goto bb_use_plt;
-
-#elif defined(__x86_64__)
-
- case R_X86_64_NONE:
- break;
-
- case R_X86_64_64:
- *loc += v;
- break;
-
- case R_X86_64_32:
- *(unsigned int *) loc += v;
- if (v > 0xffffffff)
- {
- ret = obj_reloc_overflow; /* Kernel module compiled without -mcmodel=kernel. */
- /* error("Possibly is module compiled without -mcmodel=kernel!"); */
- }
- break;
-
- case R_X86_64_32S:
- *(signed int *) loc += v;
- break;
-
- case R_X86_64_16:
- *(unsigned short *) loc += v;
- break;
-
- case R_X86_64_8:
- *(unsigned char *) loc += v;
- break;
-
- case R_X86_64_PC32:
- *(unsigned int *) loc += v - dot;
- break;
-
- case R_X86_64_PC16:
- *(unsigned short *) loc += v - dot;
- break;
-
- case R_X86_64_PC8:
- *(unsigned char *) loc += v - dot;
- break;
-
- case R_X86_64_GLOB_DAT:
- case R_X86_64_JUMP_SLOT:
- *loc = v;
- break;
-
- case R_X86_64_RELATIVE:
- *loc += f->baseaddr;
- break;
-
- case R_X86_64_GOT32:
- case R_X86_64_GOTPCREL:
- goto bb_use_got;
-# if 0
- if (!isym->gotent.reloc_done)
- {
- isym->gotent.reloc_done = 1;
- *(Elf64_Addr *)(ifile->got->contents + isym->gotent.offset) = v;
- }
- /* XXX are these really correct? */
- if (ELF64_R_TYPE(rel->r_info) == R_X86_64_GOTPCREL)
- *(unsigned int *) loc += v + isym->gotent.offset;
- else
- *loc += isym->gotent.offset;
- break;
-# endif
-
-#else
-# warning "no idea how to handle relocations on your arch"
-#endif
-
- default:
- printf("Warning: unhandled reloc %d\n",(int)ELF_R_TYPE(rel->r_info));
- ret = obj_reloc_unhandled;
- break;
-
-#if defined(USE_PLT_ENTRIES)
-
-bb_use_plt:
-
- /* find the plt entry and initialize it if necessary */
-
-#if defined(USE_PLT_LIST)
- for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;)
- pe = pe->next;
-#else
- pe = &isym->pltent;
-#endif
-
- 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
-#if defined(__v850e__)
- /* We have to trash a register, so we assume that any control
- transfer more than 21-bits away must be a function call
- (so we can use a call-clobbered register). */
- ip[0] = 0x0621 + ((v & 0xffff) << 16); /* mov sym, r1 ... */
- ip[1] = ((v >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
-#endif
- pe->inited = 1;
- }
-
- /* relative distance to target */
- v -= dot;
- /* if the target is too far away.... */
-#if defined(__arm__) || defined(__powerpc__)
- if ((int)v < -0x02000000 || (int)v >= 0x02000000)
-#elif defined(__v850e__)
- if ((ElfW(Sword))v > 0x1fffff || (ElfW(Sword))v < (ElfW(Sword))-0x200000)
-#endif
- /* go via the plt */
- v = plt + pe->offset - dot;
-
-#if defined(__v850e__)
- if (v & 1)
-#else
- if (v & 3)
-#endif
- 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
-#if defined(__v850e__)
- /* We write two shorts instead of a long because even 32-bit insns
- only need half-word alignment, but the 32-bit data write needs
- to be long-word aligned. */
- ((unsigned short *)loc)[0] =
- (*(unsigned short *)loc & 0xffc0) /* opcode + reg */
- | ((v >> 16) & 0x3f); /* offs high part */
- ((unsigned short *)loc)[1] =
- (v & 0xffff); /* offs low part */
-#endif
- break;
-#endif /* USE_PLT_ENTRIES */
-
-#if defined(USE_GOT_ENTRIES)
-bb_use_got:
-
- /* needs an entry in the .got: set it, once */
- if (!isym->gotent.inited) {
- isym->gotent.inited = 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;
-
-#endif /* USE_GOT_ENTRIES */
- }
-
- return ret;
-}
-
-
-#if defined(USE_LIST)
-
-static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list,
- int offset, int size)
-{
- struct arch_list_entry *pe;
-
- for (pe = *list; pe != NULL; pe = pe->next) {
- if (pe->addend == rel->r_addend) {
- break;
- }
- }
-
- if (pe == NULL) {
- pe = xmalloc(sizeof(struct arch_list_entry));
- pe->next = *list;
- pe->addend = rel->r_addend;
- pe->offset = offset;
- pe->inited = 0;
- *list = pe;
- return size;
- }
- return 0;
-}
-
-#endif
-
-#if defined(USE_SINGLE)
-
-static int arch_single_init(/*ElfW(RelM) *rel,*/ struct arch_single_entry *single,
- int offset, int size)
-{
- if (single->allocated == 0) {
- single->allocated = 1;
- single->offset = offset;
- single->inited = 0;
- return size;
- }
- return 0;
-}
-
-#endif
-
-#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
-
-static struct obj_section *arch_xsect_init(struct obj_file *f, const char *name,
- int offset, int size)
-{
- struct obj_section *myrelsec = obj_find_section(f, name);
-
- if (offset == 0) {
- offset += size;
- }
-
- if (myrelsec) {
- obj_extend_section(myrelsec, offset);
- } else {
- myrelsec = obj_create_alloced_section(f, name,
- size, offset);
- }
-
- return myrelsec;
-}
-
-#endif
-
-static void arch_create_got(struct obj_file *f)
-{
-#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
- struct arch_file *ifile = (struct arch_file *) f;
- int i;
-#if defined(USE_GOT_ENTRIES)
- int got_offset = 0, got_needed = 0, got_allocate;
-#endif
-#if defined(USE_PLT_ENTRIES)
- int plt_offset = 0, plt_needed = 0, plt_allocate;
-#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[ELF_R_SYM(rel->r_info)];
-
-#if defined(USE_GOT_ENTRIES)
- got_allocate = 0;
-#endif
-#if defined(USE_PLT_ENTRIES)
- plt_allocate = 0;
-#endif
-
- switch (ELF_R_TYPE(rel->r_info)) {
-#if defined(__arm__)
- case R_ARM_PC24:
- case R_ARM_PLT32:
- plt_allocate = 1;
- break;
-
- case R_ARM_GOTOFF:
- case R_ARM_GOTPC:
- got_needed = 1;
- continue;
-
- case R_ARM_GOT32:
- got_allocate = 1;
- break;
-
-#elif defined(__i386__)
- case R_386_GOTPC:
- case R_386_GOTOFF:
- got_needed = 1;
- continue;
-
- case R_386_GOT32:
- got_allocate = 1;
- break;
-
-#elif defined(__powerpc__)
- case R_PPC_REL24:
- plt_allocate = 1;
- break;
-
-#elif defined(__mc68000__)
- case R_68K_GOT32:
- got_allocate = 1;
- break;
-
-#ifdef R_68K_GOTOFF
- case R_68K_GOTOFF:
- got_needed = 1;
- continue;
-#endif
-
-#elif defined(__sh__)
- case R_SH_GOT32:
- got_allocate = 1;
- break;
-
- case R_SH_GOTPC:
- case R_SH_GOTOFF:
- got_needed = 1;
- continue;
-
-#elif defined(__v850e__)
- case R_V850_22_PCREL:
- plt_needed = 1;
- break;
-
-#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(USE_GOT_ENTRIES)
- if (got_allocate) {
- got_offset += arch_single_init(
- /*rel,*/ &intsym->gotent,
- got_offset, GOT_ENTRY_SIZE);
-
- got_needed = 1;
- }
-#endif
-#if defined(USE_PLT_ENTRIES)
- if (plt_allocate) {
-#if defined(USE_PLT_LIST)
- plt_offset += arch_list_add(
- rel, &intsym->pltent,
- plt_offset, PLT_ENTRY_SIZE);
-#else
- plt_offset += arch_single_init(
- /*rel,*/ &intsym->pltent,
- plt_offset, PLT_ENTRY_SIZE);
-#endif
- plt_needed = 1;
- }
-#endif
- }
- }
-
-#if defined(USE_GOT_ENTRIES)
- if (got_needed) {
- ifile->got = arch_xsect_init(f, ".got", got_offset,
- GOT_ENTRY_SIZE);
- }
-#endif
-
-#if defined(USE_PLT_ENTRIES)
- if (plt_needed) {
- ifile->plt = arch_xsect_init(f, ".plt", plt_offset,
- PLT_ENTRY_SIZE);
- }
-#endif
-
-#endif /* defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES) */
-}
-
-/*======================================================================*/
-
-/* Standard ELF hash function. */
-static 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;
- g = (h & 0xf0000000);
- if (g != 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));
-}
-
-#if ENABLE_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 /* 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 = ELF_ST_TYPE(info);
- int n_binding = ELF_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 = ELF_ST_TYPE(o_info);
- int o_binding = ELF_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)
- bb_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 (ELF_ST_BIND(info) == STB_LOCAL && symidx != (unsigned long)(-1)) {
- if (symidx >= f->local_symtab_size)
- bb_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;
- }
- /* 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") != 0
- ) {
- 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_vector(f->sections, 2, newidx);
- f->sections[newidx] = sec = arch_new_section();
-
- 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 = xzalloc(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_vector(f->sections, 2, newidx);
- f->sections[newidx] = sec = arch_new_section();
-
- 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 = xzalloc(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->header.sh_size += more;
- sec->contents = xrealloc(sec->contents, sec->header.sh_size);
- }
- 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;
-#ifdef SYMBOL_PREFIX
- char *name_buf = 0;
- size_t name_alloced_size = 0;
-#endif
-#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
- int gpl;
-
- gpl = obj_gpl_license(f, NULL) == 0;
-#endif
- 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;
- char *name;
-
- /* GPL licensed modules can use symbols exported with
- * EXPORT_SYMBOL_GPL, so ignore any GPLONLY_ prefix on the
- * exported names. Non-GPL modules never see any GPLONLY_
- * symbols so they cannot fudge it by adding the prefix on
- * their references.
- */
- if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) {
-#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
- if (gpl)
- s->name += 8;
- else
-#endif
- continue;
- }
- name = (char *)s->name;
-
-#ifdef SYMBOL_PREFIX
- /* Prepend SYMBOL_PREFIX to the symbol's name (the
- kernel exports `C names', but module object files
- reference `linker names'). */
- size_t extra = sizeof SYMBOL_PREFIX;
- size_t name_size = strlen(name) + extra;
- if (name_size > name_alloced_size) {
- name_alloced_size = name_size * 2;
- name_buf = alloca(name_alloced_size);
- }
- strcpy(name_buf, SYMBOL_PREFIX);
- strcpy(name_buf + extra - 1, name);
- name = name_buf;
-#endif /* SYMBOL_PREFIX */
-
- sym = obj_find_symbol(f, name);
- if (sym && !(ELF_ST_BIND(sym->info) == STB_LOCAL)) {
-#ifdef SYMBOL_PREFIX
- /* Put NAME_BUF into more permanent storage. */
- name = xmalloc(name_size);
- strcpy(name, name_buf);
-#endif
- sym = obj_add_symbol(f, name, -1,
- ELF_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 after 2.1.18. */
-
-static void
-new_process_module_arguments(struct obj_file *f, int argc, char **argv)
-{
- while (argc > 0) {
- char *p, *q, *key, *sym_name;
- struct obj_symbol *sym;
- char *contents, *loc;
- int min, max, n;
-
- p = *argv;
- q = strchr(p, '=');
- if (q == 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) {
- bb_error_msg_and_die("invalid parameter %s", key);
- }
-
-#ifdef SYMBOL_PREFIX
- sym_name = alloca(strlen(key) + sizeof SYMBOL_PREFIX);
- strcpy(sym_name, SYMBOL_PREFIX);
- strcat(sym_name, key);
-#else
- sym_name = key;
-#endif
- sym = obj_find_symbol(f, sym_name);
-
- /* Also check that the parameter was not resolved from the kernel. */
- if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
- bb_error_msg_and_die("symbol for parameter %s not found", key);
- }
-
- 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')
- bb_error_msg_and_die("improperly terminated string argument for %s",
- key);
- 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 useful, as the previous case
- doesn't nul terminate the string ??? */
- str[r - q] = '\0';
-
- /* Keep next fields */
- q = r;
- } else {
- /* last string */
- str = q;
- q = (char*)"";
- }
- }
-
- 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))) {
- bb_error_msg_and_die("parameter type 'c' for %s must be followed by"
- " the maximum size", key);
- }
- charssize = strtoul(p + 1, (char **) NULL, 10);
-
- /* Check length */
- if (strlen(str) >= charssize) {
- bb_error_msg_and_die("string too long for %s (max %ld)", key,
- charssize - 1);
- }
-
- /* 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:
- bb_error_msg_and_die("unknown parameter type '%c' for %s", *p, key);
- }
- }
- 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) {
- bb_error_msg_and_die("too many values for %s (max %d)", key, max);
- }
- ++q;
- break;
-
- default:
- bb_error_msg_and_die("invalid argument syntax for %s", key);
- }
- }
- end_of_arg:
- if (n < min) {
- bb_error_msg_and_die("too few values for %s (min %d)", key, min);
- }
-
- argc--;
- argv++;
- }
-}
-
-#if ENABLE_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 xatoi(p);
- 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;
- safe_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 /* FEATURE_INSMOD_VERSION_CHECKING */
-
-
-/* Fetch the loaded modules, and all currently exported symbols. */
-
-static void 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. */
-
- bufsize = 256;
- module_names = xmalloc(bufsize);
-
- retry_modules_load:
- if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
- if (errno == ENOSPC && bufsize < ret) {
- bufsize = ret;
- module_names = xrealloc(module_names, bufsize);
- goto retry_modules_load;
- }
- bb_perror_msg_and_die("QM_MODULES");
- }
-
- n_ext_modules = nmod = ret;
-
- /* Collect the modules' symbols. */
-
- if (nmod) {
- ext_modules = modules = xzalloc(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;
- }
- bb_perror_msg_and_die("query_module: QM_INFO: %s", mn);
- }
-
- bufsize = 1024;
- syms = xmalloc(bufsize);
- retry_mod_sym_load:
- if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
- switch (errno) {
- case ENOSPC:
- bufsize = ret;
- syms = xrealloc(syms, bufsize);
- goto retry_mod_sym_load;
- case ENOENT:
- /* The module was removed out from underneath us. */
- continue;
- default:
- bb_perror_msg_and_die("query_module: QM_SYMBOLS: %s", mn);
- }
- }
- 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) {
- bufsize = ret;
- syms = xrealloc(syms, bufsize);
- goto retry_kern_sym_load;
- }
- bb_perror_msg_and_die("kernel: QM_SYMBOLS");
- }
- nksyms = nsyms = ret;
- ksyms = syms;
-
- for (j = 0, s = syms; j < nsyms; ++j, ++s) {
- s->name += (unsigned long) syms;
- }
-}
-
-
-/* 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 void 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));
- /* done by obj_create_alloced_section_first: */
- /*memset(sec->contents, 0, sizeof(struct new_module));*/
-
- obj_add_symbol(f, SPFX "__this_module", -1,
- ELF_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);
-}
-
-#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
-/* add an entry to the __ksymtab section, creating it if necessary */
-static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym)
-{
- struct obj_section *sec;
- ElfW(Addr) ofs;
-
- /* ensure __ksymtab is allocated, EXPORT_NOSYMBOLS creates a non-alloc section.
- * If __ksymtab is defined but not marked alloc, x out the first character
- * (no obj_delete routine) and create a new __ksymtab with the correct
- * characteristics.
- */
- sec = obj_find_section(f, "__ksymtab");
- if (sec && !(sec->header.sh_flags & SHF_ALLOC)) {
- *((char *)(sec->name)) = 'x'; /* override const */
- sec = NULL;
- }
- if (!sec)
- sec = obj_create_alloced_section(f, "__ksymtab",
- tgt_sizeof_void_p, 0);
- if (!sec)
- return;
- sec->header.sh_flags |= SHF_ALLOC;
- /* Empty section might be byte-aligned */
- sec->header.sh_addralign = tgt_sizeof_void_p;
- ofs = sec->header.sh_size;
- obj_symbol_patch(f, sec->idx, ofs, sym);
- obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name);
- obj_extend_section(sec, 2 * tgt_sizeof_char_p);
-}
-#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
-
-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, SPFX "__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_noexport && !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. */
- i = f->header.e_shnum;
- loaded = alloca(sizeof(int) * i);
- 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 (ELF_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) {
- bb_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, SPFX "init_module"));
- module->cleanup =
- obj_symbol_final_value(f, obj_find_symbol(f, SPFX "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;
- }
-
- /* 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 = init_module(m_name, (struct new_module *) image);
- if (ret)
- bb_perror_msg("init_module: %s", m_name);
-
- free(image);
-
- return ret == 0;
-}
-
-
-/*======================================================================*/
-
-static void
-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);
-}
-
-static void
-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;
-}
-
-static void obj_check_undefineds(struct obj_file *f)
-{
- unsigned 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_UNDEF) {
- if (ELF_ST_BIND(sym->info) == STB_WEAK) {
- sym->secidx = SHN_ABS;
- sym->value = 0;
- } else {
- if (!flag_quiet)
- bb_error_msg_and_die("unresolved symbol %s", sym->name);
- }
- }
- }
-}
-
-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->header.e_shnum++;
- f->sections = xrealloc_vector(f->sections, 2, i);
- f->sections[i] = sec = arch_new_section();
-
- 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) {
- s->contents = NULL;
- if (s->header.sh_size != 0)
- s->contents = xzalloc(s->header.sh_size),
- 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 = ELF_R_SYM(rel->r_info);
- if (symndx) {
- /* Note we've already checked for undefined symbols. */
-
- extsym = &symtab[symndx];
- if (ELF_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
- || ELF_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) {
- bb_error_msg("%s of type %ld for %s", errmsg,
- (long) ELF_R_TYPE(rel->r_info),
- strtab + extsym->st_name);
- } else {
- bb_error_msg("%s of type %ld", errmsg,
- (long) ELF_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 UNUSED_PARAM)
-{
- struct obj_file *f;
- ElfW(Shdr) * section_headers;
- size_t shnum, i;
- char *shstrtab;
-
- /* Read the file header. */
-
- f = arch_new_file();
- 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) {
- bb_perror_msg_and_die("error reading ELF header");
- }
-
- 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
- ) {
- bb_error_msg_and_die("not an ELF file");
- }
- if (f->header.e_ident[EI_CLASS] != ELFCLASSM
- || f->header.e_ident[EI_DATA] != (BB_BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB)
- || f->header.e_ident[EI_VERSION] != EV_CURRENT
- || !MATCH_MACHINE(f->header.e_machine)
- ) {
- bb_error_msg_and_die("ELF file not for this architecture");
- }
- if (f->header.e_type != ET_REL) {
- bb_error_msg_and_die("ELF file not a relocatable object");
- }
-
- /* Read the section headers. */
-
- if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
- bb_error_msg_and_die("section header size mismatch: %lu != %lu",
- (unsigned long) f->header.e_shentsize,
- (unsigned long) sizeof(ElfW(Shdr)));
- }
-
- shnum = f->header.e_shnum;
- /* Growth of ->sections vector will be done by
- * xrealloc_vector(..., 2, ...), therefore we must allocate
- * at least 2^2 = 4 extra elements here. */
- f->sections = xzalloc(sizeof(f->sections[0]) * (shnum + 4));
-
- 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) {
- bb_perror_msg_and_die("error reading ELF section headers");
- }
-
- /* Read the section data. */
-
- for (i = 0; i < shnum; ++i) {
- struct obj_section *sec;
-
- f->sections[i] = sec = arch_new_section();
-
- 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:
- sec->contents = NULL;
- if (sec->header.sh_size > 0) {
- sec->contents = xzalloc(sec->header.sh_size);
- fseek(fp, sec->header.sh_offset, SEEK_SET);
- if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
- bb_perror_msg_and_die("error reading ELF section data");
- }
- }
- break;
-
-#if SHT_RELM == SHT_REL
- case SHT_RELA:
- bb_error_msg_and_die("RELA relocations not supported on this architecture");
-#else
- case SHT_REL:
- bb_error_msg_and_die("REL relocations not supported on this architecture");
-#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;
- }
-
- bb_error_msg_and_die("can't handle sections of type %ld",
- (long) sec->header.sh_type);
- }
- }
- }
-
- /* 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))) {
- bb_error_msg_and_die("symbol size mismatch: %lu != %lu",
- (unsigned long) sec->header.sh_entsize,
- (unsigned long) sizeof(ElfW(Sym)));
- }
-
- 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 = xzalloc(j * sizeof(struct obj_symbol *));
-
- /* Insert all symbols into the hash table. */
- for (j = 1, ++sym; j < nsym; ++j, ++sym) {
- ElfW(Addr) val = sym->st_value;
- const char *name;
- if (sym->st_name)
- name = strtab + sym->st_name;
- else if (sym->st_shndx < shnum)
- name = f->sections[sym->st_shndx]->name;
- else
- continue;
-#if defined(__SH5__)
- /*
- * For sh64 it is possible that the target of a branch
- * requires a mode switch (32 to 16 and back again).
- *
- * This is implied by the lsb being set in the target
- * address for SHmedia mode and clear for SHcompact.
- */
- val |= sym->st_other & 4;
-#endif
- obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
- val, sym->st_size);
- }
- }
- break;
-
- case SHT_RELM:
- if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
- bb_error_msg_and_die("relocation entry size mismatch: %lu != %lu",
- (unsigned long) sec->header.sh_entsize,
- (unsigned long) sizeof(ElfW(RelM)));
- }
- 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;
-}
-
-#if ENABLE_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) {
- bb_perror_msg("error reading ELF section data");
- return 0;
- }
-
- }
- return 1;
-}
-#endif
-
-static void hide_special_symbols(struct obj_file *f)
-{
- static const char *const specials[] = {
- SPFX "cleanup_module",
- SPFX "init_module",
- SPFX "kernel_version",
- NULL
- };
-
- struct obj_symbol *sym;
- const char *const *p;
-
- for (p = specials; *p; ++p) {
- sym = obj_find_symbol(f, *p);
- if (sym != NULL)
- sym->info = ELF_ST_INFO(STB_LOCAL, ELF_ST_TYPE(sym->info));
- }
-}
-
-
-#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
-static int obj_gpl_license(struct obj_file *f, const char **license)
-{
- struct obj_section *sec;
- /* This list must match *exactly* the list of allowable licenses in
- * linux/include/linux/module.h. Checking for leading "GPL" will not
- * work, somebody will use "GPL sucks, this is proprietary".
- */
- static const char *const gpl_licenses[] = {
- "GPL",
- "GPL v2",
- "GPL and additional rights",
- "Dual BSD/GPL",
- "Dual MPL/GPL"
- };
-
- sec = obj_find_section(f, ".modinfo");
- if (sec) {
- const char *value, *ptr, *endptr;
- ptr = sec->contents;
- endptr = ptr + sec->header.sh_size;
- while (ptr < endptr) {
- value = strchr(ptr, '=');
- if (value && strncmp(ptr, "license", value-ptr) == 0) {
- unsigned i;
- if (license)
- *license = value+1;
- for (i = 0; i < ARRAY_SIZE(gpl_licenses); ++i) {
- if (strcmp(value+1, gpl_licenses[i]) == 0)
- return 0;
- }
- return 2;
- }
- ptr = strchr(ptr, '\0');
- if (ptr)
- ptr++;
- else
- ptr = endptr;
- }
- }
- return 1;
-}
-
-#define TAINT_FILENAME "/proc/sys/kernel/tainted"
-#define TAINT_PROPRIETORY_MODULE (1 << 0)
-#define TAINT_FORCED_MODULE (1 << 1)
-#define TAINT_UNSAFE_SMP (1 << 2)
-#define TAINT_URL "http://www.tux.org/lkml/#export-tainted"
-
-static void set_tainted(int fd, char *m_name,
- int kernel_has_tainted, int taint, const char *text1, const char *text2)
-{
- static smallint printed_info;
-
- char buf[80];
- int oldval;
-
- if (fd < 0 && !kernel_has_tainted)
- return; /* New modutils on old kernel */
- printf("Warning: loading %s will taint the kernel: %s%s\n",
- m_name, text1, text2);
- if (!printed_info) {
- printf(" See %s for information about tainted modules\n", TAINT_URL);
- printed_info = 1;
- }
- if (fd >= 0) {
- read(fd, buf, sizeof(buf)-1);
- buf[sizeof(buf)-1] = '\0';
- oldval = strtoul(buf, NULL, 10);
- sprintf(buf, "%d\n", oldval | taint);
- write(fd, buf, strlen(buf));
- }
-}
-
-/* Check if loading this module will taint the kernel. */
-static void check_tainted_module(struct obj_file *f, char *m_name)
-{
- static const char tainted_file[] ALIGN1 = TAINT_FILENAME;
-
- int fd, kernel_has_tainted;
- const char *ptr;
-
- kernel_has_tainted = 1;
- fd = open(tainted_file, O_RDWR);
- if (fd < 0) {
- if (errno == ENOENT)
- kernel_has_tainted = 0;
- else if (errno == EACCES)
- kernel_has_tainted = 1;
- else {
- perror(tainted_file);
- kernel_has_tainted = 0;
- }
- }
-
- switch (obj_gpl_license(f, &ptr)) {
- case 0:
- break;
- case 1:
- set_tainted(fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
- break;
- case 2:
- /* The module has a non-GPL license so we pretend that the
- * kernel always has a taint flag to get a warning even on
- * kernels without the proc flag.
- */
- set_tainted(fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
- break;
- default:
- set_tainted(fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
- break;
- }
-
- if (flag_force_load)
- set_tainted(fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
-
- if (fd >= 0)
- close(fd);
-}
-#else /* FEATURE_CHECK_TAINTED_MODULE */
-#define check_tainted_module(x, y) do { } while (0);
-#endif /* FEATURE_CHECK_TAINTED_MODULE */
-
-#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
-/* add module source, timestamp, kernel version and a symbol for the
- * start of some sections. this info is used by ksymoops to do better
- * debugging.
- */
-#if !ENABLE_FEATURE_INSMOD_VERSION_CHECKING
-#define get_module_version(f, str) get_module_version(str)
-#endif
-static int
-get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
-{
-#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
- return new_get_module_version(f, str);
-#else /* FEATURE_INSMOD_VERSION_CHECKING */
- strncpy(str, "???", sizeof(str));
- return -1;
-#endif /* FEATURE_INSMOD_VERSION_CHECKING */
-}
-
-/* add module source, timestamp, kernel version and a symbol for the
- * start of some sections. this info is used by ksymoops to do better
- * debugging.
- */
-static void
-add_ksymoops_symbols(struct obj_file *f, const char *filename,
- const char *m_name)
-{
- static const char symprefix[] ALIGN1 = "__insmod_";
- static const char section_names[][8] = {
- ".text",
- ".rodata",
- ".data",
- ".bss",
- ".sbss"
- };
-
- struct obj_section *sec;
- struct obj_symbol *sym;
- char *name, *absolute_filename;
- char str[STRVERSIONLEN];
- unsigned i;
- int l, lm_name, lfilename, use_ksymtab, version;
- struct stat statbuf;
-
- /* WARNING: was using realpath, but replaced by readlink to stop using
- * lots of stack. But here it seems to be able to cause problems? */
- absolute_filename = xmalloc_readlink(filename);
- if (!absolute_filename)
- absolute_filename = xstrdup(filename);
-
- lm_name = strlen(m_name);
- lfilename = strlen(absolute_filename);
-
- /* add to ksymtab if it already exists or there is no ksymtab and other symbols
- * are not to be exported. otherwise leave ksymtab alone for now, the
- * "export all symbols" compatibility code will export these symbols later.
- */
- use_ksymtab = obj_find_section(f, "__ksymtab") || flag_noexport;
-
- sec = obj_find_section(f, ".this");
- if (sec) {
- /* tag the module header with the object name, last modified
- * timestamp and module version. worst case for module version
- * is 0xffffff, decimal 16777215. putting all three fields in
- * one symbol is less readable but saves kernel space.
- */
- l = sizeof(symprefix) + /* "__insmod_" */
- lm_name + /* module name */
- 2 + /* "_O" */
- lfilename + /* object filename */
- 2 + /* "_M" */
- 2 * sizeof(statbuf.st_mtime) + /* mtime in hex */
- 2 + /* "_V" */
- 8 + /* version in dec */
- 1; /* nul */
- name = xmalloc(l);
- if (stat(absolute_filename, &statbuf) != 0)
- statbuf.st_mtime = 0;
- version = get_module_version(f, str); /* -1 if not found */
- snprintf(name, l, "%s%s_O%s_M%0*lX_V%d",
- symprefix, m_name, absolute_filename,
- (int)(2 * sizeof(statbuf.st_mtime)), statbuf.st_mtime,
- version);
- sym = obj_add_symbol(f, name, -1,
- ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
- sec->idx, sec->header.sh_addr, 0);
- if (use_ksymtab)
- new_add_ksymtab(f, sym);
- }
- free(absolute_filename);
-#ifdef _NOT_SUPPORTED_
- /* record where the persistent data is going, same address as previous symbol */
-
- if (f->persist) {
- l = sizeof(symprefix) + /* "__insmod_" */
- lm_name + /* module name */
- 2 + /* "_P" */
- strlen(f->persist) + /* data store */
- 1; /* nul */
- name = xmalloc(l);
- snprintf(name, l, "%s%s_P%s",
- symprefix, m_name, f->persist);
- sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
- sec->idx, sec->header.sh_addr, 0);
- if (use_ksymtab)
- new_add_ksymtab(f, sym);
- }
-#endif /* _NOT_SUPPORTED_ */
- /* tag the desired sections if size is non-zero */
-
- for (i = 0; i < ARRAY_SIZE(section_names); ++i) {
- sec = obj_find_section(f, section_names[i]);
- if (sec && sec->header.sh_size) {
- l = sizeof(symprefix) + /* "__insmod_" */
- lm_name + /* module name */
- 2 + /* "_S" */
- strlen(sec->name) + /* section name */
- 2 + /* "_L" */
- 8 + /* length in dec */
- 1; /* nul */
- name = xmalloc(l);
- snprintf(name, l, "%s%s_S%s_L%ld",
- symprefix, m_name, sec->name,
- (long)sec->header.sh_size);
- sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
- sec->idx, sec->header.sh_addr, 0);
- if (use_ksymtab)
- new_add_ksymtab(f, sym);
- }
- }
-}
-#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
-
-#if ENABLE_FEATURE_INSMOD_LOAD_MAP
-static void print_load_map(struct obj_file *f)
-{
- struct obj_section *sec;
-#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL
- struct obj_symbol **all, **p;
- int i, nsyms, *loaded;
- struct obj_symbol *sym;
-#endif
- /* Report on the section layout. */
-
- printf("Sections: Size %-*s Align\n",
- (int) (2 * sizeof(void *)), "Address");
-
- for (sec = f->load_order; sec; sec = sec->load_next) {
- int a;
- unsigned long tmp;
-
- for (a = -1, tmp = sec->header.sh_addralign; tmp; ++a)
- tmp >>= 1;
- if (a == -1)
- a = 0;
-
- printf("%-15s %08lx %0*lx 2**%d\n",
- sec->name,
- (long)sec->header.sh_size,
- (int) (2 * sizeof(void *)),
- (long)sec->header.sh_addr,
- a);
- }
-#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL
- /* Quick reference which section indices are loaded. */
-
- i = f->header.e_shnum;
- loaded = alloca(sizeof(int) * i);
- while (--i >= 0)
- loaded[i] = ((f->sections[i]->header.sh_flags & SHF_ALLOC) != 0);
-
- /* Collect the symbols we'll be listing. */
-
- for (nsyms = i = 0; i < HASH_BUCKETS; ++i)
- for (sym = f->symtab[i]; sym; sym = sym->next)
- if (sym->secidx <= SHN_HIRESERVE
- && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx])
- ) {
- ++nsyms;
- }
-
- all = alloca(nsyms * sizeof(struct obj_symbol *));
-
- for (i = 0, p = all; i < HASH_BUCKETS; ++i)
- for (sym = f->symtab[i]; sym; sym = sym->next)
- if (sym->secidx <= SHN_HIRESERVE
- && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx])
- ) {
- *p++ = sym;
- }
-
- /* And list them. */
- printf("\nSymbols:\n");
- for (p = all; p < all + nsyms; ++p) {
- char type = '?';
- unsigned long value;
-
- sym = *p;
- if (sym->secidx == SHN_ABS) {
- type = 'A';
- value = sym->value;
- } else if (sym->secidx == SHN_UNDEF) {
- type = 'U';
- value = 0;
- } else {
- sec = f->sections[sym->secidx];
-
- if (sec->header.sh_type == SHT_NOBITS)
- type = 'B';
- else if (sec->header.sh_flags & SHF_ALLOC) {
- if (sec->header.sh_flags & SHF_EXECINSTR)
- type = 'T';
- else if (sec->header.sh_flags & SHF_WRITE)
- type = 'D';
- else
- type = 'R';
- }
- value = sym->value + sec->header.sh_addr;
- }
-
- if (ELF_ST_BIND(sym->info) == STB_LOCAL)
- type = tolower(type);
-
- printf("%0*lx %c %s\n", (int) (2 * sizeof(void *)), value,
- type, sym->name);
- }
-#endif
-}
-#else /* !FEATURE_INSMOD_LOAD_MAP */
-void print_load_map(struct obj_file *f);
-#endif
-
-int insmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int insmod_main(int argc, char **argv)
-{
- char *opt_o, *arg1;
- int len;
- int k_crcs;
- char *tmp, *tmp1;
- unsigned long m_size;
- ElfW(Addr) m_addr;
- struct obj_file *f;
- struct stat st;
- char *m_name = NULL;
- int exit_status = EXIT_FAILURE;
- int m_has_modinfo;
-#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
- struct utsname uts_info;
- char m_strversion[STRVERSIONLEN];
- int m_version, m_crcs;
-#endif
-#if ENABLE_FEATURE_CLEAN_UP
- FILE *fp = NULL;
-#else
- FILE *fp;
-#endif
- int k_version = 0;
- struct utsname myuname;
-
- /* Parse any options */
- getopt32(argv, OPTION_STR, &opt_o);
- arg1 = argv[optind];
- if (option_mask32 & OPT_o) { // -o /* name the output module */
- free(m_name);
- m_name = xstrdup(opt_o);
- }
-
- if (arg1 == NULL) {
- bb_show_usage();
- }
-
- /* Grab the module name */
- tmp1 = xstrdup(arg1);
- tmp = basename(tmp1);
- len = strlen(tmp);
-
- if (uname(&myuname) == 0) {
- if (myuname.release[0] == '2') {
- k_version = myuname.release[2] - '0';
- }
- }
-
-#if ENABLE_FEATURE_2_6_MODULES
- if (k_version > 4 && len > 3 && tmp[len - 3] == '.'
- && tmp[len - 2] == 'k' && tmp[len - 1] == 'o'
- ) {
- len -= 3;
- tmp[len] = '\0';
- } else
-#endif
- if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
- len -= 2;
- tmp[len] = '\0';
- }
-
-
-#if ENABLE_FEATURE_2_6_MODULES
- if (k_version > 4)
- m_fullName = xasprintf("%s.ko", tmp);
- else
-#endif
- m_fullName = xasprintf("%s.o", tmp);
-
- if (!m_name) {
- m_name = tmp;
- } else {
- free(tmp1);
- tmp1 = NULL; /* flag for free(m_name) before exit() */
- }
-
- /* Get a filedesc for the module. Check that we have a complete path */
- if (stat(arg1, &st) < 0 || !S_ISREG(st.st_mode)
- || (fp = fopen_for_read(arg1)) == NULL
- ) {
- /* 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 (k_version) { /* uname succeedd */
- char *module_dir;
- char *tmdn;
-
- tmdn = concat_path_file(CONFIG_DEFAULT_MODULES_DIR, 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... */
- module_dir = xmalloc_readlink(tmdn);
- if (!module_dir)
- module_dir = xstrdup(tmdn);
- recursive_action(module_dir, ACTION_RECURSE,
- check_module_name_match, NULL, m_fullName, 0);
- free(module_dir);
- free(tmdn);
- }
-
- /* Check if we have found anything yet */
- if (!m_filename || ((fp = fopen_for_read(m_filename)) == NULL)) {
- int r;
- char *module_dir;
-
- free(m_filename);
- m_filename = NULL;
- module_dir = xmalloc_readlink(CONFIG_DEFAULT_MODULES_DIR);
- if (!module_dir)
- module_dir = xstrdup(CONFIG_DEFAULT_MODULES_DIR);
- /* No module found under /lib/modules/`uname -r`, this
- * time cast the net a bit wider. Search /lib/modules/ */
- r = recursive_action(module_dir, ACTION_RECURSE,
- check_module_name_match, NULL, m_fullName, 0);
- if (r)
- bb_error_msg_and_die("%s: module not found", m_fullName);
- free(module_dir);
- if (m_filename == NULL
- || ((fp = fopen_for_read(m_filename)) == NULL)
- ) {
- bb_error_msg_and_die("%s: module not found", m_fullName);
- }
- }
- } else
- m_filename = xstrdup(arg1);
-
- if (flag_verbose)
- printf("Using %s\n", m_filename);
-
-#if ENABLE_FEATURE_2_6_MODULES
- if (k_version > 4) {
- argv[optind] = m_filename;
- optind--;
- return insmod_ng_main(argc - optind, argv + optind);
- }
-#endif
-
- f = obj_load(fp, LOADBITS);
-
- if (get_modinfo_value(f, "kernel_version") == NULL)
- m_has_modinfo = 0;
- else
- m_has_modinfo = 1;
-
-#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
- /* Version correspondence? */
- if (!flag_quiet) {
- if (uname(&uts_info) < 0)
- uts_info.release[0] = '\0';
- if (m_has_modinfo) {
- m_version = new_get_module_version(f, m_strversion);
- if (m_version == -1) {
- bb_error_msg_and_die("cannot find the kernel version the module was "
- "compiled for");
- }
- }
-
- if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
- bb_error_msg("%skernel-module version mismatch\n"
- "\t%s was compiled for kernel version %s\n"
- "\twhile this kernel is version %s",
- flag_force_load ? "warning: " : "",
- m_filename, m_strversion, uts_info.release);
- if (!flag_force_load)
- goto out;
- }
- }
- k_crcs = 0;
-#endif /* FEATURE_INSMOD_VERSION_CHECKING */
-
- if (query_module(NULL, 0, NULL, 0, NULL))
- bb_error_msg_and_die("not configured to support old kernels");
- new_get_kernel_symbols();
- k_crcs = new_is_kernel_checksummed();
-
-#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
- m_crcs = 0;
- if (m_has_modinfo)
- m_crcs = new_is_module_checksummed(f);
-
- if (m_crcs != k_crcs)
- obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
-#endif /* FEATURE_INSMOD_VERSION_CHECKING */
-
- /* Let the module know about the kernel symbols. */
- add_kernel_symbols(f);
-
- /* Allocate common symbols, symbol tables, and string tables. */
-
- new_create_this_module(f, m_name);
- obj_check_undefineds(f);
- obj_allocate_commons(f);
- check_tainted_module(f, m_name);
-
- /* done with the module name, on to the optional var=value arguments */
- ++optind;
- if (optind < argc) {
- new_process_module_arguments(f, argc - optind, argv + optind);
- }
-
- arch_create_got(f);
- hide_special_symbols(f);
-
-#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
- add_ksymoops_symbols(f, m_filename, m_name);
-#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
-
- 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 == (ElfW(Addr))(-1)) switch (errno) {
- case EEXIST:
- bb_error_msg_and_die("a module named %s already exists", m_name);
- case ENOMEM:
- bb_error_msg_and_die("can't allocate kernel memory for module; needed %lu bytes",
- m_size);
- default:
- bb_perror_msg_and_die("create_module: %s", m_name);
- }
-
-#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, 0);
- goto out;
- }
-#endif
-
- if (!obj_relocate(f, m_addr)) {
- delete_module(m_name, 0);
- goto out;
- }
-
- if (!new_init_module(m_name, f, m_size)) {
- delete_module(m_name, 0);
- goto out;
- }
-
- if (flag_print_load_map)
- print_load_map(f);
-
- exit_status = EXIT_SUCCESS;
-
- out:
-#if ENABLE_FEATURE_CLEAN_UP
- if (fp)
- fclose(fp);
- free(tmp1);
- if (!tmp1)
- free(m_name);
- free(m_filename);
-#endif
- return exit_status;
-}
-
-#endif /* ENABLE_FEATURE_2_4_MODULES */
-/*
- * End of big piece of 2.4-specific code
- */
-
-
-#if ENABLE_FEATURE_2_6_MODULES
-
-#include
-
-#if defined __UCLIBC__ && !ENABLE_FEATURE_2_4_MODULES
-/* big time suckage. The old prototype above renders our nice fwd-decl wrong */
-extern int init_module(void *module, unsigned long len, const char *options);
-#else
-#include
-#include
-#define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts)
-#endif
-
-/* We use error numbers in a loose translation... */
-static const char *moderror(int err)
-{
- switch (err) {
- case ENOEXEC:
- return "invalid module format";
- case ENOENT:
- return "unknown symbol in module";
- case ESRCH:
- return "module has wrong symbol version";
- case EINVAL:
- return "invalid parameters";
- default:
- return strerror(err);
- }
-}
-
-#if !ENABLE_FEATURE_2_4_MODULES
-int insmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int insmod_main(int argc UNUSED_PARAM, char **argv)
-#else
-static int insmod_ng_main(int argc UNUSED_PARAM, char **argv)
-#endif
-{
- size_t len;
- int optlen;
- void *map;
- char *filename, *options;
-
- filename = *++argv;
- if (!filename)
- bb_show_usage();
-
- /* Rest is options */
- options = xzalloc(1);
- optlen = 0;
- while (*++argv) {
- options = xrealloc(options, optlen + 2 + strlen(*argv) + 2);
- /* Spaces handled by "" pairs, but no way of escaping quotes */
- optlen += sprintf(options + optlen, (strchr(*argv,' ') ? "\"%s\" " : "%s "), *argv);
- }
-
-#if 0
- /* Any special reason why mmap? It isn't performance critical. -vda */
- /* Yes, xmalloc'ing can use *alot* of RAM. Don't forget that there are
- * modules out there that are half a megabyte! mmap()ing is way nicer
- * for small mem boxes, i guess. */
- /* But after load, these modules will take up that 0.5mb in kernel
- * anyway. Using malloc here causes only a transient spike to 1mb,
- * after module is loaded, we go back to normal 0.5mb usage
- * (in kernel). Also, mmap isn't magic - when we touch mapped data,
- * we use memory. -vda */
- int fd;
- struct stat st;
- unsigned long len;
- fd = xopen(filename, O_RDONLY);
- fstat(fd, &st);
- len = st.st_size;
- map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
- if (map == MAP_FAILED) {
- bb_perror_msg_and_die("cannot mmap '%s'", filename);
- }
-
- /* map == NULL on Blackfin, probably on other MMU-less systems too. Workaround. */
- if (map == NULL) {
- map = xmalloc(len);
- xread(fd, map, len);
- }
-#else
- len = MAXINT(ssize_t);
- map = xmalloc_xopen_read_close(filename, &len);
-#endif
-
- if (init_module(map, len, options) != 0)
- bb_error_msg_and_die("cannot insert '%s': %s",
- filename, moderror(errno));
- return 0;
-}
-
-#endif
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini insmod implementation for busybox
+ *
+ * Copyright (C) 2008 Timo Teras
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "libbb.h"
+#include "modutils.h"
+
+int insmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int insmod_main(int argc UNUSED_PARAM, char **argv)
+{
+ char *filename;
+ int rc;
+
+ /* Compat note:
+ * 2.6 style insmod has no options and required filename
+ * (not module name - .ko can't be omitted).
+ * 2.4 style insmod can take module name without .o
+ * and performs module search in default directories
+ * or in $MODPATH.
+ */
+
+ USE_FEATURE_2_4_MODULES(
+ getopt32(argv, INSMOD_OPTS INSMOD_ARGS);
+ argv += optind - 1;
+ );
+
+ filename = *++argv;
+ if (!filename)
+ bb_show_usage();
+
+ rc = bb_init_module(filename, parse_cmdline_module_options(argv));
+ if (rc)
+ bb_error_msg("can't insert '%s': %s", filename, moderror(rc));
+
+ return rc;
+}
diff --git a/release/src/router/busybox/modutils/lsmod.c b/release/src/router/busybox/modutils/lsmod.c
dissimilarity index 83%
index 3f237039e9..87dd1fcba9 100644
--- a/release/src/router/busybox/modutils/lsmod.c
+++ b/release/src/router/busybox/modutils/lsmod.c
@@ -1,194 +1,79 @@
-/* vi: set sw=4 ts=4: */
-/*
- * Mini lsmod implementation for busybox
- *
- * Copyright (C) 1999-2004 by Erik Andersen
- *
- * Modified by Alcove, Julien Gaulmin and
- * Nicolas Ferre to support pre 2.1 kernels
- * (which lack the query_module() interface).
- *
- * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
- */
-
-#include "libbb.h"
-
-
-#if !ENABLE_FEATURE_CHECK_TAINTED_MODULE
-static void check_tainted(void) { bb_putchar('\n'); }
-#else
-#define TAINT_FILENAME "/proc/sys/kernel/tainted"
-#define TAINT_PROPRIETORY_MODULE (1<<0)
-#define TAINT_FORCED_MODULE (1<<1)
-#define TAINT_UNSAFE_SMP (1<<2)
-
-static void check_tainted(void)
-{
- int tainted;
- FILE *f;
-
- tainted = 0;
- f = fopen_for_read(TAINT_FILENAME);
- if (f) {
- fscanf(f, "%d", &tainted);
- fclose(f);
- }
- if (tainted) {
- printf(" Tainted: %c%c%c\n",
- tainted & TAINT_PROPRIETORY_MODULE ? 'P' : 'G',
- tainted & TAINT_FORCED_MODULE ? 'F' : ' ',
- tainted & TAINT_UNSAFE_SMP ? 'S' : ' ');
- } else {
- printf(" Not tainted\n");
- }
-}
-#endif
-
-#if ENABLE_FEATURE_QUERY_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);
-
-enum {
-/* Values for query_module's which. */
- QM_MODULES = 1,
- QM_DEPS = 2,
- QM_REFS = 3,
- QM_SYMBOLS = 4,
- QM_INFO = 5,
-
-/* Bits of module.flags. */
- NEW_MOD_RUNNING = 1,
- NEW_MOD_DELETED = 2,
- NEW_MOD_AUTOCLEAN = 4,
- NEW_MOD_VISITED = 8,
- NEW_MOD_USED_ONCE = 16,
- NEW_MOD_INITIALIZING = 64
-};
-
-int lsmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int lsmod_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
-{
- struct module_info info;
- char *module_names, *mn, *deps, *dn;
- size_t bufsize, depsize, nmod, count, i, j;
-
- module_names = deps = NULL;
- bufsize = depsize = 0;
- while (query_module(NULL, QM_MODULES, module_names, bufsize, &nmod)) {
- if (errno != ENOSPC) bb_perror_msg_and_die("QM_MODULES");
- module_names = xmalloc(bufsize = nmod);
- }
-
- deps = xmalloc(depsize = 256);
- printf("Module\t\t\tSize Used by");
- check_tainted();
-
- 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 */
- bb_perror_msg_and_die("module %s: QM_INFO", mn);
- }
- while (query_module(mn, QM_REFS, deps, depsize, &count)) {
- if (errno == ENOENT) {
- /* The module was removed out from underneath us. */
- continue;
- } else if (errno != ENOSPC)
- bb_perror_msg_and_die("module %s: QM_REFS", mn);
- deps = xrealloc(deps, count);
- }
- 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)
- bb_putchar(']');
-
- bb_putchar('\n');
- }
-
-#if ENABLE_FEATURE_CLEAN_UP
- free(module_names);
-#endif
-
- return 0;
-}
-
-#else /* CONFIG_FEATURE_QUERY_MODULE_INTERFACE */
-
-int lsmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int lsmod_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
-{
- FILE *file = xfopen_for_read("/proc/modules");
-
- printf("Module Size Used by");
- check_tainted();
-#if ENABLE_FEATURE_LSMOD_PRETTY_2_6_OUTPUT
- {
- char *line;
- while ((line = xmalloc_fgets(file)) != NULL) {
- char *tok;
-
- tok = strtok(line, " \t");
- printf("%-19s", tok);
- tok = strtok(NULL, " \t\n");
- printf(" %8s", tok);
- tok = strtok(NULL, " \t\n");
- /* Null if no module unloading support. */
- if (tok) {
- printf(" %s", tok);
- tok = strtok(NULL, "\n");
- if (!tok)
- tok = (char*)"";
- /* New-style has commas, or -. If so,
- truncate (other fields might follow). */
- else if (strchr(tok, ',')) {
- tok = strtok(tok, "\t ");
- /* Strip trailing comma. */
- if (tok[strlen(tok)-1] == ',')
- tok[strlen(tok)-1] = '\0';
- } else if (tok[0] == '-'
- && (tok[1] == '\0' || isspace(tok[1]))
- ) {
- tok = (char*)"";
- }
- printf(" %s", tok);
- }
- bb_putchar('\n');
- free(line);
- }
- fclose(file);
- }
-#else
- xprint_and_close_file(file);
-#endif /* CONFIG_FEATURE_2_6_MODULES */
- return EXIT_SUCCESS;
-}
-
-#endif /* CONFIG_FEATURE_QUERY_MODULE_INTERFACE */
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini lsmod implementation for busybox
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen
+ * Copyright (C) 2008 by Vladimir Dronnikov
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "libbb.h"
+
+#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
+enum {
+ TAINT_PROPRIETORY_MODULE = (1 << 0),
+ TAINT_FORCED_MODULE = (1 << 1),
+ TAINT_UNSAFE_SMP = (1 << 2),
+};
+
+static void check_tainted(void)
+{
+ int tainted = 0;
+ char *buf = xmalloc_open_read_close("/proc/sys/kernel/tainted", NULL);
+ if (buf) {
+ tainted = atoi(buf);
+ if (ENABLE_FEATURE_CLEAN_UP)
+ free(buf);
+ }
+
+ if (tainted) {
+ printf(" Tainted: %c%c%c\n",
+ tainted & TAINT_PROPRIETORY_MODULE ? 'P' : 'G',
+ tainted & TAINT_FORCED_MODULE ? 'F' : ' ',
+ tainted & TAINT_UNSAFE_SMP ? 'S' : ' ');
+ } else {
+ puts(" Not tainted");
+ }
+}
+#else
+static void check_tainted(void) { putchar('\n'); }
+#endif
+
+int lsmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int lsmod_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
+{
+#if ENABLE_FEATURE_LSMOD_PRETTY_2_6_OUTPUT
+ char *token[4];
+ parser_t *parser = config_open("/proc/modules");
+ printf("%-24sSize Used by", "Module");
+ check_tainted();
+
+ if (ENABLE_FEATURE_2_4_MODULES
+ && get_linux_version_code() < KERNEL_VERSION(2,6,0)
+ ) {
+ while (config_read(parser, token, 4, 3, "# \t", PARSE_NORMAL)) {
+ if (token[3] != NULL && token[3][0] == '[') {
+ token[3]++;
+ token[3][strlen(token[3])-1] = '\0';
+ } else
+ token[3] = (char *) "";
+ printf("%-19s %8s %2s %s\n", token[0], token[1], token[2], token[3]);
+ }
+ } else {
+ while (config_read(parser, token, 4, 4, "# \t", PARSE_NORMAL & ~PARSE_GREEDY)) {
+ // N.B. token[3] is either '-' (module is not used by others)
+ // or comma-separated list ended by comma
+ // so trimming the trailing char is just what we need!
+ token[3][strlen(token[3])-1] = '\0';
+ printf("%-19s %8s %2s %s\n", token[0], token[1], token[2], token[3]);
+ }
+ }
+ if (ENABLE_FEATURE_CLEAN_UP)
+ config_close(parser);
+#else
+ check_tainted();
+ xprint_and_close_file(xfopen_for_read("/proc/modules"));
+#endif
+ return EXIT_SUCCESS;
+}
diff --git a/release/src/router/busybox/modutils/modprobe-small.c b/release/src/router/busybox/modutils/modprobe-small.c
index 06c45742b8..6eb950f32e 100644
--- a/release/src/router/busybox/modutils/modprobe-small.c
+++ b/release/src/router/busybox/modutils/modprobe-small.c
@@ -3,7 +3,7 @@
* simplified modprobe
*
* Copyright (c) 2008 Vladimir Dronnikov
- * Copyright (c) 2008 Bernhard Fischer (initial depmod code)
+ * Copyright (c) 2008 Bernhard Reutner-Fischer (initial depmod code)
*
* Licensed under GPLv2, see file LICENSE in this tarball for details.
*/
@@ -599,19 +599,23 @@ static void process_module(char *name, const char *cmdline_options)
}
free(deps);
- /* insmod -> load it */
+ /* modprobe -> load it */
if (!is_rmmod) {
- errno = 0;
- if (load_module(info->pathname, options) != 0) {
- if (EEXIST != errno) {
- bb_error_msg("'%s': %s",
+ if (!options || strstr(options, "blacklist") == NULL) {
+ errno = 0;
+ if (load_module(info->pathname, options) != 0) {
+ if (EEXIST != errno) {
+ bb_error_msg("'%s': %s",
info->pathname,
moderror(errno));
- } else {
- dbg1_error_msg("'%s': %s",
+ } else {
+ dbg1_error_msg("'%s': %s",
info->pathname,
moderror(errno));
+ }
}
+ } else {
+ dbg1_error_msg("'%s': blacklisted", info->pathname);
}
}
ret:
@@ -688,8 +692,10 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
/* Prevent ugly corner cases with no modules at all */
modinfo = xzalloc(sizeof(modinfo[0]));
- /* Goto modules directory */
- xchdir(CONFIG_DEFAULT_MODULES_DIR);
+ if ('i' != applet0) { /* not insmod */
+ /* Goto modules directory */
+ xchdir(CONFIG_DEFAULT_MODULES_DIR);
+ }
uname(&uts); /* never fails */
/* depmod? */
@@ -736,8 +742,10 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
option_mask32 |= OPT_r;
}
- /* Goto $VERSION directory */
- xchdir(uts.release);
+ if ('i' != applet0) { /* not insmod */
+ /* Goto $VERSION directory */
+ xchdir(uts.release);
+ }
#if ENABLE_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE
/* If not rmmod, parse possible module options given on command line.
@@ -758,11 +766,26 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
argv[1] = NULL;
#endif
+ if ('i' == applet0) { /* insmod */
+ size_t len;
+ void *map;
+
+ len = MAXINT(ssize_t);
+ map = xmalloc_xopen_read_close(*argv, &len);
+ if (init_module(map, len,
+ USE_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(options ? options : "")
+ SKIP_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE("")
+ ) != 0)
+ bb_error_msg_and_die("can't insert '%s': %s",
+ *argv, moderror(errno));
+ return 0;
+ }
+
/* Try to load modprobe.dep.bb */
load_dep_bb();
/* Load/remove modules.
- * Only rmmod loops here, insmod/modprobe has only argv[0] */
+ * Only rmmod loops here, modprobe has only argv[0] */
do {
process_module(*argv++, options);
} while (*argv);
diff --git a/release/src/router/busybox/modutils/modprobe.c b/release/src/router/busybox/modutils/modprobe.c
dissimilarity index 96%
index 8bbc2397c7..218a898a8e 100644
--- a/release/src/router/busybox/modutils/modprobe.c
+++ b/release/src/router/busybox/modutils/modprobe.c
@@ -1,952 +1,398 @@
-/* vi: set sw=4 ts=4: */
-/*
- * Modprobe written from scratch for BusyBox
- *
- * Copyright (c) 2002 by Robert Griebl, griebl@gmx.de
- * Copyright (c) 2003 by Andrew Dennison, andrew.dennison@motec.com.au
- * Copyright (c) 2005 by Jim Bauer, jfbauer@nfr.com
- *
- * Portions Copyright (c) 2005 by Yann E. MORIN, yann.morin.1998@anciens.enib.fr
- *
- * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
-*/
-
-#include "libbb.h"
-#include
-#include
-
-#define line_buffer bb_common_bufsiz1
-
-struct mod_opt_t { /* one-way list of options to pass to a module */
- char * m_opt_val;
- struct mod_opt_t * m_next;
-};
-
-struct dep_t { /* one-way list of dependency rules */
- /* a dependency rule */
- char * m_name; /* the module name*/
- char * m_path; /* the module file path */
- struct mod_opt_t * m_options; /* the module options */
-
- unsigned int m_isalias :1; /* the module is an alias */
- unsigned int m_isblacklisted:1; /* the module is blacklisted */
- unsigned int m_reserved :14; /* stuffin' */
-
- unsigned int m_depcnt :16; /* the number of dependable module(s) */
- char ** m_deparr; /* the list of dependable module(s) */
-
- struct dep_t * m_next; /* the next dependency rule */
-};
-
-struct mod_list_t { /* two-way list of modules to process */
- /* a module description */
- const char * m_name;
- char * m_path;
- struct mod_opt_t * m_options;
-
- struct mod_list_t * m_prev;
- struct mod_list_t * m_next;
-};
-
-struct include_conf_t {
- struct dep_t *first;
- struct dep_t *current;
-};
-
-static struct dep_t *depend;
-
-#define MAIN_OPT_STR "acdklnqrst:vVC:"
-#define INSERT_ALL 1 /* a */
-#define DUMP_CONF_EXIT 2 /* c */
-#define D_OPT_IGNORED 4 /* d */
-#define AUTOCLEAN_FLG 8 /* k */
-#define LIST_ALL 16 /* l */
-#define SHOW_ONLY 32 /* n */
-#define QUIET 64 /* q */
-#define REMOVE_OPT 128 /* r */
-#define DO_SYSLOG 256 /* s */
-#define RESTRICT_DIR 512 /* t */
-#define VERBOSE 1024 /* v */
-#define VERSION_ONLY 2048 /* V */
-#define CONFIG_FILE 4096 /* C */
-
-#define autoclean (option_mask32 & AUTOCLEAN_FLG)
-#define show_only (option_mask32 & SHOW_ONLY)
-#define quiet (option_mask32 & QUIET)
-#define remove_opt (option_mask32 & REMOVE_OPT)
-#define do_syslog (option_mask32 & DO_SYSLOG)
-#define verbose (option_mask32 & VERBOSE)
-
-static int parse_tag_value(char *buffer, char **ptag, char **pvalue)
-{
- char *tag, *value;
-
- buffer = skip_whitespace(buffer);
- tag = value = buffer;
- while (!isspace(*value)) {
- if (!*value)
- return 0;
- value++;
- }
- *value++ = '\0';
- value = skip_whitespace(value);
- if (!*value)
- return 0;
-
- *ptag = tag;
- *pvalue = value;
-
- return 1;
-}
-
-/*
- * This function appends an option to a list
- */
-static struct mod_opt_t *append_option(struct mod_opt_t *opt_list, char *opt)
-{
- struct mod_opt_t *ol = opt_list;
-
- if (ol) {
- while (ol->m_next) {
- ol = ol->m_next;
- }
- ol->m_next = xzalloc(sizeof(struct mod_opt_t));
- ol = ol->m_next;
- } else {
- ol = opt_list = xzalloc(sizeof(struct mod_opt_t));
- }
-
- ol->m_opt_val = xstrdup(opt);
- /*ol->m_next = NULL; - done by xzalloc*/
-
- return opt_list;
-}
-
-#if ENABLE_FEATURE_MODPROBE_MULTIPLE_OPTIONS
-/* static char* parse_command_string(char* src, char **dst);
- * src: pointer to string containing argument
- * dst: pointer to where to store the parsed argument
- * return value: the pointer to the first char after the parsed argument,
- * NULL if there was no argument parsed (only trailing spaces).
- * Note that memory is allocated with xstrdup when a new argument was
- * parsed. Don't forget to free it!
- */
-#define ARG_EMPTY 0x00
-#define ARG_IN_DQUOTES 0x01
-#define ARG_IN_SQUOTES 0x02
-static char *parse_command_string(char *src, char **dst)
-{
- int opt_status = ARG_EMPTY;
- char* tmp_str;
-
- /* Dumb you, I have nothing to do... */
- if (src == NULL) return src;
-
- /* Skip leading spaces */
- while (*src == ' ') {
- src++;
- }
- /* Is the end of string reached? */
- if (*src == '\0') {
- return NULL;
- }
- /* Reached the start of an argument
- * By the way, we duplicate a little too much
- * here but what is too much is freed later. */
- *dst = tmp_str = xstrdup(src);
- /* Get to the end of that argument */
- while (*tmp_str != '\0'
- && (*tmp_str != ' ' || (opt_status & (ARG_IN_DQUOTES | ARG_IN_SQUOTES)))
- ) {
- switch (*tmp_str) {
- case '\'':
- if (opt_status & ARG_IN_DQUOTES) {
- /* Already in double quotes, keep current char as is */
- } else {
- /* shift left 1 char, until end of string: get rid of the opening/closing quotes */
- memmove(tmp_str, tmp_str + 1, strlen(tmp_str));
- /* mark me: we enter or leave single quotes */
- opt_status ^= ARG_IN_SQUOTES;
- /* Back one char, as we need to re-scan the new char there. */
- tmp_str--;
- }
- break;
- case '"':
- if (opt_status & ARG_IN_SQUOTES) {
- /* Already in single quotes, keep current char as is */
- } else {
- /* shift left 1 char, until end of string: get rid of the opening/closing quotes */
- memmove(tmp_str, tmp_str + 1, strlen(tmp_str));
- /* mark me: we enter or leave double quotes */
- opt_status ^= ARG_IN_DQUOTES;
- /* Back one char, as we need to re-scan the new char there. */
- tmp_str--;
- }
- break;
- case '\\':
- if (opt_status & ARG_IN_SQUOTES) {
- /* Between single quotes: keep as is. */
- } else {
- switch (*(tmp_str+1)) {
- case 'a':
- case 'b':
- case 't':
- case 'n':
- case 'v':
- case 'f':
- case 'r':
- case '0':
- /* We escaped a special character. For now, keep
- * both the back-slash and the following char. */
- tmp_str++;
- src++;
- break;
- default:
- /* We escaped a space or a single or double quote,
- * or a back-slash, or a non-escapable char. Remove
- * the '\' and keep the new current char as is. */
- memmove(tmp_str, tmp_str + 1, strlen(tmp_str));
- break;
- }
- }
- break;
- /* Any other char that is special shall appear here.
- * Example: $ starts a variable
- case '$':
- do_variable_expansion();
- break;
- * */
- default:
- /* any other char is kept as is. */
- break;
- }
- tmp_str++; /* Go to next char */
- src++; /* Go to next char to find the end of the argument. */
- }
- /* End of string, but still no ending quote */
- if (opt_status & (ARG_IN_DQUOTES | ARG_IN_SQUOTES)) {
- bb_error_msg_and_die("unterminated (single or double) quote in options list: %s", src);
- }
- *tmp_str++ = '\0';
- *dst = xrealloc(*dst, (tmp_str - *dst));
- return src;
-}
-#else
-#define parse_command_string(src, dst) (0)
-#endif /* ENABLE_FEATURE_MODPROBE_MULTIPLE_OPTIONS */
-
-static int is_conf_command(char *buffer, const char *command)
-{
- int len = strlen(command);
- return ((strstr(buffer, command) == buffer) &&
- isspace(buffer[len]));
-}
-
-/*
- * This function reads aliases and default module options from a configuration file
- * (/etc/modprobe.conf syntax). It supports includes (only files, no directories).
- */
-
-static int FAST_FUNC include_conf_file_act(const char *filename,
- struct stat *statbuf UNUSED_PARAM,
- void *userdata,
- int depth UNUSED_PARAM);
-
-static int FAST_FUNC include_conf_dir_act(const char *filename UNUSED_PARAM,
- struct stat *statbuf UNUSED_PARAM,
- void *userdata UNUSED_PARAM,
- int depth)
-{
- if (depth > 1)
- return SKIP;
-
- return TRUE;
-}
-
-static int include_conf_recursive(struct include_conf_t *conf, const char *filename, int flags)
-{
- return recursive_action(filename, ACTION_RECURSE | flags,
- include_conf_file_act,
- include_conf_dir_act,
- conf, 1);
-}
-
-static int FAST_FUNC include_conf_file_act(const char *filename,
- struct stat *statbuf UNUSED_PARAM,
- void *userdata,
- int depth UNUSED_PARAM)
-{
- struct include_conf_t *conf = (struct include_conf_t *) userdata;
- struct dep_t **first = &conf->first;
- struct dep_t **current = &conf->current;
- int continuation_line = 0;
- FILE *f;
-
- if (bb_basename(filename)[0] == '.')
- return TRUE;
-
- f = fopen_for_read(filename);
- if (f == NULL)
- return FALSE;
-
- // alias parsing is not 100% correct (no correct handling of continuation lines within an alias)!
-
- while (fgets(line_buffer, sizeof(line_buffer), f)) {
- int l;
-
- *strchrnul(line_buffer, '#') = '\0';
-
- l = strlen(line_buffer);
-
- while (l && isspace(line_buffer[l-1])) {
- line_buffer[l-1] = '\0';
- l--;
- }
-
- if (l == 0) {
- continuation_line = 0;
- continue;
- }
-
- if (continuation_line)
- continue;
-
- if (is_conf_command(line_buffer, "alias")) {
- char *alias, *mod;
-
- if (parse_tag_value(line_buffer + 6, &alias, &mod)) {
- /* handle alias as a module dependent on the aliased module */
- if (!*current) {
- (*first) = (*current) = xzalloc(sizeof(struct dep_t));
- } else {
- (*current)->m_next = xzalloc(sizeof(struct dep_t));
- (*current) = (*current)->m_next;
- }
- (*current)->m_name = xstrdup(alias);
- (*current)->m_isalias = 1;
-
- if ((strcmp(mod, "off") == 0) || (strcmp(mod, "null") == 0)) {
- /*(*current)->m_depcnt = 0; - done by xzalloc */
- /*(*current)->m_deparr = 0;*/
- } else {
- (*current)->m_depcnt = 1;
- (*current)->m_deparr = xmalloc(sizeof(char *));
- (*current)->m_deparr[0] = xstrdup(mod);
- }
- /*(*current)->m_next = NULL; - done by xzalloc */
- }
- } else if (is_conf_command(line_buffer, "options")) {
- char *mod, *opt;
-
- /* split the line in the module/alias name, and options */
- if (parse_tag_value(line_buffer + 8, &mod, &opt)) {
- struct dep_t *dt;
-
- /* find the corresponding module */
- for (dt = *first; dt; dt = dt->m_next) {
- if (strcmp(dt->m_name, mod) == 0)
- break;
- }
- if (dt) {
- if (ENABLE_FEATURE_MODPROBE_MULTIPLE_OPTIONS) {
- char* new_opt = NULL;
- while ((opt = parse_command_string(opt, &new_opt))) {
- dt->m_options = append_option(dt->m_options, new_opt);
- }
- } else {
- dt->m_options = append_option(dt->m_options, opt);
- }
- }
- }
- } else if (is_conf_command(line_buffer, "include")) {
- char *includefile;
-
- includefile = skip_whitespace(line_buffer + 8);
- include_conf_recursive(conf, includefile, 0);
- } else if (ENABLE_FEATURE_MODPROBE_BLACKLIST &&
- (is_conf_command(line_buffer, "blacklist"))) {
- char *mod;
- struct dep_t *dt;
-
- mod = skip_whitespace(line_buffer + 10);
- for (dt = *first; dt; dt = dt->m_next) {
- if (strcmp(dt->m_name, mod) == 0)
- break;
- }
- if (dt)
- dt->m_isblacklisted = 1;
- }
- } /* while (fgets(...)) */
-
- fclose(f);
- return TRUE;
-}
-
-static int include_conf_file(struct include_conf_t *conf,
- const char *filename)
-{
- return include_conf_file_act(filename, NULL, conf, 0);
-}
-
-static int include_conf_file2(struct include_conf_t *conf,
- const char *filename, const char *oldname)
-{
- if (include_conf_file(conf, filename) == TRUE)
- return TRUE;
- return include_conf_file(conf, oldname);
-}
-
-/*
- * This function builds a list of dependency rules from /lib/modules/`uname -r`/modules.dep.
- * It then fills every modules and aliases with their default options, found by parsing
- * modprobe.conf (or modules.conf, or conf.modules).
- */
-static struct dep_t *build_dep(void)
-{
- FILE *f;
- struct utsname un;
- struct include_conf_t conf = { NULL, NULL };
- char *filename;
- int continuation_line = 0;
- int k_version;
-
- uname(&un); /* never fails */
-
- k_version = 0;
- if (un.release[0] == '2') {
- k_version = un.release[2] - '0';
- }
-
- filename = xasprintf(CONFIG_DEFAULT_MODULES_DIR"/%s/"CONFIG_DEFAULT_DEPMOD_FILE, un.release);
- f = fopen_for_read(filename);
- if (ENABLE_FEATURE_CLEAN_UP)
- free(filename);
- if (f == NULL) {
- /* Ok, that didn't work. Fall back to looking in /lib/modules */
- f = fopen_for_read(CONFIG_DEFAULT_MODULES_DIR"/"CONFIG_DEFAULT_DEPMOD_FILE);
- if (f == NULL) {
- bb_error_msg_and_die("cannot parse "CONFIG_DEFAULT_DEPMOD_FILE);
- }
- }
-
- while (fgets(line_buffer, sizeof(line_buffer), f)) {
- int l = strlen(line_buffer);
- char *p = NULL;
-
- while (l > 0 && isspace(line_buffer[l-1])) {
- line_buffer[l-1] = '\0';
- l--;
- }
-
- if (l == 0) {
- continuation_line = 0;
- continue;
- }
-
- /* Is this a new module dep description? */
- if (!continuation_line) {
- /* find the dep beginning */
- char *col = strchr(line_buffer, ':');
- char *dot = col;
-
- if (col) {
- /* This line is a dep description */
- const char *mods;
- char *modpath;
- char *mod;
-
- /* Find the beginning of the module file name */
- *col = '\0';
- mods = bb_basename(line_buffer);
-
- /* find the path of the module */
- modpath = strchr(line_buffer, '/'); /* ... and this is the path */
- if (!modpath)
- modpath = line_buffer; /* module with no path */
- /* find the end of the module name in the file name */
- if (ENABLE_FEATURE_2_6_MODULES &&
- (k_version > 4) && (col[-3] == '.') &&
- (col[-2] == 'k') && (col[-1] == 'o'))
- dot = col - 3;
- else if ((col[-2] == '.') && (col[-1] == 'o'))
- dot = col - 2;
-
- mod = xstrndup(mods, dot - mods);
-
- /* enqueue new module */
- if (!conf.current) {
- conf.first = conf.current = xzalloc(sizeof(struct dep_t));
- } else {
- conf.current->m_next = xzalloc(sizeof(struct dep_t));
- conf.current = conf.current->m_next;
- }
- conf.current->m_name = mod;
- conf.current->m_path = xstrdup(modpath);
- /*current->m_options = NULL; - xzalloc did it*/
- /*current->m_isalias = 0;*/
- /*current->m_depcnt = 0;*/
- /*current->m_deparr = 0;*/
- /*current->m_next = 0;*/
-
- p = col + 1;
- } else
- /* this line is not a dep description */
- p = NULL;
- } else
- /* It's a dep description continuation */
- p = line_buffer;
-
- /* p points to the first dependable module; if NULL, no dependable module */
- if (p && (p = skip_whitespace(p))[0] != '\0') {
- char *end = &line_buffer[l-1];
- const char *deps;
- char *dep;
- char *next;
- int ext = 0;
-
- while (isblank(*end) || (*end == '\\'))
- end--;
-
- do {
- /* search the end of the dependency */
- next = strchr(p, ' ');
- if (next) {
- *next = '\0';
- next--;
- } else
- next = end;
-
- /* find the beginning of the module file name */
- deps = bb_basename(p);
- if (deps == p)
- deps = skip_whitespace(deps);
-
- /* find the end of the module name in the file name */
- if (ENABLE_FEATURE_2_6_MODULES
- && (k_version > 4) && (next[-2] == '.')
- && (next[-1] == 'k') && (next[0] == 'o'))
- ext = 3;
- else if ((next[-1] == '.') && (next[0] == 'o'))
- ext = 2;
-
- /* Cope with blank lines */
- if ((next - deps - ext + 1) <= 0)
- continue;
- dep = xstrndup(deps, next - deps - ext + 1);
-
- /* Add the new dependable module name */
- conf.current->m_deparr = xrealloc_vector(conf.current->m_deparr, 2, conf.current->m_depcnt);
- conf.current->m_deparr[conf.current->m_depcnt++] = dep;
-
- p = next + 2;
- } while (next < end);
- }
-
- /* is there other dependable module(s) ? */
- continuation_line = (line_buffer[l-1] == '\\');
- } /* while (fgets(...)) */
- fclose(f);
-
- /*
- * First parse system-specific options and aliases
- * as they take precedence over the kernel ones.
- * >=2.6: we only care about modprobe.conf
- * <=2.4: we care about modules.conf and conf.modules
- */
- {
- int r = FALSE;
-
- if (ENABLE_FEATURE_2_6_MODULES) {
- if (include_conf_file(&conf, "/etc/modprobe.conf"))
- r = TRUE;
- if (include_conf_recursive(&conf, "/etc/modprobe.d", ACTION_QUIET))
- r = TRUE;
- }
- if (ENABLE_FEATURE_2_4_MODULES && !r)
- include_conf_file2(&conf,
- "/etc/modules.conf",
- "/etc/conf.modules");
- }
-
- /* Only 2.6 has a modules.alias file */
- if (ENABLE_FEATURE_2_6_MODULES) {
- /* Parse kernel-declared module aliases */
- filename = xasprintf(CONFIG_DEFAULT_MODULES_DIR"/%s/modules.alias", un.release);
- include_conf_file2(&conf,
- filename,
- CONFIG_DEFAULT_MODULES_DIR"/modules.alias");
- if (ENABLE_FEATURE_CLEAN_UP)
- free(filename);
-
- /* Parse kernel-declared symbol aliases */
- filename = xasprintf(CONFIG_DEFAULT_MODULES_DIR"/%s/modules.symbols", un.release);
- include_conf_file2(&conf,
- filename,
- CONFIG_DEFAULT_MODULES_DIR"/modules.symbols");
- if (ENABLE_FEATURE_CLEAN_UP)
- free(filename);
- }
-
- return conf.first;
-}
-
-/* return 1 = loaded, 0 = not loaded, -1 = can't tell */
-static int already_loaded(const char *name)
-{
- FILE *f;
- int ret;
-
- f = fopen_for_read("/proc/modules");
- if (f == NULL)
- return -1;
-
- ret = 0;
- while (fgets(line_buffer, sizeof(line_buffer), f)) {
- char *p = line_buffer;
- const char *n = name;
-
- while (1) {
- char cn = *n;
- char cp = *p;
- if (cp == ' ' || cp == '\0') {
- if (cn == '\0') {
- ret = 1; /* match! */
- goto done;
- }
- break; /* no match on this line, take next one */
- }
- if (cn == '-') cn = '_';
- if (cp == '-') cp = '_';
- if (cp != cn)
- break; /* no match on this line, take next one */
- n++;
- p++;
- }
- }
- done:
- fclose(f);
- return ret;
-}
-
-static int mod_process(const struct mod_list_t *list, int do_insert)
-{
- int rc = 0;
- char **argv = NULL;
- struct mod_opt_t *opts;
- int argc_malloc; /* never used when CONFIG_FEATURE_CLEAN_UP not defined */
- int argc;
-
- while (list) {
- argc = 0;
- if (ENABLE_FEATURE_CLEAN_UP)
- argc_malloc = 0;
- /* If CONFIG_FEATURE_CLEAN_UP is not defined, then we leak memory
- * each time we allocate memory for argv.
- * But it is (quite) small amounts of memory that leak each
- * time a module is loaded, and it is reclaimed when modprobe
- * exits anyway (even when standalone shell? Yes --vda).
- * This could become a problem when loading a module with LOTS of
- * dependencies, with LOTS of options for each dependencies, with
- * very little memory on the target... But in that case, the module
- * would not load because there is no more memory, so there's no
- * problem. */
- /* enough for minimal insmod (5 args + NULL) or rmmod (3 args + NULL) */
- argv = xmalloc(6 * sizeof(char*));
- if (do_insert) {
- if (already_loaded(list->m_name) != 1) {
- argv[argc++] = (char*)"insmod";
- if (ENABLE_FEATURE_2_4_MODULES) {
- if (do_syslog)
- argv[argc++] = (char*)"-s";
- if (autoclean)
- argv[argc++] = (char*)"-k";
- if (quiet)
- argv[argc++] = (char*)"-q";
- else if (verbose) /* verbose and quiet are mutually exclusive */
- argv[argc++] = (char*)"-v";
- }
- argv[argc++] = list->m_path;
- if (ENABLE_FEATURE_CLEAN_UP)
- argc_malloc = argc;
- opts = list->m_options;
- while (opts) {
- /* Add one more option */
- argc++;
- argv = xrealloc(argv, (argc + 1) * sizeof(char*));
- argv[argc-1] = opts->m_opt_val;
- opts = opts->m_next;
- }
- }
- } else {
- /* modutils uses short name for removal */
- if (already_loaded(list->m_name) != 0) {
- argv[argc++] = (char*)"rmmod";
- if (do_syslog)
- argv[argc++] = (char*)"-s";
- argv[argc++] = (char*)list->m_name;
- if (ENABLE_FEATURE_CLEAN_UP)
- argc_malloc = argc;
- }
- }
- argv[argc] = NULL;
-
- if (argc) {
- if (verbose) {
- printf("%s module %s\n", do_insert?"Loading":"Unloading", list->m_name);
- }
- if (!show_only) {
- int rc2 = wait4pid(spawn(argv));
-
- if (do_insert) {
- rc = rc2; /* only last module matters */
- } else if (!rc2) {
- rc = 0; /* success if remove any mod */
- }
- }
- if (ENABLE_FEATURE_CLEAN_UP) {
- /* the last value in the array has index == argc, but
- * it is the terminating NULL, so we must not free it. */
- while (argc_malloc < argc) {
- free(argv[argc_malloc++]);
- }
- }
- }
- if (ENABLE_FEATURE_CLEAN_UP) {
- free(argv);
- argv = NULL;
- }
- list = do_insert ? list->m_prev : list->m_next;
- }
- return (show_only) ? 0 : rc;
-}
-
-/*
- * Check the matching between a pattern and a module name.
- * We need this as *_* is equivalent to *-*, even in pattern matching.
- */
-static int check_pattern(const char* pat_src, const char* mod_src)
-{
- int ret;
-
- if (ENABLE_FEATURE_MODPROBE_FANCY_ALIAS) {
- char* pat;
- char* mod;
- char* p;
-
- pat = xstrdup(pat_src);
- mod = xstrdup(mod_src);
-
- for (p = pat; (p = strchr(p, '-')); *p++ = '_');
- for (p = mod; (p = strchr(p, '-')); *p++ = '_');
-
- ret = fnmatch(pat, mod, 0);
-
- if (ENABLE_FEATURE_CLEAN_UP) {
- free(pat);
- free(mod);
- }
-
- return ret;
- }
- return fnmatch(pat_src, mod_src, 0);
-}
-
-/*
- * Builds the dependency list (aka stack) of a module.
- * head: the highest module in the stack (last to insmod, first to rmmod)
- * tail: the lowest module in the stack (first to insmod, last to rmmod)
- */
-static void check_dep(char *mod, struct mod_list_t **head, struct mod_list_t **tail)
-{
- struct mod_list_t *find;
- struct dep_t *dt;
- struct mod_opt_t *opt = NULL;
- char *path = NULL;
-
- /* Search for the given module name amongst all dependency rules.
- * The module name in a dependency rule can be a shell pattern,
- * so try to match the given module name against such a pattern.
- * Of course if the name in the dependency rule is a plain string,
- * then we consider it a pattern, and matching will still work. */
- for (dt = depend; dt; dt = dt->m_next) {
- if (check_pattern(dt->m_name, mod) == 0) {
- break;
- }
- }
-
- if (!dt) {
- bb_error_msg("module %s not found", mod);
- return;
- }
-
- // resolve alias names
- while (dt->m_isalias) {
- if (dt->m_depcnt == 1) {
- struct dep_t *adt;
-
- for (adt = depend; adt; adt = adt->m_next) {
- if (check_pattern(adt->m_name, dt->m_deparr[0]) == 0 &&
- !(ENABLE_FEATURE_MODPROBE_BLACKLIST &&
- adt->m_isblacklisted))
- break;
- }
- if (adt) {
- /* This is the module we are aliased to */
- struct mod_opt_t *opts = dt->m_options;
- /* Option of the alias are appended to the options of the module */
- while (opts) {
- adt->m_options = append_option(adt->m_options, opts->m_opt_val);
- opts = opts->m_next;
- }
- dt = adt;
- } else {
- bb_error_msg("module %s not found", mod);
- return;
- }
- } else {
- bb_error_msg("bad alias %s", dt->m_name);
- return;
- }
- }
-
- mod = dt->m_name;
- path = dt->m_path;
- opt = dt->m_options;
-
- // search for duplicates
- for (find = *head; find; find = find->m_next) {
- if (strcmp(mod, find->m_name) == 0) {
- // found -> dequeue it
-
- if (find->m_prev)
- find->m_prev->m_next = find->m_next;
- else
- *head = find->m_next;
-
- if (find->m_next)
- find->m_next->m_prev = find->m_prev;
- else
- *tail = find->m_prev;
-
- break; // there can be only one duplicate
- }
- }
-
- if (!find) { // did not find a duplicate
- find = xzalloc(sizeof(struct mod_list_t));
- find->m_name = mod;
- find->m_path = path;
- find->m_options = opt;
- }
-
- // enqueue at tail
- if (*tail)
- (*tail)->m_next = find;
- find->m_prev = *tail;
- find->m_next = NULL; /* possibly NOT done by xzalloc! */
-
- if (!*head)
- *head = find;
- *tail = find;
-
- if (dt) {
- int i;
-
- /* Add all dependable module for that new module */
- for (i = 0; i < dt->m_depcnt; i++)
- check_dep(dt->m_deparr[i], head, tail);
- }
-}
-
-static int mod_insert(char **argv)
-{
- struct mod_list_t *tail = NULL;
- struct mod_list_t *head = NULL;
- char *modname = *argv++;
- int rc;
-
- // get dep list for module mod
- check_dep(modname, &head, &tail);
-
- rc = 1;
- if (head && tail) {
- while (*argv)
- head->m_options = append_option(head->m_options, *argv++);
-
- // process tail ---> head
- rc = mod_process(tail, 1);
- if (rc) {
- /*
- * In case of using udev, multiple instances of modprobe can be
- * spawned to load the same module (think of two same usb devices,
- * for example; or cold-plugging at boot time). Thus we shouldn't
- * fail if the module was loaded, and not by us.
- */
- if (already_loaded(modname))
- rc = 0;
- }
- }
- return rc;
-}
-
-static int mod_remove(char *modname)
-{
- static const struct mod_list_t rm_a_dummy = { "-a", NULL, NULL, NULL, NULL };
-
- int rc;
- struct mod_list_t *head = NULL;
- struct mod_list_t *tail = NULL;
-
- if (modname)
- check_dep(modname, &head, &tail);
- else // autoclean
- head = tail = (struct mod_list_t*) &rm_a_dummy;
-
- rc = 1;
- if (head && tail)
- rc = mod_process(head, 0); // process head ---> tail
- return rc;
-}
-
-int modprobe_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int modprobe_main(int argc UNUSED_PARAM, char **argv)
-{
- int rc = EXIT_SUCCESS;
- unsigned opt;
- char *unused;
-
- opt_complementary = "q-v:v-q";
- opt = getopt32(argv, MAIN_OPT_STR, &unused, &unused);
- argv += optind;
-
- if (opt & (DUMP_CONF_EXIT | LIST_ALL))
- return EXIT_SUCCESS;
- if (opt & (RESTRICT_DIR | CONFIG_FILE))
- bb_error_msg_and_die("-t and -C not supported");
-
- depend = build_dep();
-
- if (!depend)
- bb_error_msg_and_die("cannot parse "CONFIG_DEFAULT_DEPMOD_FILE);
-
- if (remove_opt) {
- do {
- /* (*argv) can be NULL here */
- if (mod_remove(*argv)) {
- bb_perror_msg("failed to %s module %s", "remove",
- *argv);
- rc = EXIT_FAILURE;
- }
- } while (*argv && *++argv);
- } else {
- if (!*argv)
- bb_error_msg_and_die("no module or pattern provided");
-
- if (mod_insert(argv))
- bb_perror_msg_and_die("failed to %s module %s", "load", *argv);
- }
-
- /* Here would be a good place to free up memory allocated during the dependencies build. */
-
- return rc;
-}
+/* vi: set sw=4 ts=4: */
+/*
+ * Modprobe written from scratch for BusyBox
+ *
+ * Copyright (c) 2008 Timo Teras
+ * Copyright (c) 2008 Vladimir Dronnikov
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "libbb.h"
+#include "modutils.h"
+#include
+#include
+
+//#define DBG(...) bb_error_msg(__VA_ARGS__)
+#define DBG(...) ((void)0)
+
+#define MODULE_FLAG_LOADED 0x0001
+#define MODULE_FLAG_NEED_DEPS 0x0002
+/* "was seen in modules.dep": */
+#define MODULE_FLAG_FOUND_IN_MODDEP 0x0004
+#define MODULE_FLAG_BLACKLISTED 0x0008
+
+struct module_entry { /* I'll call it ME. */
+ unsigned flags;
+ char *modname; /* stripped of /path/, .ext and s/-/_/g */
+ const char *probed_name; /* verbatim as seen on cmdline */
+ char *options; /* options from config files */
+ llist_t *realnames; /* strings. if this module is an alias, */
+ /* real module name is one of these. */
+//Can there really be more than one? Example from real kernel?
+ llist_t *deps; /* strings. modules we depend on */
+};
+
+#define MODPROBE_OPTS "acdlnrt:VC:" USE_FEATURE_MODPROBE_BLACKLIST("b")
+enum {
+ MODPROBE_OPT_INSERT_ALL = (INSMOD_OPT_UNUSED << 0), /* a */
+ MODPROBE_OPT_DUMP_ONLY = (INSMOD_OPT_UNUSED << 1), /* c */
+ MODPROBE_OPT_D = (INSMOD_OPT_UNUSED << 2), /* d */
+ MODPROBE_OPT_LIST_ONLY = (INSMOD_OPT_UNUSED << 3), /* l */
+ MODPROBE_OPT_SHOW_ONLY = (INSMOD_OPT_UNUSED << 4), /* n */
+ MODPROBE_OPT_REMOVE = (INSMOD_OPT_UNUSED << 5), /* r */
+ MODPROBE_OPT_RESTRICT = (INSMOD_OPT_UNUSED << 6), /* t */
+ MODPROBE_OPT_VERONLY = (INSMOD_OPT_UNUSED << 7), /* V */
+ MODPROBE_OPT_CONFIGFILE = (INSMOD_OPT_UNUSED << 8), /* C */
+ MODPROBE_OPT_BLACKLIST = (INSMOD_OPT_UNUSED << 9) * ENABLE_FEATURE_MODPROBE_BLACKLIST,
+};
+
+struct globals {
+ llist_t *db; /* MEs of all modules ever seen (caching for speed) */
+ llist_t *probes; /* MEs of module(s) requested on cmdline */
+ char *cmdline_mopts; /* module options from cmdline */
+ int num_unresolved_deps;
+ /* bool. "Did we have 'symbol:FOO' requested on cmdline?" */
+ smallint need_symbols;
+};
+#define G (*(struct globals*)&bb_common_bufsiz1)
+#define INIT_G() do { } while (0)
+
+
+static int read_config(const char *path);
+
+static char *gather_options_str(char *opts, const char *append)
+{
+ /* Speed-optimized. We call gather_options_str many times. */
+ if (opts == NULL) {
+ opts = xstrdup(append);
+ } else {
+ int optlen = strlen(opts);
+ opts = xrealloc(opts, optlen + strlen(append) + 2);
+ sprintf(opts + optlen, " %s", append);
+ }
+ return opts;
+}
+
+static struct module_entry *helper_get_module(const char *module, int create)
+{
+ char modname[MODULE_NAME_LEN];
+ struct module_entry *e;
+ llist_t *l;
+
+ filename2modname(module, modname);
+ for (l = G.db; l != NULL; l = l->link) {
+ e = (struct module_entry *) l->data;
+ if (strcmp(e->modname, modname) == 0)
+ return e;
+ }
+ if (!create)
+ return NULL;
+
+ e = xzalloc(sizeof(*e));
+ e->modname = xstrdup(modname);
+ llist_add_to(&G.db, e);
+
+ return e;
+}
+static struct module_entry *get_or_add_modentry(const char *module)
+{
+ return helper_get_module(module, 1);
+}
+static struct module_entry *get_modentry(const char *module)
+{
+ return helper_get_module(module, 0);
+}
+
+static void add_probe(const char *name)
+{
+ struct module_entry *m;
+
+ m = get_or_add_modentry(name);
+ if (m->flags & MODULE_FLAG_LOADED) {
+ DBG("skipping %s, it is already loaded", name);
+ return;
+ }
+
+ m->probed_name = name;
+ m->flags |= MODULE_FLAG_NEED_DEPS;
+ llist_add_to_end(&G.probes, m);
+ G.num_unresolved_deps++;
+ if (ENABLE_FEATURE_MODUTILS_SYMBOLS
+ && strncmp(m->modname, "symbol:", 7) == 0
+ ) {
+ G.need_symbols = 1;
+ }
+}
+
+static int FAST_FUNC config_file_action(const char *filename,
+ struct stat *statbuf UNUSED_PARAM,
+ void *userdata UNUSED_PARAM,
+ int depth UNUSED_PARAM)
+{
+ char *tokens[3];
+ parser_t *p;
+ struct module_entry *m;
+ int rc = TRUE;
+
+ if (bb_basename(filename)[0] == '.')
+ goto error;
+
+ p = config_open2(filename, fopen_for_read);
+ if (p == NULL) {
+ rc = FALSE;
+ goto error;
+ }
+
+ while (config_read(p, tokens, 3, 2, "# \t", PARSE_NORMAL)) {
+//Use index_in_strings?
+ if (strcmp(tokens[0], "alias") == 0) {
+ /* alias */
+ llist_t *l;
+ char wildcard[MODULE_NAME_LEN];
+ char *rmod;
+
+ if (tokens[2] == NULL)
+ continue;
+ filename2modname(tokens[1], wildcard);
+
+ for (l = G.probes; l != NULL; l = l->link) {
+ m = (struct module_entry *) l->data;
+ if (fnmatch(wildcard, m->modname, 0) != 0)
+ continue;
+ rmod = filename2modname(tokens[2], NULL);
+ llist_add_to(&m->realnames, rmod);
+
+ if (m->flags & MODULE_FLAG_NEED_DEPS) {
+ m->flags &= ~MODULE_FLAG_NEED_DEPS;
+ G.num_unresolved_deps--;
+ }
+
+ m = get_or_add_modentry(rmod);
+ if (!(m->flags & MODULE_FLAG_NEED_DEPS)) {
+ m->flags |= MODULE_FLAG_NEED_DEPS;
+ G.num_unresolved_deps++;
+ }
+ }
+ } else if (strcmp(tokens[0], "options") == 0) {
+ /* options */
+ if (tokens[2] == NULL)
+ continue;
+ m = get_or_add_modentry(tokens[1]);
+ m->options = gather_options_str(m->options, tokens[2]);
+ } else if (strcmp(tokens[0], "include") == 0) {
+ /* include */
+ read_config(tokens[1]);
+ } else if (ENABLE_FEATURE_MODPROBE_BLACKLIST
+ && strcmp(tokens[0], "blacklist") == 0
+ ) {
+ /* blacklist */
+ get_or_add_modentry(tokens[1])->flags |= MODULE_FLAG_BLACKLISTED;
+ }
+ }
+ config_close(p);
+error:
+ return rc;
+}
+
+static int read_config(const char *path)
+{
+ return recursive_action(path, ACTION_RECURSE | ACTION_QUIET,
+ config_file_action, NULL, NULL, 1);
+}
+
+static int do_modprobe(struct module_entry *m)
+{
+ struct module_entry *m2;
+ char *fn, *options;
+ int rc = -1;
+
+ if (!(m->flags & MODULE_FLAG_FOUND_IN_MODDEP)) {
+ DBG("skipping %s, not found in modules.dep", m->modname);
+ return -ENOENT;
+ }
+ DBG("do_modprob'ing %s", m->modname);
+
+ if (!(option_mask32 & MODPROBE_OPT_REMOVE))
+ m->deps = llist_rev(m->deps);
+
+ rc = 0;
+ while (m->deps && rc == 0) {
+ fn = llist_pop(&m->deps);
+ m2 = get_or_add_modentry(fn);
+ if (option_mask32 & MODPROBE_OPT_REMOVE) {
+ if (bb_delete_module(m->modname, O_EXCL) != 0)
+ rc = errno;
+ } else if (!(m2->flags & MODULE_FLAG_LOADED)) {
+ options = m2->options;
+ m2->options = NULL;
+ if (m == m2)
+ options = gather_options_str(options, G.cmdline_mopts);
+ rc = bb_init_module(fn, options);
+ DBG("loaded %s '%s', rc:%d", fn, options, rc);
+ if (rc == 0)
+ m2->flags |= MODULE_FLAG_LOADED;
+ free(options);
+ } else {
+ DBG("%s is already loaded, skipping", fn);
+ }
+
+ free(fn);
+ }
+
+//FIXME: what if rc < 0?
+ if (rc > 0 && !(option_mask32 & INSMOD_OPT_SILENT)) {
+ bb_error_msg("failed to %sload module %s: %s",
+ (option_mask32 & MODPROBE_OPT_REMOVE) ? "un" : "",
+ m->probed_name ? m->probed_name : m->modname,
+ moderror(rc)
+ );
+ }
+
+ return rc;
+}
+
+static void load_modules_dep(void)
+{
+ struct module_entry *m;
+ char *colon, *tokens[2];
+ parser_t *p;
+
+ /* Modprobe does not work at all without modprobe.dep,
+ * even if the full module name is given. Returning error here
+ * was making us later confuse user with this message:
+ * "module /full/path/to/existing/file/module.ko not found".
+ * It's better to die immediately, with good message.
+ * xfopen_for_read provides that. */
+ p = config_open2(CONFIG_DEFAULT_DEPMOD_FILE, xfopen_for_read);
+
+ while (G.num_unresolved_deps
+ && config_read(p, tokens, 2, 1, "# \t", PARSE_NORMAL)
+ ) {
+ colon = last_char_is(tokens[0], ':');
+ if (colon == NULL)
+ continue;
+ *colon = 0;
+
+ m = get_modentry(tokens[0]);
+ if (m == NULL)
+ continue;
+
+ /* Optimization... */
+ if ((m->flags & MODULE_FLAG_LOADED)
+ && !(option_mask32 & MODPROBE_OPT_REMOVE)
+ ) {
+ DBG("skip deps of %s, it's already loaded", tokens[0]);
+ continue;
+ }
+
+ m->flags |= MODULE_FLAG_FOUND_IN_MODDEP;
+ if ((m->flags & MODULE_FLAG_NEED_DEPS) && (m->deps == NULL)) {
+ G.num_unresolved_deps--;
+ llist_add_to(&m->deps, xstrdup(tokens[0]));
+ if (tokens[1])
+ string_to_llist(tokens[1], &m->deps, " ");
+ }
+ }
+ config_close(p);
+}
+
+int modprobe_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int modprobe_main(int argc UNUSED_PARAM, char **argv)
+{
+ struct utsname uts;
+ int rc;
+ unsigned opt;
+ struct module_entry *me;
+
+ opt_complementary = "q-v:v-q";
+ opt = getopt32(argv, INSMOD_OPTS MODPROBE_OPTS INSMOD_ARGS, NULL, NULL);
+ argv += optind;
+
+ if (opt & (MODPROBE_OPT_DUMP_ONLY | MODPROBE_OPT_LIST_ONLY |
+ MODPROBE_OPT_SHOW_ONLY))
+ bb_error_msg_and_die("not supported");
+
+ if (!argv[0]) {
+ if (opt & MODPROBE_OPT_REMOVE) {
+ /* "modprobe -r" (w/o params).
+ * "If name is NULL, all unused modules marked
+ * autoclean will be removed".
+ */
+ if (bb_delete_module(NULL, O_NONBLOCK|O_EXCL) != 0)
+ bb_perror_msg_and_die("rmmod");
+ }
+ return EXIT_SUCCESS;
+ }
+
+ /* Goto modules location */
+ xchdir(CONFIG_DEFAULT_MODULES_DIR);
+ uname(&uts);
+ xchdir(uts.release);
+
+ /* Retrieve module names of already loaded modules */
+ {
+ char *s;
+ parser_t *parser = config_open2("/proc/modules", fopen_for_read);
+ while (config_read(parser, &s, 1, 1, "# \t", PARSE_NORMAL & ~PARSE_GREEDY))
+ get_or_add_modentry(s)->flags |= MODULE_FLAG_LOADED;
+ config_close(parser);
+ }
+
+ if (opt & MODPROBE_OPT_INSERT_ALL) {
+ /* Each argument is a module name */
+ do {
+ add_probe(*argv++);
+ } while (*argv);
+ } else {
+ /* First argument is module name, rest are parameters */
+ add_probe(argv[0]);
+ G.cmdline_mopts = parse_cmdline_module_options(argv);
+ }
+
+ /* Happens if all requested modules are already loaded */
+ if (G.probes == NULL)
+ return EXIT_SUCCESS;
+
+ read_config("/etc/modprobe.conf");
+ read_config("/etc/modprobe.d");
+ if (ENABLE_FEATURE_MODUTILS_SYMBOLS && G.need_symbols)
+ read_config("modules.symbols");
+ load_modules_dep();
+ if (ENABLE_FEATURE_MODUTILS_ALIAS && G.num_unresolved_deps) {
+ read_config("modules.alias");
+ load_modules_dep();
+ }
+
+ while ((me = llist_pop(&G.probes)) != NULL) {
+ if (me->realnames == NULL) {
+ /* This is not an alias. Literal names are blacklisted
+ * only if '-b' is given.
+ */
+ if (!(opt & MODPROBE_OPT_BLACKLIST)
+ || !(me->flags & MODULE_FLAG_BLACKLISTED)
+ ) {
+ rc = do_modprobe(me);
+//FIXME: what if rc > 0?
+ if (rc < 0 && !(opt & INSMOD_OPT_SILENT))
+ bb_error_msg("module %s not found",
+ me->probed_name);
+ }
+ } else {
+ /* Probe all realnames */
+ do {
+ char *realname = llist_pop(&me->realnames);
+ struct module_entry *m2;
+
+ DBG("probing %s by realname %s", me->modname, realname);
+ m2 = get_or_add_modentry(realname);
+ if (!(m2->flags & MODULE_FLAG_BLACKLISTED))
+ do_modprobe(m2);
+//FIXME: error check?
+ free(realname);
+ } while (me->realnames != NULL);
+ }
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/release/src/router/busybox/modutils/modutils-24.c b/release/src/router/busybox/modutils/modutils-24.c
new file mode 100644
index 0000000000..a16cb1bbe3
--- /dev/null
+++ b/release/src/router/busybox/modutils/modutils-24.c
@@ -0,0 +1,3905 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini insmod implementation for busybox
+ *
+ * This version of insmod supports ARM, CRIS, H8/300, x86, ia64, x86_64,
+ * m68k, MIPS, PowerPC, S390, SH3/4/5, Sparc, v850e, and x86_64.
+ *
+ * Copyright (C) 1999-2004 by Erik Andersen
+ * and Ron Alder
+ *
+ * Rodney Radford 17-Aug-2004.
+ * Added x86_64 support.
+ *
+ * Miles Bader added NEC V850E support.
+ *
+ * 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.
+ *
+ * Yoshinori Sato 19-May-2004.
+ * added Renesas H8/300 support.
+ *
+ * Paul Mundt 08-Aug-2003.
+ * Integrated support for sh64 (SH-5), from preliminary modutils
+ * patches from Benedict Gaster .
+ * Currently limited to support for 32bit ABI.
+ *
+ * Magnus Damm 22-May-2002.
+ * The plt and got code are now using the same structs.
+ * Added generic linked list code to fully support PowerPC.
+ * Replaced the mess in arch_apply_relocation() with architecture blocks.
+ * The arch_create_got() function got cleaned up with architecture blocks.
+ * These blocks should be easy maintain and sync with obj_xxx.c in modutils.
+ *
+ * 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 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
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ */
+
+#include "libbb.h"
+#include "modutils.h"
+#include
+#include