diff options
-rwxr-xr-x[-rw-r--r--] | Config.in | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | lib/lib.c | 43 | ||||
-rwxr-xr-x[-rw-r--r--] | lib/lib.h | 7 | ||||
-rwxr-xr-x[-rw-r--r--] | lib/net.c | 30 | ||||
-rwxr-xr-x[-rw-r--r--] | lib/portability.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | lib/xwrap.c | 9 | ||||
-rwxr-xr-x[-rw-r--r--] | main.c | 5 | ||||
-rw-r--r-- | packaging/bin_tv.links | 2 | ||||
-rw-r--r-- | packaging/config | 67 | ||||
-rw-r--r-- | packaging/klogd.manifest | 5 | ||||
-rw-r--r-- | packaging/klogd.service | 16 | ||||
-rw-r--r-- | packaging/sbin.links | 2 | ||||
-rw-r--r-- | packaging/sbin_tv.links | 4 | ||||
-rw-r--r-- | packaging/syslogd.manifest | 5 | ||||
-rw-r--r-- | packaging/syslogd.service | 16 | ||||
-rw-r--r-- | packaging/toybox.spec | 81 | ||||
-rw-r--r-- | packaging/usrbin.links | 1 | ||||
-rwxr-xr-x | scripts/change.sh | 1 | ||||
-rwxr-xr-x[-rw-r--r--] | scripts/mkflags.c | 2 | ||||
-rw-r--r-- | tests/date.test | 22 | ||||
-rwxr-xr-x[-rw-r--r--] | toys.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | toys/other/acpi.c | 17 | ||||
-rwxr-xr-x[-rw-r--r--] | toys/other/blkid.c | 32 | ||||
-rwxr-xr-x[-rw-r--r--] | toys/other/bzcat.c | 93 | ||||
-rwxr-xr-x[-rw-r--r--] | toys/other/chcon.c | 2 | ||||
-rw-r--r-- | toys/other/fsync.c | 33 | ||||
-rwxr-xr-x[-rw-r--r--] | toys/other/hexedit.c | 2 | ||||
-rw-r--r-- | toys/other/hostid.c | 23 | ||||
-rwxr-xr-x[-rw-r--r--] | toys/other/login.c | 246 | ||||
-rwxr-xr-x[-rw-r--r--] | toys/other/lspci.c | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | toys/other/nbd_client.c | 16 | ||||
-rwxr-xr-x[-rw-r--r--] | toys/other/netcat.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | toys/other/reboot.c | 12 | ||||
-rwxr-xr-x[-rw-r--r--] | toys/other/rev.c | 2 | ||||
-rw-r--r-- | toys/other/stat.c | 58 | ||||
-rwxr-xr-x[-rw-r--r--] | toys/other/switch_root.c | 25 | ||||
-rwxr-xr-x[-rw-r--r--] | toys/other/tac.c | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | toys/other/taskset.c | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | toys/other/vmstat.c | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | toys/pending/dd.c | 4 | ||||
-rwxr-xr-x[-rw-r--r--] | toys/pending/init.c | 13 | ||||
-rwxr-xr-x[-rw-r--r--] | toys/pending/mdev.c | 33 | ||||
-rwxr-xr-x[-rw-r--r--] | toys/pending/modprobe.c | 12 | ||||
-rw-r--r-- | toys/pending/syslogd.c | 30 | ||||
-rwxr-xr-x[-rw-r--r--] | toys/pending/telnet.c | 48 | ||||
-rwxr-xr-x[-rw-r--r--] | toys/pending/telnetd.c | 0 | ||||
-rw-r--r-- | toys/pending/tftp.c | 454 | ||||
-rwxr-xr-x[-rw-r--r--] | toys/posix/cal.c | 12 | ||||
-rwxr-xr-x[-rw-r--r--] | toys/posix/chmod.c | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | toys/posix/cmp.c | 2 | ||||
-rw-r--r-- | toys/posix/cp.c | 79 | ||||
-rwxr-xr-x[-rw-r--r--] | toys/posix/date.c | 137 | ||||
-rwxr-xr-x[-rw-r--r--] | toys/posix/du.c | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | toys/posix/find.c | 35 | ||||
-rwxr-xr-x[-rw-r--r--] | toys/posix/id.c | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | toys/posix/ls.c | 13 | ||||
-rwxr-xr-x[-rw-r--r--] | toys/posix/nl.c | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | toys/posix/split.c | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | toys/posix/strings.c | 2 | ||||
-rw-r--r-- | toys/samsung/README | 3 | ||||
-rw-r--r-- | toys/samsung/nslookup.c | 181 | ||||
-rwxr-xr-x | www/news.html | 285 | ||||
-rwxr-xr-x | www/roadmap.html | 14 |
63 files changed, 476 insertions, 1780 deletions
diff --git a/Config.in b/Config.in index a2443e2..9d3a73b 100644..100755 --- a/Config.in +++ b/Config.in @@ -117,7 +117,7 @@ config TOYBOX_DEBUG default n help Enable extra checks for debugging purposes. All of them catch - things that can only go wrong at development time, not runtime. + things that can only go wrong at development time, not runtime. config TOYBOX_UID_SYS int "First system UID" diff --git a/lib/lib.c b/lib/lib.c index c16cffe..05e377f 100644..100755 --- a/lib/lib.c +++ b/lib/lib.c @@ -291,41 +291,6 @@ int stridx(char *haystack, char needle) return off-haystack; } -char *strlower(char *s) -{ - char *try, *new; - - if (!CFG_TOYBOX_I18N) { - try = new = xstrdup(s); - for (; *s; s++) *(new++) = tolower(*s); - } else { - // I can't guarantee the string _won't_ expand during reencoding, so...? - try = new = xmalloc(strlen(s)*2+1); - - while (*s) { - wchar_t c; - int len = mbrtowc(&c, s, MB_CUR_MAX, 0); - - if (len < 1) *(new++) = *(s++); - else { - s += len; - // squash title case too - c = towlower(c); - - // if we had a valid utf8 sequence, convert it to lower case, and can't - // encode back to utf8, something is wrong with your libc. But just - // in case somebody finds an exploit... - len = wcrtomb(new, c, 0); - if (len < 1) error_exit("bad utf8 %x", (int)c); - new += len; - } - } - *new = 0; - } - - return try; -} - int unescape(char c) { char *from = "\\abefnrtv", *to = "\\\a\b\033\f\n\r\t\v"; @@ -575,7 +540,7 @@ void delete_tempfile(int fdin, int fdout, char **tempname) { close(fdin); close(fdout); - if (*tempname) unlink(*tempname); + unlink(*tempname); tempfile2zap = (char *)1; free(*tempname); *tempname = NULL; @@ -868,7 +833,7 @@ void names_to_pid(char **names, int (*callback)(pid_t pid, char *name)) // display first few digits of number with power of two units, except we're // actually just counting decimal digits and showing mil/bil/trillions. -int human_readable(char *buf, unsigned long long num, int style) +int human_readable(char *buf, unsigned long long num) { int end, len; @@ -881,9 +846,9 @@ int human_readable(char *buf, unsigned long long num, int style) buf[1] = '.'; end = 3; } - if (style & HR_SPACE) buf[end++] = ' '; + buf[end++] = ' '; if (len) buf[end++] = " KMGTPE"[len]; - if (style & HR_B) buf[end++] = 'B'; + buf[end++] = 'B'; buf[end++] = 0; return end; diff --git a/lib/lib.h b/lib/lib.h index 17a4a97..3183f32 100644..100755 --- a/lib/lib.h +++ b/lib/lib.h @@ -160,7 +160,6 @@ long xstrtol(char *str, char **end, int base); long atolx(char *c); long atolx_range(char *numstr, long low, long high); int stridx(char *haystack, char needle); -char *strlower(char *s); int unescape(char c); int strstart(char **a, char *b); off_t fdlength(int fd); @@ -177,9 +176,7 @@ void replace_tempfile(int fdin, int fdout, char **tempname); void crc_init(unsigned int *crc_table, int little_endian); void base64_init(char *p); int yesno(char *prompt, int def); -#define HR_SPACE 1 -#define HR_B 2 -int human_readable(char *buf, unsigned long long num, int style); +int human_readable(char *buf, unsigned long long num); int qstrcmp(const void *a, const void *b); int xpoll(struct pollfd *fds, int nfds, int timeout); @@ -207,8 +204,6 @@ void tty_sigreset(int i); // net.c int xsocket(int domain, int type, int protocol); void xsetsockopt(int fd, int level, int opt, void *val, socklen_t len); -int xconnect(char *host, char *port, int family, int socktype, int protocol, - int flags); // password.c int get_salt(char *salt, char * algo); diff --git a/lib/net.c b/lib/net.c index 48d0a5f..5d3ea4a 100644..100755 --- a/lib/net.c +++ b/lib/net.c @@ -12,33 +12,3 @@ void xsetsockopt(int fd, int level, int opt, void *val, socklen_t len) { if (-1 == setsockopt(fd, level, opt, val, len)) perror_exit("setsockopt"); } - -int xconnect(char *host, char *port, int family, int socktype, int protocol, - int flags) -{ - struct addrinfo info, *ai, *ai2; - int fd; - - memset(&info, 0, sizeof(struct addrinfo)); - info.ai_family = family; - info.ai_socktype = socktype; - info.ai_protocol = protocol; - info.ai_flags = flags; - - fd = getaddrinfo(host, port, &info, &ai); - if (fd || !ai) - error_exit("Connect '%s%s%s': %s", host, port ? ":" : "", port ? port : "", - fd ? gai_strerror(fd) : "not found"); - - // Try all the returned addresses. Report errors if last entry can't connect. - for (ai2 = ai; ai; ai = ai->ai_next) { - fd = (ai->ai_next ? socket : xsocket)(ai->ai_family, ai->ai_socktype, - ai->ai_protocol); - if (!connect(fd, ai->ai_addr, ai->ai_addrlen)) break; - else if (!ai2->ai_next) perror_exit("connect"); - close(fd); - } - freeaddrinfo(ai2); - - return fd; -} diff --git a/lib/portability.c b/lib/portability.c index 78e500b..78e500b 100644..100755 --- a/lib/portability.c +++ b/lib/portability.c diff --git a/lib/xwrap.c b/lib/xwrap.c index 8086282..54f2cbb 100644..100755 --- a/lib/xwrap.c +++ b/lib/xwrap.c @@ -30,10 +30,10 @@ void xstrncat(char *dest, char *src, size_t size) void xexit(void) { - if (toys.rebound) longjmp(*toys.rebound, 1); if (fflush(NULL) || ferror(stdout)) if (!toys.exitval) perror_msg("write"); - exit(toys.exitval); + if (toys.rebound) longjmp(*toys.rebound, 1); + else exit(toys.exitval); } // Die unless we can allocate memory. @@ -136,10 +136,7 @@ void xexec(char **argv) if (CFG_TOYBOX && !CFG_TOYBOX_NORECURSE) toy_exec(argv); execvp(argv[0], argv); - perror_msg("exec %s", argv[0]); - toys.exitval = 127; - if (!CFG_TOYBOX_FORK) _exit(toys.exitval); - xexit(); + perror_exit("exec %s", argv[0]); } // Spawn child process, capturing stdin/stdout. @@ -163,10 +163,7 @@ void toybox_main(void) xputs(TOYBOX_VERSION); xexit(); } - if (toys.argv[1][0] != '-') { - toys.exitval = 127; - error_exit("Unknown command %s", toys.argv[1]); - } + if (toys.argv[1][0] != '-') error_exit("Unknown command %s", toys.argv[1]); } // Output list of command. diff --git a/packaging/bin_tv.links b/packaging/bin_tv.links deleted file mode 100644 index 5c3aa65..0000000 --- a/packaging/bin_tv.links +++ /dev/null @@ -1,2 +0,0 @@ -ping -ping6 diff --git a/packaging/config b/packaging/config index 4004694..c368e46 100644 --- a/packaging/config +++ b/packaging/config @@ -13,32 +13,27 @@ CONFIG_TOYBOX_SHADOW=y CONFIG_TOYBOX_FORK=y # -# Samsung developed commands -# -# CONFIG_NSLOOKUP is not set - -# # Posix commands # # CONFIG_BASENAME is not set # CONFIG_CAL is not set # CONFIG_CAT is not set # CONFIG_CAT_V is not set -CONFIG_CATV=y +# CONFIG_CATV is not set # CONFIG_CHGRP is not set # CONFIG_CHOWN is not set # CONFIG_CHMOD is not set # CONFIG_CKSUM is not set # CONFIG_CMP is not set # CONFIG_COMM is not set -CONFIG_CP=y -CONFIG_CP_MORE=y -CONFIG_CP_PRESERVE=y -CONFIG_CP_Z=y -CONFIG_MV=y -CONFIG_MV_MORE=y -CONFIG_INSTALL=y -CONFIG_INSTALL_Z=y +# CONFIG_CP is not set +# CONFIG_CP_MORE is not set +# CONFIG_CP_PRESERVE is not set +# CONFIG_CP_Z is not set +# CONFIG_MV is not set +# CONFIG_MV_MORE is not set +# CONFIG_INSTALL is not set +# CONFIG_INSTALL_Z is not set # CONFIG_CPIO is not set # CONFIG_CUT is not set # CONFIG_DATE is not set @@ -63,12 +58,12 @@ CONFIG_INSTALL_Z=y # CONFIG_KILLALL5 is not set # CONFIG_LINK is not set # CONFIG_LN is not set -CONFIG_LS=y -CONFIG_LS_COLOR=y -CONFIG_MKDIR=y -CONFIG_MKDIR_Z=y -CONFIG_MKFIFO=y -CONFIG_MKFIFO_Z=y +# CONFIG_LS is not set +# CONFIG_LS_COLOR is not set +# CONFIG_MKDIR is not set +# CONFIG_MKDIR_Z is not set +# CONFIG_MKFIFO is not set +# CONFIG_MKFIFO_Z is not set # CONFIG_NICE is not set # CONFIG_NL is not set # CONFIG_NOHUP is not set @@ -78,7 +73,7 @@ CONFIG_MKFIFO_Z=y # CONFIG_PRINTF is not set # CONFIG_PWD is not set # CONFIG_RENICE is not set -CONFIG_RM=y +# CONFIG_RM is not set # CONFIG_RMDIR is not set # CONFIG_SED is not set # CONFIG_SLEEP is not set @@ -140,10 +135,10 @@ CONFIG_DUMPLEASES=y # CONFIG_IP is not set # CONFIG_IPCRM is not set # CONFIG_IPCS is not set -CONFIG_KLOGD=y -CONFIG_KLOGD_SOURCE_RING_BUFFER=y +# CONFIG_KLOGD is not set +# CONFIG_KLOGD_SOURCE_RING_BUFFER is not set # CONFIG_LAST is not set -CONFIG_LOGGER=y +# CONFIG_LOGGER is not set # CONFIG_MDEV is not set # CONFIG_MDEV_CONF is not set # CONFIG_MKE2FS is not set @@ -164,7 +159,7 @@ CONFIG_PING=y # CONFIG_EXIT is not set # CONFIG_CD is not set # CONFIG_SULOGIN is not set -CONFIG_SYSLOGD=y +# CONFIG_SYSLOGD is not set # CONFIG_TAR is not set # CONFIG_TCPSVD is not set # CONFIG_TELNET is not set @@ -187,7 +182,7 @@ CONFIG_TRACEROUTE=y # CONFIG_BASE64 is not set # CONFIG_BLKID is not set # CONFIG_FSTYPE is not set -CONFIG_BLOCKDEV=y +# CONFIG_BLOCKDEV is not set # CONFIG_BUNZIP2 is not set # CONFIG_BZCAT is not set # CONFIG_CHCON is not set @@ -204,14 +199,14 @@ CONFIG_BLOCKDEV=y # CONFIG_FREERAMDISK is not set # CONFIG_FSFREEZE is not set # CONFIG_FSYNC is not set -CONFIG_HELP=y -CONFIG_HELP_EXTRAS=y +# CONFIG_HELP is not set +# CONFIG_HELP_EXTRAS is not set # CONFIG_HEXEDIT is not set # CONFIG_HOSTID is not set # CONFIG_HWCLOCK is not set # CONFIG_IFCONFIG is not set # CONFIG_INOTIFYD is not set -CONFIG_INSMOD=y +# CONFIG_INSMOD is not set # CONFIG_IONICE is not set # CONFIG_IORENICE is not set # CONFIG_LOGIN is not set @@ -249,8 +244,8 @@ CONFIG_INSMOD=y # CONFIG_RMMOD is not set # CONFIG_SETSID is not set # CONFIG_SHRED is not set -CONFIG_STAT=y -CONFIG_STAT_C=y +# CONFIG_STAT is not set +# CONFIG_STAT_C is not set # CONFIG_SWAPOFF is not set # CONFIG_SWAPON is not set # CONFIG_SWITCH_ROOT is not set @@ -277,16 +272,16 @@ CONFIG_STAT_C=y # CONFIG_KILLALL is not set # CONFIG_MD5SUM is not set # CONFIG_SHA1SUM is not set -CONFIG_MKNOD=y -CONFIG_MKNOD_Z=y -CONFIG_MKTEMP=y -CONFIG_MOUNT=y +# CONFIG_MKNOD is not set +# CONFIG_MKNOD_Z is not set +# CONFIG_MKTEMP is not set +# CONFIG_MOUNT is not set # CONFIG_PASSWD is not set # CONFIG_PIDOF is not set # CONFIG_SEQ is not set # CONFIG_SU is not set # CONFIG_SYNC is not set -CONFIG_UMOUNT=y +# CONFIG_UMOUNT is not set # # Example commands diff --git a/packaging/klogd.manifest b/packaging/klogd.manifest deleted file mode 100644 index 97e8c31..0000000 --- a/packaging/klogd.manifest +++ /dev/null @@ -1,5 +0,0 @@ -<manifest> - <request> - <domain name="_"/> - </request> -</manifest> diff --git a/packaging/klogd.service b/packaging/klogd.service deleted file mode 100644 index 03df845..0000000 --- a/packaging/klogd.service +++ /dev/null @@ -1,16 +0,0 @@ -[Unit] -Description=Run syslog -DefaultDependencies=no -After=syslogd.service -ConditionKernelCommandLine=|!sec_debug.enable=0 -ConditionKernelCommandLine=|!sec_debug.enable_user=0 - -[Service] -Type=forking -ExecStart=/sbin/klogd -OOMScoreAdjust=-1000 -Restart=always -RestartSec=0 - -[Install] -WantedBy=basic.target diff --git a/packaging/sbin.links b/packaging/sbin.links index ff4418a..e69de29 100644 --- a/packaging/sbin.links +++ b/packaging/sbin.links @@ -1,2 +0,0 @@ -klogd -syslogd diff --git a/packaging/sbin_tv.links b/packaging/sbin_tv.links deleted file mode 100644 index 02d4a98..0000000 --- a/packaging/sbin_tv.links +++ /dev/null @@ -1,4 +0,0 @@ -klogd -syslogd -ping -ping6 diff --git a/packaging/syslogd.manifest b/packaging/syslogd.manifest deleted file mode 100644 index 97e8c31..0000000 --- a/packaging/syslogd.manifest +++ /dev/null @@ -1,5 +0,0 @@ -<manifest> - <request> - <domain name="_"/> - </request> -</manifest> diff --git a/packaging/syslogd.service b/packaging/syslogd.service deleted file mode 100644 index 7b10609..0000000 --- a/packaging/syslogd.service +++ /dev/null @@ -1,16 +0,0 @@ -[Unit] -Description=Run syslog -DefaultDependencies=no -After=local-fs.target -ConditionKernelCommandLine=|!sec_debug.enable=0 -ConditionKernelCommandLine=|!sec_debug.enable_user=0 - -[Service] -Type=forking -ExecStart=/sbin/syslogd -b 5 -B 99 -OOMScoreAdjust=-1000 -Restart=always -RestartSec=0 - -[Install] -WantedBy=basic.target diff --git a/packaging/toybox.spec b/packaging/toybox.spec index dd6d12f..0f46c58 100644 --- a/packaging/toybox.spec +++ b/packaging/toybox.spec @@ -7,20 +7,11 @@ License: BSD-2-Clause-FreeBSD URL: http://www.landley.net/toybox/ Source: %{name}-%{version}.tar.bz2 Source1: config -%if "%{?profile}"=="tv" -Source2: bin_tv.links -Source3: sbin_tv.links -%else Source2: bin.links Source3: sbin.links -%endif Source4: usrbin.links Source5: usrsbin.links -Source101: klogd.service -Source102: syslogd.service Source1001: toybox.manifest -Source1002: syslogd.manifest -Source1003: klogd.manifest BuildRequires : smack-devel BuildRequires : libattr-devel @@ -31,22 +22,6 @@ of system commands, including a shell. This package can be very useful for recovering from certain types of system failures, particularly those involving broken shared libraries. -%package symlinks-klogd -Group: tools -Summary: ToyBox symlinks to provide 'klogd' -Requires: %{name} = %{version}-%{release} - -%description symlinks-klogd -ToyBox symlinks for utilities corresponding to 'klogd' package. - -%package symlinks-sysklogd -Group: tools -Summary: ToyBox symlinks to provide 'sysklogd' -Requires: %{name} = %{version}-%{release} - -%description symlinks-sysklogd -ToyBox symlinks for utilities corresponding to 'sysklogd' package. - %package symlinks-dhcp Group: tools Summary: ToyBox symlinks to provide 'dhcp' @@ -68,8 +43,6 @@ ToyBox symlinks for utilities corresponding to 'dhcpd' package. %build cp %{SOURCE1001} . -cp %{SOURCE1002} . -cp %{SOURCE1003} . # create dynamic toybox - the executable is toybox cp %{SOURCE1} .config make -j 4 CC="gcc $RPM_OPT_FLAGS" CFLAGS="$CFLAGS -fPIE" LDOPTIMIZE="-Wl,--gc-sections -pie" @@ -94,63 +67,21 @@ cd ../../usr/sbin for f in `cat %SOURCE5` ; do ln -s ../../bin/toybox $f ; done popd -# install systemd service files for syslogd and klogd -#mkdir -p %{buildroot}%{_unitdir}/basic.target.wants -#install -m 644 %SOURCE101 %{buildroot}%{_unitdir}/klogd.service -#ln -s ../klogd.service %{buildroot}%{_unitdir}/basic.target.wants/klogd.service -#install -m 644 %SOURCE102 %{buildroot}%{_unitdir}/syslogd.service -#ln -s ../syslogd.service %{buildroot}%{_unitdir}/basic.target.wants/syslogd.service -#rm -rf $RPM_BUILD_ROOT/sbin/syslogd -#cp -f $RPM_BUILD_ROOT/bin/toybox $RPM_BUILD_ROOT/sbin/syslogd -#rm -rf $RPM_BUILD_ROOT/sbin/klogd -#cp -f $RPM_BUILD_ROOT/bin/toybox $RPM_BUILD_ROOT/sbin/klogd - -mkdir -p $RPM_BUILD_ROOT%{_datadir}/license -cat LICENSE > $RPM_BUILD_ROOT%{_datadir}/license/toybox -cat LICENSE > $RPM_BUILD_ROOT%{_datadir}/license/toybox-symlinks-klogd -cat LICENSE > $RPM_BUILD_ROOT%{_datadir}/license/toybox-symlinks-sysklogd -cat LICENSE > $RPM_BUILD_ROOT%{_datadir}/license/toybox-symlinks-dhcp -cat LICENSE > $RPM_BUILD_ROOT%{_datadir}/license/toybox-symlinks-dhcpd - %files -%defattr(-,root,root,-) -%doc LICENSE -%{_datadir}/license/toybox -/bin/toybox -/usr/bin/nslookup -%if "%{?profile}"=="tv" -/sbin/ping -/bin/ping -/sbin/ping6 -/bin/ping6 -%endif %manifest toybox.manifest - -%files symlinks-klogd -%defattr(-,root,root,-) -%{_datadir}/license/toybox-symlinks-klogd -/sbin/klogd -#%{_unitdir}/klogd.service -#%{_unitdir}/basic.target.wants/klogd.service -%manifest klogd.manifest - -%files symlinks-sysklogd +%license LICENSE %defattr(-,root,root,-) -%{_datadir}/license/toybox-symlinks-sysklogd -/sbin/syslogd -#%{_unitdir}/syslogd.service -#%{_unitdir}/basic.target.wants/syslogd.service -%manifest syslogd.manifest +/bin/toybox %files symlinks-dhcp +%manifest toybox.manifest +%license LICENSE %defattr(-,root,root,-) -%{_datadir}/license/toybox-symlinks-dhcp %{_bindir}/dhcp -%manifest toybox.manifest %files symlinks-dhcpd +%manifest toybox.manifest +%license LICENSE %defattr(-,root,root,-) -%{_datadir}/license/toybox-symlinks-dhcpd %{_bindir}/dumpleases %{_sbindir}/dhcpd -%manifest toybox.manifest diff --git a/packaging/usrbin.links b/packaging/usrbin.links index 2ed0e8d..424150e 100644 --- a/packaging/usrbin.links +++ b/packaging/usrbin.links @@ -1,3 +1,2 @@ dumpleases dhcp -nslookup diff --git a/scripts/change.sh b/scripts/change.sh index 99dcfde..dcd581e 100755 --- a/scripts/change.sh +++ b/scripts/change.sh @@ -18,4 +18,3 @@ do scripts/single.sh $i > /dev/null 2>$PREFIX/${i}.bad && rm $PREFIX/${i}.bad || echo -n '*' done -echo diff --git a/scripts/mkflags.c b/scripts/mkflags.c index 7e57f84..d87087b 100644..100755 --- a/scripts/mkflags.c +++ b/scripts/mkflags.c @@ -6,12 +6,10 @@ // This is intentionally crappy code because we control the inputs. It leaks // memory like a sieve and segfaults if malloc returns null, but does the job. -#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> -#include <ctype.h> struct flag { struct flag *next; diff --git a/tests/date.test b/tests/date.test deleted file mode 100644 index 94a4157..0000000 --- a/tests/date.test +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -[ -f testing.sh ] && . testing.sh - -#testing "name" "command" "result" "infile" "stdin" - -# Test Unix date parsing. -testing "date -d @0" "TZ=UTC date -d @0 2>&1" "Thu Jan 1 00:00:00 GMT 1970\n" "" "" -testing "date -d @0x123" "TZ=UTC date -d @0x123 2>&1" "date: bad date '@0x123'\n" "" "" - -# Test basic date parsing. -# Note that toybox's -d format is not the same as coreutils'. -testing "date -d 06021234" "TZ=UTC date -d 06021234 2>&1" "Sun Jun 2 12:34:00 UTC 1900\n" "" "" -testing "date -d 060212341982" "TZ=UTC date -d 060212341982 2>&1" "Sun Jun 2 12:34:00 UTC 1982\n" "" "" -testing "date -d 123" "TZ=UTC date -d 123 2>&1" "date: bad date '123'\n" "" "" - -# Accidentally given a Unix time, we should trivially reject that. -testing "date Unix time missing @" "TZ=UTC date 1438053157 2>&1" \ - "date: bad date '1438053157'; Tue February 38 05:31:00 UTC 2057 != Sun Mar 10 05:31:00 UTC 2058\n" "" "" -# But some invalid dates are more subtle, like Febuary 29th in a non-leap year. -testing "date Feb 29th" "TZ=UTC date 022900001975 2>&1" \ - "date: bad date '022900001975'; Tue Feb 29 00:00:00 UTC 2075 != Fri Mar 1 00:00:00 UTC 2075\n" "" "" diff --git a/toys/other/acpi.c b/toys/other/acpi.c index 363cfb9..44fd03b 100644..100755 --- a/toys/other/acpi.c +++ b/toys/other/acpi.c @@ -25,7 +25,10 @@ config ACPI #include "toys.h" GLOBALS( - int ac, bat, therm, cool; + int ac; + int bat; + int therm; + int cool; char *cpath; ) @@ -41,7 +44,7 @@ int read_int_at(int dirfd, char *name) return ret; } -static int acpi_callback(struct dirtree *tree) +int acpi_callback(struct dirtree *tree) { int dfd, fd, len, on; @@ -82,11 +85,11 @@ done: return 0; } -static int temp_callback(struct dirtree *tree) +int temp_callback(struct dirtree *tree) { int dfd, temp; - if (*tree->name=='.') return 0; + if (tree->name[0]=='.') return 0; if (!tree->parent || !tree->parent->parent) return DIRTREE_RECURSE|DIRTREE_SYMFOLLOW; errno = 0; @@ -95,17 +98,17 @@ static int temp_callback(struct dirtree *tree) if ((0 < (temp = read_int_at(dfd, "temp"))) || !errno) { //some tempertures are in milli-C, some in deci-C //reputedly some are in deci-K, but I have not seen them - if (((temp >= 1000) || (temp <= -1000)) && (temp%100 == 0)) temp /= 100; + if (((temp >= 1000) || (temp <= -1000)) && (temp%100 == 0)) + temp /= 100; printf("Thermal %d: %d.%d degrees C\n", TT.therm++, temp/10, temp%10); } close(dfd); } free(TT.cpath); - return 0; } -static int cool_callback(struct dirtree *tree) +int cool_callback(struct dirtree *tree) { int dfd=5, cur, max; diff --git a/toys/other/blkid.c b/toys/other/blkid.c index fad1159..725f163 100644..100755 --- a/toys/other/blkid.c +++ b/toys/other/blkid.c @@ -4,7 +4,7 @@ * * See ftp://ftp.kernel.org/pub/linux/utils/util-linux/v2.24/libblkid-docs/api-index-full.html -USE_BLKID(NEWTOY(blkid, 0, TOYFLAG_BIN)) +USE_BLKID(NEWTOY(blkid, "<1", TOYFLAG_BIN)) USE_FSTYPE(NEWTOY(fstype, "<1", TOYFLAG_BIN)) config BLKID @@ -34,7 +34,6 @@ struct fstype { }; static const struct fstype fstypes[] = { - {"swap", 0x4341505350415753, 8, 4086, 1036, 15, 1052}, {"ext2", 0xEF53, 2, 1080, 1128, 16, 1144}, // keep this first for ext3/4 check // NTFS label actually 8/16 0x4d80 but horrible: 16 bit wide characters via // codepage, something called a uuid that's only 8 bytes long... @@ -57,7 +56,8 @@ static const struct fstype fstypes[] = { {"vfat", 0x31544146, 4, 54, 39+(4<<24), 11, 43} // fat1 }; -static void do_blkid(int fd, char *name) +/* TODO if no args use proc/partitions */ +void do_blkid(int fd, char *name) { int off, i, j; char *type; @@ -89,7 +89,7 @@ static void do_blkid(int fd, char *name) if (test == fstypes[i].magic) break; } - if (i == ARRAY_LEN(fstypes)) { + if (i == sizeof(fstypes)/sizeof(struct fstype)) { off += len; if (pass) continue; return; @@ -136,30 +136,10 @@ static void do_blkid(int fd, char *name) void blkid_main(void) { - if (*toys.optargs) loopfiles(toys.optargs, do_blkid); - else { - unsigned int ma, mi, sz, fd; - char *name = toybuf, *buffer = toybuf+1024, device[32]; - FILE *fp = xfopen("/proc/partitions", "r"); - - while (fgets(buffer, 1024, fp)) { - *name = 0; - if (sscanf(buffer, " %u %u %u %[^\n ]", &ma, &mi, &sz, name) != 4) - continue; - - sprintf(device, "/dev/%.20s", name); - if (-1 == (fd = open(device, O_RDONLY))) { - if (errno != ENOMEDIUM) perror_msg("%s", device); - } else { - do_blkid(fd, device); - close(fd); - } - } - if (CFG_TOYBOX_FREE) fclose(fp); - } + loopfiles(toys.optargs, do_blkid); } void fstype_main(void) { - loopfiles(toys.optargs, do_blkid); + blkid_main(); } diff --git a/toys/other/bzcat.c b/toys/other/bzcat.c index 850c51c..642590d 100644..100755 --- a/toys/other/bzcat.c +++ b/toys/other/bzcat.c @@ -1,4 +1,4 @@ -/* bzcat.c - bzip2 decompression +/* bzcat.c - decompress stdin to stdout using bunzip2. * * Copyright 2003, 2007 Rob Landley <rob@landley.net> * @@ -12,33 +12,16 @@ USE_BZCAT(NEWTOY(bzcat, NULL, TOYFLAG_USR|TOYFLAG_BIN)) -USE_BUNZIP2(NEWTOY(bunzip2, "cftkv", TOYFLAG_USR|TOYFLAG_BIN)) - -config BUNZIP2 - bool "bunzip2" - default y - help - usage: bunzip2 [-cftkv] [FILE...] - - Decompress listed files (file.bz becomes file) deleting archive file(s). - Read from stdin if no files listed. - - -c force output to stdout - -f force decompression. (If FILE doesn't end in .bz, replace original.) - -k keep input files (-c and -t imply this) - -t test integrity - -v verbose config BZCAT bool "bzcat" default y help - usage: bzcat [FILE...] + usage: bzcat [filename...] Decompress listed files to stdout. Use stdin if no files listed. */ -#define FOR_bunzip2 #include "toys.h" #define THREADS 1 @@ -438,7 +421,7 @@ static int read_huffman_data(struct bunzip_data *bd, struct bwdata *bw) } // Flush output buffer to disk -static void flush_bunzip_outbuf(struct bunzip_data *bd, int out_fd) +void flush_bunzip_outbuf(struct bunzip_data *bd, int out_fd) { if (bd->outbufPos) { if (write(out_fd, bd->outbuf, bd->outbufPos) != bd->outbufPos) @@ -447,7 +430,7 @@ static void flush_bunzip_outbuf(struct bunzip_data *bd, int out_fd) } } -static void burrows_wheeler_prep(struct bunzip_data *bd, struct bwdata *bw) +void burrows_wheeler_prep(struct bunzip_data *bd, struct bwdata *bw) { int ii, jj; unsigned int *dbuf = bw->dbuf; @@ -491,7 +474,7 @@ static void burrows_wheeler_prep(struct bunzip_data *bd, struct bwdata *bw) } // Decompress a block of text to intermediate buffer -static int read_bunzip_data(struct bunzip_data *bd) +int read_bunzip_data(struct bunzip_data *bd) { int rc = read_block_header(bd, bd->bwdata); if (!rc) rc=read_huffman_data(bd, bd->bwdata); @@ -510,8 +493,7 @@ static int read_bunzip_data(struct bunzip_data *bd) // http://dogma.net/markn/articles/bwt/bwt.htm // http://marknelson.us/1996/09/01/bwt/ -static int write_bunzip_data(struct bunzip_data *bd, struct bwdata *bw, - int out_fd, char *outbuf, int len) +int write_bunzip_data(struct bunzip_data *bd, struct bwdata *bw, int out_fd, char *outbuf, int len) { unsigned int *dbuf = bw->dbuf; int count, pos, current, run, copies, outbyte, previous, gotcount = 0; @@ -602,8 +584,7 @@ dataus_interruptus: // Allocate the structure, read file header. If !len, src_fd contains // filehandle to read from. Else inbuf contains data. -static int start_bunzip(struct bunzip_data **bdp, int src_fd, char *inbuf, - int len) +int start_bunzip(struct bunzip_data **bdp, int src_fd, char *inbuf, int len) { struct bunzip_data *bd; unsigned int i; @@ -641,10 +622,10 @@ static int start_bunzip(struct bunzip_data **bdp, int src_fd, char *inbuf, // Example usage: decompress src_fd to dst_fd. (Stops at end of bzip data, // not end of file.) -static char *bunzipStream(int src_fd, int dst_fd) +void bunzipStream(int src_fd, int dst_fd) { struct bunzip_data *bd; - char *bunzip_errors[] = {0, "not bzip", "bad data", "old format"}; + char *bunzip_errors[]={NULL, "not bzip", "bad data", "old format"}; int i, j; if (!(i = start_bunzip(&bd,src_fd, 0, 0))) { @@ -655,67 +636,15 @@ static char *bunzipStream(int src_fd, int dst_fd) for (j=0; j<THREADS; j++) free(bd->bwdata[j].dbuf); free(bd); - - return bunzip_errors[-i]; + if (i) error_exit(bunzip_errors[-i]); } static void do_bzcat(int fd, char *name) { - char *err = bunzipStream(fd, 1); - - if (err) error_exit(err); + bunzipStream(fd, 1); } void bzcat_main(void) { loopfiles(toys.optargs, do_bzcat); } - -static void do_bunzip2(int fd, char *name) -{ - int outfd = 1, rename = 0, len = strlen(name); - char *tmp, *err, *dotbz = 0; - - // Trim off .bz or .bz2 extension - dotbz = name+len-3; - if ((len>3 && !strcmp(dotbz, ".bz")) || (len>4 && !strcmp(--dotbz, ".bz2"))) - dotbz = 0; - - // For - no replace - if (toys.optflags&FLAG_t) outfd = xopen("/dev/null", O_WRONLY); - else if ((fd || strcmp(name, "-")) && !(toys.optflags&FLAG_c)) { - if (toys.optflags&FLAG_k) { - if (!dotbz || !access(name, X_OK)) { - error_msg("%s exists", name); - - return; - } - } - outfd = copy_tempfile(fd, name, &tmp); - rename++; - } - - if (toys.optflags&FLAG_v) printf("%s:", name); - err = bunzipStream(fd, outfd); - if (toys.optflags&FLAG_v) { - printf("%s\n", err ? err : "ok"); - toys.exitval |= !!err; - } else if (err) error_msg(err); - - // can't test outfd==1 because may have been called with stdin+stdout closed - if (rename) { - if (toys.optflags&FLAG_k) { - free(tmp); - tmp = 0; - } else { - if (dotbz) *dotbz = '.'; - if (!unlink(name)) perror_msg("%s", name); - } - (err ? delete_tempfile : replace_tempfile)(-1, outfd, &tmp); - } -} - -void bunzip2_main(void) -{ - loopfiles(toys.optargs, do_bunzip2); -} diff --git a/toys/other/chcon.c b/toys/other/chcon.c index 6dbdd13..a2bbb66 100644..100755 --- a/toys/other/chcon.c +++ b/toys/other/chcon.c @@ -21,7 +21,7 @@ config CHCON #define FOR_chcon #include "toys.h" -static int do_chcon(struct dirtree *try) +int do_chcon(struct dirtree *try) { char *path, *con = *toys.optargs; diff --git a/toys/other/fsync.c b/toys/other/fsync.c deleted file mode 100644 index e6f6c8d..0000000 --- a/toys/other/fsync.c +++ /dev/null @@ -1,33 +0,0 @@ -/* fsync.c - Synchronize a file's in-core state with storage device. - * - * Copyright 2015 Ranjan Kumar <ranjankumar.bth@gmail.comi> - * - * No Standard. - -USE_FSYNC(NEWTOY(fsync, "<1d", TOYFLAG_BIN)) - -config FSYNC - bool "fsync" - default y - help - usage: fsync [-d] [FILE...] - - Synchronize a file's in-core state with storage device. - - -d Avoid syncing metadata. -*/ - -#define FOR_fsync -#include "toys.h" - -static void do_fsync(int fd, char *name) -{ - if (((toys.optflags & FLAG_d) ? fdatasync(fd) : fsync(fd))) - perror_msg("can't sync '%s'", name); -} - -void fsync_main(void) -{ - loopfiles_rw(toys.optargs, O_RDONLY|O_NOATIME|O_NOCTTY|O_CLOEXEC, - 0, 0, do_fsync); -} diff --git a/toys/other/hexedit.c b/toys/other/hexedit.c index a52d66d..1f6b42e 100644..100755 --- a/toys/other/hexedit.c +++ b/toys/other/hexedit.c @@ -137,8 +137,6 @@ void hexedit_main(void) fd = xopen(*toys.optargs, ro ? O_RDONLY : O_RDWR); char keybuf[16]; - *keybuf = 0; - // Terminal setup TT.height = 25; terminal_size(0, &TT.height); diff --git a/toys/other/hostid.c b/toys/other/hostid.c deleted file mode 100644 index 883ac3c..0000000 --- a/toys/other/hostid.c +++ /dev/null @@ -1,23 +0,0 @@ -/* hostid.c - Print the numeric identifier for the current host. - * - * Copyright 2015 Ranjan Kumar <ranjankumar.bth@gmail.com> - * - * No Standard. - -USE_HOSTID(NEWTOY(hostid, ">0", TOYFLAG_USR|TOYFLAG_BIN)) - -config HOSTID - bool "hostid" - default y - help - usage: hostid - - Print the numeric identifier for the current host. -*/ -#define FOR_hostid -#include "toys.h" - -void hostid_main(void) -{ - xprintf("%08lx\n", gethostid()); -} diff --git a/toys/other/login.c b/toys/other/login.c index c727bf9..b728286 100644..100755 --- a/toys/other/login.c +++ b/toys/other/login.c @@ -8,28 +8,30 @@ * TODO: this command predates "pending" but needs cleanup. It #defines * random stuff, calls exit() form a signal handler... yeah. -USE_LOGIN(NEWTOY(login, ">1f:ph:", TOYFLAG_BIN|TOYFLAG_NEEDROOT)) +USE_LOGIN(NEWTOY(login, ">1fph:", TOYFLAG_BIN)) config LOGIN bool "login" default y depends on TOYBOX_SHADOW help - usage: login [-p] [-h host] [-f USERNAME] [USERNAME] + usage: login [-p] [-h host] [[-f] username] - Log in as a user, prompting for username and password if necessary. + Establish a new session with the system. -p Preserve environment -h The name of the remote host for this login - -f login as USERNAME without authentication + -f Do not perform authentication */ #define FOR_login #include "toys.h" +#define USER_NAME_MAX_SIZE 32 +#define HOSTNAME_SIZE 32 + GLOBALS( char *hostname; - char *username; int login_timeout, login_fail_timeout; ) @@ -40,128 +42,184 @@ static void login_timeout_handler(int sig __attribute__((unused))) exit(0); } +static char *forbid[] = { + "BASH_ENV", "ENV", "HOME", "IFS", "LD_LIBRARY_PATH", "LD_PRELOAD", + "LD_TRACE_LOADED_OBJECTS", "LD_BIND_NOW", "LD_AOUT_LIBRARY_PATH", + "LD_AOUT_PRELOAD", "LD_NOWARN", "LD_KEEPDIR", "SHELL", NULL +}; + +int verify_password(char * pwd) +{ + char *pass; + + if (read_password(toybuf, sizeof(toybuf), "Password: ")) return 1; + if (!pwd) return 1; + if (pwd[0] == '!' || pwd[0] == '*') return 1; + + pass = crypt(toybuf, pwd); + if (pass && !strcmp(pass, pwd)) return 0; + + return 1; +} + +void read_user(char * buff, int size) +{ + char hostname[HOSTNAME_SIZE+1]; + int i = 0; + + hostname[HOSTNAME_SIZE] = 0; + if (!gethostname(hostname, HOSTNAME_SIZE)) fputs(hostname, stdout); + + fputs(" login: ", stdout); + fflush(stdout); + + do { + int c = getchar(); + if (c == EOF) exit(EXIT_FAILURE); + *buff = c; + } while (isblank(*buff)); + + if (*buff != '\n') if(!fgets(&buff[1], HOSTNAME_SIZE-1, stdin)) _exit(1); + + while(i<HOSTNAME_SIZE-1 && isgraph(buff[i])) i++; + buff[i] = 0; +} + +void handle_nologin(void) +{ + int fd = open("/etc/nologin", O_RDONLY); + int size; + + if (fd == -1) return; + + size = readall(fd, toybuf,sizeof(toybuf)-1); + toybuf[size] = 0; + if (!size) puts("System closed for routine maintenance\n"); + else puts(toybuf); + + close(fd); + fflush(stdout); + exit(1); +} + +void handle_motd(void) +{ + int fd = open("/etc/motd", O_RDONLY); + int size; + if (fd == -1) return; + + size = readall(fd, toybuf,sizeof(toybuf)-1); + toybuf[size] = 0; + puts(toybuf); + + close(fd); + fflush(stdout); +} + +void spawn_shell(const char *shell) +{ + const char * exec_name = strrchr(shell,'/'); + if (exec_name) exec_name++; + else exec_name = shell; + + snprintf(toybuf,sizeof(toybuf)-1, "-%s", shell); + execl(shell, toybuf, NULL); + error_exit("Failed to spawn shell"); +} + +void setup_environment(const struct passwd *pwd, int clear_env) +{ + if (chdir(pwd->pw_dir)) printf("bad home dir: %s\n", pwd->pw_dir); + + if (clear_env) { + const char *term = getenv("TERM"); + clearenv(); + if (term) setenv("TERM", term, 1); + } + + setenv("USER", pwd->pw_name, 1); + setenv("LOGNAME", pwd->pw_name, 1); + setenv("HOME", pwd->pw_dir, 1); + setenv("SHELL", pwd->pw_shell, 1); +} + void login_main(void) { - char *forbid[] = { - "BASH_ENV", "ENV", "HOME", "IFS", "LD_LIBRARY_PATH", "LD_PRELOAD", - "LD_TRACE_LOADED_OBJECTS", "LD_BIND_NOW", "LD_AOUT_LIBRARY_PATH", - "LD_AOUT_PRELOAD", "LD_NOWARN", "LD_KEEPDIR", "SHELL" - }; - int hh = toys.optflags&FLAG_h, count, tty; - char uu[33], *username, *pass = 0, *ss; - struct passwd *pwd = 0; + int f_flag = toys.optflags & FLAG_f; + int h_flag = toys.optflags & FLAG_h; + char username[33], *pass = NULL, **ss; + struct passwd * pwd = NULL; + struct spwd * spwd = NULL; + int auth_fail_cnt = 0; + + if (f_flag && toys.optc != 1) error_exit("-f requires username"); - for (tty=0; tty<3; tty++) if (isatty(tty)) break; - if (tty == 3) error_exit("no tty"); + if (geteuid()) error_exit("not root"); - for (count = 0; count < ARRAY_LEN(forbid); count++) unsetenv(forbid[count]); + if (!isatty(0) || !isatty(1) || !isatty(2)) error_exit("no tty"); openlog("login", LOG_PID | LOG_CONS, LOG_AUTH); xsignal(SIGALRM, login_timeout_handler); + alarm(TT.login_timeout = 60); - if (TT.username) username = TT.username; - else username = *toys.optargs; - for (count = 0; count < 3; count++) { - alarm(TT.login_timeout = 60); - tcflush(0, TCIFLUSH); - - if (!username) { - int i; + for (ss = forbid; *ss; ss++) unsetenv(*ss); - memset(username = uu, 0, sizeof(uu)); - gethostname(uu, sizeof(uu)-1); - printf("%s%slogin: ", *uu ? uu : "", *uu ? " " : ""); - fflush(stdout); - - if(!fgets(uu, sizeof(uu)-1, stdin)) _exit(1); + while (1) { + tcflush(0, TCIFLUSH); - // Remove trailing \n and so on - for (i = 0; i<sizeof(uu); i++) if (uu[i]<=' ' || uu[i]==':') uu[i]=0; - if (!*uu) { - username = 0; - continue; - } + username[sizeof(username)-1] = 0; + if (*toys.optargs) xstrncpy(username, *toys.optargs, sizeof(username)); + else { + read_user(username, sizeof(username)); + if (!*username) continue; } - // If user exists and isn't locked pwd = getpwnam(username); - if (pwd && *pwd->pw_passwd != '!' && *pwd->pw_passwd != '*') { + if (!pwd) goto query_pass; // Non-existing user - // Pre-authenticated or passwordless - if (TT.username || !*pwd->pw_passwd) break; + if (pwd->pw_passwd[0] == '!' || pwd->pw_passwd[0] == '*') + goto query_pass; // Locked account - // fetch shadow password if necessary - if (*(pass = pwd->pw_passwd) == 'x') { - struct spwd *spwd = getspnam (username); + if (f_flag) break; // Pre-authenticated - if (spwd) pass = spwd->sp_pwdp; - } - } else if (TT.username) error_exit("bad -f '%s'", TT.username); + if (!pwd->pw_passwd[0]) break; // Password-less account - // Verify password. (Prompt for password _before_ checking disable state.) - if (!read_password(toybuf, sizeof(toybuf), "Password: ")) { - int x = pass && (ss = crypt(toybuf, pass)) && !strcmp(pass, ss); - - // password go bye-bye now. - memset(toybuf, 0, sizeof(toybuf)); - if (x) break; + pass = pwd->pw_passwd; + if (pwd->pw_passwd[0] == 'x') { + spwd = getspnam (username); + if (spwd) pass = spwd->sp_pwdp; } - syslog(LOG_WARNING, "invalid password for '%s' on %s %s%s", pwd->pw_name, - ttyname(tty), hh ? "from " : "", hh ? TT.hostname : ""); +query_pass: + if (!verify_password(pass)) break; + + f_flag = 0; + syslog(LOG_WARNING, "invalid password for '%s' on %s %s %s", username, + ttyname(0), h_flag?"from":"", h_flag?TT.hostname:""); sleep(3); puts("Login incorrect"); - username = 0; + if (++auth_fail_cnt == 3) + error_exit("Maximum number of tries exceeded (3)\n"); + + *username = 0; pwd = 0; + spwd = 0; } alarm(0); - // This had password data in it, and we reuse for motd below - memset(toybuf, 0, sizeof(toybuf)); - - if (!pwd) error_exit("max retries (3)"); - // Check twice because "this file exists" is a security test, and in - // theory filehandle exhaustion or other error could make open/read fail. - if (pwd->pw_uid && !access("/etc/nologin", R_OK)) { - ss = readfile("/etc/nologin", toybuf, sizeof(toybuf)); - puts ((ss && *ss) ? ss : "nologin"); - free(ss); - toys.exitval = 1; - - return; - } + if (pwd->pw_uid) handle_nologin(); xsetuser(pwd); - if (chdir(pwd->pw_dir)) printf("bad $HOME: %s\n", pwd->pw_dir); - - if (!(toys.optflags&FLAG_p)) { - char *term = getenv("TERM"); - - clearenv(); - if (term) setenv("TERM", term, 1); - } - - setenv("USER", pwd->pw_name, 1); - setenv("LOGNAME", pwd->pw_name, 1); - setenv("HOME", pwd->pw_dir, 1); - setenv("SHELL", pwd->pw_shell, 1); + setup_environment(pwd, !(toys.optflags & FLAG_p)); - // Message of the day - if ((ss = readfile("/etc/motd", 0, 0))) { - puts(ss); - free(ss); - } + handle_motd(); syslog(LOG_INFO, "%s logged in on %s %s %s", pwd->pw_name, - ttyname(tty), hh ? "from" : "", hh ? TT.hostname : ""); + ttyname(0), h_flag?"from":"", h_flag?TT.hostname:""); - // can't xexec here because name doesn't match argv[0] - snprintf(toybuf, sizeof(toybuf)-1, "-%s", basename_r(pwd->pw_shell)); - toy_exec((char *[]){toybuf, 0}); - execl(pwd->pw_shell, toybuf, NULL); - error_exit("Failed to spawn shell"); + spawn_shell(pwd->pw_shell); } diff --git a/toys/other/lspci.c b/toys/other/lspci.c index 077ce75..c9b22ab 100644..100755 --- a/toys/other/lspci.c +++ b/toys/other/lspci.c @@ -37,7 +37,7 @@ GLOBALS( FILE *db; ) -static int do_lspci(struct dirtree *new) +int do_lspci(struct dirtree *new) { char *p = toybuf, *vendor = toybuf+9, *device = toybuf+18, driver[256], *vbig = 0, *dbig = 0, **fields; diff --git a/toys/other/nbd_client.c b/toys/other/nbd_client.c index a82ff7c..c16585a 100644..100755 --- a/toys/other/nbd_client.c +++ b/toys/other/nbd_client.c @@ -40,6 +40,7 @@ void nbd_client_main(void) { int sock = -1, nbd, flags; unsigned long timeout = 0; + struct addrinfo *addr, *p; char *host=toys.optargs[0], *port=toys.optargs[1], *device=toys.optargs[2]; uint64_t devsize; @@ -48,10 +49,23 @@ void nbd_client_main(void) nbd = xopen(device, O_RDWR); for (;;) { int temp; + struct addrinfo hints; // Find and connect to server - sock = xconnect(host, port, AF_UNSPEC, SOCK_STREAM, 0, 0); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + if (getaddrinfo(host, port, &hints, &addr)) addr = 0; + for (p = addr; p; p = p->ai_next) { + sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol); + if (-1 != connect(sock, p->ai_addr, p->ai_addrlen)) break; + close(sock); + } + freeaddrinfo(addr); + + if (!p) perror_exit("%s:%s", host, port); + temp = 1; setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &temp, sizeof(int)); diff --git a/toys/other/netcat.c b/toys/other/netcat.c index 9d0c3cf..9d0c3cf 100644..100755 --- a/toys/other/netcat.c +++ b/toys/other/netcat.c diff --git a/toys/other/reboot.c b/toys/other/reboot.c index 1e8f5e9..a135888 100644..100755 --- a/toys/other/reboot.c +++ b/toys/other/reboot.c @@ -2,7 +2,7 @@ * * Copyright 2013 Elie De Brauwer <eliedebrauwer@gmail.com> -USE_REBOOT(NEWTOY(reboot, "fn", TOYFLAG_SBIN|TOYFLAG_NEEDROOT)) +USE_REBOOT(NEWTOY(reboot, "n", TOYFLAG_SBIN|TOYFLAG_NEEDROOT)) USE_REBOOT(OLDTOY(halt, reboot, TOYFLAG_SBIN|TOYFLAG_NEEDROOT)) USE_REBOOT(OLDTOY(poweroff, reboot, TOYFLAG_SBIN|TOYFLAG_NEEDROOT)) @@ -10,11 +10,10 @@ config REBOOT bool "reboot" default y help - usage: reboot/halt/poweroff [-fn] + usage: reboot/halt/poweroff [-n] Restart, halt or powerdown the system. - -f Don't signal init -n Don't sync before stopping the system. */ @@ -24,12 +23,9 @@ config REBOOT void reboot_main(void) { - int types[] = {RB_AUTOBOOT, RB_HALT_SYSTEM, RB_POWER_OFF}, - sigs[] = {SIGINT, SIGUSR1, SIGUSR2}, idx; + int types[] = {RB_AUTOBOOT, RB_HALT_SYSTEM, RB_POWER_OFF}; if (!(toys.optflags & FLAG_n)) sync(); - idx = stridx("hp", *toys.which->name)+1; - if (toys.optflags & FLAG_f) toys.exitval = reboot(types[idx]); - else toys.exitval = kill(1, sigs[idx]); + toys.exitval = reboot(types[stridx("hp", *toys.which->name)+1]); } diff --git a/toys/other/rev.c b/toys/other/rev.c index 4cf7214..b5720a3 100644..100755 --- a/toys/other/rev.c +++ b/toys/other/rev.c @@ -15,7 +15,7 @@ config REV #include "toys.h" -static void do_rev(int fd, char *name) +void do_rev(int fd, char *name) { char *c; diff --git a/toys/other/stat.c b/toys/other/stat.c index b1355a5..d6db44d 100644 --- a/toys/other/stat.c +++ b/toys/other/stat.c @@ -15,12 +15,6 @@ config STAT -f display filesystem status instead of file status -c Output specified FORMAT string instead of default - The valid format escape sequences for filesystems: - %a Available blocks |%b Total blocks |%c Total inodes - %d Free inodes |%f Free blocks |%i File system ID - %l Max filename length |%n File name |%s Fragment size - %S Best transfer size |%t File system type |%T Type in human readable form - The valid format escape sequences for files: %a Access bits (octal) |%A Access bits (flags)|%b Blocks allocated %B Bytes per block |%d Device ID (dec) |%D Device ID (hex) @@ -31,14 +25,11 @@ config STAT %x Access time |%X Access unix time |%y File write time %Y File write unix time|%z Dir change time |%Z Dir change unix time -config STAT_C - bool - default y - depends on STAT && !TOYBOX_LSM_NONE - help - usage: stat - - %C Security context + The valid format escape sequences for filesystems: + %a Available blocks |%b Total blocks |%c Total inodes + %d Free inodes |%f Free blocks |%i File system ID + %l Max filename length |%n File name |%s Fragment size + %S Best transfer size |%t File system type */ #define FOR_stat @@ -55,35 +46,6 @@ GLOBALS( struct group *group_name; ) -static char* ftype_to_string(uint64_t ftype) -{ - switch (ftype) { - case 0xADFF: return "affs"; - case 0x5346544e: return "ntfs"; - case 0x1Cd1: return "devpts"; - case 0x137D: return "ext"; - case 0xEF51: return "ext2"; - case 0xEF53: return "ext2/ext3"; - case 0x1BADFACE: return "bfs"; - case 0x9123683E: return "btrfs"; - case 0x28cd3d45: return "cramfs"; - case 0x3153464a: return "jfs"; - case 0x7275: return "romfs"; - case 0x01021994: return "tmpfs"; - case 0x3434: return "nilfs"; - case 0x6969: return "nfs"; - case 0x9fa0: return "proc"; - case 0x534F434B: return "sockfs"; - case 0x62656572: return "sysfs"; - case 0x517B: return "smb"; - case 0x4d44: return "msdos"; - case 0x4006: return "fat"; - case 0x43415d53: return "smackfs"; - case 0x73717368: return "squashfs"; - default: return "unknown"; - } -} - // Note: the atime, mtime, and ctime fields in struct stat are the start // of embedded struct timespec, but posix won't let them use that @@ -108,13 +70,6 @@ static void print_stat(char type) xprintf("%s", str); } else if (type == 'b') xprintf("%llu", stat->st_blocks); else if (type == 'B') xprintf("%lu", stat->st_blksize); - else if (CFG_STAT_C && type == 'C') { - char *label = NULL; - if ((lsm_lget_context(*toys.optargs, (char **)&label) > 0) && label) { - xprintf("%s", label); - free(label); - } - } else if (type == 'd') xprintf("%ldd", stat->st_dev); else if (type == 'D') xprintf("%llxh", stat->st_dev); else if (type == 'f') xprintf("%lx", stat->st_mode); @@ -158,7 +113,6 @@ static void print_statfs(char type) { else if (type == 'f') xprintf("%llu", statfs->f_bfree); else if (type == 'l') xprintf("%ld", statfs->f_namelen); else if (type == 't') xprintf("%lx", statfs->f_type); - else if (type == 'T') xprintf("%s", ftype_to_string(statfs->f_type)); else if (type == 'i') xprintf("%08x%08x", statfs->f_fsid.__val[0], statfs->f_fsid.__val[1]); else if (type == 's') xprintf("%d", statfs->f_frsize); @@ -170,7 +124,7 @@ void stat_main(void) { int flagf = toys.optflags & FLAG_f; char *format = flagf - ? " File: \"%n\"\n ID: %i Namelen: %l Type: %T\n" + ? " File: \"%n\"\n ID: %i Namelen: %l Type: %t\n" "Block Size: %s Fundamental block size: %S\n" "Blocks: Total: %b\tFree: %f\tAvailable: %a\n" "Inodes: Total: %c\tFree: %d" diff --git a/toys/other/switch_root.c b/toys/other/switch_root.c index acbae2b..0861c70 100644..100755 --- a/toys/other/switch_root.c +++ b/toys/other/switch_root.c @@ -67,13 +67,8 @@ void switch_root_main(void) } TT.rootdev=st2.st_dev; - // trim any / characters from the init cmdline, as we want to test it with - // stat(), relative to newroot. *cmdline is also used below, but by that - // point we are in the chroot, so a relative path is still OK. - while (**cmdline == '/') (*cmdline)++; - // init program must exist and be an executable file - if (stat(*cmdline, &st1) || !S_ISREG(st1.st_mode) || !(st1.st_mode&0100)) { + if (stat("init", &st1) || !S_ISREG(st1.st_mode) || !(st1.st_mode&0100)) { error_msg("bad init"); goto panic; } @@ -86,24 +81,6 @@ void switch_root_main(void) // Ok, enough safety checks: wipe root partition. dirtree_read("/", del_node); - // Fix the appearance of the mount table in the newroot chroot - if (mount(".", "/", NULL, MS_MOVE, NULL)) { - perror_msg("mount"); - goto panic; - } - - // Enter the new root before starting init - if (chroot(".")) { - perror_msg("chroot"); - goto panic; - } - - // Make sure cwd does not point outside of the chroot - if (chdir("/")) { - perror_msg("chdir"); - goto panic; - } - if (TT.console) { int i; for (i=0; i<3; i++) if (console != i) dup2(console, i); diff --git a/toys/other/tac.c b/toys/other/tac.c index d5f72fd..538d1b0 100644..100755 --- a/toys/other/tac.c +++ b/toys/other/tac.c @@ -15,7 +15,7 @@ config TAC #include "toys.h" -static void do_tac(int fd, char *name) +void do_tac(int fd, char *name) { struct arg_list *list = NULL; char *c; diff --git a/toys/other/taskset.c b/toys/other/taskset.c index 4ade5f1..2851923 100644..100755 --- a/toys/other/taskset.c +++ b/toys/other/taskset.c @@ -120,7 +120,7 @@ void taskset_main(void) } } -static int do_nproc(struct dirtree *new) +int do_nproc(struct dirtree *new) { if (!new->parent) return DIRTREE_RECURSE; if (!strncmp(new->name, "cpu", 3) && isdigit(new->name[3])) TT.nproc++; diff --git a/toys/other/vmstat.c b/toys/other/vmstat.c index 9a38e45..c11e46b 100644..100755 --- a/toys/other/vmstat.c +++ b/toys/other/vmstat.c @@ -39,7 +39,7 @@ struct vmstat_proc { // All the elements of vmstat_proc are the same size, so we can populate it as // a big array, then read the elements back out by name -static void get_vmstat_proc(struct vmstat_proc *vmstat_proc) +void get_vmstat_proc(struct vmstat_proc *vmstat_proc) { char *vmstuff[] = { "/proc/stat", "cpu ", 0, 0, 0, 0, 0, 0, "intr ", "ctxt ", "procs_running ", "procs_blocked ", "/proc/meminfo", diff --git a/toys/pending/dd.c b/toys/pending/dd.c index 366d3c5..3449104 100644..100755 --- a/toys/pending/dd.c +++ b/toys/pending/dd.c @@ -133,9 +133,9 @@ static void summary() //out to STDERR fprintf(stderr,"%llu+%llu records in\n%llu+%llu records out\n", st.in_full, st.in_part, st.out_full, st.out_part); - human_readable(toybuf, st.bytes, HR_SPACE|HR_B); + human_readable(toybuf, st.bytes); fprintf(stderr, "%llu bytes (%s) copied, ",st.bytes, toybuf); - human_readable(toybuf, st.bytes/seconds, HR_SPACE|HR_B); + human_readable(toybuf, st.bytes/seconds); fprintf(stderr, "%f s, %s/s\n", seconds, toybuf); } diff --git a/toys/pending/init.c b/toys/pending/init.c index d9e78ff..529c1b9 100644..100755 --- a/toys/pending/init.c +++ b/toys/pending/init.c @@ -348,7 +348,6 @@ static void halt_poweroff_reboot_handler(int sig_no) reboot_magic_no=RB_POWER_OFF; break; case SIGTERM: - case SIGINT: error_msg("Requesting system reboot"); reboot_magic_no=RB_AUTOBOOT; break; @@ -416,7 +415,7 @@ static void pause_handler(int sig_no) errno_backup = errno; signal_backup = caught_signal; - xsignal(SIGCONT, catch_signal); + signal(SIGCONT, catch_signal); while(1) { if (caught_signal == SIGCONT) break; @@ -461,11 +460,10 @@ void init_main(void) putenv("USER=root"); inittab_parsing(); - xsignal(SIGUSR1, halt_poweroff_reboot_handler);//halt - xsignal(SIGUSR2, halt_poweroff_reboot_handler);//poweroff - xsignal(SIGTERM, halt_poweroff_reboot_handler);//reboot - xsignal(SIGINT, halt_poweroff_reboot_handler);//reboot - xsignal(SIGQUIT, restart_init_handler);//restart init + signal(SIGUSR1, halt_poweroff_reboot_handler);//halt + signal(SIGUSR2, halt_poweroff_reboot_handler);//poweroff + signal(SIGTERM, halt_poweroff_reboot_handler);//reboot + signal(SIGQUIT, restart_init_handler);//restart init memset(&sig_act, 0, sizeof(sig_act)); sigfillset(&sig_act.sa_mask); sigdelset(&sig_act.sa_mask, SIGCONT); @@ -473,6 +471,7 @@ void init_main(void) sigaction(SIGTSTP, &sig_act, NULL); memset(&sig_act, 0, sizeof(sig_act)); sig_act.sa_handler = catch_signal; + sigaction(SIGINT, &sig_act, NULL); sigaction(SIGHUP, &sig_act, NULL); run_action_from_list(SYSINIT); check_if_pending_signals(); diff --git a/toys/pending/mdev.c b/toys/pending/mdev.c index a13a53d..0c49633 100644..100755 --- a/toys/pending/mdev.c +++ b/toys/pending/mdev.c @@ -35,7 +35,7 @@ config MDEV_CONF static void make_device(char *path) { char *device_name = NULL, *s, *temp; - int major = 0, minor = 0, type, len, fd; + int major, minor, type, len, fd; int mode = 0660; uid_t uid = 0; gid_t gid = 0; @@ -46,21 +46,24 @@ static void make_device(char *path) temp = strrchr(path, '/'); fd = open(path, O_RDONLY); *temp=0; - len = read(fd, toybuf, 64); + temp = toybuf; + len = read(fd, temp, 64); close(fd); if (len<1) return; - toybuf[len] = 0; + temp[len] = 0; // Determine device type, major and minor type = path[5]=='c' ? S_IFCHR : S_IFBLK; - sscanf(toybuf, "%u:%u", &major, &minor); + major = minor = 0; + sscanf(temp, "%u:%u", &major, &minor); } else { // if (!path), do hotplug if (!(temp = getenv("SUBSYSTEM"))) return; type = strcmp(temp, "block") ? S_IFCHR : S_IFBLK; + major = minor = 0; if (!(temp = getenv("MAJOR"))) return; sscanf(temp, "%u", &major); @@ -71,15 +74,11 @@ static void make_device(char *path) device_name = getenv("DEVNAME"); if (!path) return; + temp = toybuf; } if (!device_name) device_name = strrchr(path, '/') + 1; - // as in linux/drivers/base/core.c, device_get_devnode() - while ((temp = strchr(device_name, '!'))) { - *temp = '/'; - } - // If we have a config file, look up permissions for this device if (CFG_MDEV_CONF) { @@ -186,22 +185,22 @@ found_device: } } - sprintf(toybuf, "/dev/%s", device_name); + sprintf(temp, "/dev/%s", device_name); - if ((temp=getenv("ACTION")) && !strcmp(temp, "remove")) { - unlink(toybuf); + if (getenv("ACTION") && !strcmp(getenv("ACTION"), "remove")) { + unlink(temp); return; } if (strchr(device_name, '/')) - mkpathat(AT_FDCWD, toybuf, 0, 2); - if (mknod(toybuf, mode | type, makedev(major, minor)) && errno != EEXIST) - perror_exit("mknod %s failed", toybuf); + mkpathat(AT_FDCWD, temp, 0, 2); + if (mknod(temp, mode | type, makedev(major, minor)) && errno != EEXIST) + perror_exit("mknod %s failed", temp); - if (type == S_IFBLK) close(open(toybuf, O_RDONLY)); // scan for partitions + if (type == S_IFBLK) close(open(temp, O_RDONLY)); // scan for partitions - if (CFG_MDEV_CONF) mode=chown(toybuf, uid, gid); + if (CFG_MDEV_CONF) mode=chown(temp, uid, gid); } static int callback(struct dirtree *node) diff --git a/toys/pending/modprobe.c b/toys/pending/modprobe.c index 07c53fc..5431cb3 100644..100755 --- a/toys/pending/modprobe.c +++ b/toys/pending/modprobe.c @@ -65,12 +65,14 @@ struct module_s { static char *path2mod(char *file, char *mod) { int i; - char *from; + char *from, *lslash; if (!file) return NULL; if (!mod) mod = xmalloc(MODNAME_LEN); - from = basename_r(file); + lslash = strrchr(file, '/'); + if (!lslash || (lslash == file && !lslash[1])) from = file; + else from = lslash + 1; for (i = 0; i < (MODNAME_LEN-1) && from[i] && from[i] != '.'; i++) mod[i] = (from[i] == '-') ? '_' : from[i]; @@ -275,8 +277,7 @@ static int config_action(struct dirtree *node) get_mod(tokens[1], 1)->flags |= MOD_BLACKLIST; else if (!strcmp(tokens[0], "install")) continue; else if (!strcmp(tokens[0], "remove")) continue; - else if (toys.optflags & FLAG_q) - error_msg("Invalid option %s found in file %s", tokens[0], filename); + else error_msg("Invalid option %s found in file %s", tokens[0], filename); } fclose(fc); free(filename); @@ -380,6 +381,7 @@ static int ins_mod(char *modules, char *flags) } res = syscall(__NR_init_module, buf, len, toybuf); if (CFG_TOYBOX_FREE && buf != toybuf) free(buf); + if (res) perror_exit("failed to load %s ", toys.optargs[0]); return res; } @@ -426,7 +428,7 @@ static int go_probe(struct module_s *m) int rc = 0, first = 1; if (!(m->flags & MOD_FNDDEPMOD)) { - if (!(toys.optflags & FLAG_q)) + if (!(toys.optflags & FLAG_s)) error_msg("module %s not found in modules.dep", m->name); return -ENOENT; } diff --git a/toys/pending/syslogd.c b/toys/pending/syslogd.c index fd0a355..450bd72 100644 --- a/toys/pending/syslogd.c +++ b/toys/pending/syslogd.c @@ -5,14 +5,14 @@ * * No Standard -USE_SYSLOGD(NEWTOY(syslogd,">0l#<1>8=8R:b#<0>99=1B#<0>99=0s#<0=2000m#<0>71582787=20O:p:f:a:nSKLD", TOYFLAG_SBIN|TOYFLAG_STAYROOT)) +USE_SYSLOGD(NEWTOY(syslogd,">0l#<1>8=8R:b#<0>99=1s#<0=200m#<0>71582787=20O:p:f:a:nSKLD", TOYFLAG_SBIN|TOYFLAG_STAYROOT)) config SYSLOGD bool "syslogd" - default y + default n help usage: syslogd [-a socket] [-O logfile] [-f config file] [-m interval] - [-p socket] [-s SIZE] [-b N] [-B N][-R HOST] [-l N] [-nSLKD] + [-p socket] [-s SIZE] [-b N] [-R HOST] [-l N] [-nSLKD] System logging utility @@ -27,7 +27,6 @@ config SYSLOGD -L Log locally and via network (default is network only if -R)" -s SIZE Max size (KB) before rotation (default:200KB, 0=off) -b N rotated logs to keep (default:1, max=99, 0=purge) - -B N Set number of logs to keep logs in memory buffer before write (default:0, max=99, 0=purge) -K Log to kernel printk buffer (use dmesg to read it) -l N Log only messages more urgent than prio(default:8 max:8 min:1) -D Drop duplicates @@ -55,12 +54,6 @@ struct logfile { struct sockaddr_in saddr; }; -// Log buffer -struct logbuffer { - int len; - char buf[1024]; -}; - GLOBALS( char *socket; char *config_file; @@ -68,7 +61,6 @@ GLOBALS( char *logfile; long interval; long rot_size; - long buf_count; long rot_count; char *remote_log; long log_prio; @@ -286,9 +278,7 @@ static void open_logfiles(void) //write to file with rotation static int write_rotate(struct logfile *tf, int len) { - int size, isreg, idx; - static int buf_idx = 0; - static struct logbuffer buffer[100]; + int size, isreg; struct stat statf; isreg = (!fstat(tf->logfd, &statf) && S_ISREG(statf.st_mode)); size = statf.st_size; @@ -318,18 +308,6 @@ static int write_rotate(struct logfile *tf, int len) ftruncate(tf->logfd, 0); } } - if (TT.buf_count && (toys.optflags & FLAG_B)) { - if (buf_idx < TT.buf_count) { - memcpy(buffer[buf_idx].buf, toybuf, len); - buffer[buf_idx].buf[len + 1] = '\0'; - buffer[buf_idx].len = len; - buf_idx++; - return len; - } else { - for (idx = 0; idx < TT.buf_count; idx++) write(tf->logfd, buffer[idx].buf, buffer[idx].len); - buf_idx = 0; - } - } return write(tf->logfd, toybuf, len); } diff --git a/toys/pending/telnet.c b/toys/pending/telnet.c index dc3487a..f113cbb 100644..100755 --- a/toys/pending/telnet.c +++ b/toys/pending/telnet.c @@ -48,6 +48,39 @@ GLOBALS( #define UF_ECHO 0x01 #define UF_SGA 0x02 +/* + * creates a socket of family INET/INET6 and protocol TCP and connects + * it to HOST at PORT. + * if successful then returns SOCK othrwise error + */ +static int xconnect_inet_tcp(char *host, int port) +{ + int ret; + struct addrinfo *info, *rp; + char buf[32]; + + rp = xzalloc(sizeof(struct addrinfo)); + rp->ai_family = AF_UNSPEC; + rp->ai_socktype = SOCK_STREAM; + rp->ai_protocol = IPPROTO_TCP; + sprintf(buf, "%d", port); + + ret = getaddrinfo(host, buf, rp, &info); + if(ret || !info) perror_exit("BAD ADDRESS: can't find : %s ", host); + free(rp); + + for (rp = info; rp; rp = rp->ai_next) + if ( (rp->ai_family == AF_INET) || (rp->ai_family == AF_INET6)) break; + + if (!rp) error_exit("Invalid IP %s", host); + + ret = xsocket(rp->ai_family, SOCK_STREAM, IPPROTO_TCP); + if(connect(ret, rp->ai_addr, rp->ai_addrlen) == -1) perror_exit("connect"); + + freeaddrinfo(info); + return ret; +} + // sets terminal mode: LINE or CHARACTER based om internal stat. static char const es[] = "\r\nEscape character is "; static void set_mode(void) @@ -102,7 +135,7 @@ static void handle_esc(void) char input; if(toys.signal && TT.term_ok) tcsetattr(0, TCSADRAIN, &TT.raw_term); - xwrite(1,"\r\nConsole escape. Commands are:\r\n\n" + write(1,"\r\nConsole escape. Commands are:\r\n\n" " l go to line mode\r\n" " c go to character mode\r\n" " z suspend telnet\r\n" @@ -145,7 +178,7 @@ static void handle_esc(void) default: break; } - xwrite(1, "continuing...\r\n", 15); + write(1, "continuing...\r\n", 15); if (toys.signal && TT.term_ok) tcsetattr(0, TCSADRAIN, &TT.def_term); ret: @@ -259,7 +292,7 @@ static int read_server(int len) } } while (TT.pbuff < len); - if (i) xwrite(STDIN_FILENO, toybuf, i); + if (i) write(STDIN_FILENO, toybuf, i); return 0; } @@ -281,19 +314,20 @@ static void write_server(int len) if (*c == IAC) toybuf[i++] = *c; /* IAC -> IAC IAC */ else if (*c == '\r') toybuf[i++] = '\0'; /* CR -> CR NUL */ } - if(i) xwrite(TT.sfd, toybuf, i); + if(i) write(TT.sfd, toybuf, i); } void telnet_main(void) { - char *port = "23"; int set = 1, len; struct pollfd pfds[2]; + TT.port = 23; //TELNET_PORT TT.win_width = 80; //columns TT.win_height = 24; //rows - if (toys.optc == 2) port = toys.optargs[1]; + if(toys.optc == 2) TT.port = atoi(toys.optargs[1]); + if(TT.port <= 0 || TT.port > 65535) error_exit("bad PORT (1-65535)"); TT.ttype = getenv("TERM"); if(!TT.ttype) TT.ttype = ""; @@ -306,7 +340,7 @@ void telnet_main(void) } terminal_size(&TT.win_width, &TT.win_height); - TT.sfd = xconnect(*toys.optargs, port, 0, SOCK_STREAM, IPPROTO_TCP, 0); + TT.sfd = xconnect_inet_tcp(toys.optargs[0], TT.port); setsockopt(TT.sfd, SOL_SOCKET, SO_REUSEADDR, &set, sizeof(set)); setsockopt(TT.sfd, SOL_SOCKET, SO_KEEPALIVE, &set, sizeof(set)); diff --git a/toys/pending/telnetd.c b/toys/pending/telnetd.c index 4198e63..4198e63 100644..100755 --- a/toys/pending/telnetd.c +++ b/toys/pending/telnetd.c diff --git a/toys/pending/tftp.c b/toys/pending/tftp.c deleted file mode 100644 index 60d5f17..0000000 --- a/toys/pending/tftp.c +++ /dev/null @@ -1,454 +0,0 @@ -/* tftp.c - TFTP client. - * - * Copyright 2012 Madhur Verma <mad.flexi@gmail.com> - * Copyright 2015 Sameer Prakash Pradhan <sameer.p.pradhan@gmail.com> - * - * No Standard. - -USE_TFTP(NEWTOY(tftp, "<1b#<8>65464r:l:g|p|[!gp]", TOYFLAG_USR|TOYFLAG_BIN)) - -config TFTP - bool "tftp" - default n - help - usage: tftp [OPTIONS] HOST [PORT] - - Transfer file from/to tftp server. - - -l FILE Local FILE - -r FILE Remote FILE - -g Get file - -p Put file - -b SIZE Transfer blocks of SIZE octets(8 <= SIZE <= 65464) -*/ -#define FOR_tftp -#include "toys.h" - -GLOBALS( - char *local_file; - char *remote_file; - long block_size; - - struct sockaddr_storage inaddr; - int af; -) - -#define TFTP_BLKSIZE 512 -#define TFTP_RETRIES 3 -#define TFTP_DATAHEADERSIZE 4 -#define TFTP_MAXPACKETSIZE (TFTP_DATAHEADERSIZE + TFTP_BLKSIZE) -#define TFTP_PACKETSIZE TFTP_MAXPACKETSIZE -#define TFTP_DATASIZE (TFTP_PACKETSIZE-TFTP_DATAHEADERSIZE) -#define TFTP_IOBUFSIZE (TFTP_PACKETSIZE+8) - -#define TFTP_OP_RRQ 1 /* Read Request RFC 1350, RFC 2090 */ -#define TFTP_OP_WRQ 2 /* Write Request RFC 1350 */ -#define TFTP_OP_DATA 3 /* Data chunk RFC 1350 */ -#define TFTP_OP_ACK 4 /* Acknowledgement RFC 1350 */ -#define TFTP_OP_ERR 5 /* Error Message RFC 1350 */ -#define TFTP_OP_OACK 6 /* Option acknowledgment RFC 2347 */ - -#define TFTP_ER_ILLEGALOP 4 /* Illegal TFTP operation */ -#define TFTP_ER_UNKID 5 /* Unknown transfer ID */ - -#define TFTP_ES_NOSUCHFILE "File not found" -#define TFTP_ES_ACCESS "Access violation" -#define TFTP_ES_FULL "Disk full or allocation exceeded" -#define TFTP_ES_ILLEGALOP "Illegal TFTP operation" -#define TFTP_ES_UNKID "Unknown transfer ID" -#define TFTP_ES_EXISTS "File already exists" -#define TFTP_ES_UNKUSER "No such user" -#define TFTP_ES_NEGOTIATE "Terminate transfer due to option negotiation" - -// Initializes SERVER with ADDR and returns socket. -static int init_tftp(struct sockaddr_storage *server) -{ - struct timeval to = { .tv_sec = 10, //Time out - .tv_usec = 0 }; - const int set = 1; - int port = 69, sd = xsocket(TT.af, SOCK_DGRAM, IPPROTO_UDP); - - xsetsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (void *)&to, sizeof(struct timeval)); - xsetsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (void *)&set, sizeof(set)); - - if(toys.optc == 2) port = atolx_range(toys.optargs[1], 1, 65535); - memset(server, 0, sizeof(struct sockaddr_storage)); - if (TT.af == AF_INET6) { - ((struct sockaddr_in6 *)server)->sin6_family = AF_INET6; - ((struct sockaddr_in6 *)server)->sin6_addr = - ((struct sockaddr_in6 *)&TT.inaddr)->sin6_addr; - ((struct sockaddr_in6 *)server)->sin6_port = htons(port); - } - else { - ((struct sockaddr_in *)server)->sin_family = AF_INET; - ((struct sockaddr_in *)server)->sin_addr.s_addr = - ((struct sockaddr_in *)&TT.inaddr)->sin_addr.s_addr; - ((struct sockaddr_in *)server)->sin_port = htons(port); - } - return sd; -} - -/* - * Makes a request packet in BUFFER with OPCODE and file PATH of MODE - * and returns length of packet. - */ -static int mkpkt_request(uint8_t *buffer, int opcode, char *path, int mode) -{ - buffer[0] = opcode >> 8; - buffer[1] = opcode & 0xff; - if(strlen(path) > TFTP_BLKSIZE) error_exit("path too long"); - return sprintf((char*) &buffer[2], "%s%c%s", path, 0, - (mode ? "octet" : "netascii")) + 3; -} - -/* - * Makes an acknowledgement packet in BUFFER of BLOCNO - * and returns packet length. - */ -static int mkpkt_ack(uint8_t *buffer, uint16_t blockno) -{ - buffer[0] = TFTP_OP_ACK >> 8; - buffer[1] = TFTP_OP_ACK & 0xff; - buffer[2] = blockno >> 8; - buffer[3] = blockno & 0xff; - return 4; -} - -/* - * Makes an error packet in BUFFER with ERRORCODE and ERRORMSG. - * and returns packet length. - */ -static int mkpkt_err(uint8_t *buffer, uint16_t errorcode, char *errormsg) -{ - buffer[0] = TFTP_OP_ERR >> 8; - buffer[1] = TFTP_OP_ERR & 0xff; - buffer[2] = errorcode >> 8; - buffer[3] = errorcode & 0xff; - strcpy((char*) &buffer[4], errormsg); - return strlen(errormsg) + 5; -} - -/* - * Recieves data from server in BUFF with socket SD and updates FROM - * and returns read length. - */ -static ssize_t read_server(int sd, void *buf, size_t len, - struct sockaddr_storage *from) -{ - socklen_t alen; - ssize_t nb; - - for (;;) { - memset(buf, 0, len); - alen = sizeof(struct sockaddr_storage); - nb = recvfrom(sd, buf, len, 0, (struct sockaddr *) from, &alen); - if (nb < 0) { - if (errno == EAGAIN) { - perror_msg("server read timed out"); - return nb; - }else if (errno != EINTR) { - perror_msg("server read failed"); - return nb; - } - }else return nb; - } - return nb; -} - -/* - * sends data to server TO from BUFF of length LEN through socket SD - * and returns successfully send bytes number. - */ -static ssize_t write_server(int sd, void *buf, size_t len, - struct sockaddr_storage *to) -{ - ssize_t nb; - - for (;;) { - nb = sendto(sd, buf, len, 0, (struct sockaddr *)to, - sizeof(struct sockaddr_storage)); - if (nb < 0) { - if (errno != EINTR) { - perror_msg("server write failed"); - return nb; - } - } else return nb; - } - return nb; -} - -// checks packet for data and updates block no -static inline int check_data( uint8_t *packet, uint16_t *opcode, - uint16_t *blockno) -{ - *opcode = (uint16_t) packet[0] << 8 | (uint16_t) packet[1]; - if (*opcode == TFTP_OP_DATA) { - *blockno = (uint16_t) packet[2] << 8 | (uint16_t) packet[3]; - return 0; - } - return -1; -} - -// Makes data packet through FD from file OFFSET in buffer PACKET of BLOCKNO -static int mkpkt_data(int fd, off_t offset, uint8_t *packet, uint16_t blockno) -{ - off_t tmp; - int nbytesread; - - packet[0] = TFTP_OP_DATA >> 8; - packet[1] = TFTP_OP_DATA & 0xff; - packet[2] = blockno >> 8; - packet[3] = blockno & 0xff; - tmp = lseek(fd, offset, SEEK_SET); - if (tmp == (off_t) -1) { - perror_msg("lseek failed"); - return -1; - } - nbytesread = readall(fd, &packet[TFTP_DATAHEADERSIZE], TFTP_DATASIZE); - if (nbytesread < 0) return -1; - return nbytesread + TFTP_DATAHEADERSIZE; -} - -// Receives ACK responses from server and updates blockno -static int read_ack(int sd, uint8_t *packet, struct sockaddr_storage *server, - uint16_t *port, uint16_t *blockno) -{ - struct sockaddr_storage from; - ssize_t nbytes; - uint16_t opcode, rblockno; - int packetlen, retry; - - for (retry = 0; retry < TFTP_RETRIES; retry++) { - for (;;) { - nbytes = read_server(sd, packet, TFTP_IOBUFSIZE, &from); - if (nbytes < 4) { // Ack headersize = 4 - if (nbytes == 0) error_msg("Connection lost."); - else if (nbytes > 0) error_msg("Short packet: %d bytes", nbytes); - else error_msg("Server read ACK failure."); - break; - } else { - if (!*port) { - *port = ((struct sockaddr_in *)&from)->sin_port; - ((struct sockaddr_in *)server)->sin_port = - ((struct sockaddr_in *)&from)->sin_port; - } - if (((struct sockaddr_in *)server)->sin_addr.s_addr != - ((struct sockaddr_in *)&from)->sin_addr.s_addr) { - error_msg("Invalid address in DATA."); - continue; - } - if (*port != ((struct sockaddr_in *)server)->sin_port) { - error_msg("Invalid port in DATA."); - packetlen = mkpkt_err(packet, TFTP_ER_UNKID, TFTP_ES_UNKID); - (void) write_server(sd, packet, packetlen, server); - continue; - } - opcode = (uint16_t) packet[0] << 8 | (uint16_t) packet[1]; - rblockno = (uint16_t) packet[2] << 8 | (uint16_t) packet[3]; - - if (opcode != TFTP_OP_ACK) { - error_msg("Bad opcode."); - if (opcode > 5) { - packetlen = mkpkt_err(packet, TFTP_ER_ILLEGALOP, TFTP_ES_ILLEGALOP); - (void) write_server(sd, packet, packetlen, server); - } - break; - } - if (blockno) *blockno = rblockno; - return 0; - } - } - } - error_msg("Timeout, Waiting for ACK."); - return -1; -} - -// receives file from server. -static int file_get(void) -{ - struct sockaddr_storage server, from; - uint8_t *packet; - uint16_t blockno = 0, opcode, rblockno = 0; - int len, sd, fd, retry, nbytesrecvd = 0, ndatabytes, ret, result = -1; - - sd = init_tftp(&server); - - packet = (uint8_t*) xzalloc(TFTP_IOBUFSIZE); - fd = xcreate(TT.local_file, O_WRONLY | O_CREAT | O_TRUNC, 0666); - - len = mkpkt_request(packet, TFTP_OP_RRQ, TT.remote_file, 1); - ret = write_server(sd, packet, len, &server); - if (ret != len){ - unlink(TT.local_file); - goto errout_with_sd; - } - if (TT.af == AF_INET6) ((struct sockaddr_in6 *)&server)->sin6_port = 0; - else ((struct sockaddr_in *)&server)->sin_port = 0; - - do { - blockno++; - for (retry = 0 ; retry < TFTP_RETRIES; retry++) { - nbytesrecvd = read_server(sd, packet, TFTP_IOBUFSIZE, &from); - if (nbytesrecvd > 0) { - if ( ((TT.af == AF_INET) && - memcmp(&((struct sockaddr_in *)&server)->sin_addr, - &((struct sockaddr_in *)&from)->sin_addr, - sizeof(struct in_addr))) || - ((TT.af == AF_INET6) && - memcmp(&((struct sockaddr_in6 *)&server)->sin6_addr, - &((struct sockaddr_in6 *)&from)->sin6_addr, - sizeof(struct in6_addr)))) { - error_msg("Invalid address in DATA."); - retry--; - continue; - } - if ( ((TT.af == AF_INET) && ((struct sockaddr_in *)&server)->sin_port - && (((struct sockaddr_in *)&server)->sin_port != - ((struct sockaddr_in *)&from)->sin_port)) || - ((TT.af == AF_INET6) && ((struct sockaddr_in6 *)&server)->sin6_port - && (((struct sockaddr_in6 *)&server)->sin6_port != - ((struct sockaddr_in6 *)&from)->sin6_port))) { - error_msg("Invalid port in DATA."); - len = mkpkt_err(packet, TFTP_ER_UNKID, TFTP_ES_UNKID); - ret = write_server(sd, packet, len, &from); - retry--; - continue; - } - if (nbytesrecvd < TFTP_DATAHEADERSIZE) { - error_msg("Tiny data packet ignored."); - continue; - } - if (check_data(packet, &opcode, &rblockno) != 0 - || blockno != rblockno) { - - if (opcode == TFTP_OP_ERR) { - char *message = "DATA Check failure."; - char *arr[] = {TFTP_ES_NOSUCHFILE, TFTP_ES_ACCESS, - TFTP_ES_FULL, TFTP_ES_ILLEGALOP, - TFTP_ES_UNKID, TFTP_ES_EXISTS, - TFTP_ES_UNKUSER, TFTP_ES_NEGOTIATE}; - if (rblockno && (rblockno < 9)) message = arr[rblockno - 1]; - error_msg(message); - } - if (opcode > 5) { - len = mkpkt_err(packet, TFTP_ER_ILLEGALOP, TFTP_ES_ILLEGALOP); - ret = write_server(sd, packet, len, &from); - } - continue; - } - if ((TT.af == AF_INET6) && !((struct sockaddr_in6 *)&server)->sin6_port) - ((struct sockaddr_in6 *)&server)->sin6_port = - ((struct sockaddr_in6 *)&from)->sin6_port; - else if ((TT.af == AF_INET) && !((struct sockaddr_in *)&server)->sin_port) - ((struct sockaddr_in *)&server)->sin_port = - ((struct sockaddr_in *)&from)->sin_port; - break; - } - } - if (retry == TFTP_RETRIES) { - error_msg("Retry limit exceeded."); - unlink(TT.local_file); - goto errout_with_sd; - } - ndatabytes = nbytesrecvd - TFTP_DATAHEADERSIZE; - if (writeall(fd, packet + TFTP_DATAHEADERSIZE, ndatabytes) < 0){ - unlink(TT.local_file); - goto errout_with_sd; - } - len = mkpkt_ack(packet, blockno); - ret = write_server(sd, packet, len, &server); - if (ret != len){ - unlink(TT.local_file); - goto errout_with_sd; - } - } while (ndatabytes >= TFTP_DATASIZE); - - result = 0; - -errout_with_sd: xclose(sd); - free(packet); - return result; -} - -// Sends file to server. -int file_put(void) -{ - struct sockaddr_storage server; - uint8_t *packet; - off_t offset = 0; - uint16_t blockno = 1, rblockno, port = 0; - int packetlen, sd, fd, retry = 0, ret, result = -1; - - sd = init_tftp(&server); - packet = (uint8_t*)xzalloc(TFTP_IOBUFSIZE); - fd = xopen(TT.local_file, O_RDONLY); - - for (;;) { //first loop for request send and confirmation from server. - packetlen = mkpkt_request(packet, TFTP_OP_WRQ, TT.remote_file, 1); - ret = write_server(sd, packet, packetlen, &server); - if (ret != packetlen) goto errout_with_sd; - if (read_ack(sd, packet, &server, &port, NULL) == 0) break; - if (++retry > TFTP_RETRIES) { - error_msg("Retry count exceeded."); - goto errout_with_sd; - } - } - for (;;) { // loop for data sending and receving ack from server. - packetlen = mkpkt_data(fd, offset, packet, blockno); - if (packetlen < 0) goto errout_with_sd; - - ret = write_server(sd, packet, packetlen, &server); - if (ret != packetlen) goto errout_with_sd; - - if (read_ack(sd, packet, &server, &port, &rblockno) == 0) { - if (rblockno == blockno) { - if (packetlen < TFTP_PACKETSIZE) break; - blockno++; - offset += TFTP_DATASIZE; - retry = 0; - continue; - } - } - if (++retry > TFTP_RETRIES) { - error_msg("Retry count exceeded."); - goto errout_with_sd; - } - } - result = 0; - -errout_with_sd: close(sd); - free(packet); - return result; -} - -void tftp_main(void) -{ - struct addrinfo *info, rp, *res=0; - int ret; - - if (toys.optflags & FLAG_r) { - if (!(toys.optflags & FLAG_l)) { - char *slash = strrchr(TT.remote_file, '/'); - TT.local_file = (slash) ? slash + 1 : TT.remote_file; - } - } else if (toys.optflags & FLAG_l) TT.remote_file = TT.local_file; - else error_exit("Please provide some files."); - - memset(&rp, 0, sizeof(rp)); - rp.ai_family = AF_UNSPEC; - rp.ai_socktype = SOCK_STREAM; - ret = getaddrinfo(toys.optargs[0], toys.optargs[1], &rp, &info); - if (!ret) { - for (res = info; res; res = res->ai_next) - if ( (res->ai_family == AF_INET) || (res->ai_family == AF_INET6)) break; - } - if (!res) - error_exit("bad address '%s' : %s", toys.optargs[0], gai_strerror(ret)); - TT.af = info->ai_family; - - memcpy((void *)&TT.inaddr, info->ai_addr, info->ai_addrlen); - freeaddrinfo(info); - - if (toys.optflags & FLAG_g) file_get(); - if (toys.optflags & FLAG_p) file_put(); -} diff --git a/toys/posix/cal.c b/toys/posix/cal.c index bd3afad..bb476df 100644..100755 --- a/toys/posix/cal.c +++ b/toys/posix/cal.c @@ -64,6 +64,14 @@ static char *calstrings(char *buf, struct tm *tm) return buf; } +void xcheckrange(long val, long low, long high) +{ + char *err = "%ld %s than %ld"; + + if (val < low) error_exit(err, val, "less", low); + if (val > high) error_exit(err, val, "greater", high); +} + // Worst case scenario toybuf usage: sizeof(struct tm) plus 21 bytes/line // plus 8 lines/month plus 12 months, comes to a bit over 2k of our 4k buffer. @@ -78,12 +86,12 @@ void cal_main(void) buf += sizeof(struct tm); // Last argument is year, one before that (if any) is month. - tm->tm_year = atolx_range(toys.optargs[--toys.optc], 1, 9999); + xcheckrange(tm->tm_year = atol(toys.optargs[--toys.optc]),1,9999); tm->tm_year -= 1900; tm->tm_mday = 1; tm->tm_hour = 12; // noon to avoid timezone weirdness if (toys.optc) { - tm->tm_mon = atolx_range(toys.optargs[--toys.optc], 1, 12); + xcheckrange(tm->tm_mon = atol(toys.optargs[--toys.optc]),1,12); tm->tm_mon--; // Print 12 months of the year diff --git a/toys/posix/chmod.c b/toys/posix/chmod.c index 4292439..64369b6 100644..100755 --- a/toys/posix/chmod.c +++ b/toys/posix/chmod.c @@ -39,7 +39,7 @@ GLOBALS( char *mode; ) -static int do_chmod(struct dirtree *try) +int do_chmod(struct dirtree *try) { mode_t mode; diff --git a/toys/posix/cmp.c b/toys/posix/cmp.c index 829da75..2dae113 100644..100755 --- a/toys/posix/cmp.c +++ b/toys/posix/cmp.c @@ -28,7 +28,7 @@ GLOBALS( // This handles opening the file and -static void do_cmp(int fd, char *name) +void do_cmp(int fd, char *name) { int i, len1, len2, min_len, size = sizeof(toybuf)/2; long byte_no = 1, line_no = 1; diff --git a/toys/posix/cp.c b/toys/posix/cp.c index 6a395a4..d5e92f2 100644 --- a/toys/posix/cp.c +++ b/toys/posix/cp.c @@ -7,9 +7,9 @@ // options shared between mv/cp must be in same order (right to left) // for FLAG macros to work out right in shared infrastructure. -USE_CP(NEWTOY(cp, "<2"USE_CP_PRESERVE("(preserve):;")"RHLPp"USE_CP_MORE("rdasl"USE_CP_Z("Z")"vnF(remove-destination)")"fi[-HLP"USE_CP_MORE("d")"]"USE_CP_MORE("[-ni]"), TOYFLAG_BIN)) -USE_MV(NEWTOY(mv, "<2"USE_CP_Z("Z")""USE_CP_MORE("vnF")"fi"USE_CP_MORE("[-ni]"), TOYFLAG_BIN)) -USE_INSTALL(NEWTOY(install, "<1"USE_INSTALL_Z("Z:")"cdDpsvm:o:g:", TOYFLAG_USR|TOYFLAG_BIN)) +USE_CP(NEWTOY(cp, "<2"USE_CP_PRESERVE("(preserve):;")"RHLPp"USE_CP_MORE("rdaslvnF(remove-destination)")"fi[-HLP"USE_CP_MORE("d")"]"USE_CP_MORE("[-ni]"), TOYFLAG_BIN)) +USE_MV(NEWTOY(mv, "<2"USE_CP_MORE("vnF")"fi"USE_CP_MORE("[-ni]"), TOYFLAG_BIN)) +USE_INSTALL(NEWTOY(install, "<1cdDpsvm:o:g:", TOYFLAG_USR|TOYFLAG_BIN)) config CP bool "cp" @@ -49,7 +49,7 @@ config CP_PRESERVE default y depends on CP_MORE help - usage: cp [--preserve=motca] + usage: cp [--preserve=mota] --preserve takes either a comma separated list of attributes, or the first letter(s) of: @@ -57,18 +57,8 @@ config CP_PRESERVE mode - permissions (ignore umask for rwx, copy suid and sticky bit) ownership - user and group timestamps - file creation, modification, and access times. - context - preserve src's context. all - all of the above -config CP_Z - bool - default y - depends on CP_MORE && !TOYBOX_LSM_NONE - help - usage: cp [-Z] - - set security context of destination file to default type - config MV bool "mv" default y @@ -106,15 +96,6 @@ config INSTALL -p Preserve timestamps -s Call "strip -p" -v Verbose - -config INSTALL_Z - bool - default y - depends on INSTALL && !TOYBOX_LSM_NONE - help - usage: [-Z context] - - -Z set security context */ #define FOR_cp @@ -127,11 +108,9 @@ GLOBALS( char *group; char *user; char *mode; - char *context; } i; struct { char *preserve; - char *context; } c; }; @@ -337,14 +316,9 @@ int cp_node(struct dirtree *try) xclose(fdout); } - if (CFG_MV && toys.which->name[0] == 'm') { + if (CFG_MV && toys.which->name[0] == 'm') if (unlinkat(tfd, try->name, S_ISDIR(try->st.st_mode) ? AT_REMOVEDIR :0)) err = "%s"; - if (CFG_CP_Z) { - if (0>lsm_lset_context(catch, TT.c.context)) - perror_exit("-Z '%s' failed", TT.c.context); - } - } } if (err) perror_msg(err, catch); @@ -354,7 +328,7 @@ int cp_node(struct dirtree *try) void cp_main(void) { char *destname = toys.optargs[--toys.optc], - *preserve[] = {"mode", "ownership", "timestamps", "context"}; + *preserve[] = {"mode", "ownership", "timestamps"}; int i, destdir = !stat(destname, &TT.top) && S_ISDIR(TT.top.st_mode); if (toys.optc>1 && !destdir) error_exit("'%s' not directory", destname); @@ -396,30 +370,8 @@ void cp_main(void) if (destdir) TT.destname = xmprintf("%s/%s", destname, basename(src)); else TT.destname = destname; - // Preserve Context - if (TT.pflags & 8) { - TT.c.context = NULL; - if (!CFG_TOYBOX_LSM_NONE && lsm_enabled()) { - if (0>lsm_lget_context(src, &TT.c.context)) - perror_exit("unknown security context for '%s'", src); - if (0>lsm_set_create(TT.c.context)) - perror_exit("preserve context '%s' failed", TT.c.context); - free(TT.c.context); - } else error_exit("%s disabled", lsm_name()); - } - errno = EXDEV; if (CFG_MV && toys.which->name[0] == 'm') { - if (CFG_CP_Z) { - if (lsm_enabled()) { - TT.c.context = NULL; - if (toys.optflags & FLAG_Z) TT.c.context = lsm_context(); - else { - if (0>lsm_lget_context(src, &TT.c.context)) - perror_exit("unknown security context for '%s'", src); - } - } else error_exit("%s disabled", lsm_name()); - } if (!(toys.optflags & FLAG_f)) { struct stat st; @@ -434,14 +386,7 @@ void cp_main(void) } } - if (rc) { - rc = rename(src, TT.destname); - if (CFG_CP_Z) { - if (!rc && (toys.optflags&FLAG_Z) - && (0>lsm_lset_context(TT.destname, TT.c.context))) - perror_exit("-Z '%s' failed", TT.c.context); - } - } + if (rc) rc = rename(src, TT.destname); } // Skip nonexistent sources @@ -452,9 +397,6 @@ void cp_main(void) else dirtree_handle_callback(new, TT.callback); } if (destdir) free(TT.destname); - if (CFG_CP_Z && CFG_MV && toys.which->name[0] == 'm' - && (toys.optflags & FLAG_Z)) - free(TT.c.context); } } @@ -490,13 +432,6 @@ void install_main(void) char **ss; int flags = toys.optflags; - if (CFG_INSTALL_Z && (toys.optflags&FLAG_Z)) { - if (lsm_enabled()) { - if (0>lsm_set_create(TT.i.context)) - perror_exit("bad -Z '%s'", TT.i.context); - } else error_msg("%s disabled", lsm_name()); - } - if (flags & FLAG_d) { for (ss = toys.optargs; *ss; ss++) { if (mkpathat(AT_FDCWD, *ss, 0777, 3)) perror_msg("%s", *ss); diff --git a/toys/posix/date.c b/toys/posix/date.c index a42de50..d4c4524 100644..100755 --- a/toys/posix/date.c +++ b/toys/posix/date.c @@ -7,23 +7,22 @@ * Note: setting a 2 year date is 50 years back/forward from today, * not posix's hardwired magic dates. -USE_DATE(NEWTOY(date, "d:D:r:u[!dr]", TOYFLAG_BIN)) +USE_DATE(NEWTOY(date, "d:s:r:u[!dr]", TOYFLAG_BIN)) config DATE bool "date" default y help - usage: date [-u] [-r FILE] [-d DATE] [+DISPLAY_FORMAT] [-D SET_FORMAT] [SET] + usage: date [-u] [-r FILE] [-d DATE] [+DISPLAY_FORMAT] [-s SET_FORMAT] [SET] Set/get the current date/time. With no SET shows the current date. Default SET format is "MMDDhhmm[[CC]YY][.ss]", that's (2 digits each) month, day, hour (0-23), and minute. Optionally century, year, and second. - Also accepts "@UNIXTIME[.FRACTION]" as seconds since midnight Jan 1 1970. -d Show DATE instead of current time (convert date format) - -D +FORMAT for SET or -d (instead of MMDDhhmm[[CC]YY][.ss]) -r Use modification time of FILE instead of current date + -s +FORMAT for SET or -d (instead of MMDDhhmm[[CC]YY][.ss]) -u Use UTC instead of current timezone +FORMAT specifies display format string using these escapes: @@ -50,79 +49,15 @@ GLOBALS( char *file; char *setfmt; char *showdate; - - char *tz; - unsigned nano; ) -// mktime(3) normalizes the struct tm fields, but date(1) shouldn't. -static time_t chkmktime(struct tm *tm, const char *str, const char* fmt) -{ - struct tm tm0 = *tm; - struct tm tm1; - time_t t = mktime(tm); - - if (t == -1 || !localtime_r(&t, &tm1) || - tm0.tm_sec != tm1.tm_sec || tm0.tm_min != tm1.tm_min || - tm0.tm_hour != tm1.tm_hour || tm0.tm_mday != tm1.tm_mday || - tm0.tm_mon != tm1.tm_mon) { - int len; - - strftime(toybuf, sizeof(toybuf), fmt, &tm0); - len = strlen(toybuf) + 1; - strftime(toybuf + len, sizeof(toybuf) - len, fmt, &tm1); - error_exit("bad date '%s'; %s != %s", str, toybuf, toybuf + len); - } - return t; -} - -static void utzset(void) -{ - if (!(TT.tz = getenv("TZ"))) TT.tz = (char *)1; - setenv("TZ", "UTC", 1); - tzset(); -} - -static void utzreset(void) -{ - if (TT.tz) { - if (TT.tz != (char *)1) setenv("TZ", TT.tz, 1); - else unsetenv("TZ"); - tzset(); - } -} - -// Handle default posix date format (mmddhhmm[[cc]yy]) or @UNIX[.FRAC] +// Handle default posix date format: mmddhhmm[[cc]yy] // returns 0 success, nonzero for error -static int parse_default(char *str, struct tm *tm) +int parse_posixdate(char *str, struct tm *tm) { - int len = 0; - - // Parse @UNIXTIME[.FRACTION] - if (*str == '@') { - long long ll; - time_t tt; - - // Collect seconds and nanoseconds - // Note: struct tm hasn't got a fractional seconds field, thus strptime() - // doesn't support it, so store nanoseconds out of band (in globals). - // tt and ll are separate because we can't guarantee time_t is 64 bit (yet). - sscanf(str, "@%lld%n", &ll, &len); - if (str[len]=='.') { - str += len+1; - for (len = 0; len<9; len++) { - TT.nano *= 10; - if (isdigit(str[len])) TT.nano += str[len]-'0'; - } - } - if (str[len]) return 1; - tt = ll; - gmtime_r(&tt, tm); - - return 0; - } + int len; - // Posix format + len = 0; sscanf(str, "%2u%2u%2u%2u%n", &tm->tm_mon, &tm->tm_mday, &tm->tm_hour, &tm->tm_min, &len); if (len != 8) return 1; @@ -143,38 +78,40 @@ static int parse_default(char *str, struct tm *tm) // 2 digit years, next 50 years are "future", last 50 years are "past". // A "future" date in past is a century ahead. // A non-future date in the future is a century behind. - if (len == 2) { - if ((r1 < r2) ? (r1 < year && year < r2) : (year < r1 || year > r2)) { - if (year < r1) year += 100; - } else if (year > r1) year -= 100; - } + if ((r1 < r2) ? (r1 < year && year < r2) : (year < r1 || year > r2)) { + if (year < r1) year += 100; + } else if (year > r1) year -= 100; tm->tm_year = year + century; } if (*str == '.') { len = 0; sscanf(str, ".%u%n", &tm->tm_sec, &len); str += len; - } else tm->tm_sec = 0; + } return *str; } void date_main(void) { - char *setdate = *toys.optargs, *format_string = "%a %b %e %H:%M:%S %Z %Y"; + char *setdate = *toys.optargs, *format_string = "%a %b %e %H:%M:%S %Z %Y", + *tz = 0; struct tm tm; - memset(&tm, 0, sizeof(struct tm)); - // We can't just pass a timezone to mktime because posix. - if (toys.optflags & FLAG_u) utzset(); + if (toys.optflags & FLAG_u) { + if (CFG_TOYBOX_FREE) tz = getenv("TZ"); + setenv("TZ", "UTC", 1); + tzset(); + } if (TT.showdate) { + setdate = TT.showdate; if (TT.setfmt) { char *s = strptime(TT.showdate, TT.setfmt+(*TT.setfmt=='+'), &tm); - if (!s || *s) goto bad_showdate; - } else if (parse_default(TT.showdate, &tm)) goto bad_showdate; + if (!s || *s) goto bad_date; + } else if (parse_posixdate(TT.showdate, &tm)) goto bad_date; } else { time_t now; @@ -188,6 +125,7 @@ void date_main(void) ((toys.optflags & FLAG_u) ? gmtime_r : localtime_r)(&now, &tm); } + setdate = *toys.optargs; // Fall through if no arguments if (!setdate); // Display the date? @@ -199,26 +137,39 @@ void date_main(void) } else if (setdate) { struct timeval tv; - if (parse_default(setdate, &tm)) error_exit("bad date '%s'", setdate); + if (parse_posixdate(setdate, &tm)) goto bad_date; if (toys.optflags & FLAG_u) { + char *tz = CFG_TOYBOX_FREE ? getenv("TZ") : 0; + // We can't just pass a timezone to mktime because posix. - utzset(); - tv.tv_sec = chkmktime(&tm, setdate, format_string); - utzreset(); - } else tv.tv_sec = chkmktime(&tm, setdate, format_string); + setenv("TZ", "UTC", 1); + tzset(); + tv.tv_sec = mktime(&tm); + if (CFG_TOYBOX_FREE) { + if (tz) setenv("TZ", tz, 1); + else unsetenv("TZ"); + tzset(); + } + } else tv.tv_sec = mktime(&tm); + if (tv.tv_sec == (time_t)-1) goto bad_date; - tv.tv_usec = TT.nano/1000; + tv.tv_usec = 0; if (settimeofday(&tv, NULL) < 0) perror_msg("cannot set date"); } - utzreset(); + if (toys.optflags & FLAG_u) { + if (tz) setenv("TZ", tz, 1); + else unsetenv("TZ"); + tzset(); + } + if (!strftime(toybuf, sizeof(toybuf), format_string, &tm)) perror_exit("bad format '%s'", format_string); puts(toybuf); return; -bad_showdate: - error_exit("bad date '%s'", TT.showdate); +bad_date: + error_exit("bad date '%s'", setdate); } diff --git a/toys/posix/du.c b/toys/posix/du.c index 77c7b6e..4302997 100644..100755 --- a/toys/posix/du.c +++ b/toys/posix/du.c @@ -57,7 +57,7 @@ static void print(long long size, struct dirtree *node) if (TT.maxdepth && TT.depth > TT.maxdepth) return; if (toys.optflags & FLAG_h) { - human_readable(toybuf, size, 0); + human_readable(toybuf, size); printf("%s", toybuf); } else { int bits = 10; diff --git a/toys/posix/find.c b/toys/posix/find.c index 99cf5e2..a11a910 100644..100755 --- a/toys/posix/find.c +++ b/toys/posix/find.c @@ -141,6 +141,41 @@ static void do_print(struct dirtree *new, char c) free(s); } +char *strlower(char *s) +{ + char *try, *new; + + if (!CFG_TOYBOX_I18N) { + try = new = xstrdup(s); + for (; *s; s++) *(new++) = tolower(*s); + } else { + // I can't guarantee the string _won't_ expand during reencoding, so...? + try = new = xmalloc(strlen(s)*2+1); + + while (*s) { + wchar_t c; + int len = mbrtowc(&c, s, MB_CUR_MAX, 0); + + if (len < 1) *(new++) = *(s++); + else { + s += len; + // squash title case too + c = towlower(c); + + // if we had a valid utf8 sequence, convert it to lower case, and can't + // encode back to utf8, something is wrong with your libc. But just + // in case somebody finds an exploit... + len = wcrtomb(new, c, 0); + if (len < 1) error_exit("bad utf8 %x", (int)c); + new += len; + } + } + *new = 0; + } + + return try; +} + // Call this with 0 for first pass argument parsing and syntax checking (which // populates argdata). Later commands traverse argdata (in order) when they // need "do once" results. diff --git a/toys/posix/id.c b/toys/posix/id.c index 01610bc..aa43072 100644..100755 --- a/toys/posix/id.c +++ b/toys/posix/id.c @@ -82,7 +82,7 @@ static void showid(char *header, unsigned u, char *s) printf("%s%u(%s)", header, u, s); } -static void do_id(char *username) +void do_id(char *username) { int flags, i, ngroups; struct passwd *pw; diff --git a/toys/posix/ls.c b/toys/posix/ls.c index f951198..44915fa 100644..100755 --- a/toys/posix/ls.c +++ b/toys/posix/ls.c @@ -422,13 +422,6 @@ static void listfiles(int dirfd, struct dirtree *indir) mode_to_string(mode, perm); printf("%s% *ld", perm, totals[2]+1, (long)st->st_nlink); - // print user - if (!(flags&FLAG_g)) { - if (flags&FLAG_n) sprintf(ss = thyme, "%u", (unsigned)st->st_uid); - else strwidth(ss = getusername(st->st_uid)); - printf(" %*s", (int)totals[3], ss); - } - // print group if (!(flags&FLAG_o)) { if (flags&FLAG_n) sprintf(ss = thyme, "%u", (unsigned)st->st_gid); @@ -436,6 +429,12 @@ static void listfiles(int dirfd, struct dirtree *indir) printf(" %*s", (int)totals[4], ss); } + if (!(flags&FLAG_g)) { + if (flags&FLAG_n) sprintf(ss = thyme, "%u", (unsigned)st->st_uid); + else strwidth(ss = getusername(st->st_uid)); + printf(" %*s", (int)totals[3], ss); + } + if (flags & FLAG_Z) printf(" %*s", -(int)totals[7], (char *)sort[next]->extra); diff --git a/toys/posix/nl.c b/toys/posix/nl.c index 60c0a52..c7e7b92 100644..100755 --- a/toys/posix/nl.c +++ b/toys/posix/nl.c @@ -40,7 +40,7 @@ GLOBALS( long lcount; ) -static void do_nl(int fd, char *name) +void do_nl(int fd, char *name) { FILE *f = xfdopen(fd, "r"); int w = TT.w, slen = strlen(TT.s); diff --git a/toys/posix/split.c b/toys/posix/split.c index 075a414..aabf931 100644..100755 --- a/toys/posix/split.c +++ b/toys/posix/split.c @@ -35,7 +35,7 @@ GLOBALS( char *outfile; ) -static void do_split(int infd, char *in) +void do_split(int infd, char *in) { unsigned long bytesleft, linesleft, filenum, len, pos; int outfd = -1; diff --git a/toys/posix/strings.c b/toys/posix/strings.c index e87ccde..a872cf6 100644..100755 --- a/toys/posix/strings.c +++ b/toys/posix/strings.c @@ -29,7 +29,7 @@ GLOBALS( long num; ) -static void do_strings(int fd, char *filename) +void do_strings(int fd, char *filename) { int nread, i, wlen = TT.num, count = 0; off_t offset = 0; diff --git a/toys/samsung/README b/toys/samsung/README deleted file mode 100644 index fa82bef..0000000 --- a/toys/samsung/README +++ /dev/null @@ -1,3 +0,0 @@ -Samsung developed commands - -These are commands developed at Samsung Electrnocis Co. Ltd. diff --git a/toys/samsung/nslookup.c b/toys/samsung/nslookup.c deleted file mode 100644 index ac8f8ec..0000000 --- a/toys/samsung/nslookup.c +++ /dev/null @@ -1,181 +0,0 @@ -/* nslookup.c - query Internet name servers - * - * Copyright 2013 Ashwini Kumar <ak.ashwini@gmail.com> - * Copyright 2015 Rajni Kant <rajnikant12345@gmail.com> - * - -USE_NSLOOKUP(NEWTOY(nslookup, "<1?", TOYFLAG_USR|TOYFLAG_BIN)) - -config NSLOOKUP - bool "nslookup" - default y - help - usage: nslookup [HOST] [SERVER] - - Query the nameserver for the IP address of the given HOST - optionally using a specified DNS server. - - Note:- Only non-interactive mode is supported. -*/ - -#define FOR_nslookup -#include "toys.h" -#include <resolv.h> - -static char *address_to_name(struct sockaddr *sock) -{ - //man page of getnameinfo. - char hbuf[NI_MAXHOST] = {0,}, sbuf[NI_MAXSERV] = {0,}; - int status = 0; - if (sock->sa_family == AF_INET) { - socklen_t len = sizeof(struct sockaddr_in); - if ((status = getnameinfo(sock, len, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), - NI_NUMERICHOST | NI_NUMERICSERV)) == 0) - return xmprintf("%s:%s", hbuf, sbuf); - else { - fprintf(stderr, "getnameinfo: %s\n", gai_strerror(status)); - return NULL; - } - } - else if (sock->sa_family == AF_INET6) { - socklen_t len = sizeof(struct sockaddr_in6); - if ((status = getnameinfo(sock, len, hbuf, sizeof(hbuf), sbuf, - sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV)) == 0) { - //verification for resolved hostname. - if (strchr(hbuf, ':')) return xmprintf("[%s]:%s", hbuf, sbuf); - else return xmprintf("%s:%s", hbuf, sbuf); - } - else { - fprintf(stderr, "getnameinfo: %s\n", gai_strerror(status)); - return NULL; - } - } - else if (sock->sa_family == AF_UNIX) { - struct sockaddr_un *sockun = (void*)sock; - return xmprintf("local:%.*s", (int) sizeof(sockun->sun_path), sockun->sun_path); - } - return NULL; -} - -static void print_addrs(char *hostname, char *msg) -{ - struct addrinfo hints, *res = NULL, *cur = NULL; - int ret_ga; - char *n = xstrdup(hostname), *p, *tmp; - tmp = n; - if ((*n == '[') && (p = strrchr(n, ']')) != NULL ) { - n++; - *p = '\0'; - } - - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_socktype = SOCK_STREAM; - - ret_ga = getaddrinfo(n, NULL, &hints, &res); - if (ret_ga) perror_exit("Hostname %s", gai_strerror(ret_ga)); - - cur = res; - while(cur) { - char *colon = NULL; - char *name = address_to_name(cur->ai_addr); - if (name) { - colon = strrchr(name, ':'); - if (colon) *colon = '\0'; - xprintf("%-8s %s\n",msg, hostname); - xprintf("Address: %s\n", name); - free(name); - } - cur = cur->ai_next; - } - if (!res->ai_addr) error_exit("getaddrinfo failed"); - - freeaddrinfo(res); - free(tmp); -} - -static void resolve_addr(char *host, void *addr, char* port) -{ - struct addrinfo *info, hint; - int ret = atolx(port); - - if(ret <0 || ret > 65535 ) error_exit("bad port: %s", port); - if (strncmp(host, "local:", 6) == 0) { - struct sockaddr *sockun = (struct sockaddr *)addr; - sockun->sa_family = AF_UNIX; - strncpy(((struct sockaddr_un *)sockun)->sun_path, host + 6, - sizeof(((struct sockaddr_un *)sockun)->sun_path)); - return ; - } - memset(&hint, 0, sizeof(hint)); - - ret = getaddrinfo(host, port , &hint, &info); - - if (ret || !info) error_exit("bad address: %s", host); - - memcpy(addr, info->ai_addr, info->ai_addrlen); - freeaddrinfo(info); -} - -void nslookup_main(void) -{ - struct sockaddr* sock; - char *args[2] = {0,0}, *colon = NULL, *name = NULL; - - res_init(); //initialize the _res struct, for DNS name. - - for (;*toys.optargs; toys.optargs++) { - if (**toys.optargs == '-') { - if (!strncmp(&toys.optargs[0][1], "retry=", 6)) { - _res.retry = atolx(toys.optargs[0]+7); - } else if (!strncmp(&toys.optargs[0][1], "timeout=", 8)) { - _res.retrans = atolx(toys.optargs[0]+9); - } else error_msg("invalid option '%s'", *toys.optargs); - } else if (!args[0]) args[0] = *toys.optargs; - else if (!args[1]) args[1] = *toys.optargs; - else error_exit("bad arg '%s'",*toys.optargs); - } - - if ( !*args) { - toys.exithelp++; - error_exit("Needs 1 args minimum"); - } - if (args[1]) { //set the default DNS - struct sockaddr_storage addr; - char* port = NULL ; - - if (args[1][0] == '[') { - int len = strchr(args[1],']') - &args[1][0]; - if (len > 45|| len <= 0 ) error_exit("bad address: %s", args[1]); - strncpy(toybuf,&args[1][1], len-1); - args[1] += len; - } - if ((port = strchr(args[1],':'))) { - *port = '\0'; - port++; - } - else port = "53"; - - resolve_addr((toybuf[0])?toybuf:args[1], &addr, port ); - - if (addr.ss_family == AF_INET) { - _res.nscount = 1; - _res.nsaddr_list[0] = *((struct sockaddr_in*)&addr); - } - else if (addr.ss_family == AF_INET6) { - _res._u._ext.nscount = 1; - _res._u._ext.nsaddrs[0] = ((struct sockaddr_in6*)&addr); - } - } - - sock = (struct sockaddr*)_res._u._ext.nsaddrs[0]; - if (!sock) sock = (struct sockaddr*)&_res.nsaddr_list[0]; - if ((name = address_to_name(sock))) { - colon = strrchr(name, ':'); - if (colon) *colon = '\0'; - print_addrs(name, "Server:"); - free(name); - } - puts(""); - - print_addrs(args[0], "Name:"); -} diff --git a/www/news.html b/www/news.html index 0c5da77..084d753 100755 --- a/www/news.html +++ b/www/news.html @@ -8,245 +8,7 @@ a development environment. See the links on the left for details.</p> <h2>News</h2> -<a name="23-07-2015" /><a href="#23-07-2015"><hr><h2><b>July 23, 2015</b></h2></a> -<p>I recreated the <a href=downloads/toybox-0.6.0.tar.gz>0.6.0 source tarball</a> -(new sha1sum 08fb1c23f520c25a15f262a8a95ea5b676a98d54) -because I forgot to add --prefix to the git archive command when I updated -my release script from mercurial, so the files weren't in an enclosing -directory. (Ooops.)</p> - -<a name="19-07-2015" /><a href="#19-07-2015"><hr><h2><b>July 19, 2015</b></h2></a> -<blockquote><p> -The reason why it was published in the form of a micro sub meson electronic -component is that if it were printed in normal book form, an interstellar -hitchhiker would require several inconveniently large buildings to carry it -around in." - The Hitchhiker's Guide to the Galaxy </p></blockquote> - -<p><a href=downloads/toybox-0.6.0.tar.gz>Toybox 0.6.0</a> -(<a href=https://github.com/landley/toybox/releases/tag/0.6.0>git commit</a>) -is out. (Yes, git. See the <a href=#05-04-2015>previous news entry</a>.)</p> - -<p>Sorry for the unusually long gap between releases. Since last release Ye -Olde Project Maintainer traveled to japan twice and had two more "once -a century" floods at home. (Probably a coincidence.) Still catching up.</p> - -<h3><b>CELF/ELC talk and Wikipedia[citation needed] article</b></h3> - -<p>I gave another State Of The Toybox talk -(<a href=https://www.youtube.com/watch?v=04XwAbtPmAg>video</a> -<a href=http://landley.net/talks/celf-2015.txt>outline</a>), in which I -repeat my <a href=http://landley.net/notes-2013.html#07-11-2013>perennial</a> -<a href=https://twitter.com/landley/status/557309224535851009>complaint</a> -that Wikipedia[citation needed] -<a href=http://en.wikipedia.org/wiki/Toybox>still</a> -<a href=https://en.wikipedia.org/wiki/BusyBox#Controversy_over_Toybox>says</a> -toybox was relicensed before its hiatus, when relicensing was why -the hiatus ended.</p> - -<p>Since Wikipedia[citation needed] seems unable to do the -<a href=#15-11-2011>most</a> -<a href=http://landley.net/hg/toybox/log/tip/LICENSE>basic</a> -<a href=http://landley.net/notes-2011.html#13-11-2011>research</a> on -this point, and has stuck to an incorrect sequence of events for years, -I've been gradually escalating my attempts to correct them. Toybox -came out of mothballs in November 2011 <b>because</b> it could be -relicensed. That's what opened up a new niche busybox wasn't already -filling with a 10 year headstart.</p> - -<a name="asterisk_back" /> -<p>The article has plenty of smaller issues<a href=#asterisk>*</a>, but -given that I gave an entire talk at Ohio LinuxFest in 2013 -(<a href=http://landley.net/talks/ohio-2013.txt>outline</a>, -<a href=https://archive.org/download/OhioLinuxfest2013/24-Rob_Landley-The_Rise_and_Fall_of_Copyleft.mp3>audio</a>) on why I switched away from GPL for -my projects, that one bugs me.</p> - -<h3><b>New stuff this release</b></h3> - -<p>There's a new android menu in menuconfig, and rather a lot of Linux -Security Module support (Smack for Tizen from Xavier Roche and José Bollo, -and SELinux for Android from Elliott Hughes; see -the Security Blanket menu under global settings in menuconfig) has -trickled in, although there's still more to come.</p> - -<p><b>New commands:</b> Added reset, nproc, ionice, and iorenice. -Elliott Hughes contributed xxd, runcon, -restorecon, load_policy, getenforce, setenforce, getprop, and setprop. -Promoted shred, nsenter, and hwclock.</p> - -<p>You can once again build catv now the flag infrastructure's been updated to -let it coexist with cat -v. -And on a long plane flight I wrote -hexedit, an interactive hex editor that implements the start of -cursor control infrastructure (for eventual use by less and vi and shell -command history and so on).</p> - -<p><b>New options:</b> Added sed -E as a BSD-compatible synonym for -r. -Upgraded oneit with -r (restart), -3 (send exiting PID values to child), -and signal handling. Added -v option to timeout, -m to mknod, -u to shred, --t to dmesg, and -123 to head and tail. Added implicit "." to grep -r without -any files to work on. Hyejin Kim requested prefix support for truncate -s. -Greg Hackman added -inum to find. -Jan Cybulski added the smack side of ls -Z support. Various patches also -added -Z to mkdir, mknod, and mkfifo. -Basic cp --preserve support went in, but not yet the xattr/LSM parts.</p> - -<p>The toybox command now has a --version option, -which uses "git describe" if available.</p> - -<p><b>Build infrastructure:</b> -The "make change" target now saves the output of each failed standalone -command build in a .bad file, and "make defconfig" is quieter now.</p> - -<p>Paul Barker submitted a large patch changing command install paths so -"toybox can be installed alongside busybox without confusing -update-alternatives". (There's some argument over -what the right paths should be, and I'm waiting for -people to tell me what else needs fixing because I have no idea. I've -been symlinking /bin to /usr/bin since 2002 -<a href=http://landley.net/writing/hackermonthly-issue022-pg33.pdf>for -historical reasons</a>.)</p> - -<p><b>Docs:</b> The repository link now goes to github, with another link -to the commit rss feed.</p> - -<p>Elliott Hughes updated the Android section of the roadmap -(and he would know). Redid bits of scripts/mkstatus.py to make updating -status.html easier, and the README is larger.</p> - -<p>More description of option parsing in code.html, which now describes the -FLAG_x macros, switching flag macro sets with FOR_newcommand, how -configuration zeroes flag macros and using FORCE_FLAGS to suppress the -zeroing of options shared between commands. Also added description of ";" -to make --longopts take an optional =value part, and more about TOYBOX_DEBUG -to check NEWTOY() option strings (otherwise a bad option string makes -lib/args.c obviously segfault, but doesn't explain why).</p> - -<p>Added a "Why 0BSD?" section to license.html when submitting zero clause bsd -to SPDX (according to the pending license spreadsheet, it's been approved for -SPDX 2.2).</p> - -<p>The old list of commands needing cleanup but not in pending was -removed from toys/pending/README and instead the issues were added -as TODO comments in the individual commands.</p> - -<p><b>Bugfixes:</b> -Fixed mount -a segfaulting without -O (reported by Janus Troelsen), -and made it try a "become rw" ioctl() on the block device before falling -back to mounting read only (because Android expects that). -Fixed printf -- and printf ---. Lots of tweaks to ls -l spacing with -different options. Make touch -d and -t actually set time when you don't -specify nanoseconds. -Fixed a subtle bug where recursive calls (toybox commands that run other -toybox commands) weren't resetting all their state. (This manifested as -a "no }" error from "find | xargs sed", but could cause other problems.) -And David Halls reported another sed bug trying to compile libiconv (which -left extra \ at the start of lines in a generated shell script, breaking -the build). Output an error message for "cat /mnt".</p> - -<p>Kylie McClain reported that mktemp broke when $TMPDIR was set to an empty -string (which is not the same as unset), that install/find didn't support -numeric uid/gids, and that sort -z affects both input and output. -Isabella Parakiss fixed a printf.c bug. -David Halls fixed bugs in install -D and find -exec. Samuel Holland -fixed unshare -r. Hyejin Kim fixed makedevs with a count of 1, fold -w -range checking, an error path in scripts/mkflags.c, added -i to dhcpd, -and stopped su from prompting the root user for the new user's password. -Jan Cybulski spotted wrong indentation when combining ls -s and -i with -C and --x. José Bollo fixed stat %G. Sameer Pradhan fixed a bug in mkfifo -Z.</p> - -<p>Elliott Hughes asked for a default SIGPIPE handler to disable -the signal handler bionic's dynamic loader installs (yes really). Still not -100% sure what the correct behavior is there. (Posix is -(<a href=http://permalink.gmane.org/gmane.comp.standards.posix.austin.general/10915>actively unhelpful</a>, but at least they're taking -<a href=http://austingroupbugs.net/view.php?id=789#c1976>years to -make up their mind</a>. Elliott also sent patches to fix a typo in -useradd.test, add missing arguments to error_exit() calls and clean up -printf() format strings, fix an off by one error in human_readable(), -fix dmesg -c error reporting, fix a segfault in comma_scan where the option -was the last item in optlist (triggered by mount -o ro,remount), fix -hwclock -w, made ifconfig print lowercase MAC addresses (it was bothering -him), and make terminal_size() read the right environment variable -(LINES, not ROWS). And he suggested the test suite notice high command exit -values (corresponding to segfault or other signals).</p> - -<p>People are apparently using toys/pending commands, despite the police tape -and flashing lights, so added louder warnings to toys/pending/README. -Elliott Hughes fixed various problems with tar, dd, more, and top. -Hyejin Kim cleaned up syslogd and dumpleases. Isaac Dunham added hotplug -support to mdev. Yeongdeok Suh added RFC-3315 ipv6 support to dhcpd.</p> - -<p>I rewrote ps.c from scratch (in pending), but it's not ready for real use -yet.</p> - -<p><b>Portability:</b> -On the portability front Bernhard Rosenkranzer fixed a problem where the -menuconfig code wouldn't compile in C99 mode. (This led to me documenting -the craptacular nature of kconfig in a README, and the plan to replace it -sometime before 1.0.) Some extra flags to shut up overzealous llvm warnings -were added (and have to be probed for because gcc complains about -arguments it doesn't recognize even when they switch stuff _off_ using -a standard syntax). Don't depend on malloc(0) to return non-null in ls. -David Halls fixed some mac/ios portability issues, -implying somebody's built at least part of toybox on a mac.</p> - -<p>Added basename_r() to lib/lib.c because the posix semantics for basename() -are stupid but what the gnu guys did to it was appalling. -Turns out bionic already had a basename_r(), but posix still doesn't. -Fixed it up in portability.h, but this -could break more stuff in future. (Correct fix is to lobby posix to add it, -which would probably take about 15 years...)</p> - -<p><b>Infrastructure:</b> -The build now checks $LDFLAGS for linker-only flags, and allows the strip -command to fail (binflt toolchains provide a strip that doesn't work). -Since time.c uses floating point, added TOYBOX_FLOAT dependency in config.</p> - -<p>There's a lib/lsm.h defining varous inline functions for linux -security modules stuff, if (lsm_enabled()) should turn into a compile-time -constant 0 and let code drop out when TOYBOX_LSM_NONE selected, but -testing against CFG_TOYBOX_LSM_NONE or derived symbols is still useful -becuase when it _is_ enabled the probe turns into a system call you -don't want to repeat too much.</p> - -<p>Switched a bunch of commands from signal() to xsignal(). Factored out -xgetgrnamid() and xgetpwnamid() into xwrap.c. Make time.c depend on -TOYBOX_FLOAT (since it always uses float so shouldn't be available on -build targets without even software float). Added readfileat() to lib/lib.c.</p> - -<p>The dirtree infrastructure now passes in full flags for the old symlink -field, and the new DIRTREE_SHUTUP flag disables warnings if a file vanishes -out from under you during traverse. New dirtree_start() wrapper to -create dirtree root with only two arguments.</p> - -<p>The not-curses infrastructure introduced by hexedit mostly moved to -lib/interestingtimes.c.</p> - -<a name="asterisk" /> -<a href="#asterisk_back" />Asterisk:</a> such when -Tim contacted me (my blog says a couple days before nov 13, 2011, I.E. -11/11/11 not some specific day 2 months later) to ask if I wanted to work -on a new project he was proposing called -<a href=http://www.elinux.org/Busybox_replacement_project>BentoBox</a> -(because I used to do busybox, he'd forgotten toybox existed -until I brought it up). And don't ask me what "focuses not on compatibility -with its GNU counterparts" means when CP_MORE adds 7 non-posix options -and toys/other has 84 commands in neither posix nor LSB. I think they're -struggling to explain the difference having dismissed "licensing" as being -the reason it started up again after a long hiatus? The reason I don't think -GNU is special is there are a half-dozen other independent -implementations of the same unix command tools out there (AT&T, -BSD, Coherent, Minix, plan 9, busybox, toybox, and several more analyzed in -the <a href=roadmap.html>roadmap</a>, and that's ignoring the implementations -written for DOS or in assembly over the years). But I do care what -Linux From Scratch expects, and if it's -<a href=http://archive.linuxfromscratch.org/lfs-museum/7.6/LFS-BOOK-7.6-NOCHUNKS.html#ch-tools-gcc-pass1>calling mv -v</a> -then I impelement mv -v -even if <a href=http://landley.net/toybox/roadmap.html>posix hasn't got -it</a>. And I don't know why "gnu counterparts" would describe this when -util-linux isn't a gnu package, nor are info-zip, e2fsprogs, kmod, less, -procps, shadow, sysklogd, vim, zlib, sudo, dhcpcd...</p> - -<a name="05-04-2015" /><a href="#05-04-2015"><hr><h2><b>April 5, 2015</b></h2></a> +<hr><b>April 5, 2015</b> <p>Since <a href=https://android.googlesource.com/platform/external/toybox/>android</a> and <a href=https://git.tizen.org/cgit/platform/upstream/toybox.git>tizen</a> and <a href=https://github.com/kraj/meta-musl/tree/master/recipes-core/toybox>openembedded</a> @@ -256,7 +18,7 @@ than the mercurial repository, I bit the bullet and switched the project's repo <a href=https://github.com/landley/toybox>to git</a>. Georgi's <a href=https://github.com/gfto/toybox>mirror</a> is now pulling from that.</p> -<a name="25-02-2015" /><a href="#25-02-2015"><hr><h2><b>February 25, 2015</b></h2></a> +<hr><b>February 25, 2015</b> <blockquote><p>"A common mistake that people make when trying to design something completely foolproof is to underestimate the ingenuity of complete fools."</p><p>- The Hitchhiker's Guide to the Galaxy.</p></blockquote> @@ -376,7 +138,7 @@ supported, so stop using it.</p> <p>Fixed toy_exec() to detect when argc is in optargs, so we don't need a separate xexec_optargs().</p> -<a name="18-02-2015" /><a href="#18-02-2015"><hr><h2><b>February 18, 2015</b></h2></a> +<hr><b>February 18, 2015</b> <p>Dreamhost continues to be unable to make mailing list archives work, so here's <a href=http://www.mail-archive.com/toybox@lists.landley.net/>another list archive</a> with a less awkward interface than gmane.</p> @@ -393,7 +155,7 @@ web archive, from Dec 15-Jan 3, and then another hole from Jan 16-Feb 18. The relevant messages are in both of the other archives. Here's hoping the chronic archive constipation problem won't happen a sixth time.</p> -<a name="30-12-2014" /><a href="#30-12-2014"><hr><h2><b>December 30, 2014</b></h2></a> +<hr><b>December 30, 2014</b> <p>Due to Dreamhost's <a href=http://landley.net/dreamhost.txt>ongoing</a> <a href=http://landley.net/dreamhost2.txt>inability</a> to make mailman work reliably, I've added a link to a backup web archive at @@ -405,7 +167,7 @@ on the left.</p> <p>Update (January 27, 2015): they're <a href=https://twitter.com/landley/status/558428839462703104>still working on it</a>.</p> -<a name="19-11-2014" /><a href="#19-11-2014"><hr><h2><b>November 19, 2014</b></h2></a> +<hr><b>November 19, 2014</b> <blockquote><p>"This time it was right, it would work, and no one would have to get nailed to anything." - The Hitchhiker's Guide to the Galaxy.</p></blockquote> @@ -484,7 +246,7 @@ close each supplied filehandle itself.)</p> <p>The printf-style escape parsing ("\n" and friends) got factored out into a new unescape() function.</p> -<a name="02-10-2014" /><a href="#02-10-2014"><hr><h2><b>October 2, 2014</b></h2></a> +<hr><b>October 2, 2014</b> <blockquote><p>"There is an art, it says, or rather, a knack to flying. The knack lies in learning how to throw yourself at the ground and miss... Clearly, it is this second part, the missing, which presents the @@ -635,7 +397,7 @@ sort on the host broke in non-C locales.</p> <p>Divya Kothari submitted tests for chmod, link, tar, bzcat, xzcat, zcat, and hostname. (And more, but that's all that's merged so far.)</p> -<a name="07-07-2014" /><a href="#07-07-2014"><hr><h2><b>July 7, 2014</b></h2></a> +<hr><b>July 7, 2014</b> <blockquote><p>"This planet has - or rather had - a problem, which was this: most of the people living on it were unhappy for pretty much of the time. Many solutions were suggested for this problem, but most of these were largely @@ -757,7 +519,7 @@ bytes). The build infrastructure now notices duplicate commands (so if you cp toys/pending/command.c toys/other/command.c and forget to delete the first one, the build break is now more informative).</p> -<a name="20-04-2014" /><a href="#20-04-2014"><hr><h2><b>April 20, 2014</b></h2></a> +<hr><b>April 20, 2014</b> <blockquote><p>And to this end they built themselves a stupendous supercomputer which was so amazingly intelligent that even before the data banks had been connected up it had started from "I think therefore I am" and got as @@ -843,7 +605,7 @@ of different kinds of simplicity, and why comments aren't a substitute for good code. The README no longer trails off into obvious unfinished confusion at the end. Each page on the website should now have its own title.</p> -<a name="18-11-2013" /><a href="#18-11-2013"><hr><h2><b>November 18, 2013</b></h2></a> +<hr><b>November 18, 2013</b> <blockquote><p>"Space," it says, "is big. Really big. You just won't believe how vastly, hugely, mindbogglingly big it is. I mean, you may think it's a long way down the street to the chemist's, but that's just peanuts to space." - The Hitchhiker's Guide to the Galaxy.</p></blockquote> @@ -880,7 +642,7 @@ The "toynet.h" file got folded into toys.h since musl supports it and micromanging uClibc options isn't very interesting anymore. The test suite now uses scripts/single.sh when testing a single command.</p> -<a name="17-09-2013" /><a href="#17-09-2013"><hr><h2><b>September 17, 2013</b></h2></a> +<hr><b>September 17, 2013</b> <blockquote><p>"Think of a number," said the computer, "any number." Arthur told the computer the telephone number of King's Cross railway station passenger inquiries, on the grounds that it must have some function, @@ -1009,13 +771,13 @@ delete sub and didn't exit with an error either. Neither was correct, rm should now be fixed.</p> <p> -<a name="26-07-2013" /><a href="#26-07-2013"><hr><h2><b>July 26, 2013</b></h2></a> +<hr><b>July 26, 2013</b> <p>Georgi Chorbadzhiyski maintains a <a href=https://github.com/gfto/toybox>git mirror</a> of the repository on github, automatically updated from the mercurial every 6 hours. The mirror is read only, but you can generate patches against it and post them to the list.</p> -<a name="02-07-2013" /><a href="#02-07-2013"><hr><h2><b>July 2, 2013</b></h2></a> +<hr><b>July 2, 2013</b> <blockquote><p>"Time is an illusion. Lunchtime doubly so." "Very deep. You should send that in to the Reader's Digest. They've got a page for people like you." - @@ -1094,7 +856,7 @@ the GPL but "all copies must include this magic text blob" somehow don't?</p> or less public domain with a liability disclaimer, but we're still calling it BSD (sometimes "0 clause BSD") to avoid explaining.</p> -<a name="21-03-2013" /><a href="#21-03-2013"><hr><h2><b>March 21, 2013</b></h2></a> +<hr><b>March 21, 2013</b> <p>Video of my ELC talk "<a href=http://youtu.be/SGmtP5Lg_t0>Why is Toybox?</a>" is up on youtube. Related materials include the @@ -1129,7 +891,7 @@ the ads, it's The Linux Foundation.)</p> </span> -<a name="14-03-2013" /><a href="#14-03-2013"><hr><h2><b>March 14, 2013</b></h2></a> +<hr><b>March 14, 2013</b> <blockquote><p>"Ford, you're turning into a penguin. Stop it." - The Hitchhiker's Guide to the Galaxy.</p></blockquote> @@ -1152,7 +914,7 @@ should at least compile (although defconfig is still what's useful).</p> <p>Significant roadmap updates, checking several other multicall binaries (klibc, sash, sbase, s6...) to see what commands they include.</p> -<a name="18-01-2013" /><a href="#18-01-2013"><hr><h2><b>January 18, 2013</b></h2></a> +<hr><b>January 18, 2013</b> <blockquote><p>This must be Thursday. I never could get the hang of Thursdays. - The Hitchhiker's Guide to the Galaxy.</p></blockquote> <p><a href=downloads/toybox-0.4.3.tar.bz2>Toybox 0.4.3</a> is based on @@ -1193,7 +955,7 @@ it now correctly detects "/trailing/slash/" which the previous code didn't.</p> disabled compiler optimization, so the binary size bloated a bit. It's back to -Os by default now.</p> -<a name="15-12-2012" /><a href="#15-12-2012"><hr><h2><b>December 15, 2012</b></h2></a> +<hr><b>December 15, 2012</b> <blockquote><p>"The major difference between a thing that might go wrong and a thing that cannot possibly go wrong is that when a thing that cannot possibly go wrong goes wrong it usually turns out to be impossible to get at or repair." @@ -1244,7 +1006,7 @@ to do it Posix's way, which is more brittle and needs extra security checks, but am waiting for somebody to complain first. The default "ulimit -n" is 1024 filehandles, so drilling down over 1000 nested subdirectories).</p> -<a name="13-11-2012" /><a href="#13-11-2012"><hr><h2><b>November 13, 2012</b></h2></a> +<hr><b>November 13, 2012</b> <blockquote><p>"Rule Six: The winning team shall be the first team that wins." - The Hitchhiker's Guide to the Galaxy.</p></blockquote> @@ -1308,7 +1070,7 @@ a separate <a href=oldnews.html>oldnews</a> page.</p> back now.</p> </span> -<a name="23-07-2012" /><a href="#23-07-2012"><hr><h2><b>July 23, 2012</b></h2></a> +<hr><b>July 23, 2012</b> <blockquote><p>"Ford", Arthur said. "There's an infinite number of monkeys out here who want to talk to us about this script for Hamlet they've worked out." - The Hitchhiker's Guide to the Galaxy.</p></blockquote> @@ -1333,7 +1095,7 @@ corresponding executable bit wasn't set, and worked around a longstanding glibc bug where static linking prevents stdout from automatically flushing pending output on exit.</p> -<a name="25-06-2012" /><a href="#25-06-2012"><hr><h2><b>June 25, 2012</b></h2></a> +<hr><b>June 25, 2012</b> <blockquote><p>"For a moment, nothing happened. Then, after a second or so, nothing continued to happen." - The Hitchhiker's Guide to the Galaxy.</p></blockquote> <p><a href=downloads/toybox-0.3.1.tar.bz2>Toybox 0.3.1</a> is based on commit @@ -1349,7 +1111,7 @@ it is. The roadmap and documentation are a bit behind, and I've got ~40 pending submissions to review. I need to catch up...</p> </span> -<a name="12-06-2012" /><a href="#12-06-2012"><hr><h2><b>June 12, 2012</b></h2></a> +<hr><b>June 12, 2012</b> <blockquote><p>"For instance, on the planet Earth, man had always assumed that he was more intelligent than dolphins because he had achieved so much - the wheel, New York, wars and so on - whilst all the dolphins had ever done was @@ -1414,7 +1176,7 @@ yet, but if I wait until everything works we won't have a release before 1.0, so here's a checkpoint.)</p> -<a name="03-03-2012" /><a href="#03-03-2012"><hr><h2><b>March 3, 2012</b></h2></a> +<hr><b>March 3, 2012</b> <blockquote><p>"They went unnoticed at Goonhilly, passed over Cape Canaveral without a blip, and Woomera and Jodrell Bank looked straight through them. @@ -1454,7 +1216,7 @@ dirname, unshare, and various infrastructure tweaks, but it took me 3 months and those guys did their stuff in a week or so.)</p> -<a name="12-02-2012" /><a href="#12-02-2012"><hr><h2><b>February 12, 2012</b></h2></a> +<hr><b>February 12, 2012</b> <blockquote><p> "for though it has many omissions and contains much that is apocryphal, or at least wildly inaccurate, it scores over the older, more pedestrian work in two @@ -1471,8 +1233,7 @@ patches pending on the mailing list I need to review and merge.</p> <p>More to come...</p> <hr> -<a name="15-11-2011" /><a href="#15-11-2011"><hr><h2><b>November 15, 2011</b></h2></a> -- Back from the dead, Toybox is now under a 2 +<p><b>November 15, 2011</b> - Back from the dead, Toybox is now under a 2 clause BSD license, and aiming to become the default command line implementation of Android systems everywhere.</p> diff --git a/www/roadmap.html b/www/roadmap.html index e5105b8..bba08b1 100755 --- a/www/roadmap.html +++ b/www/roadmap.html @@ -244,13 +244,15 @@ sendevent start stop top uptime watchprops <h3>Other Android core commands</h3> <p>Other than the toolbox directory, the currently interesting -subdirectories in the core repository are init, -logcat, logwrapper, reboot, and run-as.</p> +subdirectories in the core repository are gpttool, init, +logcat, logwrapper, mkbootimg, reboot, and run-as.</p> <ul> +<li><b>gpttool</b> - subset of fdisk</li> <li><b>init</b> - Android's PID 1</li> <li><b>logcat</b> - read android log format</li> <li><b>logwrapper</b> - redirect stdio to android log</li> +<li><b>mkbootimg</b> - create signed boot image</li> <li><b>reboot</b> - Android's reboot(1)</li> <li><b>run-as</b> - subset of sudo</li> </ul> @@ -259,13 +261,17 @@ logcat, logwrapper, reboot, and run-as.</p> different user interface. We may want to provide that interface, but implementing the full commands (fdisk, init, and sudo) come first.</p> +<p>Also, gpttool and mkbootimg are install tools. +These aren't a priority if android wants to use its own +bespoke code to install itself.</p> + <h3>Analysis</h3> <p>For reference, combining everything listed above, we get:</p> <blockquote><b> -dd du df getevent iftop init ioctl ionice -log logcat logwrapper ls lsof mount nandread +dd du df getevent gpttool iftop init ioctl ionice +log logcat logwrapper ls lsof mkbootimg mount nandread newfs_msdos ps prlimit reboot renice run-as sendevent start stop top uptime watchprops </b></blockquote> |