├── www ├── index.html ├── footer.html ├── toycans.png ├── status.html └── header.html ├── toys ├── net │ ├── README │ └── tunctl.c ├── android │ ├── README │ ├── runcon.c │ ├── getenforce.c │ ├── load_policy.c │ ├── setenforce.c │ ├── sendevent.c │ ├── restorecon.c │ ├── log.c │ ├── start.c │ └── setprop.c ├── example │ ├── README │ ├── test_human_readable.c │ ├── test_many_options.c │ └── hello.c ├── posix │ ├── README │ ├── false.c │ ├── true.c │ ├── dirname.c │ ├── unlink.c │ ├── link.c │ ├── tty.c │ ├── basename.c │ ├── sleep.c │ ├── rmdir.c │ ├── nice.c │ ├── nohup.c │ ├── env.c │ ├── mkfifo.c │ ├── renice.c │ ├── who.c │ ├── mkdir.c │ ├── time.c │ ├── pwd.c │ ├── head.c │ ├── uuencode.c │ ├── tee.c │ ├── uname.c │ ├── strings.c │ ├── chmod.c │ └── cksum.c ├── lsb │ ├── README │ ├── sync.c │ ├── pidof.c │ ├── hostname.c │ ├── mknod.c │ └── mktemp.c ├── other │ ├── clear.c │ ├── README │ ├── reset.c │ ├── swapoff.c │ ├── hostid.c │ ├── usleep.c │ ├── realpath.c │ ├── yes.c │ ├── freeramdisk.c │ ├── setsid.c │ ├── fsfreeze.c │ ├── count.c │ ├── fallocate.c │ ├── w.c │ ├── partprobe.c │ ├── pwdx.c │ ├── fsync.c │ ├── rev.c │ ├── swapon.c │ ├── readahead.c │ ├── chroot.c │ ├── flock.c │ ├── pivot_root.c │ ├── tac.c │ ├── lsmod.c │ ├── reboot.c │ ├── chvt.c │ ├── printenv.c │ ├── setfattr.c │ ├── rmmod.c │ ├── readlink.c │ ├── chcon.c │ ├── lsusb.c │ ├── mkswap.c │ ├── insmod.c │ ├── uptime.c │ ├── which.c │ ├── free.c │ ├── truncate.c │ ├── factor.c │ ├── dos2unix.c │ ├── blockdev.c │ ├── help.c │ ├── mix.c │ ├── mountpoint.c │ └── timeout.c └── pending │ ├── README │ ├── vi.c │ ├── groupdel.c │ ├── iconv.c │ ├── watch.c │ └── logger.c ├── tests ├── files │ ├── utf8 │ │ ├── 0xabad1dea.txt │ │ ├── japan.txt │ │ ├── arabic.txt │ │ ├── bad.txt │ │ ├── test1.txt │ │ └── test2.txt │ ├── blkid │ │ ├── xfs.bz2 │ │ ├── cramfs.bz2 │ │ ├── ext2.bz2 │ │ ├── ext3.bz2 │ │ ├── ext4.bz2 │ │ ├── f2fs.bz2 │ │ ├── minix.bz2 │ │ ├── msdos.bz2 │ │ ├── ntfs.bz2 │ │ ├── vfat.bz2 │ │ ├── reiser3.bz2 │ │ └── squashfs.bz2 │ └── bzcat │ │ └── overflow.bz2 ├── top.test ├── more.test ├── dirname.test ├── losetup.test ├── bzcat.test ├── diff.test ├── hostname.test ├── getfattr.test ├── mkfifo.test ├── fstype.test ├── pwd.test ├── head.test ├── setfattr.test ├── factor.test ├── test_human_readable.test ├── link.test ├── uuencode.test ├── split.test ├── rev.test ├── basename.test ├── zcat.test ├── xzcat.test ├── cat.test ├── uudecode.test ├── truncate.test ├── file.test ├── tac.test ├── chown.test ├── groupdel.test ├── xargs.test ├── date.test ├── pgrep.test ├── cksum.test ├── md5sum.test ├── touch.test ├── wc.test ├── echo.test ├── du.test ├── lsattr.test ├── cpio.test ├── base64.test ├── modinfo.test ├── expand.test ├── rm.test ├── rmdir.test ├── cmp.test ├── test.test ├── sha1sum.test ├── blkid.test ├── nl.test ├── sh.test ├── cut.test ├── mkdir.test └── seq.test ├── .gitignore ├── scripts ├── findglobals.sh ├── minicom.sh ├── showasm ├── change.sh ├── install.c ├── single.sh ├── test.sh ├── mktags.c └── bloatcheck ├── kconfig ├── lxdialog │ ├── BIG.FAT.WARNING │ └── check-lxdialog.sh ├── README └── lkc_proto.h ├── lib ├── pending.h ├── help.c ├── toyflags.h └── net.c ├── LICENSE └── configure /www/index.html: -------------------------------------------------------------------------------- 1 | news.html -------------------------------------------------------------------------------- /toys/net/README: -------------------------------------------------------------------------------- 1 | Networking 2 | -------------------------------------------------------------------------------- /tests/files/utf8/0xabad1dea.txt: -------------------------------------------------------------------------------- 1 | ‮ ασσιλέΜ ‭ 2 | -------------------------------------------------------------------------------- /tests/files/utf8/japan.txt: -------------------------------------------------------------------------------- 1 | 私はガラスを食べられます。それは私を傷つけません。 -------------------------------------------------------------------------------- /www/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /www/toycans.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gfto/toybox/HEAD/www/toycans.png -------------------------------------------------------------------------------- /tests/files/blkid/xfs.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gfto/toybox/HEAD/tests/files/blkid/xfs.bz2 -------------------------------------------------------------------------------- /tests/files/utf8/arabic.txt: -------------------------------------------------------------------------------- 1 | بلدي الحوامات مليء الثعابين 2 | وأنا لن شراء هذه السجائر مخدوش ذلك. -------------------------------------------------------------------------------- /tests/files/utf8/bad.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gfto/toybox/HEAD/tests/files/utf8/bad.txt -------------------------------------------------------------------------------- /tests/files/blkid/cramfs.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gfto/toybox/HEAD/tests/files/blkid/cramfs.bz2 -------------------------------------------------------------------------------- /tests/files/blkid/ext2.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gfto/toybox/HEAD/tests/files/blkid/ext2.bz2 -------------------------------------------------------------------------------- /tests/files/blkid/ext3.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gfto/toybox/HEAD/tests/files/blkid/ext3.bz2 -------------------------------------------------------------------------------- /tests/files/blkid/ext4.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gfto/toybox/HEAD/tests/files/blkid/ext4.bz2 -------------------------------------------------------------------------------- /tests/files/blkid/f2fs.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gfto/toybox/HEAD/tests/files/blkid/f2fs.bz2 -------------------------------------------------------------------------------- /tests/files/blkid/minix.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gfto/toybox/HEAD/tests/files/blkid/minix.bz2 -------------------------------------------------------------------------------- /tests/files/blkid/msdos.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gfto/toybox/HEAD/tests/files/blkid/msdos.bz2 -------------------------------------------------------------------------------- /tests/files/blkid/ntfs.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gfto/toybox/HEAD/tests/files/blkid/ntfs.bz2 -------------------------------------------------------------------------------- /tests/files/blkid/vfat.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gfto/toybox/HEAD/tests/files/blkid/vfat.bz2 -------------------------------------------------------------------------------- /tests/files/blkid/reiser3.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gfto/toybox/HEAD/tests/files/blkid/reiser3.bz2 -------------------------------------------------------------------------------- /tests/files/blkid/squashfs.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gfto/toybox/HEAD/tests/files/blkid/squashfs.bz2 -------------------------------------------------------------------------------- /tests/files/bzcat/overflow.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gfto/toybox/HEAD/tests/files/bzcat/overflow.bz2 -------------------------------------------------------------------------------- /tests/files/utf8/test1.txt: -------------------------------------------------------------------------------- 1 | l̴̗̞̠ȩ̸̩̥ṱ̴͍̻ ̴̲͜ͅt̷͇̗̮h̵̥͉̝e̴̡̺̼ ̸̤̜͜ŗ̴͓͉i̶͉͓͎t̷̞̝̻u̶̻̫̗a̴̺͎̯l̴͍͜ͅ ̵̩̲̱c̷̩̟̖o̴̠͍̻m̸͚̬̘ṃ̷̢͜e̵̗͎̫n̸̨̦̖c̷̰̩͎e̴̱̞̗ 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | syntax: glob 2 | .config* 3 | .single* 4 | change/ 5 | generated/ 6 | kconfig/mconf 7 | kconfig/conf 8 | kconfig/*.c 9 | toybox 10 | toybox_unstripped 11 | -------------------------------------------------------------------------------- /toys/android/README: -------------------------------------------------------------------------------- 1 | Android 2 | 3 | Commands primarily used by Android, not vanilla Linux. (Also SELinux stuff.) 4 | 5 | Bug Elliott Hughes about this. 6 | -------------------------------------------------------------------------------- /toys/example/README: -------------------------------------------------------------------------------- 1 | Example commands 2 | 3 | You probably don't want to deploy this, but it shows how to use the 4 | toybox infrastructure and provides templates for new commands. 5 | -------------------------------------------------------------------------------- /tests/files/utf8/test2.txt: -------------------------------------------------------------------------------- 1 | l̴̗̞̠ȩ̸̩̥ṱ̴͍̻ ̴̲͜ͅt̷͇̗̮h̵̥͉̝e̴̡̺̼ ̸̤̜͜ŗ̴͓͉i̶͉͓͎t̷̞̝̻u̶̻̫̗a̴̺͎̯l̴͍͜ͅ ̵̩̲̱c̷̩̟̖o̴̠͍̻m̸͚̬̘ṃ̷̢͜e̵̗͎̫n̸̨̦̖c̷̰̩͎e̴̱̞̗ 2 | the̡ ҉̷ŕ͠͡į͞ţų͠al͘ ̛͏i͘҉s̛ ͜͞ḉ͏om̶͏pl̵͜ęt̴͠e̛ 3 | -------------------------------------------------------------------------------- /tests/top.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | testing "batch termination" "top -b -n1 | tail -c 1" "\n" "" "" 8 | -------------------------------------------------------------------------------- /toys/posix/README: -------------------------------------------------------------------------------- 1 | Posix commands 2 | 3 | Commands defined in POSIX-2008, also known as the Single Unix 4 | Specification version 4, available online at 5 | http://pubs.opengroup.org/onlinepubs/9699919799/idx/utilities.html 6 | -------------------------------------------------------------------------------- /scripts/findglobals.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Quick and dirty check to see if anybody's leaked global variables. 4 | # We should have this, toy_list, toybuf, and toys. 5 | 6 | nm toybox_unstripped | grep '[0-9A-Fa-f]* [BCDGRS]' | cut -d ' ' -f 3 7 | -------------------------------------------------------------------------------- /kconfig/lxdialog/BIG.FAT.WARNING: -------------------------------------------------------------------------------- 1 | This is NOT the official version of dialog. This version has been 2 | significantly modified from the original. It is for use by the Linux 3 | kernel configuration script. Please do not bother Savio Lam with 4 | questions about this program. 5 | -------------------------------------------------------------------------------- /tests/more.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | cat >file1 <toybox current status 2 | 3 | Toybox Status 4 | 5 | 6 | 7 |

See the Roadmap page for more information.

8 | 9 | 10 | -------------------------------------------------------------------------------- /toys/lsb/README: -------------------------------------------------------------------------------- 1 | Linux Standard Base commands 2 | 3 | Commands defined in the Linux Standard Base 4.1: 4 | http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/cmdbehav.html 5 | 6 | Downloadable as one big file from: 7 | http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic.html 8 | -------------------------------------------------------------------------------- /tests/dirname.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | testing "/-only" "dirname ///////" "/\n" "" "" 8 | testing "trailing /" "dirname a//////" ".\n" "" "" 9 | testing "combined" "dirname /////a///b///c///d/////" "/////a///b///c\n" "" "" 10 | testing "/a/" "dirname /////a///" "/\n" "" "" 11 | -------------------------------------------------------------------------------- /toys/other/clear.c: -------------------------------------------------------------------------------- 1 | /* clear.c - clear the screen 2 | * 3 | * Copyright 2012 Rob Landley 4 | 5 | USE_CLEAR(NEWTOY(clear, NULL, TOYFLAG_USR|TOYFLAG_BIN)) 6 | 7 | config CLEAR 8 | bool "clear" 9 | default y 10 | help 11 | Clear the screen. 12 | */ 13 | 14 | #include "toys.h" 15 | 16 | void clear_main(void) 17 | { 18 | xwrite(1, "\e[2J\e[H", 7); 19 | } 20 | -------------------------------------------------------------------------------- /scripts/minicom.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # If you want to use toybox netcat to talk to a serial port, use this. 4 | 5 | if [ ! -c "$1" ] 6 | then 7 | echo "Usage: minicom.sh /dev/ttyS0" 8 | exit 1 9 | fi 10 | 11 | SPEED="$2" 12 | [ -z "$SPEED" ] && SPEED=115200 13 | 14 | stty $SPEED -F "$1" 15 | stty raw -echo -ctlecho -F "$1" 16 | stty raw -echo # Need to do it on stdin, too. 17 | ./toybox netcat -f "$1" 18 | stty cooked echo # Put stdin back. 19 | -------------------------------------------------------------------------------- /toys/posix/false.c: -------------------------------------------------------------------------------- 1 | /* false.c - Return nonzero. 2 | * 3 | * Copyright 2007 Rob Landley 4 | * 5 | * See http://opengroup.org/onlinepubs/9699919799/utilities/false.html 6 | 7 | USE_FALSE(NEWTOY(false, NULL, TOYFLAG_BIN|TOYFLAG_NOHELP)) 8 | 9 | config FALSE 10 | bool "false" 11 | default y 12 | help 13 | Return nonzero. 14 | */ 15 | 16 | #include "toys.h" 17 | 18 | void false_main(void) 19 | { 20 | toys.exitval = 1; 21 | } 22 | -------------------------------------------------------------------------------- /toys/other/README: -------------------------------------------------------------------------------- 1 | Other commands 2 | 3 | These are commands not present in Posix or LSB. 4 | 5 | Most of them are necessary to provide a development environment capable of 6 | booting a system image and building Linux From Scratch under it. 7 | 8 | Tested with Aboriginal Linux system image and the lfs-bootstrap.hdc automated 9 | build control image for Linux From Scratch 6.8): 10 | 11 | http://landley.net/aboriginal 12 | 13 | http://landley.net/aboriginal/control-images 14 | -------------------------------------------------------------------------------- /toys/posix/true.c: -------------------------------------------------------------------------------- 1 | /* true.c - Return zero. 2 | * 3 | * Copyright 2007 Rob Landley 4 | * 5 | * See http://opengroup.org/onlinepubs/9699919799/utilities/true.html 6 | 7 | USE_TRUE(NEWTOY(true, NULL, TOYFLAG_BIN|TOYFLAG_NOHELP)) 8 | USE_TRUE(OLDTOY(:, true, TOYFLAG_NOFORK|TOYFLAG_NOHELP)) 9 | 10 | config TRUE 11 | bool "true" 12 | default y 13 | help 14 | Return zero. 15 | */ 16 | 17 | #include "toys.h" 18 | 19 | void true_main(void) 20 | { 21 | return; 22 | } 23 | -------------------------------------------------------------------------------- /lib/pending.h: -------------------------------------------------------------------------------- 1 | // pending.h - header for pending.c 2 | 3 | // password.c 4 | #define MAX_SALT_LEN 20 //3 for id, 16 for key, 1 for '\0' 5 | int read_password(char * buff, int buflen, char* mesg); 6 | int update_password(char *filename, char* username, char* encrypted); 7 | 8 | // lib.c 9 | // These should be switched to posix-2008 getline() and getdelim() 10 | char *get_rawline(int fd, long *plen, char end); 11 | char *get_line(int fd); 12 | 13 | 14 | // TODO this goes away when lib/password.c cleaned up 15 | -------------------------------------------------------------------------------- /toys/other/reset.c: -------------------------------------------------------------------------------- 1 | /* reset.c - reset the terminal. 2 | * 3 | * Copyright 2015 Rob Landley 4 | * 5 | * No standard. 6 | 7 | USE_RESET(NEWTOY(reset, 0, TOYFLAG_USR|TOYFLAG_BIN)) 8 | 9 | config RESET 10 | bool "reset" 11 | default y 12 | help 13 | usage: reset 14 | 15 | reset the terminal 16 | */ 17 | #include "toys.h" 18 | 19 | void reset_main(void) 20 | { 21 | // man 4 console codes: reset terminal is ESC (no left bracket) c 22 | xwrite(xgettty(), "\033c", 2); 23 | } 24 | -------------------------------------------------------------------------------- /toys/other/swapoff.c: -------------------------------------------------------------------------------- 1 | /* swapoff.c - Disable region for swapping 2 | * 3 | * Copyright 2012 Elie De Brauwer 4 | 5 | USE_SWAPOFF(NEWTOY(swapoff, "<1>1", TOYFLAG_SBIN|TOYFLAG_NEEDROOT)) 6 | 7 | config SWAPOFF 8 | bool "swapoff" 9 | default y 10 | help 11 | usage: swapoff swapregion 12 | 13 | Disable swapping on a given swapregion. 14 | */ 15 | 16 | #include "toys.h" 17 | 18 | void swapoff_main(void) 19 | { 20 | if (swapoff(toys.optargs[0])) perror_exit("failed to remove swaparea"); 21 | } 22 | -------------------------------------------------------------------------------- /tests/losetup.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | if [ "$(id -u)" -ne 0 ] 6 | then 7 | echo "$SHOWSKIP: losetup (not root)" 8 | continue 2>/dev/null 9 | exit 10 | fi 11 | 12 | #testing "name" "command" "result" "infile" "stdin" 13 | 14 | truncate -s 1M blah.img && 15 | FILE="$(readlink -f blah.img)" 16 | DEV="$(printf '%04d' $(stat -t blah.img | awk '{print $7}'))" 17 | NODE="$(awk '{print $7}')" 18 | 19 | losetup -f 20 | losetup -f -s 21 | losetup -f file 22 | 23 | losetup -d 24 | 25 | rm blah.img 26 | -------------------------------------------------------------------------------- /toys/lsb/sync.c: -------------------------------------------------------------------------------- 1 | /* sync.c - Write all pending data to disk. 2 | * 3 | * Copyright 2007 Rob Landley 4 | * 5 | * http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/sync.html 6 | 7 | USE_SYNC(NEWTOY(sync, NULL, TOYFLAG_BIN)) 8 | 9 | config SYNC 10 | bool "sync" 11 | default y 12 | help 13 | usage: sync 14 | 15 | Write pending cached data to disk (synchronize), blocking until done. 16 | */ 17 | 18 | #include "toys.h" 19 | 20 | void sync_main(void) 21 | { 22 | sync(); 23 | } 24 | -------------------------------------------------------------------------------- /toys/other/hostid.c: -------------------------------------------------------------------------------- 1 | /* hostid.c - Print the numeric identifier for the current host. 2 | * 3 | * Copyright 2015 Ranjan Kumar 4 | * 5 | * No Standard. 6 | 7 | USE_HOSTID(NEWTOY(hostid, ">0", TOYFLAG_USR|TOYFLAG_BIN)) 8 | 9 | config HOSTID 10 | bool "hostid" 11 | default y 12 | help 13 | usage: hostid 14 | 15 | Print the numeric identifier for the current host. 16 | */ 17 | #define FOR_hostid 18 | #include "toys.h" 19 | 20 | void hostid_main(void) 21 | { 22 | xprintf("%08lx\n", gethostid()); 23 | } 24 | -------------------------------------------------------------------------------- /toys/posix/dirname.c: -------------------------------------------------------------------------------- 1 | /* dirname.c - show directory portion of path 2 | * 3 | * Copyright 2011 Rob Landley 4 | * 5 | * See http://opengroup.org/onlinepubs/9699919799/utilities/dirname.html 6 | 7 | USE_DIRNAME(NEWTOY(dirname, "<1", TOYFLAG_USR|TOYFLAG_BIN)) 8 | 9 | config DIRNAME 10 | bool "dirname" 11 | default y 12 | help 13 | usage: dirname PATH 14 | 15 | Show directory portion of path. 16 | */ 17 | 18 | #include "toys.h" 19 | 20 | void dirname_main(void) 21 | { 22 | puts(dirname(*toys.optargs)); 23 | } 24 | -------------------------------------------------------------------------------- /toys/posix/unlink.c: -------------------------------------------------------------------------------- 1 | /* unlink.c - delete one file 2 | * 3 | * Copyright 2011 Rob Landley 4 | * 5 | * See http://opengroup.org/onlinepubs/9699919799/utilities/unlink.html 6 | 7 | USE_UNLINK(NEWTOY(unlink, "<1>1", TOYFLAG_USR|TOYFLAG_BIN)) 8 | 9 | config UNLINK 10 | bool "unlink" 11 | default y 12 | help 13 | usage: unlink FILE 14 | 15 | Deletes one file. 16 | */ 17 | 18 | #include "toys.h" 19 | 20 | void unlink_main(void) 21 | { 22 | if (unlink(*toys.optargs)) 23 | perror_exit("Couldn't unlink `%s'", *toys.optargs); 24 | } 25 | -------------------------------------------------------------------------------- /tests/bzcat.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | testing "2 known files" \ 7 | 'bzcat "$FILES/blkid/"{minix,ntfs}.bz2 | sha1sum | '"awk '{print \$1}'" \ 8 | 'c0b7469c9660d6056a988ef8a7fe73925efc9266\n' '' '' 9 | 10 | testing "overflow" \ 11 | 'bzcat "$FILES/bzcat/overflow.bz2" >/dev/null 2>/dev/null ; 12 | [ $? -ne 0 ] && echo good' "good\n" "" "" 13 | 14 | testing "badcrc" \ 15 | 'bzcat "$FILES/bzcat/badcrc.bz2" > /dev/null 2>/dev/null ; 16 | [ $? -ne 0 ] && echo good' "good\n" "" "" 17 | -------------------------------------------------------------------------------- /tests/diff.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #testing "name" "command" "result" "infile" "stdin" 4 | 5 | seq 10 > left 6 | seq 11 > right 7 | 8 | expected='--- left 9 | +++ right 10 | @@ -8,3 +8,4 @@ 11 | 8 12 | 9 13 | 10 14 | +11 15 | ' 16 | # Hm this only gives unified diffs? 17 | testing "simple" "diff left right" "$expected" "" "" 18 | 19 | 20 | expected='--- tree1/file 21 | +++ tree2/file 22 | @@ -1 +1 @@ 23 | -foo 24 | +food 25 | ' 26 | mkdir -p tree1 tree2 27 | echo foo > tree1/file 28 | echo food > tree2/file 29 | 30 | testing "simple" "diff -r tree1 tree2 |tee out" "$expected" "" "" 31 | -------------------------------------------------------------------------------- /tests/hostname.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2014 Divya Kothari 4 | # Copyright 2014 Naha Maggu 5 | 6 | [ -f testing.sh ] && . testing.sh 7 | 8 | #testing "name" "command" "result" "infile" "stdin" 9 | 10 | # Get system hostname 11 | hostnameExe=`which hostname` 12 | hostnameOut=`$hostnameExe` 13 | 14 | # New hostname 15 | NewHostname="NewHostName.system" 16 | 17 | testing "get" "hostname" "$hostnameOut\n" "" "" 18 | testing "set, Get and then Reset" "hostname $NewHostname; hostname; hostname $hostnameOut; hostname" "$NewHostname\n$hostnameOut\n" "" "" 19 | -------------------------------------------------------------------------------- /toys/posix/link.c: -------------------------------------------------------------------------------- 1 | /* link.c - hardlink a file 2 | * 3 | * Copyright 2011 Rob Landley 4 | * 5 | * See http://opengroup.org/onlinepubs/9699919799/utilities/link.html 6 | 7 | USE_LINK(NEWTOY(link, "<2>2", TOYFLAG_USR|TOYFLAG_BIN)) 8 | 9 | config LINK 10 | bool "link" 11 | default y 12 | help 13 | usage: link FILE NEWLINK 14 | 15 | Create hardlink to a file. 16 | */ 17 | 18 | #include "toys.h" 19 | 20 | void link_main(void) 21 | { 22 | if (link(toys.optargs[0], toys.optargs[1])) 23 | perror_exit("couldn't link '%s' to '%s'", toys.optargs[1], 24 | toys.optargs[0]); 25 | } 26 | -------------------------------------------------------------------------------- /toys/other/usleep.c: -------------------------------------------------------------------------------- 1 | /* usleep.c - Wait for a number of microseconds. 2 | * 3 | * Copyright 2012 Elie De Brauwer 4 | 5 | USE_USLEEP(NEWTOY(usleep, "<1", TOYFLAG_BIN)) 6 | 7 | config USLEEP 8 | bool "usleep" 9 | default y 10 | help 11 | usage: usleep MICROSECONDS 12 | 13 | Pause for MICROSECONDS microseconds. 14 | */ 15 | 16 | #include "toys.h" 17 | 18 | void usleep_main(void) 19 | { 20 | struct timespec tv; 21 | long delay = atol(*toys.optargs); 22 | 23 | tv.tv_sec = delay/1000000; 24 | tv.tv_nsec = (delay%1000000) * 1000; 25 | toys.exitval = !!nanosleep(&tv, NULL); 26 | } 27 | -------------------------------------------------------------------------------- /toys/other/realpath.c: -------------------------------------------------------------------------------- 1 | /* realpath.c - Return the canonical version of a pathname 2 | * 3 | * Copyright 2012 Andre Renaud 4 | 5 | USE_REALPATH(NEWTOY(realpath, "<1", TOYFLAG_USR|TOYFLAG_BIN)) 6 | 7 | config REALPATH 8 | bool "realpath" 9 | default y 10 | help 11 | usage: realpath FILE... 12 | 13 | Display the canonical absolute pathname 14 | */ 15 | 16 | #include "toys.h" 17 | 18 | void realpath_main(void) 19 | { 20 | char **s = toys.optargs; 21 | 22 | for (s = toys.optargs; *s; s++) { 23 | if (!realpath(*s, toybuf)) perror_msg_raw(*s); 24 | else xputs(toybuf); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /toys/other/yes.c: -------------------------------------------------------------------------------- 1 | /* yes.c - Repeatedly output a string. 2 | * 3 | * Copyright 2007 Rob Landley 4 | 5 | USE_YES(NEWTOY(yes, NULL, TOYFLAG_USR|TOYFLAG_BIN)) 6 | 7 | config YES 8 | bool "yes" 9 | default y 10 | help 11 | usage: yes [args...] 12 | 13 | Repeatedly output line until killed. If no args, output 'y'. 14 | */ 15 | 16 | #include "toys.h" 17 | 18 | void yes_main(void) 19 | { 20 | for (;;) { 21 | int i; 22 | for (i=0; toys.optargs[i]; i++) { 23 | if (i) xputc(' '); 24 | xprintf("%s", toys.optargs[i]); 25 | } 26 | if (!i) xputc('y'); 27 | xputc('\n'); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /toys/example/test_human_readable.c: -------------------------------------------------------------------------------- 1 | /* test_human_readable.c - Expose lib/lib.c human_readable() for testing. 2 | * 3 | * Copyright 2015 Rob Landley 4 | 5 | USE_TEST_HUMAN_READABLE(NEWTOY(test_human_readable, "<1>1ibs", TOYFLAG_BIN)) 6 | 7 | config TEST_HUMAN_READABLE 8 | bool "test_human_readable" 9 | default n 10 | help 11 | usage: test_human_readable [-sbi] NUMBER 12 | */ 13 | 14 | #define FOR_test_human_readable 15 | #include "toys.h" 16 | 17 | void test_human_readable_main(void) 18 | { 19 | char *c; 20 | 21 | human_readable(toybuf, strtoll(*toys.optargs, &c, 0), toys.optflags); 22 | printf("%s\n", toybuf); 23 | } 24 | -------------------------------------------------------------------------------- /toys/example/test_many_options.c: -------------------------------------------------------------------------------- 1 | /* test_many_options.c - test more than 32 bits worth of option flags 2 | * 3 | * Copyright 2015 Rob Landley 4 | 5 | USE_TEST_MANY_OPTIONS(NEWTOY(test_many_options, "ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba", TOYFLAG_BIN)) 6 | 7 | config TEST_MANY_OPTIONS 8 | bool "test_many_options" 9 | default n 10 | help 11 | usage: test_many_options -[a-zA-Z] 12 | 13 | Print the optflags value of the command arguments, in hex. 14 | */ 15 | 16 | #define FOR_test_many_options 17 | #include "toys.h" 18 | 19 | void test_many_options_main(void) 20 | { 21 | xprintf("optflags=%llx\n", toys.optflags); 22 | } 23 | -------------------------------------------------------------------------------- /scripts/showasm: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright 2006 Rob Landley 4 | 5 | # Dumb little utility function to print out the assembly dump of a single 6 | # function, or list the functions so dumpable in an executable. You'd think 7 | # there would be a way to get objdump to do this, but I can't find it. 8 | 9 | [ $# -lt 1 ] || [ $# -gt 2 ] && { echo "usage: showasm file function"; exit 1; } 10 | 11 | [ ! -f $1 ] && { echo "File $1 not found"; exit 1; } 12 | 13 | if [ $# -eq 1 ] 14 | then 15 | objdump -d $1 | sed -n -e 's/^[0-9a-fA-F]* <\(.*\)>:$/\1/p' 16 | exit 0 17 | fi 18 | 19 | objdump -d $1 | sed -n -e '/./{H;$!d}' -e "x;/^.[0-9a-fA-F]* <$2>:/p" 20 | 21 | -------------------------------------------------------------------------------- /toys/other/freeramdisk.c: -------------------------------------------------------------------------------- 1 | /* freeramdisk.c - Free all memory allocated to ramdisk 2 | * 3 | * Copyright 2014 Vivek Kumar Bhagat 4 | * 5 | * No Standard 6 | 7 | USE_FREERAMDISK(NEWTOY(freeramdisk, "<1>1", TOYFLAG_SBIN|TOYFLAG_NEEDROOT)) 8 | 9 | config FREERAMDISK 10 | bool "freeramdisk" 11 | default y 12 | help 13 | usage: freeramdisk [RAM device] 14 | 15 | Free all memory allocated to specified ramdisk 16 | */ 17 | 18 | #include "toys.h" 19 | 20 | void freeramdisk_main(void) 21 | { 22 | int fd; 23 | 24 | fd = xopen(toys.optargs[0], O_RDWR); 25 | xioctl(fd, BLKFLSBUF, toys.optargs[0]); 26 | if (CFG_TOYBOX_FREE) xclose(fd); 27 | } 28 | -------------------------------------------------------------------------------- /toys/other/setsid.c: -------------------------------------------------------------------------------- 1 | /* setsid.c - Run program in a new session ID. 2 | * 3 | * Copyright 2006 Rob Landley 4 | 5 | USE_SETSID(NEWTOY(setsid, "^<1t", TOYFLAG_USR|TOYFLAG_BIN)) 6 | 7 | config SETSID 8 | bool "setsid" 9 | default y 10 | help 11 | usage: setsid [-t] command [args...] 12 | 13 | Run process in a new session. 14 | 15 | -t Grab tty (become foreground process, receiving keyboard signals) 16 | */ 17 | 18 | #include "toys.h" 19 | 20 | void setsid_main(void) 21 | { 22 | while (setsid()<0) if (XVFORK()) _exit(0); 23 | if (toys.optflags) { 24 | setpgid(0, 0); 25 | tcsetpgrp(0, getpid()); 26 | } 27 | xexec(toys.optargs); 28 | } 29 | -------------------------------------------------------------------------------- /scripts/change.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # build each command as a standalone executable 4 | 5 | NOBUILD=1 scripts/make.sh > /dev/null && 6 | ${HOSTCC:-cc} -I . scripts/install.c -o generated/instlist && 7 | export PREFIX=${PREFIX:-change/} && 8 | mkdir -p "$PREFIX" || exit 1 9 | 10 | # Build all the commands standalone except: 11 | 12 | # sh - shell builtins like "cd" and "exit" need the multiplexer 13 | # help - needs to know what other commands are enabled (use command --help) 14 | 15 | for i in $(generated/instlist | egrep -vw "sh|help") 16 | do 17 | echo -n " $i" && 18 | scripts/single.sh $i > /dev/null 2>$PREFIX/${i}.bad && 19 | rm $PREFIX/${i}.bad || echo -n '*' 20 | done 21 | echo 22 | -------------------------------------------------------------------------------- /toys/other/fsfreeze.c: -------------------------------------------------------------------------------- 1 | /* fsfreeze.c - freeze or thaw filesystem 2 | * 3 | * No standard. 4 | 5 | USE_FSFREEZE(NEWTOY(fsfreeze, "<1>1f|u|[!fu]", TOYFLAG_USR|TOYFLAG_SBIN)) 6 | 7 | config FSFREEZE 8 | bool "fsfreeze" 9 | default y 10 | depends on TOYBOX_FIFREEZE 11 | help 12 | usage: fsfreeze {-f | -u} MOUNTPOINT 13 | 14 | Freeze or unfreeze a filesystem. 15 | 16 | -f freeze 17 | -u unfreeze 18 | */ 19 | 20 | #define FOR_fsfreeze 21 | #include "toys.h" 22 | #include 23 | 24 | void fsfreeze_main(void) 25 | { 26 | int fd = xopenro(*toys.optargs); 27 | long p = 1; 28 | 29 | xioctl(fd, (toys.optflags & FLAG_f) ? FIFREEZE : FITHAW, &p); 30 | xclose(fd); 31 | } 32 | -------------------------------------------------------------------------------- /toys/android/runcon.c: -------------------------------------------------------------------------------- 1 | /* runcon.c - Run command in specified security context 2 | * 3 | * Copyright 2015 The Android Open Source Project 4 | 5 | USE_RUNCON(NEWTOY(runcon, "<2", TOYFLAG_USR|TOYFLAG_SBIN)) 6 | 7 | config RUNCON 8 | bool "runcon" 9 | depends on TOYBOX_SELINUX 10 | default y 11 | help 12 | usage: runcon CONTEXT COMMAND [ARGS...] 13 | 14 | Run a command in a specified security context. 15 | */ 16 | 17 | #define FOR_runcon 18 | #include "toys.h" 19 | 20 | void runcon_main(void) 21 | { 22 | char *context = *toys.optargs; 23 | 24 | if (setexeccon(context)) perror_exit("Could not set context to %s", context); 25 | 26 | toys.stacktop = 0; 27 | xexec(++toys.optargs); 28 | } 29 | -------------------------------------------------------------------------------- /tests/getfattr.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | mkdir attrs 8 | touch attrs/file 9 | setfattr -n user.empty attrs/file 10 | setfattr -n user.data -v hello attrs/file 11 | 12 | testing "" "getfattr attrs/file" \ 13 | "# file: attrs/file\nuser.data\nuser.empty\n\n" "" "" 14 | testing "-d" "getfattr -d attrs/file" \ 15 | "# file: attrs/file\nuser.data=\"hello\"\nuser.empty\n\n" "" "" 16 | testing "-n" "getfattr -n user.empty attrs/file" \ 17 | "# file: attrs/file\nuser.empty\n\n" "" "" 18 | testing "-d -n" "getfattr -d -n user.data attrs/file" \ 19 | "# file: attrs/file\nuser.data=\"hello\"\n\n" "" "" 20 | 21 | rm -rf attrs 22 | -------------------------------------------------------------------------------- /tests/mkfifo.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | testing "mkfifo" "mkfifo one && [ -p one ] && echo yes" "yes\n" "" "" 8 | rm one 9 | 10 | touch existing 11 | testing "existing" \ 12 | "mkfifo existing 2> /dev/null || [ -f existing ] && echo yes" "yes\n" "" "" 13 | rm existing 14 | 15 | testing "one two" \ 16 | "mkfifo one two && [ -p one ] && [ -p two ] && echo yes" "yes\n" "" "" 17 | rm one two 18 | 19 | umask 123 20 | testing "(default permissions)" \ 21 | "mkfifo one && stat -c %a one" "644\n" "" "" 22 | rm one 23 | 24 | umask 000 25 | 26 | testing "-m 124" \ 27 | "mkfifo -m 124 one && stat -c %a one" "124\n" "" "" 28 | rm -f one 29 | -------------------------------------------------------------------------------- /tests/fstype.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | BDIR="$FILES/blkid" 8 | 9 | bzcat "$BDIR"/squashfs.bz2 > temp.img 10 | testing "file" "fstype temp.img" 'squashfs\n' "" "" 11 | rm temp.img 12 | 13 | for i in cramfs ext2 ext3 ext4 f2fs ntfs squashfs vfat xfs 14 | do 15 | testing "$i" 'bzcat "$BDIR"/$i.bz2 | fstype -' "$i\n" "" "" 16 | done 17 | 18 | testing "msdos" 'bzcat "$BDIR"/msdos.bz2 | fstype -' 'vfat\n' "" "" 19 | testing "reiserfs" 'bzcat "$BDIR"/reiser3.bz2 | fstype -' 'reiserfs\n' "" "" 20 | 21 | #testing "blkid minix" 'bzcat "$BDIR"/minix.bz2 | blkid -' 22 | #adfs bfs btrfs cramfs jfs nilfs romfs 23 | #vfat // fat32 fat12 fat16 24 | -------------------------------------------------------------------------------- /tests/pwd.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | #TODO: Find better tests 8 | 9 | testing "pwd" "[ $(stat -c %i "$(pwd)") = $(stat -c %i .) ] && echo yes" \ 10 | "yes\n" "" "" 11 | testing "-P" "[ $(stat -c %i "$(pwd -P)") = $(stat -c %i .) ] && echo yes" \ 12 | "yes\n" "" "" 13 | 14 | 15 | ln -s . sym 16 | cd sym 17 | testing "pwd" "[ $(stat -c %i "$(pwd)") = $(stat -c %i "$PWD") ] && echo yes" \ 18 | "yes\n" "" "" 19 | testing "-P" "[ $(stat -c %i "$(pwd -P)") = $(stat -c %i "$PWD") ] || echo yes" \ 20 | "yes\n" "" "" 21 | cd .. 22 | rm sym 23 | 24 | export PWD=walrus 25 | testing "(bad PWD)" "[ "$(pwd)" = "$(cd . ; pwd)" ] && echo yes" \ 26 | "yes\n" "" "" 27 | -------------------------------------------------------------------------------- /toys/posix/tty.c: -------------------------------------------------------------------------------- 1 | /* tty.c - Show stdin's terminal name 2 | * 3 | * Copyright 2011 Rob Landley 4 | * 5 | * See http://opengroup.org/onlinepubs/9699919799/utilities/tty.html 6 | 7 | USE_TTY(NEWTOY(tty, "s", TOYFLAG_USR|TOYFLAG_BIN)) 8 | 9 | config TTY 10 | bool "tty" 11 | default y 12 | help 13 | usage: tty [-s] 14 | 15 | Show filename of terminal connected to stdin. 16 | 17 | Prints "not a tty" and exits with nonzero status if no terminal 18 | is connected to stdin. 19 | 20 | -s silent, exit code only 21 | */ 22 | 23 | #include "toys.h" 24 | 25 | void tty_main(void) 26 | { 27 | char *tty = ttyname(0); 28 | 29 | if (!toys.optflags) puts(tty ? tty : "not a tty"); 30 | 31 | toys.exitval = !tty; 32 | } 33 | -------------------------------------------------------------------------------- /toys/other/count.c: -------------------------------------------------------------------------------- 1 | /* count.c - Progress indicator from stdin to stdout 2 | * 3 | * Copyright 2002 Rob Landley 4 | 5 | USE_COUNT(NEWTOY(count, NULL, TOYFLAG_USR|TOYFLAG_BIN)) 6 | 7 | config COUNT 8 | bool "count" 9 | default y 10 | help 11 | usage: count 12 | 13 | Copy stdin to stdout, displaying simple progress indicator to stderr. 14 | */ 15 | 16 | #include "toys.h" 17 | 18 | void count_main(void) 19 | { 20 | uint64_t size = 0; 21 | int len; 22 | char buf[32]; 23 | 24 | for (;;) { 25 | len = xread(0, toybuf, sizeof(toybuf)); 26 | if (!len) break; 27 | size += len; 28 | xwrite(1, toybuf, len); 29 | xwrite(2, buf, sprintf(buf, "%"PRIu64" bytes\r", size)); 30 | } 31 | xwrite(2, "\n", 1); 32 | } 33 | -------------------------------------------------------------------------------- /toys/pending/README: -------------------------------------------------------------------------------- 1 | pending (see toys/pending/README) 2 | 3 | Commands in this directory are external submissions awaiting review and/or 4 | cleanup before being "promoted" to one of the other directories. 5 | 6 | Code in this directory may or may not work, some of the commands here are 7 | unfinished stubs, others just need a more thorough inspection than we've had 8 | time for yet. Everything in here defaults to "n" in defconfig. 9 | 10 | Outside of this directory, several commands (and some library code) have 11 | TODO annotations. 12 | 13 | This directory should go away before the 1.0 release. It's just a staging 14 | area so code submissions don't get lost while awaiting more thorough (and 15 | very time consuming) scrutiny as described in www/cleanup.html. 16 | -------------------------------------------------------------------------------- /toys/android/getenforce.c: -------------------------------------------------------------------------------- 1 | /* getenforce.c - Get the current SELinux mode 2 | * 3 | * Copyright 2014 The Android Open Source Project 4 | 5 | USE_GETENFORCE(NEWTOY(getenforce, ">0", TOYFLAG_USR|TOYFLAG_SBIN)) 6 | 7 | config GETENFORCE 8 | bool "getenforce" 9 | default y 10 | depends on TOYBOX_SELINUX 11 | help 12 | usage: getenforce 13 | 14 | Shows whether SELinux is disabled, enforcing, or permissive. 15 | */ 16 | 17 | #define FOR_getenforce 18 | #include "toys.h" 19 | 20 | void getenforce_main(void) 21 | { 22 | if (!is_selinux_enabled()) puts("Disabled"); 23 | else { 24 | int ret = security_getenforce(); 25 | 26 | if (ret == -1) perror_exit("Couldn't get enforcing status"); 27 | else puts(ret ? "Enforcing" : "Permissive"); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /toys/other/fallocate.c: -------------------------------------------------------------------------------- 1 | /* fallocate.c - Preallocate space to a file 2 | * 3 | * Copyright 2013 Felix Janda 4 | * 5 | * No standard 6 | 7 | USE_FALLOCATE(NEWTOY(fallocate, ">1l#|", TOYFLAG_USR|TOYFLAG_BIN)) 8 | 9 | config FALLOCATE 10 | bool "fallocate" 11 | depends on TOYBOX_FALLOCATE 12 | default y 13 | help 14 | usage: fallocate [-l size] file 15 | 16 | Tell the filesystem to allocate space for a file. 17 | */ 18 | 19 | #define FOR_fallocate 20 | #include "toys.h" 21 | 22 | GLOBALS( 23 | long size; 24 | ) 25 | 26 | void fallocate_main(void) 27 | { 28 | int fd = xcreate(*toys.optargs, O_RDWR | O_CREAT, 0644); 29 | if (posix_fallocate(fd, 0, TT.size)) error_exit("Not enough space"); 30 | if (CFG_TOYBOX_FREE) close(fd); 31 | } 32 | -------------------------------------------------------------------------------- /tests/head.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | testing "head, stdin" "head -n 1 && echo yes" "one\nyes\n" "" "one\ntwo" 8 | testing "head, stdin via -" "head -n 1 - && echo yes" "one\nyes\n" "" "one\ntwo" 9 | testing "head, file" "head input -n 1 && echo yes" "one\nyes\n" "one\ntwo" "" 10 | testing "-number" "head -2 input && echo yes" "one\ntwo\nyes\n" \ 11 | "one\ntwo\nthree\nfour" "" 12 | testing "head, default lines" "head" "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n" "" "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12" 13 | 14 | echo "foo 15 | bar 16 | baz" > file1 17 | testing "head, multiple files" "head -n 2 input file1" "==> input <==\none\ntwo\n\n==> file1 <==\nfoo\nbar\n" "one\ntwo\nthree\n" "" 18 | rm file1 19 | 20 | -------------------------------------------------------------------------------- /toys/other/w.c: -------------------------------------------------------------------------------- 1 | /* w.c - shows logged in users 2 | * 3 | * Copyright 2012 Gaurang Shastri 4 | 5 | USE_W(NEWTOY(w, NULL, TOYFLAG_USR|TOYFLAG_BIN)) 6 | 7 | config W 8 | bool "w" 9 | default y 10 | depends on TOYBOX_UTMPX 11 | help 12 | usage: w 13 | 14 | Show who is logged on and since how long they logged in. 15 | */ 16 | 17 | #include "toys.h" 18 | 19 | void w_main(void) 20 | { 21 | struct utmpx *x; 22 | 23 | xprintf("USER TTY LOGIN@ FROM"); 24 | setutxent(); 25 | while ((x=getutxent()) != NULL) { 26 | if (x->ut_type==7) { 27 | time_t tt = x->ut_tv.tv_sec; 28 | 29 | xprintf("\n%-9.8s%-9.8s %-4.24s (%-1.12s)", x->ut_user, x->ut_line, 30 | ctime(&tt), x->ut_host); 31 | } 32 | } 33 | xputc('\n'); 34 | } 35 | -------------------------------------------------------------------------------- /toys/other/partprobe.c: -------------------------------------------------------------------------------- 1 | /* partprobe.c - Tell the kernel about partition table changes 2 | * 3 | * Copyright 2014 Bertold Van den Bergh 4 | * 5 | * see http://man7.org/linux/man-pages/man8/partprobe.8.html 6 | 7 | USE_PARTPROBE(NEWTOY(partprobe, "<1", TOYFLAG_SBIN)) 8 | 9 | config PARTPROBE 10 | bool "partprobe" 11 | default y 12 | help 13 | usage: partprobe DEVICE... 14 | 15 | Tell the kernel about partition table changes 16 | 17 | Ask the kernel to re-read the partition table on the specified devices. 18 | */ 19 | 20 | #include "toys.h" 21 | 22 | static void do_partprobe(int fd, char *name) 23 | { 24 | if (ioctl(fd, BLKRRPART, 0)) perror_msg("ioctl failed"); 25 | } 26 | 27 | void partprobe_main(void) 28 | { 29 | loopfiles(toys.optargs, do_partprobe); 30 | } 31 | -------------------------------------------------------------------------------- /toys/other/pwdx.c: -------------------------------------------------------------------------------- 1 | /* pwdx.c - report current directory of a process. 2 | * 3 | * Copyright 2013 Lukasz Skalski 4 | 5 | USE_PWDX(NEWTOY(pwdx, "<1a", TOYFLAG_USR|TOYFLAG_BIN)) 6 | 7 | config PWDX 8 | bool "pwdx" 9 | default y 10 | help 11 | usage: pwdx PID... 12 | 13 | Print working directory of processes listed on command line. 14 | */ 15 | 16 | #include "toys.h" 17 | 18 | void pwdx_main(void) 19 | { 20 | char **optargs; 21 | 22 | for (optargs = toys.optargs; *optargs; optargs++) { 23 | char *path = toybuf; 24 | 25 | sprintf(toybuf, "/proc/%d/cwd", atoi(*optargs)); 26 | if (!readlink0(path, toybuf, sizeof(toybuf))) { 27 | path = strerror(errno); 28 | toys.exitval = 1; 29 | } 30 | 31 | xprintf("%s: %s\n", *optargs, path); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/setfattr.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | mkdir attrs 8 | touch attrs/file 9 | setfattr -n user.empty attrs/file 10 | setfattr -n user.data -v hello attrs/file 11 | setfattr -n user.delete-me -v hello attrs/file 12 | 13 | testing "-x" \ 14 | "setfattr -x user.delete-me attrs/file && getfattr attrs/file" \ 15 | "# file: attrs/file\nuser.data\nuser.empty\n\n" "" "" 16 | testing "-n" "setfattr -n user.new attrs/file && getfattr -d attrs/file" \ 17 | "# file: attrs/file\nuser.data=\"hello\"\nuser.empty\nuser.new\n\n" "" "" 18 | testing "-n -v" "setfattr -n user.new -v data attrs/file && getfattr -d attrs/file" \ 19 | "# file: attrs/file\nuser.data=\"hello\"\nuser.empty\nuser.new=\"data\"\n\n" "" "" 20 | 21 | rm -rf attrs 22 | -------------------------------------------------------------------------------- /toys/other/fsync.c: -------------------------------------------------------------------------------- 1 | /* fsync.c - Synchronize a file's in-core state with storage device. 2 | * 3 | * Copyright 2015 Ranjan Kumar 4 | * 5 | * No Standard. 6 | 7 | USE_FSYNC(NEWTOY(fsync, "<1d", TOYFLAG_BIN)) 8 | 9 | config FSYNC 10 | bool "fsync" 11 | default y 12 | help 13 | usage: fsync [-d] [FILE...] 14 | 15 | Synchronize a file's in-core state with storage device. 16 | 17 | -d Avoid syncing metadata. 18 | */ 19 | 20 | #define FOR_fsync 21 | #include "toys.h" 22 | 23 | static void do_fsync(int fd, char *name) 24 | { 25 | if (((toys.optflags & FLAG_d) ? fdatasync(fd) : fsync(fd))) 26 | perror_msg("can't sync '%s'", name); 27 | } 28 | 29 | void fsync_main(void) 30 | { 31 | loopfiles_rw(toys.optargs, O_RDONLY|O_NOATIME|O_NOCTTY|O_CLOEXEC|WARN_ONLY, 32 | 0, do_fsync); 33 | } 34 | -------------------------------------------------------------------------------- /lib/help.c: -------------------------------------------------------------------------------- 1 | // Function to display help text 2 | 3 | #include "toys.h" 4 | 5 | #include "generated/help.h" 6 | 7 | #undef NEWTOY 8 | #undef OLDTOY 9 | #define NEWTOY(name,opt,flags) HELP_##name "\0" 10 | #if CFG_TOYBOX 11 | #define OLDTOY(name,oldname,flags) "\xff" #oldname "\0" 12 | #else 13 | #define OLDTOY(name, oldname, flags) HELP_##oldname "\0" 14 | #endif 15 | static char *help_data = 16 | #include "generated/newtoys.h" 17 | ; 18 | 19 | void show_help(FILE *out) 20 | { 21 | int i = toys.which-toy_list; 22 | char *s; 23 | 24 | if (CFG_TOYBOX_HELP) { 25 | for (;;) { 26 | s = help_data; 27 | while (i--) s += strlen(s) + 1; 28 | // If it's an alias, restart search for real name 29 | if (*s != 255) break; 30 | i = toy_find(++s)-toy_list; 31 | } 32 | 33 | fprintf(out, "%s", s); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /tests/factor.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | testing "-32" "factor -32" "-32: -1 2 2 2 2 2\n" "" "" 8 | testing "0" "factor 0" "0: 0\n" "" "" 9 | testing "1" "factor 1" "1: 1\n" "" "" 10 | testing "2" "factor 2" "2: 2\n" "" "" 11 | testing "3" "factor 3" "3: 3\n" "" "" 12 | testing "4" "factor 4" "4: 2 2\n" "" "" 13 | testing "10000000017" "factor 10000000017" \ 14 | "10000000017: 3 3 3 7 7 7 1079797\n" "" "" 15 | testing "10000000018" "factor 10000000018" \ 16 | "10000000018: 2 131 521 73259\n" "" "" 17 | testing "10000000019" "factor 10000000019" \ 18 | "10000000019: 10000000019\n" "" "" 19 | 20 | testing "3 6 from stdin" "factor" "3: 3\n6: 2 3\n" "" "3 6" 21 | testing "stdin newline" "factor" "3: 3\n6: 2 3\n" "" "3\n6\n" 22 | 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2006, 2013 by Rob Landley 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any 4 | purpose with or without fee is hereby granted. 5 | 6 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 7 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 8 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 9 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 10 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 11 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 12 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 13 | 14 | (Note: some build infrastructure in the kconfig directory is still GPLv2, 15 | cleaning that out is a TODO item, but it doesn't affect the resulting 16 | binary.) 17 | -------------------------------------------------------------------------------- /toys/other/rev.c: -------------------------------------------------------------------------------- 1 | /* rev.c - reverse lines of a set of given input files 2 | * 3 | * Copyright 2012 Elie De Brauwer 4 | 5 | USE_REV(NEWTOY(rev, NULL, TOYFLAG_USR|TOYFLAG_BIN)) 6 | 7 | config REV 8 | bool "rev" 9 | default y 10 | help 11 | usage: rev [FILE...] 12 | 13 | Output each line reversed, when no files are given stdin is used. 14 | */ 15 | 16 | #include "toys.h" 17 | 18 | static void do_rev(int fd, char *name) 19 | { 20 | char *c; 21 | 22 | for (;;) { 23 | unsigned len, i; 24 | 25 | if (!(c = get_line(fd))) break; 26 | len = strlen(c); 27 | if (len--) for (i = 0; i <= len/2; i++) { 28 | char tmp = c[i]; 29 | 30 | c[i] = c[len-i]; 31 | c[len-i] = tmp; 32 | } 33 | xputs(c); 34 | free(c); 35 | } 36 | } 37 | 38 | void rev_main(void) 39 | { 40 | loopfiles(toys.optargs, do_rev); 41 | } 42 | -------------------------------------------------------------------------------- /toys/android/load_policy.c: -------------------------------------------------------------------------------- 1 | /* load_policy.c - Load a policy file 2 | * 3 | * Copyright 2015 The Android Open Source Project 4 | 5 | USE_LOAD_POLICY(NEWTOY(load_policy, "<1>1", TOYFLAG_USR|TOYFLAG_SBIN)) 6 | 7 | config LOAD_POLICY 8 | bool "load_policy" 9 | depends on TOYBOX_SELINUX 10 | default y 11 | help 12 | usage: load_policy FILE 13 | 14 | Load the specified policy file. 15 | */ 16 | 17 | #define FOR_load_policy 18 | #include "toys.h" 19 | 20 | void load_policy_main(void) 21 | { 22 | int fd = xopenro(*toys.optargs); 23 | off_t policy_len = fdlength(fd); 24 | char *policy_data = mmap(0, policy_len, PROT_READ, MAP_PRIVATE, fd, 0); 25 | 26 | close(fd); 27 | if (!policy_data || security_load_policy(policy_data, policy_len) < 0) 28 | perror_exit("Couldn't %s %s", policy_data ? "load" : "read", *toys.optargs); 29 | 30 | munmap(policy_data, policy_len); 31 | } 32 | -------------------------------------------------------------------------------- /tests/test_human_readable.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | testing "l 1024" "test_human_readable 123456789" "118M\n" "" "" 8 | testing "l 1000" "test_human_readable -i 123456789" "123M\n" "" "" 9 | testing "s 1024" "test_human_readable 5675" "5.5K\n" "" "" 10 | testing "s 1000" "test_human_readable -i 5675" "5.6k\n" "" "" 11 | 12 | # An example input where we give a better result than coreutils. 13 | # 267350/1024=261.08. We say 261K and coreutils says 262K. 14 | testing "test_human_readable" "test_human_readable 267350" "261K\n" "" "" 15 | 16 | testing "-b" "test_human_readable -b 123" "123B\n" "" "" 17 | testing "-b" "test_human_readable -b 123456789" "118M\n" "" "" 18 | testing "-s" "test_human_readable -s 123456789" "118 M\n" "" "" 19 | testing "-bs" "test_human_readable -bs 123456789" "118 M\n" "" "" 20 | -------------------------------------------------------------------------------- /toys/posix/basename.c: -------------------------------------------------------------------------------- 1 | /* basename.c - Return non-directory portion of a pathname 2 | * 3 | * Copyright 2012 Tryn Mirell 4 | * 5 | * See http://opengroup.org/onlinepubs/9699919799/utilities/basename.html 6 | 7 | 8 | USE_BASENAME(NEWTOY(basename, "<1>2", TOYFLAG_USR|TOYFLAG_BIN)) 9 | 10 | config BASENAME 11 | bool "basename" 12 | default y 13 | help 14 | usage: basename string [suffix] 15 | 16 | Return non-directory portion of a pathname removing suffix 17 | */ 18 | 19 | #include "toys.h" 20 | 21 | void basename_main(void) 22 | { 23 | char *base = basename(*toys.optargs), *suffix = toys.optargs[1]; 24 | 25 | // chop off the suffix if provided 26 | if (suffix && *suffix) { 27 | long bl = strlen(base), sl = strlen(suffix); 28 | char *s = base + bl - sl; 29 | 30 | if (bl > sl && !strcmp(s, suffix)) *s = 0; 31 | } 32 | 33 | puts(base); 34 | } 35 | -------------------------------------------------------------------------------- /tests/link.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2014 Divya Kothari 4 | # Copyright 2014 Naha Maggu 5 | 6 | [ -f testing.sh ] && . testing.sh 7 | 8 | #testing "name" "command" "result" "infile" "stdin" 9 | 10 | echo "" >foo 11 | testing "fails on non-existent file" "link foo/foo baz || echo GOOD" "GOOD\n" "" "" 12 | rm -f foo bar 13 | 14 | echo file1 > file 15 | testing "create_hardlink" "link file hlink && [ file -ef hlink ] && 16 | echo 'yes'; rm -rf hlink" "yes\n" "" "" 17 | 18 | echo hlink1 > hlink 19 | set +e 20 | testing "preserves_hardlinks" "link file hlink 2>/dev/null || echo 'yes'; rm -rf hlink" \ 21 | "yes\n" "" "" 22 | 23 | echo file1 > file 24 | testing "create_hardlink_and_remove_sourcefile" "link file hlink && 25 | [ file -ef hlink ] && rm -rf file && [ -f hlink ] && echo 'yes'; rm -f file hlink" \ 26 | "yes\n" "" "" 27 | -------------------------------------------------------------------------------- /toys/other/swapon.c: -------------------------------------------------------------------------------- 1 | /* swapon.c - Enable region for swapping 2 | * 3 | * Copyright 2012 Elie De Brauwer 4 | 5 | USE_SWAPON(NEWTOY(swapon, "<1>1p#<0>32767d", TOYFLAG_SBIN|TOYFLAG_NEEDROOT)) 6 | 7 | config SWAPON 8 | bool "swapon" 9 | default y 10 | help 11 | usage: swapon [-d] [-p priority] filename 12 | 13 | Enable swapping on a given device/file. 14 | 15 | -d Discard freed SSD pages 16 | */ 17 | 18 | #define FOR_swapon 19 | #include "toys.h" 20 | 21 | GLOBALS( 22 | long priority; 23 | ) 24 | 25 | void swapon_main(void) 26 | { 27 | // 0x70000 = SWAP_FLAG_DISCARD|SWAP_FLAG_DISCARD_ONCE|SWAP_FLAG_DISCARD_PAGES 28 | int flags = (toys.optflags&FLAG_d)*0x70000; 29 | 30 | if (toys.optflags) 31 | flags |= SWAP_FLAG_PREFER | (TT.priority << SWAP_FLAG_PRIO_SHIFT); 32 | 33 | if (swapon(*toys.optargs, flags)) 34 | perror_exit("Couldn't swapon '%s'", *toys.optargs); 35 | } 36 | -------------------------------------------------------------------------------- /toys/posix/sleep.c: -------------------------------------------------------------------------------- 1 | /* sleep.c - Wait for a number of seconds. 2 | * 3 | * Copyright 2007 Rob Landley 4 | * Copyright 2012 Georgi Chorbadzhiyski 5 | * 6 | * See http://opengroup.org/onlinepubs/9699919799/utilities/sleep.html 7 | 8 | USE_SLEEP(NEWTOY(sleep, "<1", TOYFLAG_BIN)) 9 | 10 | config SLEEP 11 | bool "sleep" 12 | default y 13 | help 14 | usage: sleep LENGTH 15 | 16 | Wait before exiting. An optional suffix can be "m" (minutes), "h" (hours), 17 | "d" (days), or "s" (seconds, the default). 18 | 19 | 20 | config SLEEP_FLOAT 21 | bool 22 | default y 23 | depends on SLEEP && TOYBOX_FLOAT 24 | help 25 | Length can be a decimal fraction. 26 | */ 27 | 28 | #include "toys.h" 29 | 30 | void sleep_main(void) 31 | { 32 | struct timespec tv; 33 | 34 | tv.tv_sec = xparsetime(*toys.optargs, 1000000000, &tv.tv_nsec); 35 | toys.exitval = !!nanosleep(&tv, NULL); 36 | } 37 | -------------------------------------------------------------------------------- /tests/uuencode.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | testing "not enough args [fail]" "uuencode 2>/dev/null" "" "" "" 8 | 9 | testing "uu empty file" "uuencode test" \ 10 | "begin 744 test\nend\n" "" "" 11 | testing "uu 1-char" "uuencode test" \ 12 | "begin 744 test\n!80\`\`\nend\n" "" "a" 13 | testing "uu 2-char" "uuencode test" \ 14 | "begin 744 test\n\"86(\`\nend\n" "" "ab" 15 | testing "uu 3-char" "uuencode test" \ 16 | "begin 744 test\n#86)C\nend\n" "" "abc" 17 | 18 | testing "b64 empty file" "uuencode -m test" \ 19 | "begin-base64 744 test\n====\n" "" "" 20 | testing "b64 1-char" "uuencode -m test" \ 21 | "begin-base64 744 test\nYQ==\n====\n" "" "a" 22 | testing "b64 2-char" "uuencode -m test" \ 23 | "begin-base64 744 test\nYWI=\n====\n" "" "ab" 24 | testing "b64 3-char" "uuencode -m test" \ 25 | "begin-base64 744 test\nYWJj\n====\n" "" "abc" 26 | 27 | -------------------------------------------------------------------------------- /tests/split.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | testing "split" "seq 1 12345 | split && ls xa[a-z] | wc -l" "13\n" "" "" 8 | rm xa[a-z] 9 | 10 | testing "-" "seq 1 12345 | split - && ls xa[a-z] | wc -l" "13\n" "" "" 11 | rm xa[a-z] 12 | 13 | seq 1 12345 > file 14 | testing "file" "split file && ls xa[a-z] | wc -l" "13\n" "" "" 15 | rm xa[a-z] 16 | 17 | testing "-l" "split file -l 10k && wc -l xab" "2105 xab\n" "" "" 18 | rm xa[ab] 19 | 20 | testing "suffix exhaustion" \ 21 | "split file -l 10 -a 1 walrus 2>/dev/null || ls walrus* | wc -l" "26\n" "" "" 22 | rm walrus* 23 | 24 | testing "bytes" \ 25 | "toybox seq 1 20000 | split -b 100 -a 3 - whang && ls whang* | wc -l && wc -c whangbpw" "1089\n94 whangbpw\n" "" "" 26 | 27 | testing "reassembly" \ 28 | 'diff -u <(ls whang* | sort | xargs cat) <(seq 1 20000) && echo yes' \ 29 | "yes\n" "" "" 30 | 31 | rm file whang* 32 | -------------------------------------------------------------------------------- /toys/other/readahead.c: -------------------------------------------------------------------------------- 1 | /* readahead.c - preload files into disk cache. 2 | * 3 | * Copyright 2013 Rob Landley 4 | * 5 | * No standard. 6 | 7 | USE_READAHEAD(NEWTOY(readahead, NULL, TOYFLAG_BIN)) 8 | 9 | config READAHEAD 10 | bool "readahead" 11 | default y 12 | help 13 | usage: readahead FILE... 14 | 15 | Preload files into disk cache. 16 | */ 17 | 18 | #include "toys.h" 19 | 20 | #include 21 | 22 | static void do_readahead(int fd, char *name) 23 | { 24 | int rc; 25 | 26 | // Since including fcntl.h doesn't give us the wrapper, use the syscall. 27 | // 32 bits takes LO/HI offset (we don't care about endianness of 0). 28 | if (sizeof(long) == 4) rc = syscall(__NR_readahead, fd, 0, 0, INT_MAX); 29 | else rc = syscall(__NR_readahead, fd, 0, INT_MAX); 30 | 31 | if (rc) perror_msg("readahead: %s", name); 32 | } 33 | 34 | void readahead_main(void) 35 | { 36 | loopfiles(toys.optargs, do_readahead); 37 | } 38 | -------------------------------------------------------------------------------- /toys/example/hello.c: -------------------------------------------------------------------------------- 1 | /* hello.c - A hello world program. (Simple template for new commands.) 2 | * 3 | * Copyright 2012 Rob Landley 4 | * 5 | * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ 6 | * See http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/cmdbehav.html 7 | 8 | USE_HELLO(NEWTOY(hello, 0, TOYFLAG_USR|TOYFLAG_BIN)) 9 | 10 | config HELLO 11 | bool "hello" 12 | default n 13 | help 14 | usage: hello [-s] 15 | 16 | A hello world program. You don't need this. 17 | 18 | Mostly used as a simple template for adding new commands. 19 | Occasionally nice to smoketest kernel booting via "init=/usr/bin/hello". 20 | */ 21 | 22 | #define FOR_hello 23 | #include "toys.h" 24 | 25 | GLOBALS( 26 | int unused; 27 | ) 28 | 29 | void hello_main(void) 30 | { 31 | xprintf("Hello world\n"); 32 | 33 | // Avoid kernel panic if run as init. 34 | if (getpid() == 1) wait(&TT.unused); 35 | } 36 | -------------------------------------------------------------------------------- /toys/other/chroot.c: -------------------------------------------------------------------------------- 1 | /* chroot.c - Run command in new root directory. 2 | * 3 | * Copyright 2007 Rob Landley 4 | * 5 | * TODO: The test for root is "==" so root can trivially escape a chroot by 6 | * moving it below cwd, ala mkdir("sub"); chroot("sub"); chdir("../../../..") 7 | * The container guys use pivot_root() to deal with this, which does actually 8 | * edit mount tree. (New option? Kernel patch?) 9 | 10 | USE_CHROOT(NEWTOY(chroot, "^<1", TOYFLAG_USR|TOYFLAG_SBIN)) 11 | 12 | config CHROOT 13 | bool "chroot" 14 | default y 15 | help 16 | usage: chroot NEWPATH [commandline...] 17 | 18 | Run command within a new root directory. If no command, run /bin/sh. 19 | */ 20 | 21 | #include "toys.h" 22 | 23 | void chroot_main(void) 24 | { 25 | char *binsh[] = {"/bin/sh", "-i", 0}; 26 | 27 | if (chdir(*toys.optargs) || chroot(".")) perror_exit_raw(*toys.optargs); 28 | if (toys.optargs[1]) xexec(toys.optargs+1); 29 | else xexec(binsh); 30 | } 31 | -------------------------------------------------------------------------------- /tests/rev.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | echo -e "one" > file1 8 | echo -e "two" > file2 9 | testing "rev" "rev && echo yes" "orez\nyes\n" "" "zero\n" 10 | testing "-" "rev - && echo yes" "orez\nyes\n" "" "zero\n" 11 | testing "file1 file2" "rev file1 file2" "eno\nowt\n" "" "" 12 | testing "- file" "rev - file1" "orez\neno\n" "" "zero\n" 13 | testing "file -" "rev file1 -" "eno\norez\n" "" "zero\n" 14 | testing "no trailing newline" "rev -" "cba\nfed\n" "" "abc\ndef" 15 | 16 | testing "file1 notfound file2" \ 17 | "rev file1 notfound file2 2>stderr && echo ok ; cat stderr; rm stderr" \ 18 | "eno\nowt\nrev: notfound: No such file or directory\n" "" "" 19 | 20 | testing "different input sizes"\ 21 | "rev"\ 22 | "\n1\n21\n321\n4321\n54321\n4321\n321\n21\n1\n\n"\ 23 | "" "\n1\n12\n123\n1234\n12345\n1234\n123\n12\n1\n\n" 24 | 25 | rm file1 file2 -------------------------------------------------------------------------------- /toys/other/flock.c: -------------------------------------------------------------------------------- 1 | /* flock.c - manage advisory file locks 2 | * 3 | * Copyright 2015 The Android Open Source Project 4 | 5 | USE_FLOCK(NEWTOY(flock, "<1>1nsux[-sux]", TOYFLAG_USR|TOYFLAG_BIN)) 6 | 7 | config FLOCK 8 | bool "flock" 9 | default y 10 | help 11 | usage: flock [-sxun] fd 12 | 13 | Manage advisory file locks. 14 | 15 | -s Shared lock. 16 | -x Exclusive lock (default). 17 | -u Unlock. 18 | -n Non-blocking: fail rather than wait for the lock. 19 | */ 20 | 21 | #define FOR_flock 22 | #include "toys.h" 23 | 24 | #include 25 | 26 | void flock_main(void) 27 | { 28 | int fd = xstrtol(*toys.optargs, NULL, 10), op; 29 | 30 | if (toys.optflags & FLAG_u) op = LOCK_UN; 31 | else op = (toys.optflags & FLAG_s) ? LOCK_SH : LOCK_EX; 32 | 33 | if (toys.optflags & FLAG_n) op |= LOCK_NB; 34 | 35 | if (flock(fd, op)) { 36 | if ((op & LOCK_NB) && errno == EAGAIN) toys.exitval = 1; 37 | else perror_exit("flock"); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/basename.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | # Removal of extra /'s 8 | testing "/-only" "basename ///////" "/\n" "" "" 9 | testing "trailing /" "basename a//////" "a\n" "" "" 10 | testing "combined" "basename /////a///b///c///d/////" "d\n" "" "" 11 | 12 | # Standard suffix behavior. 13 | testing "suffix" "basename a/b/c/d.suffix .suffix" "d\n" "" "" 14 | 15 | # A suffix cannot be the entire result. 16 | testing "suffix=result" "basename .txt .txt" ".txt\n" "" "" 17 | 18 | # Deal with suffix appearing in the filename 19 | testing "reappearing suffix 1" "basename a.txt.txt .txt" "a.txt\n" "" "" 20 | testing "reappearing suffix 2" "basename a.txt.old .txt" "a.txt.old\n" "" "" 21 | 22 | # A suffix should be a real suffix, only a the end. 23 | testing "invalid suffix" "basename isthisasuffix? suffix" "isthisasuffix?\n" "" "" 24 | 25 | # Zero-length suffix 26 | testing "zero-length suffix" "basename a/b/c ''" "c\n" "" "" 27 | -------------------------------------------------------------------------------- /toys/android/setenforce.c: -------------------------------------------------------------------------------- 1 | /* setenforce.c - Set the current SELinux mode 2 | * 3 | * Copyright 2014 The Android Open Source Project 4 | 5 | USE_SETENFORCE(NEWTOY(setenforce, "<1>1", TOYFLAG_USR|TOYFLAG_SBIN)) 6 | 7 | config SETENFORCE 8 | bool "setenforce" 9 | default y 10 | depends on TOYBOX_SELINUX 11 | help 12 | usage: setenforce [enforcing|permissive|1|0] 13 | 14 | Sets whether SELinux is enforcing (1) or permissive (0). 15 | */ 16 | 17 | #define FOR_setenforce 18 | #include "toys.h" 19 | 20 | void setenforce_main(void) 21 | { 22 | char *new = *toys.optargs; 23 | int state, ret; 24 | 25 | if (!is_selinux_enabled()) error_exit("SELinux is disabled"); 26 | else if (!strcmp(new, "1") || !strcasecmp(new, "enforcing")) state = 1; 27 | else if (!strcmp(new, "0") || !strcasecmp(new, "permissive")) state = 0; 28 | else error_exit("Invalid state: %s", new); 29 | 30 | ret = security_setenforce(state); 31 | if (ret == -1) perror_msg("Couldn't set enforcing status to '%s'", new); 32 | } 33 | -------------------------------------------------------------------------------- /toys/other/pivot_root.c: -------------------------------------------------------------------------------- 1 | /* pivot_root.c - edit system mount tree 2 | * 3 | * Copyright 2012 Rob Landley 4 | 5 | USE_PIVOT_ROOT(NEWTOY(pivot_root, "<2>2", TOYFLAG_SBIN)) 6 | 7 | config PIVOT_ROOT 8 | bool "pivot_root" 9 | default y 10 | help 11 | usage: pivot_root OLD NEW 12 | 13 | Swap OLD and NEW filesystems (as if by simultaneous mount --move), and 14 | move all processes with chdir or chroot under OLD into NEW (including 15 | kernel threads) so OLD may be unmounted. 16 | 17 | The directory NEW must exist under OLD. This doesn't work on initramfs, 18 | which can't be moved (about the same way PID 1 can't be killed; see 19 | switch_root instead). 20 | */ 21 | 22 | #define FOR_pivot_root 23 | #include "toys.h" 24 | 25 | #include 26 | #include 27 | 28 | void pivot_root_main(void) 29 | { 30 | if (syscall(__NR_pivot_root, toys.optargs[0], toys.optargs[1])) 31 | perror_exit("'%s' -> '%s'", toys.optargs[0], toys.optargs[1]); 32 | } 33 | -------------------------------------------------------------------------------- /toys/android/sendevent.c: -------------------------------------------------------------------------------- 1 | /* sendevent.c - Send Linux input events. 2 | * 3 | * Copyright 2016 The Android Open Source Project 4 | 5 | USE_SENDEVENT(NEWTOY(sendevent, "<4>4", TOYFLAG_USR|TOYFLAG_SBIN)) 6 | 7 | config SENDEVENT 8 | bool "sendevent" 9 | default y 10 | depends on TOYBOX_ON_ANDROID 11 | help 12 | usage: sendevent DEVICE TYPE CODE VALUE 13 | 14 | Sends a Linux input event. 15 | */ 16 | 17 | #define FOR_sendevent 18 | #include "toys.h" 19 | 20 | #include 21 | 22 | void sendevent_main(void) 23 | { 24 | int fd = xopen(*toys.optargs, O_RDWR); 25 | int version; 26 | struct input_event ev; 27 | 28 | if (ioctl(fd, EVIOCGVERSION, &version)) 29 | perror_exit("EVIOCGVERSION failed for %s", *toys.optargs); 30 | 31 | memset(&ev, 0, sizeof(ev)); 32 | // TODO: error checking and support for named constants. 33 | ev.type = atoi(toys.optargs[1]); 34 | ev.code = atoi(toys.optargs[2]); 35 | ev.value = atoi(toys.optargs[3]); 36 | xwrite(fd, &ev, sizeof(ev)); 37 | } 38 | -------------------------------------------------------------------------------- /toys/posix/rmdir.c: -------------------------------------------------------------------------------- 1 | /* rmdir.c - remove directory/path 2 | * 3 | * Copyright 2008 Rob Landley 4 | * 5 | * See http://opengroup.org/onlinepubs/9699919799/utilities/rmdir.html 6 | 7 | USE_RMDIR(NEWTOY(rmdir, "<1p", TOYFLAG_BIN)) 8 | 9 | config RMDIR 10 | bool "rmdir" 11 | default y 12 | help 13 | usage: rmdir [-p] [dirname...] 14 | 15 | Remove one or more directories. 16 | 17 | -p Remove path. 18 | */ 19 | 20 | #include "toys.h" 21 | 22 | static void do_rmdir(char *name) 23 | { 24 | char *temp; 25 | 26 | for (;;) { 27 | if (rmdir(name)) { 28 | perror_msg_raw(name); 29 | return; 30 | } 31 | 32 | // Each -p cycle back up one slash, ignoring trailing and repeated /. 33 | 34 | if (!toys.optflags) return; 35 | do { 36 | if (!(temp = strrchr(name, '/'))) return; 37 | *temp = 0; 38 | } while (!temp[1]); 39 | } 40 | } 41 | 42 | void rmdir_main(void) 43 | { 44 | char **s; 45 | 46 | for (s=toys.optargs; *s; s++) do_rmdir(*s); 47 | } 48 | -------------------------------------------------------------------------------- /scripts/install.c: -------------------------------------------------------------------------------- 1 | /* Wrapper to make installation easier with cross-compiling. 2 | * 3 | * Copyright 2006 Rob Landley 4 | */ 5 | 6 | #include 7 | #include "generated/config.h" 8 | #include "lib/toyflags.h" 9 | 10 | #define NEWTOY(name, opts, flags) {#name, flags}, 11 | #define OLDTOY(name, oldname, flags) {#name, flags}, 12 | 13 | // Populate toy_list[]. 14 | 15 | struct {char *name; int flags;} toy_list[] = { 16 | #include "generated/newtoys.h" 17 | }; 18 | 19 | int main(int argc, char *argv[]) 20 | { 21 | static char *toy_paths[]={"usr/","bin/","sbin/",0}; 22 | int i, len = 0; 23 | 24 | // Output list of applets. 25 | for (i=1; i1) { 29 | int j; 30 | for (j=0; toy_paths[j]; j++) 31 | if (fl & (1< 4 | 5 | USE_TAC(NEWTOY(tac, NULL, TOYFLAG_USR|TOYFLAG_BIN)) 6 | 7 | config TAC 8 | bool "tac" 9 | default y 10 | help 11 | usage: tac [FILE...] 12 | 13 | Output lines in reverse order. 14 | */ 15 | 16 | #include "toys.h" 17 | 18 | static void do_tac(int fd, char *name) 19 | { 20 | struct arg_list *list = NULL; 21 | char *c; 22 | 23 | // Read in lines 24 | for (;;) { 25 | struct arg_list *temp; 26 | long len; 27 | 28 | if (!(c = get_rawline(fd, &len, '\n'))) break; 29 | 30 | temp = xmalloc(sizeof(struct arg_list)); 31 | temp->next = list; 32 | temp->arg = c; 33 | list = temp; 34 | } 35 | 36 | // Play them back. 37 | while (list) { 38 | struct arg_list *temp = list->next; 39 | xprintf("%s", list->arg); 40 | free(list->arg); 41 | free(list); 42 | list = temp; 43 | } 44 | } 45 | 46 | void tac_main(void) 47 | { 48 | loopfiles(toys.optargs, do_tac); 49 | } 50 | -------------------------------------------------------------------------------- /configure: -------------------------------------------------------------------------------- 1 | # Toybox configuration file. 2 | 3 | # This sets environment variables used by scripts/make.sh 4 | 5 | # A synonym. 6 | [ -z "$CROSS_COMPILE" ] && CROSS_COMPILE="$CROSS" 7 | 8 | # CFLAGS and OPTIMIZE are different so you can add extra CFLAGS without 9 | # disabling default optimizations 10 | [ -z "$CFLAGS" ] && CFLAGS="-Wall -Wundef -Wno-char-subscripts" 11 | # Required for our expected ABI. we're 8-bit clean thus "char" must be unsigned. 12 | CFLAGS="$CFLAGS -funsigned-char" 13 | [ -z "$OPTIMIZE" ] && OPTIMIZE="-Os -ffunction-sections -fdata-sections -fno-asynchronous-unwind-tables -fno-strict-aliasing" 14 | 15 | # We accept LDFLAGS, but by default don't have anything in it 16 | [ -z "$LDOPTIMIZE" ] && LDOPTIMIZE="-Wl,--gc-sections" 17 | 18 | # The makefile provides defaults for these, so this only gets used if 19 | # you call scripts/make.sh and friends directly. 20 | 21 | [ -z "$CC" ] && CC=cc 22 | 23 | # If HOSTCC needs CFLAGS or LDFLAGS, just add them to the variable 24 | # ala HOSTCC="blah-cc --static" 25 | [ -z "$HOSTCC" ] && HOSTCC=cc 26 | -------------------------------------------------------------------------------- /toys/other/lsmod.c: -------------------------------------------------------------------------------- 1 | /* lsmod.c - Show the status of modules in the kernel 2 | * 3 | * Copyright 2012 Elie De Brauwer 4 | 5 | USE_LSMOD(NEWTOY(lsmod, NULL, TOYFLAG_SBIN)) 6 | 7 | config LSMOD 8 | bool "lsmod" 9 | default y 10 | help 11 | usage: lsmod 12 | 13 | Display the currently loaded modules, their sizes and their dependencies. 14 | */ 15 | 16 | #include "toys.h" 17 | 18 | void lsmod_main(void) 19 | { 20 | char *modfile = "/proc/modules"; 21 | FILE * file = xfopen(modfile, "r"); 22 | 23 | xprintf("%-23s Size Used by\n", "Module"); 24 | 25 | while (fgets(toybuf, sizeof(toybuf), file)) { 26 | char *name = strtok(toybuf, " "), *size = strtok(NULL, " "), 27 | *refcnt = strtok(NULL, " "), *users = strtok(NULL, " "); 28 | 29 | if(users) { 30 | int len = strlen(users)-1; 31 | if (users[len] == ',' || users[len] == '-') users[len] = 0; 32 | xprintf("%-19s %8s %s %s\n", name, size, refcnt, users); 33 | } else perror_exit("bad %s", modfile); 34 | } 35 | fclose(file); 36 | } 37 | -------------------------------------------------------------------------------- /toys/other/reboot.c: -------------------------------------------------------------------------------- 1 | /* reboot.c - Restart, halt or powerdown the system. 2 | * 3 | * Copyright 2013 Elie De Brauwer 4 | 5 | USE_REBOOT(NEWTOY(reboot, "fn", TOYFLAG_SBIN|TOYFLAG_NEEDROOT)) 6 | USE_REBOOT(OLDTOY(halt, reboot, TOYFLAG_SBIN|TOYFLAG_NEEDROOT)) 7 | USE_REBOOT(OLDTOY(poweroff, reboot, TOYFLAG_SBIN|TOYFLAG_NEEDROOT)) 8 | 9 | config REBOOT 10 | bool "reboot" 11 | default y 12 | help 13 | usage: reboot/halt/poweroff [-fn] 14 | 15 | Restart, halt or powerdown the system. 16 | 17 | -f Don't signal init 18 | -n Don't sync before stopping the system. 19 | */ 20 | 21 | #define FOR_reboot 22 | #include "toys.h" 23 | #include 24 | 25 | void reboot_main(void) 26 | { 27 | int types[] = {RB_AUTOBOOT, RB_HALT_SYSTEM, RB_POWER_OFF}, 28 | sigs[] = {SIGTERM, SIGUSR1, SIGUSR2}, idx; 29 | 30 | if (!(toys.optflags & FLAG_n)) sync(); 31 | 32 | idx = stridx("hp", *toys.which->name)+1; 33 | if (toys.optflags & FLAG_f) toys.exitval = reboot(types[idx]); 34 | else toys.exitval = kill(1, sigs[idx]); 35 | } 36 | -------------------------------------------------------------------------------- /toys/other/chvt.c: -------------------------------------------------------------------------------- 1 | /* chvt.c - switch virtual terminals 2 | * 3 | * Copyright (C) 2008 David Anders 4 | 5 | USE_CHVT(NEWTOY(chvt, "<1", TOYFLAG_USR|TOYFLAG_BIN)) 6 | 7 | config CHVT 8 | bool "chvt" 9 | default y 10 | help 11 | usage: chvt N 12 | 13 | Change to virtual terminal number N. (This only works in text mode.) 14 | 15 | Virtual terminals are the Linux VGA text mode displays, ordinarily 16 | switched between via alt-F1, alt-F2, etc. Use ctrl-alt-F1 to switch 17 | from X to a virtual terminal, and alt-F6 (or F7, or F8) to get back. 18 | */ 19 | 20 | #include "toys.h" 21 | 22 | void chvt_main(void) 23 | { 24 | int vtnum, fd = fd; 25 | char *consoles[]={"/dev/console", "/dev/vc/0", "/dev/tty", NULL}, **cc; 26 | 27 | vtnum=atoi(*toys.optargs); 28 | for (cc = consoles; *cc; cc++) 29 | if (-1 != (fd = open(*cc, O_RDWR))) break; 30 | 31 | // These numbers are VT_ACTIVATE and VT_WAITACTIVE from linux/vt.h 32 | if (!*cc || fd < 0 || ioctl(fd, 0x5606, vtnum) || ioctl(fd, 0x5607, vtnum)) 33 | perror_exit(0); 34 | } 35 | -------------------------------------------------------------------------------- /tests/zcat.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2014 Divya Kothari 4 | # Copyright 2014 Naha Maggu 5 | 6 | [ -f testing.sh ] && . testing.sh 7 | 8 | #testing "name" "command" "result" "infile" "stdin" 9 | echo "hello" > file 10 | tar -czf file.gz file 11 | # Get system zcat 12 | zcatExe=`which zcat` 13 | $zcatExe file.gz > zcatOut 14 | testing "- decompresses a single file" "zcat file.gz > Tempfile && echo "yes"; diff Tempfile zcatOut && echo "yes"; rm -rf file* zcatOut Tempfile" "yes\nyes\n" "" "" 15 | 16 | #testing "name" "command" "result" "infile" "stdin" 17 | echo "hello" > file1 18 | echo "hi" > file2 19 | echo "Hi, Good morning !! I am a bzcat tester" > file3 20 | tar -czf file1.gz file1 21 | tar -czf file2.gz file2 22 | tar -czf file3.gz file3 23 | # Get system zcat 24 | zcatExe=`which zcat` 25 | $zcatExe file1.gz file2.gz file3.gz > zcatOut 26 | testing "- decompresses multiple files" "zcat file1.gz file2.gz file3.gz > Tempfile && echo "yes" ; diff Tempfile zcatOut && echo "yes"; rm -rf file* zcatOut Tempfile " "yes\nyes\n" "" "" 27 | -------------------------------------------------------------------------------- /toys/other/printenv.c: -------------------------------------------------------------------------------- 1 | /* printenv.c - Print environment variables. 2 | * 3 | * Copyright 2012 Georgi Chorbadzhiyski 4 | 5 | USE_PRINTENV(NEWTOY(printenv, "0(null)", TOYFLAG_USR|TOYFLAG_BIN)) 6 | 7 | config PRINTENV 8 | bool "printenv" 9 | default y 10 | help 11 | usage: printenv [-0] [env_var...] 12 | 13 | Print environment variables. 14 | 15 | -0 Use \0 as delimiter instead of \n 16 | */ 17 | 18 | #include "toys.h" 19 | 20 | extern char **environ; 21 | 22 | void printenv_main(void) 23 | { 24 | char **env, **var = toys.optargs; 25 | char delim = '\n'; 26 | 27 | if (toys.optflags) delim = 0; 28 | 29 | do { 30 | int catch = 0, len = *var ? strlen(*var) : 0; 31 | 32 | for (env = environ; *env; env++) { 33 | char *out = *env; 34 | if (*var) { 35 | if (!strncmp(out, *var, len) && out[len] == '=') out += len +1; 36 | else continue; 37 | } 38 | xprintf("%s%c", out, delim); 39 | catch++; 40 | } 41 | if (*var && !catch) toys.exitval = 1; 42 | } while (*var && *(++var)); 43 | } 44 | -------------------------------------------------------------------------------- /tests/xzcat.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2014 Divya Kothari 4 | # Copyright 2014 Naha Maggu 5 | 6 | [ -f testing.sh ] && . testing.sh 7 | 8 | #testing "name" "command" "result" "infile" "stdin" 9 | echo "hello" > file 10 | tar -cJf file.xz file 11 | # Get system xzcat 12 | xzcatExe=`which xzcat` 13 | $xzcatExe file.xz > xzcatOut 14 | testing "- decompresses a single file" "xzcat file.xz > Tempfile && echo "yes"; diff Tempfile xzcatOut && echo "yes"; rm -rf file* xzcatOut Tempfile" "yes\nyes\n" "" "" 15 | 16 | #testing "name" "command" "result" "infile" "stdin" 17 | echo "hello" > file1 18 | echo "hi" > file2 19 | echo "Hi, Good morning !! I am a xzcat tester" > file3 20 | tar -cJf file1.xz file1 21 | tar -cJf file2.xz file2 22 | tar -cJf file3.xz file3 23 | # Get system xzcat 24 | xzcatExe=`which xzcat` 25 | $xzcatExe file1.xz file2.xz file3.xz > xzcatOut 26 | testing "- decompresses multiple files" "xzcat file1.xz file2.xz file3.xz > Tempfile && echo "yes" ; diff Tempfile xzcatOut && echo "yes"; rm -rf file* xzcatOut Tempfile " "yes\nyes\n" "" "" 27 | -------------------------------------------------------------------------------- /lib/toyflags.h: -------------------------------------------------------------------------------- 1 | /* Flags values for the third argument of NEWTOY() 2 | * 3 | * Included from both main.c (runs in toys.h context) and scripts/install.c 4 | * (which may build on crazy things like macosx when cross compiling). 5 | */ 6 | 7 | // Flags describing command behavior. 8 | 9 | #define TOYFLAG_USR (1<<0) 10 | #define TOYFLAG_BIN (1<<1) 11 | #define TOYFLAG_SBIN (1<<2) 12 | #define TOYMASK_LOCATION ((1<<4)-1) 13 | 14 | // This is a shell built-in function, running in the same process context. 15 | #define TOYFLAG_NOFORK (1<<4) 16 | 17 | // Start command with a umask of 0 (saves old umask in this.old_umask) 18 | #define TOYFLAG_UMASK (1<<5) 19 | 20 | // This command runs as root. 21 | #define TOYFLAG_STAYROOT (1<<6) 22 | #define TOYFLAG_NEEDROOT (1<<7) 23 | #define TOYFLAG_ROOTONLY (TOYFLAG_STAYROOT|TOYFLAG_NEEDROOT) 24 | 25 | // Call setlocale to listen to environment variables. 26 | // This invalidates sprintf("%.*s", size, string) as a valid length constraint. 27 | #define TOYFLAG_LOCALE (1<<8) 28 | 29 | // Suppress default --help processing 30 | #define TOYFLAG_NOHELP (1<<9) 31 | -------------------------------------------------------------------------------- /toys/posix/nice.c: -------------------------------------------------------------------------------- 1 | /* nice.c - Run a program at a different niceness level. 2 | * 3 | * Copyright 2010 Rob Landley 4 | * 5 | * See http://opengroup.org/onlinepubs/9699919799/utilities/nice.html 6 | 7 | USE_NICE(NEWTOY(nice, "^<1n#", TOYFLAG_USR|TOYFLAG_BIN)) 8 | 9 | config NICE 10 | bool "nice" 11 | default y 12 | help 13 | usage: nice [-n PRIORITY] command [args...] 14 | 15 | Run a command line at an increased or decreased scheduling priority. 16 | 17 | Higher numbers make a program yield more CPU time, from -20 (highest 18 | priority) to 19 (lowest). By default processes inherit their parent's 19 | niceness (usually 0). By default this command adds 10 to the parent's 20 | priority. Only root can set a negative niceness level. 21 | */ 22 | 23 | #define FOR_nice 24 | #include "toys.h" 25 | 26 | GLOBALS( 27 | long priority; 28 | ) 29 | 30 | void nice_main(void) 31 | { 32 | if (!toys.optflags) TT.priority = 10; 33 | 34 | errno = 0; 35 | if (nice(TT.priority)==-1 && errno) perror_exit("Can't set priority"); 36 | 37 | xexec(toys.optargs); 38 | } 39 | -------------------------------------------------------------------------------- /toys/posix/nohup.c: -------------------------------------------------------------------------------- 1 | /* nohup.c - run commandline with SIGHUP blocked. 2 | * 3 | * Copyright 2011 Rob Landley 4 | * 5 | * See http://opengroup.org/onlinepubs/9699919799/utilities/nohup.html 6 | 7 | USE_NOHUP(NEWTOY(nohup, "<1^", TOYFLAG_USR|TOYFLAG_BIN)) 8 | 9 | config NOHUP 10 | bool "nohup" 11 | default y 12 | help 13 | usage: nohup COMMAND [ARGS...] 14 | 15 | Run a command that survives the end of its terminal. 16 | 17 | Redirect tty on stdin to /dev/null, tty on stdout to "nohup.out". 18 | */ 19 | 20 | #include "toys.h" 21 | 22 | void nohup_main(void) 23 | { 24 | xsignal(SIGHUP, SIG_IGN); 25 | if (isatty(1)) { 26 | close(1); 27 | if (-1 == open("nohup.out", O_CREAT|O_APPEND|O_WRONLY, 28 | S_IRUSR|S_IWUSR )) 29 | { 30 | char *temp = getenv("HOME"); 31 | 32 | temp = xmprintf("%s/%s", temp ? temp : "", "nohup.out"); 33 | xcreate(temp, O_CREAT|O_APPEND|O_WRONLY, 0600); 34 | free(temp); 35 | } 36 | } 37 | if (isatty(0)) { 38 | close(0); 39 | xopen_stdio("/dev/null", O_RDONLY); 40 | } 41 | xexec(toys.optargs); 42 | } 43 | -------------------------------------------------------------------------------- /toys/lsb/pidof.c: -------------------------------------------------------------------------------- 1 | /* pidof.c - Print the Process IDs of all processes with the given names. 2 | * 3 | * Copyright 2012 Andreas Heck 4 | * Copyright 2012 Elie De Brauwer 5 | * 6 | * http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/pidof.html 7 | 8 | USE_PIDOF(NEWTOY(pidof, "<1so:", TOYFLAG_BIN)) 9 | 10 | config PIDOF 11 | bool "pidof" 12 | default y 13 | help 14 | usage: pidof [-s] [-o omitpid[,omitpid...]] [NAME]... 15 | 16 | Print the PIDs of all processes with the given names. 17 | 18 | -s single shot, only return one pid. 19 | -o omit PID(s) 20 | */ 21 | 22 | #define FOR_pidof 23 | #include "toys.h" 24 | 25 | GLOBALS( 26 | char *omit; 27 | ) 28 | 29 | static int print_pid(pid_t pid, char *name) 30 | { 31 | sprintf(toybuf, "%d", (int)pid); 32 | if (comma_scan(TT.omit, toybuf, 0)) return 0; 33 | xprintf(" %s"+!!toys.exitval, toybuf); 34 | toys.exitval = 0; 35 | 36 | return toys.optflags & FLAG_s; 37 | } 38 | 39 | void pidof_main(void) 40 | { 41 | toys.exitval = 1; 42 | names_to_pid(toys.optargs, print_pid); 43 | if (!toys.exitval) xputc('\n'); 44 | } 45 | -------------------------------------------------------------------------------- /toys/posix/env.c: -------------------------------------------------------------------------------- 1 | /* env.c - Set the environment for command invocation. 2 | * 3 | * Copyright 2012 Tryn Mirell 4 | * 5 | * http://opengroup.org/onlinepubs/9699919799/utilities/env.html 6 | 7 | USE_ENV(NEWTOY(env, "^iu*", TOYFLAG_USR|TOYFLAG_BIN)) 8 | 9 | config ENV 10 | bool "env" 11 | default y 12 | help 13 | usage: env [-i] [-u NAME] [NAME=VALUE...] [command [option...]] 14 | 15 | Set the environment for command invocation. 16 | 17 | -i Clear existing environment. 18 | -u NAME Remove NAME from the environment 19 | */ 20 | 21 | #define FOR_env 22 | #include "toys.h" 23 | 24 | GLOBALS( 25 | struct arg_list *u; 26 | ); 27 | 28 | extern char **environ; 29 | 30 | void env_main(void) 31 | { 32 | char **ev; 33 | 34 | if (toys.optflags & FLAG_i) clearenv(); 35 | while (TT.u) { 36 | unsetenv(TT.u->arg); 37 | TT.u = TT.u->next; 38 | } 39 | 40 | for (ev = toys.optargs; *ev; ev++) { 41 | char *name = *ev, *val = strchr(name, '='); 42 | 43 | if (val) { 44 | *(val++) = 0; 45 | setenv(name, val, 1); 46 | } else xexec(ev); 47 | } 48 | 49 | if (environ) for (ev = environ; *ev; ev++) xputs(*ev); 50 | } 51 | -------------------------------------------------------------------------------- /tests/cat.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | echo "one" > file1 8 | echo "two" > file2 9 | testing "cat" "cat && echo yes" "oneyes\n" "" "one" 10 | testing "-" "cat - && echo yes" "oneyes\n" "" "one" 11 | testing "file1 file2" "cat file1 file2" "one\ntwo\n" "" "" 12 | testing "- file" "cat - file1" "zero\none\n" "" "zero\n" 13 | testing "file -" "cat file1 -" "one\nzero\n" "" "zero\n" 14 | 15 | testing "file1 notfound file2" \ 16 | "cat file1 notfound file2 2>stderr && echo ok ; cat stderr; rm stderr" \ 17 | "one\ntwo\ncat: notfound: No such file or directory\n" "" "" 18 | 19 | FILE="$(readlink -f /proc/self/exe)" 20 | testing "file1" \ 21 | 'cat "$FILE" > file1 && cmp "$FILE" file1 && echo yes' \ 22 | "yes\n" "" "" 23 | 24 | testing "- file1" \ 25 | "cat - file1 | diff -a -U 0 - file1 | tail -n 1" \ 26 | "-hello\n" "" "hello\n" 27 | 28 | testing "> /dev/full" \ 29 | "cat - > /dev/full 2>stderr && echo ok; cat stderr; rm stderr" \ 30 | "cat: xwrite: No space left on device\n" "" "zero\n" 31 | 32 | rm file1 file2 33 | -------------------------------------------------------------------------------- /tests/uudecode.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | testing "uu empty file" "uudecode -o /dev/stdout && echo yes" \ 8 | "yes\n" "" "begin 744 test\n\`\nend\n" 9 | testing "uu 1-char" "uudecode -o /dev/stdout" "a" "" \ 10 | "begin 744 test\n!80 \n\`\nend\n" 11 | testing "uu 2-char" "uudecode -o /dev/stdout" "ab" "" \ 12 | "begin 744 test\n\"86( \n\`\nend\n" 13 | testing "uu 3-char" "uudecode -o /dev/stdout" "abc" "" \ 14 | "begin 744 test\n#86)C\n\`\nend\n" 15 | 16 | testing "b64 empty file" "uudecode -o /dev/stdout && echo yes" \ 17 | "yes\n" "" "begin-base64 744 test\n====\n" 18 | testing "b64 1-char" "uudecode -o /dev/stdout" "a" "" \ 19 | "begin-base64 744 test\nYQ==\n====\n" 20 | testing "b64 2-char" "uudecode -o /dev/stdout" "ab" "" \ 21 | "begin-base64 744 test\nYWI=\n====\n" 22 | testing "b64 3-char" "uudecode -o /dev/stdout" "abc" "" \ 23 | "begin-base64 744 test\nYWJj\n====\n" 24 | 25 | testing "filename" "uudecode && echo -ne 'abc' | cmp uudecode-fn-test /dev/stdin && echo -ne yes && rm uudecode-fn-test" \ 26 | "yes" "" "begin-base64 744 uudecode-fn-test\nYWJj\n====\n" 27 | 28 | -------------------------------------------------------------------------------- /toys/pending/vi.c: -------------------------------------------------------------------------------- 1 | /* vi.c - You can't spell "evil" without "vi". 2 | * 3 | * Copyright 2015 Rob Landley 4 | * 5 | * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/vi.html 6 | 7 | USE_VI(NEWTOY(vi, "<1>1", TOYFLAG_USR|TOYFLAG_BIN)) 8 | 9 | config VI 10 | bool "vi" 11 | default n 12 | help 13 | usage: vi FILE 14 | 15 | Visual text editor. Predates the existence of standardized cursor keys, 16 | so the controls are weird and historical. 17 | */ 18 | 19 | #define FOR_vi 20 | #include "toys.h" 21 | 22 | GLOBALS( 23 | struct linestack *ls; 24 | char *statline; 25 | ) 26 | 27 | struct linestack_show { 28 | struct linestack_show *next; 29 | long top, left; 30 | int x, width, y, height; 31 | }; 32 | 33 | // linestack, what to show, where to show it 34 | void linestack_show(struct linestack *ls, struct linestack_show *lss) 35 | { 36 | return; 37 | } 38 | 39 | void vi_main(void) 40 | { 41 | int i; 42 | 43 | if (!(TT.ls = linestack_load(*toys.optargs))) 44 | TT.ls = xzalloc(sizeof(struct linestack)); 45 | 46 | for (i=0; ilen; i++) 47 | printf("%.*s\n", (int)TT.ls->idx[i].len, (char *)TT.ls->idx[i].ptr); 48 | } 49 | -------------------------------------------------------------------------------- /toys/posix/mkfifo.c: -------------------------------------------------------------------------------- 1 | /* mkfifo.c - Create FIFOs (named pipes) 2 | * 3 | * Copyright 2012 Georgi Chorbadzhiyski 4 | * 5 | * See http://opengroup.org/onlinepubs/9699919799/utilities/mkfifo.html 6 | 7 | USE_MKFIFO(NEWTOY(mkfifo, "<1"USE_MKFIFO_Z("Z:")"m:", TOYFLAG_USR|TOYFLAG_BIN)) 8 | 9 | config MKFIFO 10 | bool "mkfifo" 11 | default y 12 | help 13 | usage: mkfifo [NAME...] 14 | 15 | Create FIFOs (named pipes). 16 | 17 | config MKFIFO_Z 18 | bool 19 | default y 20 | depends on MKFIFO && !TOYBOX_LSM_NONE 21 | help 22 | usage: mkfifo [-Z CONTEXT] 23 | 24 | -Z Security context 25 | */ 26 | 27 | #define FOR_mkfifo 28 | #include "toys.h" 29 | 30 | GLOBALS( 31 | char *m_string; 32 | char *Z; 33 | 34 | mode_t mode; 35 | ) 36 | 37 | void mkfifo_main(void) 38 | { 39 | char **s; 40 | 41 | TT.mode = 0666; 42 | if (toys.optflags & FLAG_m) TT.mode = string_to_mode(TT.m_string, 0); 43 | 44 | if (CFG_MKFIFO_Z && (toys.optflags&FLAG_Z)) 45 | if (0>lsm_set_create(TT.Z)) 46 | perror_exit("-Z '%s' failed", TT.Z); 47 | 48 | for (s = toys.optargs; *s; s++) 49 | if (mknod(*s, S_IFIFO | TT.mode, 0) < 0) perror_msg_raw(*s); 50 | } 51 | -------------------------------------------------------------------------------- /tests/truncate.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | SIZE='&& stat -c %s freep' 8 | testing "0" "truncate -s 0 freep $SIZE" "0\n" "" "" 9 | testing "12345" "truncate -s 12345 freep $SIZE" "12345\n" "" "" 10 | testing "1m" "truncate -s 1m freep $SIZE" "1048576\n" "" "" 11 | testing "is sparse" "truncate -s 1g freep && stat -c %b freep" \ 12 | "0\n" "" "" 13 | testing "+" "truncate -s 1k freep && truncate -s +1k freep $SIZE" \ 14 | "2048\n" "" "" 15 | testing "-" "truncate -s 4k freep && truncate -s -1k freep $SIZE" \ 16 | "3072\n" "" "" 17 | testing "< hit" \ 18 | "truncate -s 5k freep && truncate -s \<4k freep $SIZE" "4096\n" "" "" 19 | testing "< miss" \ 20 | "truncate -s 4k freep && truncate -s \<6k freep $SIZE" "4096\n" "" "" 21 | testing "> hit" \ 22 | "truncate -s 3k freep && truncate -s \>4k freep $SIZE" "4096\n" "" "" 23 | testing "> miss" \ 24 | "truncate -s 4k freep && truncate -s \>2k freep $SIZE" "4096\n" "" "" 25 | testing "/" "truncate -s 7k freep && truncate -s /3k freep $SIZE" \ 26 | "6144\n" "" "" 27 | testing "%" "truncate -s 7k freep && truncate -s %3k freep $SIZE" \ 28 | "9216\n" "" "" 29 | -------------------------------------------------------------------------------- /toys/other/setfattr.c: -------------------------------------------------------------------------------- 1 | /* setfattr.c - Write POSIX extended attributes. 2 | * 3 | * Copyright 2016 Android Open Source Project. 4 | * 5 | * No standard 6 | 7 | USE_SETFATTR(NEWTOY(setfattr, "hn:|v:x:|[!xv]", TOYFLAG_USR|TOYFLAG_BIN)) 8 | 9 | config SETFATTR 10 | bool "setfattr" 11 | default y 12 | help 13 | usage: setfattr [-h] [-x|-n NAME] [-v VALUE] FILE... 14 | 15 | Write POSIX extended attributes. 16 | 17 | -h Do not dereference symlink. 18 | -n Set given attribute. 19 | -x Remove given attribute. 20 | -v Set value for attribute -n (default is empty). 21 | */ 22 | 23 | #define FOR_setfattr 24 | #include "toys.h" 25 | 26 | GLOBALS( 27 | char *x, *v, *n; 28 | ) 29 | 30 | static void do_setfattr(char *file) 31 | { 32 | int h = toys.optflags & FLAG_h; 33 | 34 | if (toys.optflags&FLAG_x) { 35 | if ((h ? lremovexattr : removexattr)(file, TT.x)) 36 | perror_msg("removexattr failed"); 37 | } else 38 | if ((h ? lsetxattr : setxattr)(file, TT.n, TT.v, TT.v?strlen(TT.v):0, 0)) 39 | perror_msg("setxattr failed"); 40 | } 41 | 42 | void setfattr_main(void) 43 | { 44 | char **s; 45 | 46 | for (s=toys.optargs; *s; s++) do_setfattr(*s); 47 | } 48 | -------------------------------------------------------------------------------- /toys/other/rmmod.c: -------------------------------------------------------------------------------- 1 | /* rmmod.c - Remove a module from the Linux kernel. 2 | * 3 | * Copyright 2012 Elie De Brauwer 4 | 5 | USE_RMMOD(NEWTOY(rmmod, "<1wf", TOYFLAG_SBIN|TOYFLAG_NEEDROOT)) 6 | 7 | config RMMOD 8 | bool "rmmod" 9 | default y 10 | help 11 | usage: rmmod [-wf] [MODULE] 12 | 13 | Unload the module named MODULE from the Linux kernel. 14 | -f Force unload of a module 15 | -w Wait until the module is no longer used. 16 | 17 | */ 18 | 19 | #define FOR_rmmod 20 | #include "toys.h" 21 | 22 | #include 23 | #define delete_module(mod, flags) syscall(__NR_delete_module, mod, flags) 24 | 25 | void rmmod_main(void) 26 | { 27 | unsigned int flags = O_NONBLOCK|O_EXCL; 28 | char * mod_name; 29 | int len; 30 | 31 | // Basename 32 | mod_name = basename(*toys.optargs); 33 | 34 | // Remove .ko if present 35 | len = strlen(mod_name); 36 | if (len > 3 && !strcmp(&mod_name[len-3], ".ko" )) mod_name[len-3] = 0; 37 | 38 | if (toys.optflags & FLAG_f) flags |= O_TRUNC; 39 | if (toys.optflags & FLAG_w) flags &= ~O_NONBLOCK; 40 | 41 | if (delete_module(mod_name, flags)) 42 | perror_exit("failed to unload %s", mod_name); 43 | } 44 | -------------------------------------------------------------------------------- /tests/file.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | touch empty 8 | echo "#!/bin/bash" > bash.script 9 | echo "#! /bin/bash" > bash.script2 10 | echo "#! /usr/bin/env python" > env.python.script 11 | echo "Hello, world!" > ascii 12 | echo "cafebabe000000310000" | xxd -r -p > java.class 13 | ln -s java.class symlink 14 | 15 | testing "empty" "file empty" "empty: empty\n" "" "" 16 | testing "bash.script" "file bash.script" "bash.script: /bin/bash script\n" "" "" 17 | testing "bash.script with spaces" "file bash.script2" "bash.script2: /bin/bash script\n" "" "" 18 | testing "env python script" "file env.python.script" "env.python.script: python script\n" "" "" 19 | testing "ascii" "file ascii" "ascii: ASCII text\n" "" "" 20 | testing "java class" "file java.class" "java.class: Java class file, version 49.0\n" "" "" 21 | testing "symlink" "file symlink" "symlink: symbolic link\n" "" "" 22 | testing "symlink -h" "file -h symlink" "symlink: symbolic link\n" "" "" 23 | testing "symlink -L" "file -L symlink" "symlink: Java class file, version 49.0\n" "" "" 24 | 25 | rm empty bash.script bash.script2 env.python.script ascii java.class 26 | -------------------------------------------------------------------------------- /tests/tac.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | 8 | echo -e "one-A\none-B" > file1 9 | echo -e "two-A\ntwo-B" > file2 10 | testing "tac" "tac && echo yes" "one-B\none-A\nyes\n" "" "one-A\none-B\n" 11 | testing "-" "tac - && echo yes" "one-B\none-A\nyes\n" "" "one-A\none-B\n" 12 | testing "file1 file2" "tac file1 file2" "one-B\none-A\ntwo-B\ntwo-A\n" "" "" 13 | testing "- file" "tac - file1" "zero-B\nzero-A\none-B\none-A\n" "" "zero-A\nzero-B\n" 14 | testing "file -" "tac file1 -" "one-B\none-A\nzero-B\nzero-A\n" "" "zero-A\nzero-B\n" 15 | 16 | testing "file1 notfound file2" \ 17 | "tac file1 notfound file2 2>stderr && echo ok ; tac stderr; rm stderr" \ 18 | "one-B\none-A\ntwo-B\ntwo-A\ntac: notfound: No such file or directory\n" "" "" 19 | 20 | testing "no trailing newline" "tac -" "defabc\n" "" "abc\ndef" 21 | 22 | # xputs used by tac does not propagate this error condition properly. 23 | #testing "> /dev/full" \ 24 | # "tac - > /dev/full 2>stderr && echo ok; cat stderr; rm stderr" \ 25 | # "tac: write: No space left on device\n" "" "zero\n" 26 | 27 | # 28 | 29 | rm file1 file2 -------------------------------------------------------------------------------- /toys/other/readlink.c: -------------------------------------------------------------------------------- 1 | /* readlink.c - Return string representation of a symbolic link. 2 | * 3 | * Copyright 2007 Rob Landley 4 | 5 | USE_READLINK(NEWTOY(readlink, "<1>1fenq[-fe]", TOYFLAG_USR|TOYFLAG_BIN)) 6 | 7 | config READLINK 8 | bool "readlink" 9 | default y 10 | help 11 | usage: readlink FILE 12 | 13 | With no options, show what symlink points to, return error if not symlink. 14 | 15 | Options for producing cannonical paths (all symlinks/./.. resolved): 16 | 17 | -e cannonical path to existing entry (fail if missing) 18 | -f full path (fail if directory missing) 19 | -n no trailing newline 20 | -q quiet (no output, just error code) 21 | */ 22 | 23 | #define FOR_readlink 24 | #include "toys.h" 25 | 26 | void readlink_main(void) 27 | { 28 | char *s; 29 | 30 | // Calculating full cannonical path? 31 | 32 | if (toys.optflags & (FLAG_f|FLAG_e)) 33 | s = xabspath(*toys.optargs, toys.optflags & FLAG_e); 34 | else s = xreadlink(*toys.optargs); 35 | 36 | if (s) { 37 | if (!(toys.optflags & FLAG_q)) 38 | xprintf((toys.optflags & FLAG_n) ? "%s" : "%s\n", s); 39 | if (CFG_TOYBOX_FREE) free(s); 40 | } else toys.exitval = 1; 41 | } 42 | -------------------------------------------------------------------------------- /toys/other/chcon.c: -------------------------------------------------------------------------------- 1 | /* chcon.c - Change file security context 2 | * 3 | * Copyright 2014 The Android Open Source Project 4 | 5 | USE_CHCON(NEWTOY(chcon, "<2hvR", TOYFLAG_USR|TOYFLAG_BIN)) 6 | 7 | config CHCON 8 | bool "chcon" 9 | depends on TOYBOX_SELINUX 10 | default y 11 | help 12 | usage: chcon [-hRv] CONTEXT FILE... 13 | 14 | Change the SELinux security context of listed file[s]. 15 | 16 | -h change symlinks instead of what they point to. 17 | -R recurse into subdirectories. 18 | -v verbose output. 19 | */ 20 | 21 | #define FOR_chcon 22 | #include "toys.h" 23 | 24 | static int do_chcon(struct dirtree *try) 25 | { 26 | char *path, *con = *toys.optargs; 27 | 28 | if (!dirtree_notdotdot(try)) return 0; 29 | 30 | path = dirtree_path(try, 0); 31 | if (toys.optflags & FLAG_v) printf("chcon '%s' to %s\n", path, con); 32 | if (-1 == ((toys.optflags & FLAG_h) ? lsetfilecon : setfilecon)(path, con)) 33 | perror_msg("'%s' to %s", path, con); 34 | free(path); 35 | 36 | return (toys.optflags & FLAG_R)*DIRTREE_RECURSE; 37 | } 38 | 39 | void chcon_main(void) 40 | { 41 | char **file; 42 | 43 | for (file = toys.optargs+1; *file; file++) dirtree_read(*file, do_chcon); 44 | } 45 | -------------------------------------------------------------------------------- /tests/chown.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | if [ "$(id -u)" -ne 0 ] 6 | then 7 | echo "$SHOWSKIP: chown (not root)" 8 | continue 2>/dev/null 9 | exit 10 | fi 11 | 12 | # We chown between user "root" and the last user in /etc/passwd, 13 | # and group "root" and the last group in /etc/group. 14 | 15 | USR="$(sed -n '$s/:.*//p' /etc/passwd)" 16 | GRP="$(sed -n '$s/:.*//p' /etc/group)" 17 | 18 | # Set up a little testing hierarchy 19 | 20 | rm -rf testdir && 21 | mkdir testdir && 22 | touch testdir/file 23 | F=testdir/file 24 | 25 | # Wrapper to reset groups and return results 26 | 27 | OUT="&& echo \$(ls -l testdir/file | awk '{print \$3,\$4}')" 28 | 29 | #testing "name" "command" "result" "infile" "stdin" 30 | 31 | # Basic smoketest 32 | testing "initial" "chown root:root $F $OUT" "root root\n" "" "" 33 | testing "usr:grp" "chown $USR:$GRP $F $OUT" "$USR $GRP\n" "" "" 34 | testing "root" "chown root $F $OUT" "root $GRP\n" "" "" 35 | # TODO: can we test "owner:"? 36 | testing ":grp" "chown root:root $F && chown :$GRP $F $OUT" \ 37 | "root $GRP\n" "" "" 38 | testing ":" "chown $USR:$GRP $F && chown : $F $OUT" \ 39 | "$USR $GRP\n" "" "" 40 | 41 | rm -rf testdir 42 | -------------------------------------------------------------------------------- /toys/posix/renice.c: -------------------------------------------------------------------------------- 1 | /* renice.c - renice process 2 | * 3 | * Copyright 2013 CE Strake 4 | * 5 | * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/renice.html 6 | 7 | USE_RENICE(NEWTOY(renice, "<1gpun#|", TOYFLAG_USR|TOYFLAG_BIN)) 8 | 9 | config RENICE 10 | bool "renice" 11 | default y 12 | help 13 | usage: renice [-gpu] -n increment ID ... 14 | */ 15 | 16 | #define FOR_renice 17 | #include "toys.h" 18 | 19 | GLOBALS( 20 | long nArgu; 21 | ) 22 | 23 | void renice_main(void) { 24 | int which = (toys.optflags & FLAG_g) ? PRIO_PGRP : 25 | ((toys.optflags & FLAG_u) ? PRIO_USER : PRIO_PROCESS); 26 | char **arg; 27 | 28 | for (arg = toys.optargs; *arg; arg++) { 29 | char *s = *arg; 30 | int id = -1; 31 | 32 | if (toys.optflags & FLAG_u) { 33 | struct passwd *p = getpwnam(s); 34 | if (p) id = p->pw_uid; 35 | } else { 36 | id = strtol(s, &s, 10); 37 | if (*s) id = -1; 38 | } 39 | 40 | if (id < 0) { 41 | error_msg("bad '%s'", *arg); 42 | continue; 43 | } 44 | 45 | if (setpriority(which, id, getpriority(which, id)+TT.nArgu) < 0) 46 | perror_msg("setpriority %d", id); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /tests/groupdel.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2013 Divya Kothari 4 | # Copyright 2013 Robin Mittal 5 | 6 | [ -f testing.sh ] && . testing.sh 7 | 8 | # Redirecting all output to /dev/null for grep and delgroup 9 | arg="&>/dev/null" 10 | 11 | #testing "name" "command" "result" "infile" "stdin" 12 | 13 | testing "group_name (text)" "groupadd toyTestGroup && 14 | grep '^toyTestGroup:' /etc/group $arg && groupdel toyTestGroup $arg && 15 | echo 'yes'" "yes\n" "" "" 16 | testing "group_name (alphanumeric)" "groupadd toy1Test2Group3 && 17 | grep '^toy1Test2Group3:' /etc/group $arg && groupdel toy1Test2Group3 $arg && 18 | echo 'yes'" "yes\n" "" "" 19 | testing "group_name (numeric)" "groupadd 987654321 && 20 | grep '^987654321:' /etc/group $arg && groupdel 987654321 $arg && 21 | echo 'yes'" "yes\n" "" "" 22 | testing "group_name (with ./-)" "groupadd toy.1Test-2Group.3 && 23 | grep '^toy.1Test-2Group.3:' /etc/group $arg && 24 | groupdel toy.1Test-2Group.3 $arg && echo 'yes'" "yes\n" "" "" 25 | testing "group_name with group_id" "groupadd -g 49999 toyTestGroup && 26 | grep '^toyTestGroup:' /etc/group $arg && groupdel toyTestGroup $arg && 27 | echo 'yes'" "yes\n" "" "" 28 | -------------------------------------------------------------------------------- /tests/xargs.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | testing "xargs" "xargs && echo yes" "hello\nyes\n" "" "hello" 8 | testing "spaces" "xargs" \ 9 | "one two three four\n" "" "one two\tthree \nfour\n\n" 10 | 11 | testing "-n 0" "xargs -n 0 2>/dev/null || echo ok" "ok\n" \ 12 | "" "one \ntwo\n three" 13 | testing "-n 2" "xargs -n 2" "one two\nthree\n" "" "one \ntwo\n three" 14 | testing "-n exact match" "xargs -n 3" "one two three\n" "" "one two three" 15 | testing "xargs2" "xargs -n2" "one two\nthree four\nfive\n" "" \ 16 | "one two three four five" 17 | testing "-s too long" "xargs -s 9 echo 2>/dev/null || echo ok" \ 18 | "one\ntwo\nok\n" "" "one two three" 19 | testing "-s 13" "xargs -s 13 echo" "one two\nthree\n" "" "one \ntwo\n three" 20 | testing "-s 12" "xargs -s 12 echo" "one\ntwo\nthree\n" "" "one \ntwo\n three" 21 | 22 | touch one two three 23 | testing "command -opt" "xargs -n2 ls -1" "one\ntwo\nthree\n" "" \ 24 | "one two three" 25 | rm one two three 26 | 27 | #testing "-n exact match" 28 | #testing "-s exact match" 29 | #testing "-s 0" 30 | #testing "-s impossible" 31 | 32 | # xargs command_not_found - returns 127 33 | # xargs false - returns 1 34 | -------------------------------------------------------------------------------- /scripts/single.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Build a standalone toybox command 4 | 5 | if [ -z "$1" ] 6 | then 7 | echo "usage: single.sh command..." >&2 8 | exit 1 9 | fi 10 | 11 | # Harvest TOYBOX_* symbols from .config 12 | if [ ! -e .config ] 13 | then 14 | echo "Need .config for toybox global settings. Run defconfig/menuconfig." >&2 15 | exit 1 16 | fi 17 | 18 | export KCONFIG_CONFIG=.singleconfig 19 | for i in "$@" 20 | do 21 | echo -n "$i:" 22 | TOYFILE="$(egrep -l "TOY[(]($i)[ ,]" toys/*/*.c)" 23 | 24 | if [ -z "$TOYFILE" ] 25 | then 26 | echo "Unknown command '$i'" >&2 27 | exit 1 28 | fi 29 | 30 | # Enable stuff this command depends on 31 | DEPENDS="$(sed -n "/^config *$i"'$/,/^$/{s/^[ \t]*depends on //;T;s/[!][A-Z0-9_]*//g;s/ *&& */|/g;p}' $TOYFILE | xargs | tr ' ' '|')" 32 | 33 | NAME=$(echo $i | tr a-z- A-Z_) 34 | make allnoconfig > /dev/null && 35 | sed -ri -e '/CONFIG_TOYBOX/d' \ 36 | -e "s/# (CONFIG_($NAME|${NAME}_.*${DEPENDS:+|$DEPENDS})) is not set/\1=y/" \ 37 | "$KCONFIG_CONFIG" && 38 | echo "# CONFIG_TOYBOX is not set" >> "$KCONFIG_CONFIG" && 39 | grep "CONFIG_TOYBOX_" .config >> "$KCONFIG_CONFIG" && 40 | 41 | rm -f "$PREFIX$i" && 42 | OUTNAME="$PREFIX$i" scripts/make.sh || exit 1 43 | done 44 | -------------------------------------------------------------------------------- /scripts/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | TOPDIR="$PWD" 4 | FILES="$PWD"/tests/files 5 | 6 | trap 'kill $(jobs -p) 2>/dev/null; exit 1' INT 7 | 8 | rm -rf generated/testdir 9 | mkdir -p generated/testdir/testdir 10 | 11 | if [ -z "$TEST_HOST" ] 12 | then 13 | if [ $# -ne 0 ] 14 | then 15 | PREFIX=generated/testdir/ scripts/single.sh "$@" || exit 1 16 | else 17 | make install_flat PREFIX=generated/testdir || exit 1 18 | fi 19 | fi 20 | 21 | cd generated/testdir 22 | PATH="$PWD:$PATH" 23 | cd testdir 24 | export LC_COLLATE=C 25 | 26 | . "$TOPDIR"/scripts/runtest.sh 27 | [ -f "$TOPDIR/generated/config.h" ] && export OPTIONFLAGS=:$(echo $(sed -nr 's/^#define CFG_(.*) 1/\1/p' "$TOPDIR/generated/config.h") | sed 's/ /:/g') 28 | 29 | if [ $# -ne 0 ] 30 | then 31 | for i in "$@" 32 | do 33 | CMDNAME="${i##*/}" 34 | CMDNAME="${CMDNAME%.test}" 35 | . "$TOPDIR"/tests/$i.test 36 | done 37 | else 38 | for i in "$TOPDIR"/tests/*.test 39 | do 40 | CMDNAME="${i##*/}" 41 | CMDNAME="${CMDNAME%.test}" 42 | if [ -h ../$CMDNAME ] || [ ! -z "$TEST_HOST" ] 43 | then 44 | cd .. && rm -rf testdir && mkdir testdir && cd testdir || exit 1 45 | . $i 46 | else 47 | echo "$CMDNAME disabled" 48 | fi 49 | done 50 | fi 51 | -------------------------------------------------------------------------------- /toys/posix/who.c: -------------------------------------------------------------------------------- 1 | /* who.c - display who is on the system 2 | * 3 | * Copyright 2012 ProFUSION Embedded Systems 4 | * 5 | * by Luis Felipe Strano Moraes 6 | * 7 | * See http://opengroup.org/onlinepubs/9699919799/utilities/who.html 8 | * 9 | * Posix says to support many options (-abdHlmpqrstTu) but this 10 | * isn't aimed at minicomputers with modem pools. 11 | 12 | USE_WHO(NEWTOY(who, "a", TOYFLAG_USR|TOYFLAG_BIN)) 13 | 14 | config WHO 15 | bool "who" 16 | default y 17 | depends on TOYBOX_UTMPX 18 | help 19 | usage: who 20 | 21 | Print logged user information on system 22 | */ 23 | 24 | #define FOR_who 25 | #include "toys.h" 26 | 27 | void who_main(void) 28 | { 29 | struct utmpx *entry; 30 | 31 | setutxent(); 32 | 33 | while ((entry = getutxent())) { 34 | if ((toys.optflags & FLAG_a) || entry->ut_type == USER_PROCESS) { 35 | time_t time; 36 | int time_size; 37 | char *times; 38 | 39 | time = entry->ut_tv.tv_sec; 40 | times = ctime(&time); 41 | time_size = strlen(times) - 2; 42 | printf("%s\t%s\t%*.*s\t(%s)\n", entry->ut_user, entry->ut_line, 43 | time_size, time_size, ctime(&time), entry->ut_host); 44 | } 45 | } 46 | 47 | endutxent(); 48 | } 49 | -------------------------------------------------------------------------------- /toys/other/lsusb.c: -------------------------------------------------------------------------------- 1 | /* lsusb.c - list available USB devices 2 | * 3 | * Copyright 2013 Andre Renaud 4 | 5 | USE_LSUSB(NEWTOY(lsusb, NULL, TOYFLAG_USR|TOYFLAG_BIN)) 6 | 7 | config LSUSB 8 | bool "lsusb" 9 | default y 10 | help 11 | usage: lsusb 12 | 13 | List USB hosts/devices. 14 | */ 15 | 16 | #include "toys.h" 17 | 18 | static int list_device(struct dirtree *new) 19 | { 20 | FILE *file; 21 | char *name; 22 | int busnum = 0, devnum = 0, pid = 0, vid = 0; 23 | 24 | if (!new->parent) return DIRTREE_RECURSE; 25 | if (new->name[0] == '.') return 0; 26 | name = dirtree_path(new, 0); 27 | snprintf(toybuf, sizeof(toybuf), "%s/%s", name, "/uevent"); 28 | file = fopen(toybuf, "r"); 29 | if (file) { 30 | int count = 0; 31 | 32 | while (fgets(toybuf, sizeof(toybuf), file)) 33 | if (sscanf(toybuf, "BUSNUM=%u\n", &busnum) 34 | || sscanf(toybuf, "DEVNUM=%u\n", &devnum) 35 | || sscanf(toybuf, "PRODUCT=%x/%x/", &pid, &vid)) count++; 36 | 37 | if (count == 3) 38 | printf("Bus %03d Device %03d: ID %04x:%04x\n", busnum, devnum, pid, vid); 39 | fclose(file); 40 | } 41 | free(name); 42 | 43 | return 0; 44 | } 45 | 46 | void lsusb_main(void) 47 | { 48 | dirtree_read("/sys/bus/usb/devices/", list_device); 49 | } 50 | -------------------------------------------------------------------------------- /tests/date.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | # Test Unix date parsing. 8 | testing "-d @0" "TZ=UTC date -d @0 2>&1" "Thu Jan 1 00:00:00 GMT 1970\n" "" "" 9 | testing "-d @0x123" "TZ=UTC date -d @0x123 2>&1" "date: bad date '@0x123'\n" "" "" 10 | 11 | # Test basic date parsing. 12 | # Note that toybox's -d format is not the same as coreutils'. 13 | testing "-d 06021234" "TZ=UTC date -d 06021234 2>&1" "Sun Jun 2 12:34:00 UTC 1900\n" "" "" 14 | testing "-d 060212341982" "TZ=UTC date -d 060212341982 2>&1" "Sun Jun 2 12:34:00 UTC 1982\n" "" "" 15 | testing "-d 123" "TZ=UTC date -d 123 2>&1" "date: bad date '123'\n" "" "" 16 | 17 | # Test parsing 2- and 4-digit years. 18 | testing "-d 1110143115.30" "TZ=UTC date -d 1110143115.30 2>&1" "Sun Nov 10 14:31:30 UTC 1915\n" "" "" 19 | testing "-d 111014312015.30" "TZ=UTC date -d 111014312015.30 2>&1" "Sun Nov 10 14:31:30 UTC 2015\n" "" "" 20 | 21 | # Accidentally given a Unix time, we should trivially reject that. 22 | testing "Unix time missing @" "TZ=UTC date 1438053157 2>/dev/null || echo no" \ 23 | "no\n" "" "" 24 | # But some invalid dates are more subtle, like Febuary 29th in a non-leap year. 25 | testing "Feb 29th" "TZ=UTC date 022900001975 2>/dev/null || echo no" \ 26 | "no\n" "" "" 27 | -------------------------------------------------------------------------------- /tests/pgrep.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2013 Divya Kothari 4 | # Copyright 2013 Robin Mittal 5 | 6 | #cleaning 'yes' processes 7 | killall yes >/dev/null 2>&1 8 | 9 | [ -f testing.sh ] && . testing.sh 10 | 11 | #testing "name" "command" "result" "infile" "stdin" 12 | 13 | # Starting processes to test pgrep command 14 | yes >/dev/null & 15 | proc=$! 16 | #echo "# Process created with id: $proc" 17 | sleep .1 18 | session_id=0 19 | proc_parent=`cat /proc/${proc}/stat | awk '{ print $4 }'` 20 | #echo "# Parent Process id of $proc is $proc_parent" 21 | 22 | # Testcases for pgrep command 23 | testing "pattern" "pgrep yes" "$proc\n" "" "" 24 | testing "wildCardPattern" "pgrep ^y.*s$" "$proc\n" "" "" 25 | testing "-l pattern" "pgrep -l yes" "$proc yes\n" "" "" 26 | testing "-f pattern" "pgrep -f yes" "$proc\n" "" "" 27 | testing "-n pattern" "pgrep -n yes" "$proc\n" "" "" 28 | testing "-o pattern" "pgrep -o yes" "$proc\n" "" "" 29 | testing "-s" "pgrep -s $session_id yes" "$proc\n" "" "" 30 | testing "-P" "pgrep -P $proc_parent yes" "$proc\n" "" "" 31 | 32 | testing "return success" "pgrep yes && echo success" "$proc\nsuccess\n" "" "" 33 | testing "return failure" "pgrep almost-certainly-not || echo failure" \ 34 | "failure\n" "" "" 35 | 36 | #Clean-up 37 | killall yes >/dev/null 2>&1 38 | -------------------------------------------------------------------------------- /tests/cksum.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | 6 | #testing "name" "command" "result" "infile" "stdin" 7 | 8 | # Default behavior on stdin and on files. 9 | testing "on stdin" "echo -n hello | cksum" "3287646509 5\n" "" "" 10 | echo -n "hello" > tmpfile 11 | testing "on file" "cksum tmpfile" "3287646509 5 tmpfile\n" "" "" 12 | rm -f tmpfile 13 | touch one two 14 | testing "on multiple files" "cksum one two" "4294967295 0 one\n4294967295 0 two\n" "" "" 15 | rm -f one two 16 | 17 | # Check the length suppression, both calculate the CRC on 'abc' but the second 18 | # option has length suppression on and has the length concatenated to 'abc'. 19 | testing "on abc including length" "echo -n 'abc' | cksum" "1219131554 3\n" "" "" 20 | testing "on abc excluding length" "echo -ne 'abc\x3' | cksum -N" "1219131554 4\n" "" "" 21 | 22 | # cksum on no contents gives 0xffffffff (=4294967295) 23 | testing "on no data post-inversion" "echo -n "" | cksum" "4294967295 0\n" "" "" 24 | # If we do preinversion we will then get 0. 25 | testing "on no data pre+post-inversion" "echo -n "" | cksum -P" "0 0\n" "" "" 26 | # If we skip the post-inversion we also get 0 27 | testing "on no data no inversion" "echo -n "" | cksum -I" "0 0\n" "" "" 28 | # Two wrongs make a right. 29 | testing "on no data pre-inversion" "echo -n "" | cksum -PI" "4294967295 0\n" "" "" 30 | -------------------------------------------------------------------------------- /toys/posix/mkdir.c: -------------------------------------------------------------------------------- 1 | /* mkdir.c - Make directories 2 | * 3 | * Copyright 2012 Georgi Chorbadzhiyski 4 | * 5 | * See http://opengroup.org/onlinepubs/9699919799/utilities/mkdir.html 6 | 7 | USE_MKDIR(NEWTOY(mkdir, "<1"USE_MKDIR_Z("Z:")"vpm:", TOYFLAG_BIN|TOYFLAG_UMASK)) 8 | 9 | config MKDIR 10 | bool "mkdir" 11 | default y 12 | help 13 | usage: mkdir [-vp] [-m mode] [dirname...] 14 | 15 | Create one or more directories. 16 | 17 | -m set permissions of directory to mode. 18 | -p make parent directories as needed. 19 | -v verbose 20 | 21 | config MKDIR_Z 22 | bool 23 | default y 24 | depends on MKDIR && !TOYBOX_LSM_NONE 25 | help 26 | usage: [-Z context] 27 | 28 | -Z set security context 29 | */ 30 | 31 | #define FOR_mkdir 32 | #include "toys.h" 33 | 34 | GLOBALS( 35 | char *arg_mode; 36 | char *arg_context; 37 | ) 38 | 39 | void mkdir_main(void) 40 | { 41 | char **s; 42 | mode_t mode = (0777&~toys.old_umask); 43 | 44 | if (CFG_MKDIR_Z && (toys.optflags&FLAG_Z)) 45 | if (0>lsm_set_create(TT.arg_context)) 46 | perror_exit("-Z '%s' failed", TT.arg_context); 47 | 48 | if (TT.arg_mode) mode = string_to_mode(TT.arg_mode, 0777); 49 | 50 | // Note, -p and -v flags line up with mkpathat() flags 51 | for (s=toys.optargs; *s; s++) { 52 | if (mkpathat(AT_FDCWD, *s, mode, toys.optflags|1)) 53 | perror_msg("'%s'", *s); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /tests/md5sum.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | # These tests are from RFC 1321 appendix 5, reshuffled slightly to test 8 | # varying argument numbers 9 | 10 | testing "''" "md5sum" "d41d8cd98f00b204e9800998ecf8427e -\n" "" "" 11 | testing "infile" "md5sum input" \ 12 | "0cc175b9c0f1b6a831c399e269772661 input\n" "a" "" 13 | testing "two files" "md5sum - input" \ 14 | "900150983cd24fb0d6963f7d28e17f72 -\nf96b697d7cb7938d525a2f31aaf161d0 input\n" \ 15 | "message digest" "abc" 16 | testing "4" "md5sum" "c3fcd3d76192e4007dfb496cca67e13b -\n" \ 17 | "" "abcdefghijklmnopqrstuvwxyz" 18 | testing "5" "md5sum" "d174ab98d277d9f5a5611c2c9f419d9f -\n" \ 19 | "" "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" 20 | testing "6" "md5sum" "57edf4a22be3c955ac49da2e2107b67a -\n" \ 21 | "" "12345678901234567890123456789012345678901234567890123456789012345678901234567890" 22 | 23 | echo -n "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" > "te st" 24 | touch empty 25 | testing "-c spaces" "md5sum -c input || echo ok" \ 26 | "te st: OK\nempty: FAILED\n-: OK\nok\n" \ 27 | "$(printf "d174ab98d277d9f5a5611c2c9f419d9f te st\n12345678901234567890123456789012 empty\nd41d8cd98f00b204e9800998ecf8427e -\n")" "" 28 | rm "te st" empty 29 | 30 | testing "-c nolines" "md5sum -c input 2>/dev/null || echo ok" "ok\n" "" "" 31 | -------------------------------------------------------------------------------- /toys/lsb/hostname.c: -------------------------------------------------------------------------------- 1 | /* hostname.c - Get/Set the hostname 2 | * 3 | * Copyright 2012 Andre Renaud 4 | * 5 | * http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/hostname.html 6 | 7 | USE_HOSTNAME(NEWTOY(hostname, "bF:", TOYFLAG_BIN)) 8 | 9 | config HOSTNAME 10 | bool "hostname" 11 | default y 12 | help 13 | usage: hostname [-b] [-F FILENAME] [newname] 14 | 15 | Get/Set the current hostname 16 | 17 | -b Set hostname to 'localhost' if otherwise unset 18 | -F Set hostname to contents of FILENAME 19 | */ 20 | 21 | #define FOR_hostname 22 | #include "toys.h" 23 | 24 | GLOBALS( 25 | char *fname; 26 | ) 27 | 28 | void hostname_main(void) 29 | { 30 | char *hostname = *toys.optargs; 31 | 32 | if (TT.fname && (hostname = xreadfile(TT.fname, 0, 0))) { 33 | if (!*chomp(hostname)) { 34 | if (CFG_TOYBOX_FREE) free(hostname); 35 | if (!(toys.optflags&FLAG_b)) error_exit("empty '%s'", TT.fname); 36 | hostname = 0; 37 | } 38 | } 39 | 40 | if (!hostname && (toys.optflags&FLAG_b)) 41 | if (gethostname(toybuf, sizeof(toybuf)-1) || !*toybuf) 42 | hostname = "localhost"; 43 | 44 | if (hostname) { 45 | if (sethostname(hostname, strlen(hostname))) 46 | perror_exit("set '%s'", hostname); 47 | } else { 48 | if (gethostname(toybuf, sizeof(toybuf)-1)) perror_exit("gethostname"); 49 | xputs(toybuf); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /tests/touch.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | testing "touch" "touch walrus && [ -e walrus ] && echo yes" "yes\n" "" "" 8 | testing "1 2 3" "touch one two three && rm one two three && echo yes" "yes\n" \ 9 | "" "" 10 | testing "-c" "touch -c walrus && [ -e walrus ] && echo yes" "yes\n" "" "" 11 | testing "-c missing" "touch -c warrus && [ ! -e warrus ] && echo yes" \ 12 | "yes\n" "" "" 13 | 14 | testing "-t" \ 15 | "touch -t 201201231234 walrus && date -r walrus +%Y%m%d-%H%M%S.%N" \ 16 | "20120123-123400.000000000\n" "" "" 17 | 18 | testing "-t seconds" \ 19 | "touch -t 201201231234.56 walrus && date -r walrus +%Y%m%d-%H%M%S.%N" \ 20 | "20120123-123456.000000000\n" "" "" 21 | 22 | testing "-t nanoseconds" \ 23 | "touch -t 201201231234.56123456789 walrus && date -r walrus +%Y%m%d-%H%M%S.%N" \ 24 | "20120123-123456.123456789\n" "" "" 25 | 26 | testing "-d" \ 27 | "touch -d 2009-02-13T23:31:30Z walrus && date -r walrus +%s" \ 28 | "1234567890\n" "" "" 29 | 30 | testing "-d nanoseconds" \ 31 | "touch -d 2009-02-13T23:31:30.123456789Z walrus && date -r walrus +%s.%N" \ 32 | "1234567890.123456789\n" "" "" 33 | 34 | testing "-r" \ 35 | "touch -r walrus walrus2 && date -r walrus2 +%s.%N" \ 36 | "1234567890.123456789\n" "" "" 37 | 38 | #testing "-a" 39 | #testing "-m" 40 | #testing "-am" 41 | #testing "-t" 42 | rm walrus walrus2 43 | -------------------------------------------------------------------------------- /tests/wc.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | cat >file1 </dev/null && echo yes" "yes\n" "" "" 15 | testing "empty file" "wc" " 0 0 0\n" "" "" 16 | testing "standard input" "wc" " 1 3 5\n" "" "a b\nc" 17 | testing "-c" "wc -c file1" "26 file1\n" "" "" 18 | testing "-l" "wc -l file1" "4 file1\n" "" "" 19 | testing "-w" "wc -w file1" "5 file1\n" "" "" 20 | NOSPACE=1 testing "format" "wc file1" " 4 5 26 file1\n" "" "" 21 | testing "multiple files" "wc input - file1" \ 22 | " 1 2 3 input\n 0 2 3 -\n 4 5 26 file1\n 5 9 32 total\n" "a\nb" "a b" 23 | 24 | #Tests for wc -m 25 | if printf "%s" "$LANG" | grep -q UTF-8 26 | then 27 | 28 | printf " " > file1 29 | for i in $(seq 1 8192) 30 | do 31 | printf "ü" >> file1 32 | done 33 | testing "-m" "wc -m file1" "8193 file1\n" "" "" 34 | testing "-m 2" 'cat "$FILES/utf8/test2.txt" | wc -m' "169\n" "" "" 35 | printf " " > file1 36 | for i in $(seq 1 8192) 37 | do 38 | printf "ü" >> file1 39 | done 40 | testing "-m (invalid chars)" "wc -m file1" "8193 file1\n" "" "" 41 | NOSPACE=1 testing "-mlw" "wc -mlw input" " 1 2 11 input\n" "hello, 世界!\n" "" 42 | 43 | else 44 | printf "skipping tests for wc -m" 45 | fi 46 | 47 | rm file1 48 | -------------------------------------------------------------------------------- /toys/other/mkswap.c: -------------------------------------------------------------------------------- 1 | /* mkswap.c - Format swap device. 2 | * 3 | * Copyright 2009 Rob Landley 4 | 5 | USE_MKSWAP(NEWTOY(mkswap, "<1>1L:", TOYFLAG_SBIN)) 6 | 7 | config MKSWAP 8 | bool "mkswap" 9 | default y 10 | help 11 | usage: mkswap [-L LABEL] DEVICE 12 | 13 | Sets up a Linux swap area on a device or file. 14 | */ 15 | 16 | #define FOR_mkswap 17 | #include "toys.h" 18 | 19 | GLOBALS( 20 | char *L; 21 | ) 22 | 23 | void mkswap_main(void) 24 | { 25 | int fd = xopen(*toys.optargs, O_RDWR), pagesize = sysconf(_SC_PAGE_SIZE); 26 | off_t len = fdlength(fd); 27 | unsigned int pages = (len/pagesize)-1, *swap = (unsigned int *)toybuf; 28 | char *label = (char *)(swap+7), *uuid = (char *)(swap+3); 29 | 30 | // Write header. Note that older kernel versions checked signature 31 | // on disk (not in cache) during swapon, so sync after writing. 32 | 33 | swap[0] = 1; 34 | swap[1] = pages; 35 | xlseek(fd, 1024, SEEK_SET); 36 | create_uuid(uuid); 37 | if (TT.L) strncpy(label, TT.L, 15); 38 | xwrite(fd, swap, 129*sizeof(unsigned int)); 39 | xlseek(fd, pagesize-10, SEEK_SET); 40 | xwrite(fd, "SWAPSPACE2", 10); 41 | fsync(fd); 42 | 43 | if (CFG_TOYBOX_FREE) close(fd); 44 | 45 | if (TT.L) sprintf(toybuf, ", LABEL=%s", label); 46 | else *toybuf = 0; 47 | printf("Swapspace size: %luk%s, UUID=%s\n", 48 | pages*(unsigned long)(pagesize/1024), 49 | toybuf, show_uuid(uuid)); 50 | } 51 | -------------------------------------------------------------------------------- /tests/echo.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | # This one's tricky both because echo is a shell builtin (so $PATH is 6 | # irrelevant) and because the "result" field is parsed with echo -e. 7 | # To make it work, "$CMD" is an explicit path to the command being tested, 8 | # so "result" keeps using the shell builtin but we test the one in toybox. 9 | 10 | CMD="$(which echo)" 11 | 12 | #testing "name" "command" "result" "infile" "stdin" 13 | 14 | testing "echo" "$CMD && echo yes" "\nyes\n" "" "" 15 | testing "1 2 3" "$CMD one two three" "one two three\n" "" "" 16 | testing "with spaces" "$CMD 'one two three'" \ 17 | "one two three\n" "" "" 18 | testing "-n" "$CMD -n" "" "" "" 19 | testing "-n one" "$CMD -n one" "one" "" "" 20 | testing "one -n" "$CMD one -n" "one -n\n" "" "" 21 | testing "-en" "$CMD -en 'one\ntwo'" "one\ntwo" "" "" 22 | testing "--hello" "$CMD --hello" "--hello\n" "" "" 23 | testing "-e all" "$CMD -e '\a\b\c\f\n\r\t\v\\\0123'" \ 24 | "\a\b\c\f\n\r\t\v\\\0123\n" "" "" 25 | testing "-nex hello" "$CMD -nex hello" "-nex hello\n" "" "" 26 | 27 | # Octal formatting tests 28 | testing "-e octal values" \ 29 | "$CMD -ne '\01234 \0060 \060 \0130\0131\0132 \077\012'" \ 30 | "S4 0 0 XYZ ?\n" "" "" 31 | 32 | # Hexadecimal value tests 33 | testing "-e hexadecimal values" \ 34 | "$CMD -ne '\x534 \x30 \x58\x59\x5a \x3F\x0A'"\ 35 | "S4 0 XYZ ?\n" "" "" 36 | 37 | testing "-e \p" "$CMD -e '\\p'" "\\p\n" "" "" 38 | -------------------------------------------------------------------------------- /tests/du.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | # we only test with -k since getting POSIX version is variable 8 | # POSIXLY_CORRECT is sometimes needed, sometimes -P is needed, 9 | # while -k is the default on most Linux systems 10 | 11 | mkdir -p du_test/test du_2/foo 12 | testing "(no options)" "du -k du_test" "4\tdu_test/test\n8\tdu_test\n" "" "" 13 | testing "-s" "du -k -s du_test" "8\tdu_test\n" "" "" 14 | ln -s ../du_2 du_test/xyz 15 | # "du shall count the size of the symbolic link" 16 | # The tests assume that like for most POSIX systems symbolic 17 | # links are stored directly in the inode so that the 18 | # allocated file space is zero. 19 | testing "counts symlinks without following" "du -ks du_test" "8\tdu_test\n" "" "" 20 | testing "-L follows symlinks" "du -ksL du_test" "16\tdu_test\n" "" "" 21 | ln -s . du_test/up 22 | testing "-L avoid endless loop" "du -ksL du_test" "16\tdu_test\n" "" "" 23 | rm du_test/up 24 | # if -H and -L are specified, the last takes priority 25 | testing "-HL follows symlinks" "du -ksHL du_test" "16\tdu_test\n" "" "" 26 | testing "-H does not follow unspecified symlinks" "du -ksH du_test" "8\tdu_test\n" "" "" 27 | testing "-LH does not follow unspecified symlinks" "du -ksLH du_test" "8\tdu_test\n" "" "" 28 | testing "-H follows specified symlinks" "du -ksH du_test/xyz" "8\tdu_test/xyz\n" "" "" 29 | 30 | rm -rf du_test du_2 31 | 32 | -------------------------------------------------------------------------------- /tests/lsattr.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | # lsattr - Testcases 8 | mkdir dir && cd dir && touch file 9 | chattr +A file &>/dev/null 10 | 11 | _p=$PWD 12 | _b="-------------" 13 | _A="-------A-----" 14 | 15 | testing "file" "lsattr file" "$_A file\n" "" "" 16 | testing "file_path" "lsattr $_p/file" "$_A $_p/file\n" "" "" 17 | testing "-R file" "lsattr -R file" "$_A file\n" "" "" 18 | testing "-R file_path" "lsattr -R $_p/file" "$_A $_p/file\n" "" "" 19 | testing "-a file" "lsattr -a file" "$_A file\n" "" "" 20 | testing "-a file_path" "lsattr -a $_p/file" "$_A $_p/file\n" "" "" 21 | testing "-d ." "lsattr -d ." "$_b .\n" "" "" 22 | testing "-d dir_path" "lsattr -d $_p" "$_b $_p\n" "" "" 23 | testing "-d file" "lsattr -d file" "$_A file\n" "" "" 24 | testing "-d file_path" "lsattr -d $_p/file" "$_A $_p/file\n" "" "" 25 | sp_44=" " 26 | testing "-l file" "lsattr -l file" "file $sp_44 No_Atime\n" "" "" 27 | _v="12345" 28 | testing "-v file" "chattr -v $_v * && lsattr -v file" \ 29 | "$_v $_A file\n" "" "" 30 | testing "-v file_path" "chattr -v $_v * && lsattr -v $_p/file" \ 31 | "$_v $_A $_p/file\n" "" "" 32 | testing "-Radlv file1 file2" "chattr -v $_v * && 33 | lsattr -Radlv file input" \ 34 | "$_v file $sp_44 No_Atime\n$_v input $sp_44 ---\n" "" "" 35 | 36 | # Cleanup 37 | chattr -AacDdijsStTu file && cd .. 38 | rm -rf dir 39 | -------------------------------------------------------------------------------- /toys/posix/time.c: -------------------------------------------------------------------------------- 1 | /* time.c - time a simple command 2 | * 3 | * Copyright 2013 Rob Landley 4 | * 5 | * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/time.html 6 | 7 | USE_TIME(NEWTOY(time, "<1^p", TOYFLAG_USR|TOYFLAG_BIN)) 8 | 9 | config TIME 10 | bool "time" 11 | default y 12 | depends on TOYBOX_FLOAT 13 | help 14 | usage: time [-p] COMMAND [ARGS...] 15 | 16 | Run command line and report real, user, and system time elapsed in seconds. 17 | (real = clock on the wall, user = cpu used by command's code, 18 | system = cpu used by OS on behalf of command.) 19 | 20 | -p posix mode (ignored) 21 | */ 22 | 23 | #include "toys.h" 24 | 25 | void time_main(void) 26 | { 27 | pid_t pid; 28 | struct timeval tv, tv2; 29 | 30 | gettimeofday(&tv, NULL); 31 | if (!(pid = XVFORK())) xexec(toys.optargs); 32 | else { 33 | int stat; 34 | struct rusage ru; 35 | float r, u, s; 36 | 37 | wait4(pid, &stat, 0, &ru); 38 | gettimeofday(&tv2, NULL); 39 | if (tv.tv_usec > tv2.tv_usec) { 40 | tv2.tv_usec += 1000000; 41 | tv2.tv_sec--; 42 | } 43 | r = (tv2.tv_sec-tv.tv_sec)+((tv2.tv_usec-tv.tv_usec)/1000000.0); 44 | u = ru.ru_utime.tv_sec+(ru.ru_utime.tv_usec/1000000.0); 45 | s = ru.ru_stime.tv_sec+(ru.ru_stime.tv_usec/1000000.0); 46 | fprintf(stderr, "real %f\nuser %f\nsys %f\n", r, u, s); 47 | toys.exitval = WIFEXITED(stat) ? WEXITSTATUS(stat) : WTERMSIG(stat); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /tests/cpio.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | # We need to test name and file padding. 6 | # This means all possible values of strlen(name)+1 % 4, 7 | # plus file sizes of at least 0-4. 8 | 9 | touch a bb ccc dddd 10 | testing "name padding" "cpio -o -H newc|cpio -it" "a\nbb\nccc\ndddd\n" "" "a\nbb\nccc\ndddd\n" 11 | rm a bb ccc dddd 12 | 13 | touch a 14 | printf '1' >b 15 | printf '22' >c 16 | printf '333' >d 17 | testing "file padding" "cpio -o -H newc|cpio -it" "a\nb\nc\nd\n" "" "a\nb\nc\nd\n" 18 | rm a b c d 19 | 20 | touch a 21 | printf '1' >bb 22 | printf '22' >ccc 23 | printf '333' >dddd 24 | # With the proper padding, header length, and file length, 25 | # the relevant bit should be here: 26 | # 110*5 + 4*3 + 2 + 6*3 = 550 + 12 + 20 = 582 27 | # files are padded to n*4, names are padded to 2 + n*4 due to the header length 28 | testing "archive length" "cpio -o -H newc|dd ibs=2 skip=291 count=5 2>/dev/null" "TRAILER!!!" "" "a\nbb\nccc\ndddd\n" 29 | testing "archive magic" "cpio -o -H newc|dd ibs=2 count=3 2>/dev/null" "070701" "" "a\n" 30 | # check name length (8 bytes before the empty "crc") 31 | testing "name length" "cpio -o -H newc|dd ibs=2 skip=47 count=4 2>/dev/null" "00000002" "" "a\n" 32 | rm a bb ccc dddd 33 | 34 | # archive dangling symlinks and empty files even if we cannot open them 35 | touch a; chmod a-rwx a; ln -s a/cant b 36 | testing "archives unreadable empty files" "cpio -o -H newc|cpio -it" "a\nb\n" "" "a\nb\n" 37 | chmod u+rw a; rm -f a b 38 | 39 | 40 | -------------------------------------------------------------------------------- /toys/android/restorecon.c: -------------------------------------------------------------------------------- 1 | /* restorecon.c - Restore default security contexts for files 2 | * 3 | * Copyright 2015 The Android Open Source Project 4 | 5 | USE_RESTORECON(NEWTOY(restorecon, "<1DFnRrv", TOYFLAG_USR|TOYFLAG_SBIN)) 6 | 7 | config RESTORECON 8 | bool "restorecon" 9 | depends on TOYBOX_SELINUX 10 | default y 11 | help 12 | usage: restorecon [-D] [-F] [-R] [-n] [-v] FILE... 13 | 14 | Restores the default security contexts for the given files. 15 | 16 | -D apply to /data/data too 17 | -F force reset 18 | -R recurse into directories 19 | -n don't make any changes; useful with -v to see what would change 20 | -v verbose: show any changes 21 | */ 22 | 23 | #define FOR_restorecon 24 | #include "toys.h" 25 | 26 | #if defined(__ANDROID__) 27 | #include 28 | #endif 29 | 30 | void restorecon_main(void) 31 | { 32 | #if defined(__ANDROID__) 33 | char **s; 34 | int flags = 0; 35 | 36 | if (toys.optflags & FLAG_D) flags |= SELINUX_ANDROID_RESTORECON_DATADATA; 37 | if (toys.optflags & FLAG_F) flags |= SELINUX_ANDROID_RESTORECON_FORCE; 38 | if (toys.optflags & (FLAG_R|FLAG_r)) 39 | flags |= SELINUX_ANDROID_RESTORECON_RECURSE; 40 | if (toys.optflags & FLAG_n) flags |= SELINUX_ANDROID_RESTORECON_NOCHANGE; 41 | if (toys.optflags & FLAG_v) flags |= SELINUX_ANDROID_RESTORECON_VERBOSE; 42 | 43 | for (s = toys.optargs; *s; s++) 44 | if (selinux_android_restorecon(*s, flags) < 0) 45 | perror_msg("restorecon failed: %s", *s); 46 | #endif 47 | } 48 | -------------------------------------------------------------------------------- /toys/posix/pwd.c: -------------------------------------------------------------------------------- 1 | /* pwd.c - Print working directory. 2 | * 3 | * Copyright 2006 Rob Landley 4 | * 5 | * See http://opengroup.org/onlinepubs/9699919799/utilities/pwd.html 6 | 7 | USE_PWD(NEWTOY(pwd, ">0LP[-LP]", TOYFLAG_BIN)) 8 | 9 | config PWD 10 | bool "pwd" 11 | default y 12 | help 13 | usage: pwd [-L|-P] 14 | 15 | Print working (current) directory. 16 | 17 | -L Use shell's path from $PWD (when applicable) 18 | -P Print cannonical absolute path 19 | */ 20 | 21 | #define FOR_pwd 22 | #include "toys.h" 23 | 24 | void pwd_main(void) 25 | { 26 | char *s, *pwd = getcwd(0, 0), *PWD; 27 | 28 | // Only use $PWD if it's an absolute path alias for cwd with no "." or ".." 29 | if (!(toys.optflags & FLAG_P) && (s = PWD = getenv("PWD"))) { 30 | struct stat st1, st2; 31 | 32 | while (*s == '/') { 33 | if (*(++s) == '.') { 34 | if (s[1] == '/' || !s[1]) break; 35 | if (s[1] == '.' && (s[2] == '/' || !s[2])) break; 36 | } 37 | while (*s && *s != '/') s++; 38 | } 39 | if (!*s && s != PWD) s = PWD; 40 | else s = NULL; 41 | 42 | // If current directory exists, make sure it matches. 43 | if (s && pwd) 44 | if (stat(pwd, &st1) || stat(PWD, &st2) || st1.st_ino != st2.st_ino || 45 | st1.st_dev != st2.st_dev) s = NULL; 46 | } else s = NULL; 47 | 48 | // If -L didn't give us a valid path, use cwd. 49 | if (!s && !(s = pwd)) perror_exit("xgetcwd"); 50 | 51 | xprintf("%s\n", s); 52 | 53 | if (CFG_TOYBOX_FREE) free(pwd); 54 | } 55 | -------------------------------------------------------------------------------- /toys/posix/head.c: -------------------------------------------------------------------------------- 1 | /* head.c - copy first lines from input to stdout. 2 | * 3 | * Copyright 2006 Timothy Elliott 4 | * 5 | * See http://opengroup.org/onlinepubs/9699919799/utilities/head.html 6 | 7 | USE_HEAD(NEWTOY(head, "?n#<0=10", TOYFLAG_USR|TOYFLAG_BIN)) 8 | 9 | config HEAD 10 | bool "head" 11 | default y 12 | help 13 | usage: head [-n number] [file...] 14 | 15 | Copy first lines from files to stdout. If no files listed, copy from 16 | stdin. Filename "-" is a synonym for stdin. 17 | 18 | -n Number of lines to copy. 19 | */ 20 | 21 | #define FOR_head 22 | #include "toys.h" 23 | 24 | GLOBALS( 25 | long lines; 26 | int file_no; 27 | ) 28 | 29 | static void do_head(int fd, char *name) 30 | { 31 | int i, len, lines=TT.lines, size=sizeof(toybuf); 32 | 33 | if (toys.optc > 1) { 34 | // Print an extra newline for all but the first file 35 | if (TT.file_no++) xprintf("\n"); 36 | xprintf("==> %s <==\n", name); 37 | xflush(); 38 | } 39 | 40 | while (lines) { 41 | len = read(fd, toybuf, size); 42 | if (len<0) perror_msg_raw(name); 43 | if (len<1) break; 44 | 45 | for(i=0; i 4 | * 5 | * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/uuencode.html 6 | 7 | USE_UUENCODE(NEWTOY(uuencode, "<1>2m", TOYFLAG_USR|TOYFLAG_BIN)) 8 | 9 | config UUENCODE 10 | bool "uuencode" 11 | default y 12 | help 13 | usage: uuencode [-m] [file] encode-filename 14 | 15 | Uuencode stdin (or file) to stdout, with encode-filename in the output. 16 | 17 | -m base64-encode 18 | */ 19 | 20 | #define FOR_uuencode 21 | #include "toys.h" 22 | 23 | void uuencode_main(void) 24 | { 25 | char *name = toys.optargs[toys.optc-1], buf[(76/4)*3]; 26 | 27 | int i, m = toys.optflags & FLAG_m, fd = 0; 28 | 29 | if (toys.optc > 1) fd = xopenro(toys.optargs[0]); 30 | 31 | base64_init(toybuf); 32 | 33 | xprintf("begin%s 744 %s\n", m ? "-base64" : "", name); 34 | for (;;) { 35 | char *in; 36 | 37 | if (!(i = xread(fd, buf, m ? sizeof(buf) : 45))) break; 38 | 39 | if (!m) xputc(i+32); 40 | in = buf; 41 | 42 | for (in = buf; in-buf < i; ) { 43 | int j, x, bytes = i - (in-buf); 44 | 45 | if (bytes > 3) bytes = 3; 46 | 47 | for (j = x = 0; j<4; j++) { 48 | int out; 49 | 50 | if (j < bytes) x |= (*(in++) & 0x0ff) << (8*(2-j)); 51 | out = (x>>((3-j)*6)) & 0x3f; 52 | xputc(m ? (j > bytes ? '=' : toybuf[out]) : (out ? out + 0x20 : 0x60)); 53 | } 54 | } 55 | xputc('\n'); 56 | } 57 | xputs(m ? "====" : "end"); 58 | } 59 | -------------------------------------------------------------------------------- /tests/modinfo.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | [ -e /proc/modules ] || { echo "Skipping test because modules are not supported"; exit 1; } 8 | 9 | # modinfo does not need to output fields in a specified order. 10 | # Instead, there are labelled fields. We can use sort to make up for this. 11 | # Other issues to beware of are the volatile nature of srcversion and vermagic, 12 | # which change from kernel to kernel and can be disabled. 13 | # We grep to remove these. 14 | 15 | #We expect they have ne2k-pci as a module. 16 | 17 | testing "gets right number of fields" "modinfo ne2k-pci |cut -d: -f1 |grep -v ver|sort" "alias\nalias\nalias\nalias\nalias\nalias\nalias\nalias\nalias\nalias\nalias\nauthor\ndepends\ndescription\nfilename\nlicense\nparm\nparm\nparm\n" "" "" 18 | testing "treats - and _ as equivalent" "modinfo ne2k_pci |cut -d: -f1 |grep -v ver|sort" "alias\nalias\nalias\nalias\nalias\nalias\nalias\nalias\nalias\nalias\nalias\nauthor\ndepends\ndescription\nfilename\nlicense\nparm\nparm\nparm\n" "" "" 19 | 20 | # Output of -F filename should be an absolute path to the module. 21 | # Otherwise, initrd generating scripts will break. 22 | 23 | testing "-F filename gets absolute path" "[ -e `modinfo -F filename ne2k-pci` ] && echo ne2k-pci " "ne2k-pci\n" "" "" 24 | 25 | testing "supports multiple modules" "modinfo -F filename ne2k-pci 8390 | wc -l" "2\n" "" "" 26 | 27 | testing "does not output filename for bad module" "modinfo -F filename zxcvbnm__9753" "" "" "" 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /tests/expand.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # POSIX 2008 compliant expand tests. 4 | # Copyright 2012 by Jonathan Clairembault 5 | 6 | [ -f testing.sh ] && . testing.sh 7 | 8 | # some basic tests 9 | 10 | testing "default" "expand input" " foo bar\n" "\tfoo\tbar\n" "" 11 | testing "default stdin" "expand" " foo bar\n" "" "\tfoo\tbar\n" 12 | testing "single" "expand -t 2 input" " foo bar\n" "\tfoo\tbar\n" "" 13 | testing "tablist" "expand -t 5,10,12 input" " foo bar foo\n" "\tfoo\tbar\tfoo\n" "" 14 | testing "backspace" "expand input" "foobarfoo\b\b bar\n" "foobarfoo\b\b\tbar\n" "" 15 | 16 | # advanced tests 17 | 18 | POW=15 19 | TABSTOP=1 20 | BIGTAB=" " 21 | for i in $(seq $POW); do 22 | BIGTAB=$BIGTAB$BIGTAB 23 | TABSTOP=$[$TABSTOP*2] 24 | done 25 | testing "long tab single" "expand -t $TABSTOP input" "${BIGTAB}foo\n" "\tfoo\n" "" 26 | testing "long tab tablist" "expand -t $TABSTOP,$[TABSTOP+5] input" \ 27 | "${BIGTAB}foo bar\n" "\tfoo\tbar\n" "" 28 | 29 | testing "multiline single" "expand -t 4 input" "foo \n bar\n" "foo\t\n\tbar\n" "" 30 | testing "multiline tablist" "expand -t 4,8 input" \ 31 | "foo bar\n bar foo\n" "foo\t\tbar\n\tbar\tfoo\n" "" 32 | POW=15 33 | BIGLINE="foo " 34 | for i in $(seq $POW); do 35 | BIGLINE=$BIGLINE$BIGLINE 36 | done 37 | if [ $POW -gt 0 ]; then 38 | EXPANDLINE="${BIGLINE} foo\n" 39 | else 40 | EXPANDLINE="${BIGLINE} foo\n" 41 | fi 42 | BIGLINE="${BIGLINE}\tfoo\n" 43 | testing "long line single" "expand input" \ 44 | "${EXPANDLINE}" "$BIGLINE" "" 45 | -------------------------------------------------------------------------------- /toys/android/log.c: -------------------------------------------------------------------------------- 1 | /* log.c - Log to logcat. 2 | * 3 | * Copyright 2016 The Android Open Source Project 4 | 5 | USE_LOG(NEWTOY(log, "<1p:t:", TOYFLAG_USR|TOYFLAG_SBIN)) 6 | 7 | config LOG 8 | bool "log" 9 | depends on TOYBOX_ON_ANDROID 10 | default y 11 | help 12 | usage: log [-p PRI] [-t TAG] MESSAGE... 13 | 14 | Logs message to logcat. 15 | 16 | -p use the given priority instead of INFO: 17 | d: DEBUG e: ERROR f: FATAL i: INFO v: VERBOSE w: WARN s: SILENT 18 | -t use the given tag instead of "log" 19 | */ 20 | 21 | #define FOR_log 22 | #include "toys.h" 23 | #include 24 | 25 | GLOBALS( 26 | char *tag; 27 | char *pri; 28 | ) 29 | 30 | void log_main(void) 31 | { 32 | android_LogPriority pri = ANDROID_LOG_INFO; 33 | char *s = toybuf; 34 | int i; 35 | 36 | if (TT.pri) { 37 | i = stridx("defisvw", tolower(*TT.pri)); 38 | if (i==-1 || strlen(TT.pri)!=1) error_exit("bad -p '%s'", TT.pri); 39 | pri = (android_LogPriority []){ANDROID_LOG_DEBUG, ANDROID_LOG_ERROR, 40 | ANDROID_LOG_FATAL, ANDROID_LOG_INFO, ANDROID_LOG_SILENT, 41 | ANDROID_LOG_VERBOSE, ANDROID_LOG_WARN}[i]; 42 | } 43 | if (!TT.tag) TT.tag = "log"; 44 | 45 | for (i = 0; toys.optargs[i]; i++) { 46 | if (i) *s++ = ' '; 47 | if ((s-toybuf)+strlen(toys.optargs[i])>=1024) { 48 | memcpy(s, toys.optargs[i], 1024-(s-toybuf)); 49 | toybuf[1024] = 0; 50 | perror_msg("log cut at 1024 bytes"); 51 | 52 | break; 53 | } 54 | s = stpcpy(s, toys.optargs[i]); 55 | } 56 | 57 | __android_log_write(pri, TT.tag, toybuf); 58 | } 59 | -------------------------------------------------------------------------------- /toys/android/start.c: -------------------------------------------------------------------------------- 1 | /* start.c - Start/stop system services. 2 | * 3 | * Copyright 2016 The Android Open Source Project 4 | 5 | USE_START(NEWTOY(start, "", TOYFLAG_USR|TOYFLAG_SBIN)) 6 | USE_STOP(NEWTOY(stop, "", TOYFLAG_USR|TOYFLAG_SBIN)) 7 | 8 | config START 9 | bool "start" 10 | depends on TOYBOX_ON_ANDROID 11 | default y 12 | help 13 | usage: start [SERVICE...] 14 | 15 | Starts the given system service, or netd/surfaceflinger/zygotes. 16 | 17 | config STOP 18 | bool "stop" 19 | depends on TOYBOX_ON_ANDROID 20 | default y 21 | help 22 | usage: stop [SERVICE...] 23 | 24 | Stop the given system service, or netd/surfaceflinger/zygotes. 25 | */ 26 | 27 | #define FOR_start 28 | #include "toys.h" 29 | 30 | #include 31 | 32 | static void start_stop(int start) 33 | { 34 | char *property = start ? "ctl.start" : "ctl.stop"; 35 | // null terminated in both directions 36 | char *services[] = {0,"netd","surfaceflinger","zygote","zygote_secondary",0}, 37 | **ss = toys.optargs; 38 | int direction = 1; 39 | 40 | if (getuid()) error_exit("must be root"); 41 | 42 | if (!*ss) { 43 | // If we don't have optargs, iterate through services forward/backward. 44 | ss = services+1; 45 | if (!start) ss = services+ARRAY_LEN(services)-2, direction = -1; 46 | } 47 | 48 | for (; *ss; ss += direction) 49 | if (property_set(property, *ss)) 50 | error_exit("failed to set property '%s' to '%s'", property, *ss); 51 | } 52 | 53 | void start_main(void) 54 | { 55 | start_stop(1); 56 | } 57 | 58 | void stop_main(void) 59 | { 60 | start_stop(0); 61 | } 62 | -------------------------------------------------------------------------------- /scripts/mktags.c: -------------------------------------------------------------------------------- 1 | // Process TAGGED_ARRAY() macros to emit TAG_STRING index macros. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int main(int argc, char *argv[]) 9 | { 10 | char *tag = 0; 11 | int idx = 0; 12 | 13 | for (;;) { 14 | char *line = 0, *s; 15 | ssize_t len; 16 | 17 | len = getline(&line, &len, stdin); 18 | if (len<0) break; 19 | while (len && isspace(line[len-1])) line[--len]=0; 20 | 21 | // Very simple parser: If we haven't got a TAG then first line is TAG. 22 | // Then look for { followed by "str" (must be on same line, may have 23 | // more than one per line), for each one emit #define. Current TAG ended 24 | // by ) at start of line. 25 | 26 | if (!tag) { 27 | if (!isalpha(*line)) { 28 | fprintf(stderr, "bad tag %s\n", line); 29 | exit(1); 30 | } 31 | tag = strdup(line); 32 | idx = 0; 33 | 34 | continue; 35 | } 36 | 37 | for (s = line; isspace(*s); s++); 38 | if (*s == ')') tag = 0; 39 | else for (;;) { 40 | char *start; 41 | 42 | while (*s && *s != '{') s++; 43 | while (*s && *s != '"') s++; 44 | if (!*s) break; 45 | 46 | start = ++s; 47 | while (*s && *s != '"') { 48 | if (!isalpha(*s) && !isdigit(*s)) *s = '_'; 49 | s++; 50 | } 51 | printf("#define %s_%*.*s %d\n", tag, -40, (int)(s-start), start, idx); 52 | printf("#define _%s_%*.*s (1%s<<%d)\n", tag, -39, (int)(s-start), start, 53 | idx>31 ? "LL": "", idx); 54 | idx++; 55 | } 56 | free(line); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /toys/other/insmod.c: -------------------------------------------------------------------------------- 1 | /* insmod.c - Load a module into the Linux kernel. 2 | * 3 | * Copyright 2012 Elie De Brauwer 4 | 5 | USE_INSMOD(NEWTOY(insmod, "<1", TOYFLAG_SBIN|TOYFLAG_NEEDROOT)) 6 | 7 | config INSMOD 8 | bool "insmod" 9 | default y 10 | help 11 | usage: insmod MODULE [MODULE_OPTIONS] 12 | 13 | Load the module named MODULE passing options if given. 14 | */ 15 | 16 | #include "toys.h" 17 | 18 | #include 19 | #ifdef SYS_finit_module 20 | #define finit_module(fd, opts, flags) syscall(SYS_finit_module, fd, opts, flags) 21 | #else 22 | #define finit_module(a, b, c) (errno = ENOSYS) 23 | #endif 24 | #define init_module(mod, len, opts) syscall(SYS_init_module, mod, len, opts) 25 | 26 | void insmod_main(void) 27 | { 28 | int fd = xopenro(*toys.optargs); 29 | int i, rc; 30 | 31 | i = 1; 32 | while (toys.optargs[i] && 33 | strlen(toybuf) + strlen(toys.optargs[i]) + 2 < sizeof(toybuf)) 34 | { 35 | strcat(toybuf, toys.optargs[i++]); 36 | strcat(toybuf, " "); 37 | } 38 | 39 | // finit_module was new in Linux 3.8, and doesn't work on stdin, 40 | // so we fall back to init_module if necessary. 41 | rc = finit_module(fd, toybuf, 0); 42 | if (rc && (fd == 0 || errno == ENOSYS)) { 43 | off_t len = 0; 44 | char *path = !strcmp(*toys.optargs, "-") ? "/dev/stdin" : *toys.optargs; 45 | char *buf = readfileat(AT_FDCWD, path, NULL, &len); 46 | 47 | rc = init_module(buf, len, toybuf); 48 | if (CFG_TOYBOX_FREE) free(buf); 49 | } 50 | 51 | if (rc) perror_exit("failed to load %s", toys.optargs[0]); 52 | 53 | if (CFG_TOYBOX_FREE) close(fd); 54 | } 55 | -------------------------------------------------------------------------------- /tests/rm.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2013 Robin Mittal 4 | # Copyright 2013 Divya Kothari 5 | 6 | [ -f testing.sh ] && . testing.sh 7 | 8 | #testing "name" "command" "result" "infile" "stdin" 9 | 10 | echo "abcdefghijklmnopqrstuvwxyz" > file.txt 11 | testing "text-file" "rm file.txt && [ ! -e file.txt ] && echo 'yes'" "yes\n" "" "" 12 | rm -f file* 13 | 14 | mkdir dir 15 | testing "empty directory" "rm -r dir && [ ! -d dir ] && echo 'yes'" "yes\n" "" "" 16 | rm -rf dir 17 | 18 | echo "abcdefghijklmnopqrstuvwxyz" > file.txt && chmod 000 file.txt 19 | testing "text file(mode 000)" "rm -f file.txt && [ ! -e file.txt ] && echo 'yes'" \ 20 | "yes\n" "" "" 21 | rm -f file* 22 | 23 | touch file1.txt file2.txt 24 | mkdir dir1 dir2 25 | testing "-r (multiple files and dirs)" \ 26 | "rm -r file1.txt file2.txt dir1 dir2 2>/dev/null && 27 | [ ! -e file1.txt -a ! -e file2.txt -a ! -d dir1 -a ! -d dir2 ] && echo 'yes'" \ 28 | "yes\n" "" "" 29 | rm -rf file* dir* 30 | 31 | touch file1.txt file2.txt 32 | mkdir dir1 dir2 33 | testing "-rf (present + missing files and dirs)" \ 34 | "rm -rf file1.txt file2.txt file3.txt dir1 dir2 dir3 2>/dev/null && 35 | [ ! -e file1.txt -a ! -e file2.txt -a ! -d dir1 -a ! -d dir2 ] && echo 'yes'" \ 36 | "yes\n" "" "" 37 | rm -rf file* dir* 38 | 39 | # testing with nested dirs. 40 | mkdir -p dir1/dir2/dir3 dir1/dir2/dir4 41 | touch dir1/file1.txt dir1/dir2/file2.txt dir1/dir2/dir3/file3.txt 42 | testing "-r nested_dir" "rm -r dir1/dir2/ 2>/dev/null && 43 | [ -d dir1 -a -f dir1/file1.txt -a ! -d dir1/dir2 ] && echo 'yes'" \ 44 | "yes\n" "" "" 45 | rm -rf dir* 46 | 47 | -------------------------------------------------------------------------------- /toys/android/setprop.c: -------------------------------------------------------------------------------- 1 | /* setprop.c - Set an Android system property 2 | * 3 | * Copyright 2015 The Android Open Source Project 4 | 5 | USE_SETPROP(NEWTOY(setprop, "<2>2", TOYFLAG_USR|TOYFLAG_SBIN)) 6 | 7 | config SETPROP 8 | bool "setprop" 9 | default y 10 | depends on TOYBOX_ON_ANDROID 11 | help 12 | usage: setprop NAME VALUE 13 | 14 | Sets an Android system property. 15 | */ 16 | 17 | #define FOR_setprop 18 | #include "toys.h" 19 | 20 | #include 21 | 22 | void setprop_main(void) 23 | { 24 | char *name = toys.optargs[0], *value = toys.optargs[1]; 25 | char *p; 26 | size_t name_len = strlen(name), value_len = strlen(value); 27 | 28 | // property_set doesn't tell us why it failed, and actually can't 29 | // recognize most failures (because it doesn't wait for init), so 30 | // we duplicate all of init's checks here to help the user. 31 | 32 | if (name_len >= PROP_NAME_MAX) 33 | error_exit("name '%s' too long; try '%.*s'", 34 | name, PROP_NAME_MAX - 1, name); 35 | if (value_len >= PROP_VALUE_MAX) 36 | error_exit("value '%s' too long; try '%.*s'", 37 | value, PROP_VALUE_MAX - 1, value); 38 | 39 | if (*name == '.' || name[name_len - 1] == '.') 40 | error_exit("property names must not start or end with '.'"); 41 | if (strstr(name, "..")) 42 | error_exit("'..' is not allowed in a property name"); 43 | for (p = name; *p; ++p) 44 | if (!isalnum(*p) && !strchr("_.-", *p)) 45 | error_exit("invalid character '%c' in name '%s'", *p, name); 46 | 47 | if (property_set(name, value)) 48 | error_msg("failed to set property '%s' to '%s'", name, value); 49 | } 50 | -------------------------------------------------------------------------------- /toys/net/tunctl.c: -------------------------------------------------------------------------------- 1 | /* tunctl.c - Control tap/tun network devices. 2 | * 3 | * Copyright 2016 Rob Landley 4 | * 5 | * See http://kernel.org/doc/Documentation/networking/tuntap.txt 6 | * 7 | * This is useful for things like "kvm -netdev tap" and containers. 8 | * See https://landley.net/lxc/02-networking.html for example usage. 9 | * 10 | * todo: bridge mode 11 | * -b bridge daemon (forwards packets between NAME and NAME2 interfaces) 12 | 13 | 14 | USE_TUNCTL(NEWTOY(tunctl, "<1>1t|d|u:T[!td]", TOYFLAG_USR|TOYFLAG_BIN)) 15 | 16 | config TUNCTL 17 | bool "tunctl" 18 | default y 19 | help 20 | usage: tunctl [-dtT] [-u USER] NAME 21 | 22 | Create and delete tun/tap virtual ethernet devices. 23 | 24 | -T Use tap (ethernet frames) instead of tun (ip packets) 25 | -d Delete tun/tap device 26 | -t Create tun/tap device 27 | -u Set owner (user who can read/write device without root access) 28 | */ 29 | 30 | #define FOR_tunctl 31 | #include "toys.h" 32 | #include 33 | 34 | GLOBALS( 35 | char *user; 36 | ) 37 | 38 | void tunctl_main(void) 39 | { 40 | struct ifreq *ifr = (void *)toybuf; 41 | uid_t u = TT.user ? xgetuid(TT.user) : 0; 42 | int fd = xopen("/dev/net/tun", O_RDWR); 43 | 44 | // Associate filehandle with device 45 | ifr->ifr_flags = ((toys.optflags&FLAG_T) ? IFF_TUN : IFF_TAP)|IFF_NO_PI; 46 | strncpy(ifr->ifr_name, *toys.optargs, sizeof(ifr->ifr_name)); 47 | xioctl(fd, TUNSETIFF, toybuf); 48 | 49 | if (toys.optflags&FLAG_t) { 50 | xioctl(fd, TUNSETPERSIST, (void *)1); 51 | xioctl(fd, TUNSETOWNER, (void *)(long)u); 52 | } else xioctl(fd, TUNSETPERSIST, (void *)0); 53 | } 54 | -------------------------------------------------------------------------------- /scripts/bloatcheck: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ $# -ne 2 ] 4 | then 5 | echo "usage: bloatcheck old new" 6 | exit 1 7 | fi 8 | 9 | addline() 10 | { 11 | NEXT="$(printf "%s% $((50-${#LASTNAME}))d% 10d %10d" "$LASTNAME" "$OLD" "$NEW" "$DELTA")" 12 | [ -z "$STUFF" ] && 13 | STUFF="$NEXT" || 14 | STUFF="$(printf "%s\n%s" "$STUFF" "$NEXT")" 15 | } 16 | 17 | do_bloatcheck() 18 | { 19 | LASTNAME= 20 | DELTA=0 21 | TOTAL=0 22 | OLD=0 23 | NEW=0 24 | STUFF= 25 | 26 | printf "name% 46s% 10s% 11s\n" old new delta 27 | echo "-----------------------------------------------------------------------" 28 | while read a b c d 29 | do 30 | THISNAME=$(echo "$d" | sed 's/[.][0-9]*$//') 31 | 32 | if [ "$LASTNAME" != "$THISNAME" ] 33 | then 34 | TOTAL=$(($TOTAL+$DELTA)) 35 | [ $DELTA -ne 0 ] && addline 36 | LASTNAME="$THISNAME" 37 | DELTA=0 38 | OLD=0 39 | NEW=0 40 | fi 41 | 42 | SIZE=$(printf "%d" "0x$b") 43 | if [ "$a" == "-" ] 44 | then 45 | OLD=$(($OLD+$SIZE)) 46 | SIZE=$((-1*$SIZE)) 47 | else 48 | NEW=$(($NEW+$SIZE)) 49 | fi 50 | DELTA=$(($DELTA+$SIZE)) 51 | done 52 | 53 | TOTAL=$(($TOTAL+$DELTA)) 54 | [ $DELTA -ne 0 ] && addline 55 | 56 | echo "$STUFF" | sort -k4,4nr 57 | echo "-----------------------------------------------------------------------" 58 | printf "% 71d total\n" "$TOTAL" 59 | } 60 | 61 | DIFF1=`mktemp base.XXXXXXX` 62 | DIFF2=`mktemp bloat.XXXXXXX` 63 | trap "rm $DIFF1 $DIFF2" EXIT 64 | nm --size-sort "$1" | sort -k3,3 > $DIFF1 65 | nm --size-sort "$2" | sort -k3,3 > $DIFF2 66 | diff -U 0 $DIFF1 $DIFF2 | tail -n +3 | sed -n 's/^\([-+]\)/\1 /p' \ 67 | | sort -k4,4 | do_bloatcheck 68 | -------------------------------------------------------------------------------- /toys/posix/tee.c: -------------------------------------------------------------------------------- 1 | /* tee.c - cat to multiple outputs. 2 | * 3 | * Copyright 2008 Rob Landley 4 | * 5 | * See http://opengroup.org/onlinepubs/9699919799/utilities/tee.html 6 | 7 | USE_TEE(NEWTOY(tee, "ia", TOYFLAG_USR|TOYFLAG_BIN)) 8 | 9 | config TEE 10 | bool "tee" 11 | default y 12 | help 13 | usage: tee [-ai] [file...] 14 | 15 | Copy stdin to each listed file, and also to stdout. 16 | Filename "-" is a synonym for stdout. 17 | 18 | -a append to files. 19 | -i ignore SIGINT. 20 | */ 21 | 22 | #define FOR_tee 23 | #include "toys.h" 24 | 25 | GLOBALS( 26 | void *outputs; 27 | ) 28 | 29 | struct fd_list { 30 | struct fd_list *next; 31 | int fd; 32 | }; 33 | 34 | // Open each output file, saving filehandles to a linked list. 35 | 36 | static void do_tee_open(int fd, char *name) 37 | { 38 | struct fd_list *temp; 39 | 40 | temp = xmalloc(sizeof(struct fd_list)); 41 | temp->next = TT.outputs; 42 | temp->fd = fd; 43 | TT.outputs = temp; 44 | } 45 | 46 | void tee_main(void) 47 | { 48 | if (toys.optflags & FLAG_i) xsignal(SIGINT, SIG_IGN); 49 | 50 | // Open output files 51 | loopfiles_rw(toys.optargs, 52 | O_RDWR|O_CREAT|WARN_ONLY|((toys.optflags & FLAG_a)?O_APPEND:O_TRUNC), 53 | 0666, do_tee_open); 54 | 55 | for (;;) { 56 | struct fd_list *fdl; 57 | int len; 58 | 59 | // Read data from stdin 60 | len = xread(0, toybuf, sizeof(toybuf)); 61 | if (len<1) break; 62 | 63 | // Write data to each output file, plus stdout. 64 | fdl = TT.outputs; 65 | for (;;) { 66 | if(len != writeall(fdl ? fdl->fd : 1, toybuf, len)) toys.exitval=1; 67 | if (!fdl) break; 68 | fdl = fdl->next; 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /tests/rmdir.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | mkdir one 8 | testing "rmdir" "rmdir one && [ ! -d one ] && echo yes" "yes\n" "" "" 9 | 10 | touch walrus 11 | testing "file" \ 12 | "rmdir walrus 2> /dev/null || [ -f walrus ] && echo yes" "yes\n" "" "" 13 | 14 | mkdir one two 15 | testing "one two" \ 16 | "rmdir one two 2> /dev/null && [ ! -d one ] && [ ! -d two ] && echo yes" \ 17 | "yes\n" "" "" 18 | 19 | mkdir one two three 20 | testing "one missing two file three" \ 21 | "rmdir one missing two walrus three 2> /dev/null || [ ! -d three ] && echo yes" \ 22 | "yes\n" "" "" 23 | rm walrus 24 | 25 | mkdir one 26 | chmod 000 one 27 | testing "mode 000" "rmdir one && [ ! -d one ] && echo yes" "yes\n" "" "" 28 | 29 | mkdir temp 30 | touch temp/thing 31 | testing "non-empty" \ 32 | "rmdir temp 2>/dev/null || [ -d temp ] && echo yes" "yes\n" "" "" 33 | testing "-p dir/file" \ 34 | "rmdir -p temp/thing 2>/dev/null || [ -f temp/thing ] && echo yes" \ 35 | "yes\n" "" "" 36 | 37 | mkdir -p temp/one/two/three 38 | testing "-p part of path" \ 39 | "rmdir -p temp/one/two/three 2>/dev/null || [ -d temp ] && [ ! -e temp/one ] && echo yes" \ 40 | "yes\n" "" "" 41 | rm -rf temp 42 | 43 | 44 | mkdir -p one/two/three 45 | testing "-p one/two/three" \ 46 | "rmdir -p one/two/three && [ ! -e one ] && echo yes" "yes\n" "" "" 47 | 48 | mkdir -p one/two/three 49 | testing "-p one/two/three/" \ 50 | "rmdir -p one/two/three/ && [ ! -e one ] && echo yes" "yes\n" "" "" 51 | 52 | #mkdir -p one/two/three 53 | #chmod 000 one/two/three one/two one 54 | #testing "-p one/two/three" \ 55 | # "rmdir -p one/two/three && [ ! -e one ] && echo yes" "yes\n" "" "" 56 | -------------------------------------------------------------------------------- /toys/other/uptime.c: -------------------------------------------------------------------------------- 1 | /* uptime.c - Tell how long the system has been running. 2 | * 3 | * Copyright 2012 Elie De Brauwer 4 | * Copyright 2012 Luis Felipe Strano Moraes 5 | * Copyright 2013 Jeroen van Rijn 6 | 7 | 8 | USE_UPTIME(NEWTOY(uptime, NULL, TOYFLAG_USR|TOYFLAG_BIN)) 9 | 10 | config UPTIME 11 | bool "uptime" 12 | default y 13 | depends on TOYBOX_UTMPX 14 | help 15 | usage: uptime 16 | 17 | Tell how long the system has been running and the system load 18 | averages for the past 1, 5 and 15 minutes. 19 | */ 20 | 21 | #include "toys.h" 22 | 23 | void uptime_main(void) 24 | { 25 | struct sysinfo info; 26 | time_t tmptime; 27 | struct tm * now; 28 | unsigned int days, hours, minutes; 29 | struct utmpx *entry; 30 | int users = 0; 31 | 32 | // Obtain the data we need. 33 | sysinfo(&info); 34 | time(&tmptime); 35 | now = localtime(&tmptime); 36 | 37 | // Obtain info about logged on users 38 | setutxent(); 39 | while ((entry = getutxent())) if (entry->ut_type == USER_PROCESS) users++; 40 | endutxent(); 41 | 42 | // Time 43 | xprintf(" %02d:%02d:%02d up ", now->tm_hour, now->tm_min, now->tm_sec); 44 | // Uptime 45 | info.uptime /= 60; 46 | minutes = info.uptime%60; 47 | info.uptime /= 60; 48 | hours = info.uptime%24; 49 | days = info.uptime/24; 50 | if (days) xprintf("%d day%s, ", days, (days!=1)?"s":""); 51 | if (hours) xprintf("%2d:%02d, ", hours, minutes); 52 | else printf("%d min, ", minutes); 53 | printf(" %d user%s, ", users, (users!=1) ? "s" : ""); 54 | printf(" load average: %.02f, %.02f, %.02f\n", info.loads[0]/65536.0, 55 | info.loads[1]/65536.0, info.loads[2]/65536.0); 56 | } 57 | -------------------------------------------------------------------------------- /lib/net.c: -------------------------------------------------------------------------------- 1 | #include "toys.h" 2 | 3 | int xsocket(int domain, int type, int protocol) 4 | { 5 | int fd = socket(domain, type, protocol); 6 | 7 | if (fd < 0) perror_exit("socket %x %x", type, protocol); 8 | return fd; 9 | } 10 | 11 | void xsetsockopt(int fd, int level, int opt, void *val, socklen_t len) 12 | { 13 | if (-1 == setsockopt(fd, level, opt, val, len)) perror_exit("setsockopt"); 14 | } 15 | 16 | int xconnect(char *host, char *port, int family, int socktype, int protocol, 17 | int flags) 18 | { 19 | struct addrinfo info, *ai, *ai2; 20 | int fd; 21 | 22 | memset(&info, 0, sizeof(struct addrinfo)); 23 | info.ai_family = family; 24 | info.ai_socktype = socktype; 25 | info.ai_protocol = protocol; 26 | info.ai_flags = flags; 27 | 28 | fd = getaddrinfo(host, port, &info, &ai); 29 | if (fd || !ai) 30 | error_exit("Connect '%s%s%s': %s", host, port ? ":" : "", port ? port : "", 31 | fd ? gai_strerror(fd) : "not found"); 32 | 33 | // Try all the returned addresses. Report errors if last entry can't connect. 34 | for (ai2 = ai; ai; ai = ai->ai_next) { 35 | fd = (ai->ai_next ? socket : xsocket)(ai->ai_family, ai->ai_socktype, 36 | ai->ai_protocol); 37 | if (!connect(fd, ai->ai_addr, ai->ai_addrlen)) break; 38 | else if (!ai2->ai_next) perror_exit("connect"); 39 | close(fd); 40 | } 41 | freeaddrinfo(ai2); 42 | 43 | return fd; 44 | } 45 | 46 | int xpoll(struct pollfd *fds, int nfds, int timeout) 47 | { 48 | int i; 49 | 50 | for (;;) { 51 | if (0>(i = poll(fds, nfds, timeout))) { 52 | if (toys.signal) return i; 53 | if (errno != EINTR && errno != ENOMEM) perror_exit("xpoll"); 54 | else if (timeout>0) timeout--; 55 | } else return i; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /www/header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 41 | 42 |
6 |

toybox

7 | 8 | About 9 | 23 | Download 24 | 29 | Development 30 | 40 |
43 | 44 | -------------------------------------------------------------------------------- /tests/cmp.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | testing "not enough arguments [fail]" "cmp input 2>/dev/null || echo yes" "yes\n" "foo" "" 6 | testing "missing file1 [fail]" "cmp file1 input 2>/dev/null || echo yes" "yes\n" "foo" "" 7 | 8 | #mkdir dir 9 | #testing "directory [fail]" "cmp dir dir 2>/dev/null || echo yes" \ 10 | #"yes\n" "" "" 11 | #rmdir dir 12 | 13 | echo "ab 14 | c" > input2 15 | 16 | testing "identical files, stdout" "cmp input input2" "" "ab\nc\n" "" 17 | testing "identical files, return code" "cmp input input2 && echo yes" "yes\n" "ab\nc\n" "" 18 | 19 | testing "EOF, stderr" "cmp input input2 2>&1" "cmp: EOF on input2\n" "ab\nc\nx" "" 20 | testing "EOF, return code" "cmp input input2 2>/dev/null || echo yes" "yes\n" "ab\nc\nx" "" 21 | # The gnu/dammit version fails this because posix says "char" and they don't. 22 | testing "diff, stdout" "cmp input input2" "input input2 differ: char 4, line 2\n" "ab\nx\nx" "" 23 | testing "diff, return code" "cmp input input2 > /dev/null || echo yes" "yes\n" "ab\nx\nx" "" 24 | 25 | testing "-s EOF, return code" "cmp -s input input2 2>&1 || echo yes" "yes\n" "ab\nc\nx" "" 26 | testing "-s diff, return code" "cmp -s input input2 2>&1 || echo yes" "yes\n" "ab\nx\nx" "" 27 | 28 | testing "-l EOF, stderr" "cmp -l input input2 2>&1" "cmp: EOF on input2\n" "ab\nc\nx" "" 29 | testing "-l diff and EOF, stdout and stderr" "cmp -l input input2 2>&1 | sort" "4 170 143\ncmp: EOF on input2\n" "ab\nx\nx" "" 30 | 31 | testing "-s not exist" "cmp -s input doesnotexist 2>&1 || echo yes" "yes\n" "" "" 32 | 33 | rm input2 34 | 35 | testing "stdin and file" "cmp input -" "input - differ: char 4, line 2\n" "ab\nc\n" "ab\nx\n" 36 | #testing "stdin and stdin" "cmp input -" "" "" "ab\nc\n" 37 | 38 | -------------------------------------------------------------------------------- /toys/other/which.c: -------------------------------------------------------------------------------- 1 | /* which.c - Find executable files in $PATH. 2 | * 3 | * Copyright 2006 Rob landley 4 | 5 | USE_WHICH(NEWTOY(which, "<1a", TOYFLAG_USR|TOYFLAG_BIN)) 6 | 7 | config WHICH 8 | bool "which" 9 | default y 10 | help 11 | usage: which [-a] filename ... 12 | 13 | Search $PATH for executable files matching filename(s). 14 | 15 | -a Show all matches 16 | */ 17 | #include "toys.h" 18 | 19 | // Find an exectuable file either at a path with a slash in it (absolute or 20 | // relative to current directory), or in $PATH. Returns absolute path to file, 21 | // or NULL if not found. 22 | 23 | static int which_in_path(char *filename) 24 | { 25 | struct string_list *list; 26 | 27 | // If they gave us a path, don't worry about $PATH or -a 28 | 29 | if (strchr(filename, '/')) { 30 | // Confirm it has the executable bit set, and it's not a directory. 31 | if (!access(filename, X_OK)) { 32 | struct stat st; 33 | 34 | if (!stat(filename, &st) && S_ISREG(st.st_mode)) { 35 | puts(filename); 36 | return 0; 37 | } 38 | return 1; 39 | } 40 | } 41 | 42 | // Search $PATH for matches. 43 | list = find_in_path(getenv("PATH"), filename); 44 | if (!list) return 1; 45 | 46 | // Print out matches 47 | while (list) { 48 | if (!access(list->str, X_OK)) { 49 | puts(list->str); 50 | // If we should stop at one match, do so 51 | if (!toys.optflags) { 52 | llist_traverse(list, free); 53 | break; 54 | } 55 | } 56 | free(llist_pop(&list)); 57 | } 58 | 59 | return 0; 60 | } 61 | 62 | void which_main(void) 63 | { 64 | int i; 65 | 66 | for (i=0; toys.optargs[i]; i++) 67 | toys.exitval |= which_in_path(toys.optargs[i]); 68 | } 69 | -------------------------------------------------------------------------------- /toys/other/free.c: -------------------------------------------------------------------------------- 1 | /* free.c - Display amount of free and used memory in the system. 2 | * 3 | * Copyright 2012 Elie De Brauwer 4 | 5 | // Flag order is signifcant: b-t are units in order, FLAG_h-1 is unit mask 6 | USE_FREE(NEWTOY(free, "htgmkb[!htgmkb]", TOYFLAG_USR|TOYFLAG_BIN)) 7 | 8 | config FREE 9 | bool "free" 10 | default y 11 | help 12 | usage: free [-bkmgt] 13 | 14 | Display the total, free and used amount of physical memory and swap space. 15 | 16 | -bkmgt Output units (default is bytes) 17 | -h Human readable 18 | */ 19 | 20 | #define FOR_free 21 | #include "toys.h" 22 | 23 | GLOBALS( 24 | unsigned bits; 25 | unsigned long long units; 26 | char *buf; 27 | ) 28 | 29 | static char *convert(unsigned long d) 30 | { 31 | long long ll = d*TT.units; 32 | char *s = TT.buf; 33 | 34 | if (toys.optflags & FLAG_h) human_readable(s, ll, 0); 35 | else sprintf(s, "%llu",ll>>TT.bits); 36 | TT.buf += strlen(TT.buf)+1; 37 | 38 | return s; 39 | } 40 | 41 | void free_main(void) 42 | { 43 | struct sysinfo in; 44 | 45 | sysinfo(&in); 46 | TT.units = in.mem_unit ? in.mem_unit : 1; 47 | while ((toys.optflags&(FLAG_h-1)) && !(toys.optflags&(1< 4 | * 5 | * http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/mknod.html 6 | 7 | USE_MKNOD(NEWTOY(mknod, "<2>4m(mode):"USE_MKNOD_Z("Z:"), TOYFLAG_BIN|TOYFLAG_UMASK)) 8 | 9 | config MKNOD 10 | bool "mknod" 11 | default y 12 | help 13 | usage: mknod [-m MODE] NAME TYPE [MAJOR MINOR] 14 | 15 | Create a special file NAME with a given type. TYPE is b for block device, 16 | c or u for character device, p for named pipe (which ignores MAJOR/MINOR). 17 | 18 | -m Mode (file permissions) of new device, in octal or u+x format 19 | 20 | config MKNOD_Z 21 | bool 22 | default y 23 | depends on MKNOD && !TOYBOX_LSM_NONE 24 | help 25 | usage: mknod [-Z CONTEXT] ... 26 | 27 | -Z Set security context to created file 28 | */ 29 | 30 | #define FOR_mknod 31 | #include "toys.h" 32 | 33 | GLOBALS( 34 | char *arg_context; 35 | char *m; 36 | ) 37 | 38 | void mknod_main(void) 39 | { 40 | mode_t modes[] = {S_IFIFO, S_IFCHR, S_IFCHR, S_IFBLK}; 41 | int major=0, minor=0, type; 42 | int mode = TT.m ? string_to_mode(TT.m, 0777) : 0660; 43 | 44 | type = stridx("pcub", *toys.optargs[1]); 45 | if (type == -1) perror_exit("bad type '%c'", *toys.optargs[1]); 46 | if (type) { 47 | if (toys.optc != 4) perror_exit("need major/minor"); 48 | 49 | major = atoi(toys.optargs[2]); 50 | minor = atoi(toys.optargs[3]); 51 | } 52 | 53 | if (toys.optflags & FLAG_Z) 54 | if (-1 == lsm_set_create(TT.arg_context)) 55 | perror_exit("-Z '%s' failed", TT.arg_context); 56 | if (mknod(*toys.optargs, mode|modes[type], dev_makedev(major, minor))) 57 | perror_exit_raw(*toys.optargs); 58 | } 59 | -------------------------------------------------------------------------------- /toys/lsb/mktemp.c: -------------------------------------------------------------------------------- 1 | /* mktemp.c - Create a temporary file or directory. 2 | * 3 | * Copyright 2012 Elie De Brauwer 4 | * 5 | * http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/mktemp.html 6 | 7 | USE_MKTEMP(NEWTOY(mktemp, ">1uqd(directory)p(tmpdir):", TOYFLAG_BIN)) 8 | 9 | config MKTEMP 10 | bool "mktemp" 11 | default y 12 | help 13 | usage: mktemp [-dqu] [-p DIR] [TEMPLATE] 14 | 15 | Safely create a new file "DIR/TEMPLATE" and print its name. 16 | 17 | -d Create directory instead of file (--directory) 18 | -p Put new file in DIR (--tmpdir) 19 | -q Quiet, no error messages 20 | -u Don't create anything, just print what would be created 21 | 22 | Each X in TEMPLATE is replaced with a random printable character. The 23 | default TEMPLATE is tmp.XXXXXX, and the default DIR is $TMPDIR if set, 24 | else "/tmp". 25 | */ 26 | 27 | #define FOR_mktemp 28 | #include "toys.h" 29 | 30 | GLOBALS( 31 | char *tmpdir; 32 | ) 33 | 34 | void mktemp_main(void) 35 | { 36 | int d_flag = toys.optflags & FLAG_d; 37 | char *template = *toys.optargs; 38 | 39 | if (!template) template = "tmp.XXXXXX"; 40 | 41 | if (!TT.tmpdir) TT.tmpdir = getenv("TMPDIR"); 42 | if (!TT.tmpdir || !*TT.tmpdir) TT.tmpdir = "/tmp"; 43 | 44 | template = strchr(template, '/') ? xstrdup(template) 45 | : xmprintf("%s/%s", TT.tmpdir, template); 46 | 47 | if (d_flag ? !mkdtemp(template) : mkstemp(template) == -1) { 48 | if (toys.optflags & FLAG_q) toys.exitval = 1; 49 | else perror_exit("Failed to create %s %s/%s", 50 | d_flag ? "directory" : "file", TT.tmpdir, template); 51 | } else { 52 | if (toys.optflags & FLAG_u) unlink(template); 53 | xputs(template); 54 | } 55 | 56 | if (CFG_TOYBOX_FREE) free(template); 57 | } 58 | -------------------------------------------------------------------------------- /toys/posix/uname.c: -------------------------------------------------------------------------------- 1 | /* uname.c - return system name 2 | * 3 | * Copyright 2008 Rob Landley 4 | * 5 | * See http://opengroup.org/onlinepubs/9699919799/utilities/uname.html 6 | 7 | USE_UNAME(NEWTOY(uname, "oamvrns[+os]", TOYFLAG_BIN)) 8 | 9 | config UNAME 10 | bool "uname" 11 | default y 12 | help 13 | usage: uname [-asnrvm] 14 | 15 | Print system information. 16 | 17 | -s System name 18 | -n Network (domain) name 19 | -r Kernel Release number 20 | -v Kernel Version 21 | -m Machine (hardware) name 22 | -a All of the above 23 | */ 24 | 25 | #define FOR_uname 26 | #include "toys.h" 27 | 28 | // If a 32 bit x86 build environment working in a chroot under an x86-64 29 | // kernel returns x86_64 for -m it confuses ./configure. Special case it. 30 | 31 | #if defined(__i686__) 32 | #define GROSS "i686" 33 | #elif defined(__i586__) 34 | #define GROSS "i586" 35 | #elif defined(__i486__) 36 | #define GROSS "i486" 37 | #elif defined(__i386__) 38 | #define GROSS "i386" 39 | #endif 40 | 41 | void uname_main(void) 42 | { 43 | int i, flags = toys.optflags, needspace=0; 44 | 45 | uname((void *)toybuf); 46 | 47 | if (!flags) flags = FLAG_s; 48 | for (i=0; i<5; i++) { 49 | char *c = toybuf+(65*i); 50 | 51 | if (flags & ((1< 4 | 5 | USE_TRUNCATE(NEWTOY(truncate, "<1s:|c", TOYFLAG_BIN)) 6 | 7 | config TRUNCATE 8 | bool "truncate" 9 | default y 10 | help 11 | usage: truncate [-c] -s SIZE file... 12 | 13 | Set length of file(s), extending sparsely if necessary. 14 | 15 | -c Don't create file if it doesn't exist. 16 | -s New size (with optional prefix and suffix) 17 | 18 | SIZE prefix: + add, - subtract, < shrink to, > expand to, 19 | / multiple rounding down, % multiple rounding up 20 | SIZE suffix: k=1024, m=1024^2, g=1024^3, t=1024^4, p=1024^5, e=1024^6 21 | */ 22 | 23 | #define FOR_truncate 24 | #include "toys.h" 25 | 26 | GLOBALS( 27 | char *s; 28 | 29 | long size; 30 | int type; 31 | ) 32 | 33 | static void do_truncate(int fd, char *name) 34 | { 35 | long long size; 36 | 37 | if (fd<0) return; 38 | 39 | if (TT.type == -1) size = TT.size; 40 | else { 41 | size = fdlength(fd); 42 | if (TT.type<2) size += TT.size*(1-(2*TT.type)); 43 | else if (TT.type<4) { 44 | if ((TT.type==2) ? (size <= TT.size) : (size >= TT.size)) return; 45 | size = TT.size; 46 | } else { 47 | size = (size+(TT.type-4)*(TT.size-1))/TT.size; 48 | size *= TT.size; 49 | } 50 | } 51 | if (ftruncate(fd, size)) perror_msg("'%s' to '%lld'", name, size); 52 | } 53 | 54 | void truncate_main(void) 55 | { 56 | int cr = !(toys.optflags&FLAG_c); 57 | 58 | if (-1 != (TT.type = stridx("+-<>/%", *TT.s))) TT.s++; 59 | TT.size = atolx(TT.s); 60 | 61 | // Create files with mask rwrwrw. 62 | // Nonexistent files are only an error if we're supposed to create them. 63 | loopfiles_rw(toys.optargs, O_WRONLY|O_CLOEXEC|(cr ? O_CREAT|WARN_ONLY : 0), 64 | 0666, do_truncate); 65 | } 66 | -------------------------------------------------------------------------------- /tests/test.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | # TODO: Should also have device and socket files 8 | 9 | mkdir d 10 | touch f 11 | ln -s /dev/null L 12 | echo nonempty > s 13 | mkfifo p 14 | 15 | type_test() 16 | { 17 | result="" 18 | for i in d f L s p n 19 | do 20 | if test $* $i 21 | then 22 | result=$result$i 23 | fi 24 | done 25 | printf "%s" $result 26 | } 27 | 28 | testing "-b" "type_test -b" "" "" "" 29 | testing "-c" "type_test -c" "L" "" "" 30 | testing "-d" "type_test -d" "d" "" "" 31 | testing "-f" "type_test -f" "fs" "" "" 32 | testing "-h" "type_test -h" "L" "" "" 33 | testing "-L" "type_test -L" "L" "" "" 34 | testing "-s" "type_test -s" "ds" "" "" 35 | testing "-S" "type_test -S" "" "" "" 36 | testing "-p" "type_test -p" "p" "" "" 37 | testing "-e" "type_test -e" "dfLsp" "" "" 38 | testing "! -e" "type_test ! -e" "n" "" "" 39 | 40 | rm f L s p 41 | rmdir d 42 | 43 | # TODO: Test rwx gu t 44 | 45 | testing "test" "test "" || test a && echo yes" "yes\n" "" "" 46 | testing "-n" "test -n "" || test -n a && echo yes" "yes\n" "" "" 47 | testing "-z" "test -n a || test -n "" && echo yes" "yes\n" "" "" 48 | testing "a = b" "test a = b || test "" = "" && echo yes" "yes\n" "" "" 49 | testing "a != b" "test "" != "" || test a = b && echo yes" "yes\n" "" "" 50 | 51 | arith_test() 52 | { 53 | test -1 $1 1 && echo l 54 | test 0 $1 0 && echo e 55 | test -3 $1 -5 && echo g 56 | } 57 | 58 | testing "-eq" "arith_test -eq" "e\n" "" "" 59 | testing "-ne" "arith_test -ne" "l\ng\n" "" "" 60 | testing "-gt" "arith_test -gt" "g\n" "" "" 61 | testing "-ge" "arith_test -ge" "e\ng\n" "" "" 62 | testing "-lt" "arith_test -lt" "l\n" "" "" 63 | testing "-le" "arith_test -le" "l\ne\n" "" "" 64 | 65 | # test ! = -o a 66 | # test ! \( = -o a \) 67 | # test \( ! = \) -o a 68 | -------------------------------------------------------------------------------- /toys/pending/groupdel.c: -------------------------------------------------------------------------------- 1 | /* groupdel.c - delete a group 2 | * 3 | * Copyright 2013 Ashwini Kumar 4 | * Copyright 2013 Kyungwan Han 5 | * 6 | * See http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/groupdel.html 7 | 8 | USE_GROUPDEL(NEWTOY(groupdel, "<1>2", TOYFLAG_NEEDROOT|TOYFLAG_SBIN)) 9 | USE_GROUPDEL(OLDTOY(delgroup, groupdel, TOYFLAG_NEEDROOT|TOYFLAG_SBIN)) 10 | 11 | config GROUPDEL 12 | bool "groupdel" 13 | default n 14 | help 15 | usage: groupdel [USER] GROUP 16 | 17 | Delete a group or remove a user from a group 18 | */ 19 | 20 | #define FOR_groupdel 21 | #include "toys.h" 22 | 23 | void groupdel_main(void) 24 | { 25 | struct group *grp = xgetgrnam(toys.optargs[toys.optc-1]); 26 | char *entry = 0; 27 | 28 | // delete user from group 29 | if (toys.optc == 2) { 30 | int i, len = 0, found = 0; 31 | char *s; 32 | 33 | xgetpwnam(*toys.optargs); 34 | if (grp->gr_mem) for (i = 0; grp->gr_mem[i]; i++) { 35 | if (!found && !strcmp(*toys.optargs, grp->gr_mem[i])) found++; 36 | else len += strlen(grp->gr_mem[i]) + 1; 37 | } 38 | if (!found) 39 | error_exit("user '%s' not in group '%s'", *toys.optargs, toys.optargs[1]); 40 | 41 | entry = s = xmalloc(len); 42 | for (i = 0; grp->gr_mem[i]; ) { 43 | if (i) *(s++) = ','; 44 | s = stpcpy(s, grp->gr_mem[i]); 45 | } 46 | 47 | // delete group 48 | } else { 49 | struct passwd *pw; 50 | 51 | for (endpwent(); (pw = getpwent());) 52 | if (pw->pw_gid == grp->gr_gid) break; 53 | 54 | if (pw) error_exit("can't remove primary group of user '%s'", pw->pw_name); 55 | if (CFG_TOYBOX_FREE) endpwent(); 56 | } 57 | 58 | update_password("/etc/group", grp->gr_name, entry); 59 | update_password("/etc/gshadow", grp->gr_name, entry); 60 | if (CFG_TOYBOX_FREE) free(entry); 61 | } 62 | -------------------------------------------------------------------------------- /toys/posix/strings.c: -------------------------------------------------------------------------------- 1 | /*strings.c - print the strings of printable characters in files. 2 | * 3 | * Copyright 2014 Kyung-su Kim 4 | * Copyright 2014 Kyungwan Han 5 | * 6 | * No Standard 7 | * TODO: utf8 strings 8 | * TODO: posix -t 9 | 10 | USE_STRINGS(NEWTOY(strings, "an#=4<1fo", TOYFLAG_USR|TOYFLAG_BIN)) 11 | 12 | config STRINGS 13 | bool "strings" 14 | default y 15 | help 16 | usage: strings [-fo] [-n LEN] [FILE...] 17 | 18 | Display printable strings in a binary file 19 | 20 | -f Precede strings with filenames 21 | -n At least LEN characters form a string (default 4) 22 | -o Precede strings with decimal offsets 23 | */ 24 | 25 | #define FOR_strings 26 | #include "toys.h" 27 | 28 | GLOBALS( 29 | long num; 30 | ) 31 | 32 | static void do_strings(int fd, char *filename) 33 | { 34 | int nread, i, wlen = TT.num, count = 0; 35 | off_t offset = 0; 36 | char *string = xzalloc(wlen + 1); 37 | 38 | for (;;) { 39 | nread = read(fd, toybuf, sizeof(toybuf)); 40 | if (nread < 0) perror_msg_raw(filename); 41 | if (nread < 1) break; 42 | for (i = 0; i < nread; i++, offset++) { 43 | if (((toybuf[i] >= 32) && (toybuf[i] <= 126)) || (toybuf[i] == '\t')) { 44 | if (count == wlen) fputc(toybuf[i], stdout); 45 | else { 46 | string[count++] = toybuf[i]; 47 | if (count == wlen) { 48 | if (toys.optflags & FLAG_f) printf("%s: ", filename); 49 | if (toys.optflags & FLAG_o) 50 | printf("%7lld ",(long long)(offset - wlen)); 51 | printf("%s", string); 52 | } 53 | } 54 | } else { 55 | if (count == wlen) xputc('\n'); 56 | count = 0; 57 | } 58 | } 59 | } 60 | xclose(fd); 61 | free(string); 62 | } 63 | 64 | void strings_main(void) 65 | { 66 | loopfiles(toys.optargs, do_strings); 67 | } 68 | -------------------------------------------------------------------------------- /toys/other/factor.c: -------------------------------------------------------------------------------- 1 | /* factor.c - Factor integers 2 | * 3 | * Copyright 2014 Rob Landley 4 | * 5 | * No standard, but it's in coreutils 6 | 7 | USE_FACTOR(NEWTOY(factor, 0, TOYFLAG_USR|TOYFLAG_BIN)) 8 | 9 | config FACTOR 10 | bool "factor" 11 | default y 12 | help 13 | usage: factor NUMBER... 14 | 15 | Factor integers. 16 | */ 17 | 18 | #include "toys.h" 19 | 20 | static void factor(char *s) 21 | { 22 | unsigned long long l, ll; 23 | 24 | for (;;) { 25 | char *err = s; 26 | int dash = 0; 27 | 28 | while(isspace(*s)) s++; 29 | if (*s=='-') dash = *s++; 30 | if (!*s) return; 31 | 32 | l = strtoull(s, &s, 0); 33 | if (*s && !isspace(*s)) { 34 | error_msg("%s: not integer", err); 35 | while (*s && !isspace(*s)) s++; 36 | continue; 37 | } 38 | 39 | printf("-%llu:"+!dash, l); 40 | 41 | // Negative numbers have -1 as a factor 42 | if (dash) printf(" -1"); 43 | 44 | // Nothing below 4 has factors 45 | if (l < 4) { 46 | printf(" %llu\n", l); 47 | continue; 48 | } 49 | 50 | // Special case factors of 2 51 | while (l && !(l&1)) { 52 | printf(" 2"); 53 | l >>= 1; 54 | } 55 | 56 | // test odd numbers until square is > remainder or integer wrap. 57 | for (ll=3; ;ll += 2) { 58 | long lll = ll*ll; 59 | 60 | if (lll>l || lll1) printf(" %llu", l); 62 | break; 63 | } 64 | while (!(l%ll)) { 65 | printf(" %llu", ll); 66 | l /= ll; 67 | } 68 | } 69 | xputc('\n'); 70 | } 71 | } 72 | 73 | void factor_main(void) 74 | { 75 | if (toys.optc) { 76 | char **ss; 77 | 78 | for (ss = toys.optargs; *ss; ss++) factor(*ss); 79 | } else for (;;) { 80 | char *s = 0; 81 | size_t len = 0; 82 | 83 | if (-1 == getline(&s, &len, stdin)) break; 84 | factor(s); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /tests/sha1sum.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | # These tests are based on RFC3174 which were based on FIPS PUB 180-1 8 | 9 | testing "TEST1" \ 10 | "sha1sum" \ 11 | "a9993e364706816aba3e25717850c26c9cd0d89d -\n" \ 12 | "" "abc" 13 | 14 | testing "TEST2" \ 15 | "sha1sum" \ 16 | "84983e441c3bd26ebaae4aa1f95129e5e54670f1 -\n" \ 17 | "" "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" 18 | 19 | testing "TEST3" \ 20 | 'dd if=/dev/zero bs=1000 count=1000 2>/dev/null | tr \\0 a | sha1sum' \ 21 | "34aa973cd4c4daa4f61eeb2bdbad27316534016f -\n" \ 22 | "" "" 23 | 24 | testing "TEST4" \ 25 | 'for i in `seq 1 10`; do echo -n 0123456701234567012345670123456701234567012345670123456701234567 ; done | sha1sum' \ 26 | "dea356a2cddd90c7a7ecedc5ebb563934f460452 -\n" \ 27 | "" "" 28 | 29 | echo -n "abc" > file1 30 | echo -n "def" > file2 31 | testing "sha1sum" \ 32 | "sha1sum" \ 33 | "a9993e364706816aba3e25717850c26c9cd0d89d -\n" \ 34 | "" "abc" 35 | 36 | testing "-" \ 37 | "sha1sum -" \ 38 | "a9993e364706816aba3e25717850c26c9cd0d89d -\n" \ 39 | "" "abc" 40 | 41 | testing "file" \ 42 | "sha1sum file1" \ 43 | "a9993e364706816aba3e25717850c26c9cd0d89d file1\n" \ 44 | "" "" 45 | 46 | testing "file1 file2" \ 47 | "sha1sum file1 file2" \ 48 | "a9993e364706816aba3e25717850c26c9cd0d89d file1\n589c22335a381f122d129225f5c0ba3056ed5811 file2\n" \ 49 | "" "" 50 | 51 | testing "file1 file2 -" \ 52 | "sha1sum file1 file2 -" \ 53 | "a9993e364706816aba3e25717850c26c9cd0d89d file1\n589c22335a381f122d129225f5c0ba3056ed5811 file2\na9993e364706816aba3e25717850c26c9cd0d89d -\n" \ 54 | "" "abc" 55 | 56 | rm -f file1 file2 57 | 58 | -------------------------------------------------------------------------------- /tests/blkid.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | BDIR="$FILES/blkid" 8 | 9 | bzcat "$BDIR"/squashfs.bz2 > temp.img 10 | testing "file" "blkid temp.img" 'temp.img: TYPE="squashfs"\n' "" "" 11 | rm temp.img 12 | 13 | testing "cramfs" 'bzcat "$BDIR"/cramfs.bz2 | blkid -' \ 14 | '-: LABEL="mycramfs" TYPE="cramfs"\n' "" "" 15 | testing "ext2" 'bzcat "$BDIR"/ext2.bz2 | blkid -' \ 16 | '-: LABEL="myext2" UUID="e59093ba-4135-4fdb-bcc4-f20beae4dfaf" TYPE="ext2"\n' \ 17 | "" "" 18 | testing "ext3" 'bzcat "$BDIR"/ext3.bz2 | blkid -' \ 19 | '-: LABEL="myext3" UUID="79d1c877-1a0f-4e7d-b21d-fc32ae3ef101" TYPE="ext3"\n' \ 20 | "" "" 21 | testing "ext4" 'bzcat "$BDIR"/ext4.bz2 | blkid -' \ 22 | '-: LABEL="myext4" UUID="dc4b7c00-c0c0-4600-af7e-0335f09770fa" TYPE="ext4"\n' \ 23 | "" "" 24 | testing "f2fs" 'bzcat "$BDIR"/f2fs.bz2 | blkid -' \ 25 | '-: LABEL="" UUID="b53d3619-c204-4c0b-8504-36363578491c" TYPE="f2fs"\n' \ 26 | "" "" 27 | testing "msdos" 'bzcat "$BDIR"/msdos.bz2 | blkid -' \ 28 | '-: LABEL="mymsdos" UUID="5108-1e6e" TYPE="vfat"\n' "" "" 29 | testing "ntfs" 'bzcat "$BDIR"/ntfs.bz2 | blkid -' \ 30 | '-: UUID="8585600838bfe16e" TYPE="ntfs"\n' "" "" 31 | testing "reiserfs" 'bzcat "$BDIR"/reiser3.bz2 | blkid -' \ 32 | '-: LABEL="myreiser" UUID="a5b99bec-45cc-41d7-986e-32f4b6fc28f2" TYPE="reiserfs"\n' \ 33 | "" "" 34 | testing "squashfs" 'bzcat "$BDIR"/squashfs.bz2 | blkid -' \ 35 | '-: TYPE="squashfs"\n' "" "" 36 | testing "vfat" 'bzcat "$BDIR"/vfat.bz2 | blkid -' \ 37 | '-: LABEL="myvfat" UUID="1db9-5673" TYPE="vfat"\n' "" "" 38 | testing "xfs" 'bzcat "$BDIR"/xfs.bz2 | blkid -' \ 39 | '-: LABEL="XFS_test" UUID="d63a1dc3-27d5-4dd4-8b38-f4f97f495c6f" TYPE="xfs"\n' \ 40 | "" "" 41 | 42 | #testing "minix" 'bzcat "$BDIR"/minix.bz2 | blkid -' 43 | #adfs bfs btrfs cramfs jfs nilfs romfs 44 | #vfat // fat32 fat12 fat16 45 | -------------------------------------------------------------------------------- /kconfig/lkc_proto.h: -------------------------------------------------------------------------------- 1 | 2 | /* confdata.c */ 3 | P(conf_parse,void,(const char *name)); 4 | P(conf_read,int,(const char *name)); 5 | P(conf_read_simple,int,(const char *name, int)); 6 | P(conf_write,int,(const char *name)); 7 | P(conf_write_autoconf,int,(void)); 8 | 9 | /* menu.c */ 10 | P(rootmenu,struct menu,); 11 | 12 | P(menu_is_visible,bool,(struct menu *menu)); 13 | P(menu_get_prompt,const char *,(struct menu *menu)); 14 | P(menu_get_root_menu,struct menu *,(struct menu *menu)); 15 | P(menu_get_parent_menu,struct menu *,(struct menu *menu)); 16 | 17 | /* symbol.c */ 18 | P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]); 19 | P(sym_change_count,int,); 20 | 21 | P(sym_lookup,struct symbol *,(const char *name, int isconst)); 22 | P(sym_find,struct symbol *,(const char *name)); 23 | P(sym_re_search,struct symbol **,(const char *pattern)); 24 | P(sym_type_name,const char *,(enum symbol_type type)); 25 | P(sym_calc_value,void,(struct symbol *sym)); 26 | P(sym_get_type,enum symbol_type,(struct symbol *sym)); 27 | P(sym_tristate_within_range,bool,(struct symbol *sym,tristate tri)); 28 | P(sym_set_tristate_value,bool,(struct symbol *sym,tristate tri)); 29 | P(sym_toggle_tristate_value,tristate,(struct symbol *sym)); 30 | P(sym_string_valid,bool,(struct symbol *sym, const char *newval)); 31 | P(sym_string_within_range,bool,(struct symbol *sym, const char *str)); 32 | P(sym_set_string_value,bool,(struct symbol *sym, const char *newval)); 33 | P(sym_is_changable,bool,(struct symbol *sym)); 34 | P(sym_get_choice_prop,struct property *,(struct symbol *sym)); 35 | P(sym_get_default_prop,struct property *,(struct symbol *sym)); 36 | P(sym_get_string_value,const char *,(struct symbol *sym)); 37 | 38 | P(prop_get_type_name,const char *,(enum prop_type type)); 39 | 40 | /* expr.c */ 41 | P(expr_compare_type,int,(enum expr_type t1, enum expr_type t2)); 42 | P(expr_print,void,(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken)); 43 | -------------------------------------------------------------------------------- /toys/pending/iconv.c: -------------------------------------------------------------------------------- 1 | /* iconv.c - Convert character encoding 2 | * 3 | * Copyright 2014 Felix Janda 4 | * 5 | * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/iconv.html 6 | 7 | USE_ICONV(NEWTOY(iconv, "cst:f:", TOYFLAG_USR|TOYFLAG_BIN)) 8 | 9 | config ICONV 10 | bool "iconv" 11 | default n 12 | depends on TOYBOX_ICONV 13 | help 14 | usage: iconv [-f FROM] [-t TO] [FILE...] 15 | 16 | Convert character encoding of files. 17 | 18 | -f convert from (default utf8) 19 | -t convert to (default utf8) 20 | */ 21 | 22 | #define FOR_iconv 23 | #include "toys.h" 24 | #include 25 | 26 | GLOBALS( 27 | char *from; 28 | char *to; 29 | 30 | void *ic; 31 | ) 32 | 33 | static void do_iconv(int fd, char *name) 34 | { 35 | char *outstart = toybuf+2048; 36 | size_t inleft = 0; 37 | int len = 1; 38 | 39 | do { 40 | size_t outleft = 2048; 41 | char *in = toybuf+inleft, *out = outstart; 42 | 43 | len = read(fd, in, 2048-inleft); 44 | 45 | if (len < 0) { 46 | perror_msg("read '%s'"); 47 | return; 48 | } 49 | inleft += len; 50 | 51 | do { 52 | if (iconv(TT.ic, &in, &inleft, &out, &outleft) == -1 53 | && (errno == EILSEQ || (in == toybuf+inleft-len && errno == EINVAL))) 54 | { 55 | if (outleft) { 56 | // Skip first byte of illegal sequence to avoid endless loops 57 | *(out++) = *(in++); 58 | inleft--; 59 | } 60 | } 61 | xwrite(1, outstart, out-outstart); 62 | // Top off input buffer 63 | memmove(in, toybuf, inleft); 64 | } while (len < 1 && inleft); 65 | } while (len > 0); 66 | } 67 | 68 | void iconv_main(void) 69 | { 70 | TT.ic = iconv_open(TT.to ? TT.to : "utf8", TT.from ? TT.from : "utf8"); 71 | if (TT.ic == (iconv_t)-1) error_exit("bad encoding"); 72 | loopfiles(toys.optargs, do_iconv); 73 | if (CFG_TOYBOX_FREE) iconv_close(TT.ic); 74 | } 75 | -------------------------------------------------------------------------------- /kconfig/lxdialog/check-lxdialog.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Check ncurses compatibility 3 | 4 | # What library to link 5 | ldflags() 6 | { 7 | $cc -print-file-name=libncursesw.so | grep -q / 8 | if [ $? -eq 0 ]; then 9 | echo '-lncursesw' 10 | exit 11 | fi 12 | $cc -print-file-name=libncurses.so | grep -q / 13 | if [ $? -eq 0 ]; then 14 | echo '-lncurses' 15 | exit 16 | fi 17 | $cc -print-file-name=libcurses.so | grep -q / 18 | if [ $? -eq 0 ]; then 19 | echo '-lcurses' 20 | exit 21 | fi 22 | exit 1 23 | } 24 | 25 | # Where is ncurses.h? 26 | ccflags() 27 | { 28 | if [ -f /usr/include/ncurses/ncurses.h ]; then 29 | echo '-I/usr/include/ncurses -DCURSES_LOC=""' 30 | elif [ -f /usr/include/ncurses/curses.h ]; then 31 | echo '-I/usr/include/ncurses -DCURSES_LOC=""' 32 | elif [ -f /usr/include/ncurses.h ]; then 33 | echo '-DCURSES_LOC=""' 34 | else 35 | echo '-DCURSES_LOC=""' 36 | fi 37 | } 38 | 39 | # Temp file, try to clean up after us 40 | tmp=.lxdialog.tmp 41 | trap "rm -f $tmp" 0 1 2 3 15 42 | 43 | # Check if we can link to ncurses 44 | check() { 45 | echo "main() {}" | $cc -xc - -o $tmp 2> /dev/null 46 | if [ $? != 0 ]; then 47 | echo " *** Unable to find the ncurses libraries." 1>&2 48 | echo " *** make menuconfig require the ncurses libraries" 1>&2 49 | echo " *** " 1>&2 50 | echo " *** Install ncurses (ncurses-devel) and try again" 1>&2 51 | echo " *** " 1>&2 52 | exit 1 53 | fi 54 | } 55 | 56 | usage() { 57 | printf "Usage: $0 [-check compiler options|-header|-library]\n" 58 | } 59 | 60 | if [ $# == 0 ]; then 61 | usage 62 | exit 1 63 | fi 64 | 65 | cc="" 66 | case "$1" in 67 | "-check") 68 | shift 69 | cc="$@" 70 | check 71 | ;; 72 | "-ccflags") 73 | ccflags 74 | ;; 75 | "-ldflags") 76 | shift 77 | cc="$@" 78 | ldflags 79 | ;; 80 | "*") 81 | usage 82 | exit 1 83 | ;; 84 | esac 85 | -------------------------------------------------------------------------------- /toys/pending/watch.c: -------------------------------------------------------------------------------- 1 | /* watch.c - Execute a program periodically 2 | * 3 | * Copyright 2013 Sandeep Sharma 4 | * Copyright 2013 Kyungwan Han 5 | * 6 | USE_WATCH(NEWTOY(watch, "^<1n#<0=2te", TOYFLAG_USR|TOYFLAG_BIN)) 7 | 8 | config WATCH 9 | bool "watch" 10 | default n 11 | help 12 | usage: watch [-n SEC] [-t] PROG ARGS 13 | 14 | Run PROG periodically 15 | 16 | -n Loop period in seconds (default 2) 17 | -t Don't print header 18 | -e Freeze updates on command error, and exit after enter. 19 | */ 20 | #define FOR_watch 21 | #include "toys.h" 22 | 23 | GLOBALS( 24 | int interval; 25 | ) 26 | 27 | void watch_main(void) 28 | { 29 | int i = 0, hlen; 30 | time_t t; 31 | unsigned width = 80, len = sizeof("Www Mmm dd hh:mm:ss yyyy") - 1 ; 32 | char *header, *cmd = *toys.optargs; 33 | int retval; 34 | 35 | while(toys.optargs[++i]) 36 | { 37 | char * oldcmd = cmd; 38 | cmd = xmprintf("%s %s", oldcmd, toys.optargs[i]); 39 | if (CFG_TOYBOX_FREE) free(oldcmd); 40 | } 41 | header = xmprintf("Every %us: %s", TT.interval, cmd); 42 | hlen = strlen(header); 43 | 44 | while(1) { 45 | xprintf("\033[H\033[J"); 46 | if(!(toys.optflags & FLAG_t)) { 47 | terminal_size(&width, NULL); 48 | if (!width) width = 80; //on serial it may return 0. 49 | time(&t); 50 | if (width > (hlen + len)) xprintf("%s", header); 51 | if(width >= len) 52 | xprintf("%*s\n",width + ((width > (hlen + len))?-hlen:0) + 1, ctime(&t)); 53 | else 54 | xprintf("\n\n"); 55 | } 56 | fflush(NULL); //making sure the screen is clear 57 | retval = system(cmd); 58 | if ((toys.optflags & FLAG_e) && retval){ 59 | xprintf("command exit with non-zero status, press enter to exit\n"); 60 | getchar(); 61 | break; 62 | } 63 | sleep(TT.interval); 64 | } 65 | 66 | if (CFG_TOYBOX_FREE){ 67 | free(header); 68 | if (cmd != *toys.optargs) free(cmd); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /tests/nl.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | testing "nl" "nl" " 1\tone\n 2\ttwo\n 3\tthree\n" \ 8 | "" "one\ntwo\nthree\n" 9 | 10 | testing "explicit defaults" "nl -nrn -b a" \ 11 | " 1\tone\n 2\ttwo\n 3\tthree\n" "" "one\ntwo\nthree\n" 12 | 13 | # -n ln rn rz 14 | 15 | testing "-nln" "nl -nln" "1 \tone\n2 \ttwo\n3 \tthree\n" \ 16 | "" "one\ntwo\nthree\n" 17 | testing "-nln -w" "nl -nln -w 8" \ 18 | "1 \tone\n2 \ttwo\n3 \tthree\n" "" "one\ntwo\nthree\n" 19 | 20 | testing "-nrz" "nl -nrz" "000001\tone\n000002\ttwo\n000003\tthree\n" \ 21 | "" "one\ntwo\nthree\n" 22 | 23 | testing "-nrz -w" "nl -w3 -nrz" "001\tone\n002\ttwo\n003\tthree\n" \ 24 | "" "one\ntwo\nthree\n" 25 | 26 | 27 | # For non-matching lines the separator is "suppressed" meaning it... 28 | # turns into spaces! And the tab turns into one space, and -d boom turns 29 | # into 4 spaces, but these: 30 | # nl -s"$(echo -e 'bo\tom')" -bpand README 31 | # nl -w 3 -bpthe README 32 | # Yeah. And I doubt utf8 fontmetrics are used either. 33 | 34 | testing "-b t" "nl -b t" " \n 1\tone\n \n 2\ttwo\n" \ 35 | "" "\none\n\ntwo\n" 36 | testing "-b n" "nl -b n" " one\n two\n three\n" \ 37 | "" "one\ntwo\nthree\n" 38 | testing "-sook -b p" "nl -sook -bpoing" \ 39 | " one\n 1ookboing\n 2ooksproingy\n" \ 40 | "" "one\nboing\nsproingy\n" 41 | 42 | testing "-v" "nl -v 42" " 42\tone\n 43\ttwo\n 44\tthree\n" \ 43 | "" "one\ntwo\nthree\n" 44 | testing "-l" "nl -ba -l2 -w2 - input" \ 45 | " 1\tone\n \n 2\t\n 3\ttwo\n \n 4\t\n \n 5\tthree\n 6\tfour\n \n 7\t\n \n 8\tbang\n \n" \ 46 | "\n\nbang\n\n" "one\n\n\ntwo\n\n\n\nthree\nfour\n\n" 47 | testing "no space" "nl -w 1 -v 42" "42\tline\n" "" "line\n" 48 | 49 | # Should test for -E but no other implementation seems to have it? 50 | #testing "-E" "nl -w2 -sx -Ebp'(one|two)'" " 1x" "one\nand\ntwo\n" 51 | -------------------------------------------------------------------------------- /toys/other/dos2unix.c: -------------------------------------------------------------------------------- 1 | /* dos2unix.c - convert newline format 2 | * 3 | * Copyright 2012 Rob Landley 4 | 5 | USE_DOS2UNIX(NEWTOY(dos2unix, 0, TOYFLAG_BIN)) 6 | USE_UNIX2DOS(NEWTOY(unix2dos, 0, TOYFLAG_BIN)) 7 | 8 | config DOS2UNIX 9 | bool "dos2unix/unix2dos" 10 | default y 11 | help 12 | usage: dos2unix [FILE...] 13 | 14 | Convert newline format from dos "\r\n" to unix "\n". 15 | If no files listed copy from stdin, "-" is a synonym for stdin. 16 | 17 | config UNIX2DOS 18 | bool "unix2dos" 19 | default y 20 | help 21 | usage: unix2dos [FILE...] 22 | 23 | Convert newline format from unix "\n" to dos "\r\n". 24 | If no files listed copy from stdin, "-" is a synonym for stdin. 25 | */ 26 | 27 | #define FOR_dos2unix 28 | #include "toys.h" 29 | 30 | GLOBALS( 31 | char *tempfile; 32 | ) 33 | 34 | static void do_dos2unix(int fd, char *name) 35 | { 36 | char c = toys.which->name[0]; 37 | int outfd = 1, catch = 0; 38 | 39 | if (fd) outfd = copy_tempfile(fd, name, &TT.tempfile); 40 | 41 | for (;;) { 42 | int len, in, out; 43 | 44 | len = read(fd, toybuf+(sizeof(toybuf)/2), sizeof(toybuf)/2); 45 | if (len<0) perror_msg_raw(name); 46 | if (len<1) break; 47 | 48 | for (in = out = 0; in < len; in++) { 49 | char x = toybuf[in+sizeof(toybuf)/2]; 50 | 51 | // Drop \r only if followed by \n in dos2unix mode 52 | if (catch) { 53 | if (c == 'u' || x != '\n') toybuf[out++] = '\r'; 54 | catch = 0; 55 | // Add \r only if \n not after \r in unix2dos mode 56 | } else if (c == 'u' && x == '\n') toybuf[out++] = '\r'; 57 | 58 | if (x == '\r') catch++; 59 | else toybuf[out++] = x; 60 | } 61 | xwrite(outfd, toybuf, out); 62 | } 63 | if (catch) xwrite(outfd, "\r", 1); 64 | 65 | if (fd) replace_tempfile(-1, outfd, &TT.tempfile); 66 | } 67 | 68 | void dos2unix_main(void) 69 | { 70 | loopfiles(toys.optargs, do_dos2unix); 71 | } 72 | 73 | void unix2dos_main(void) 74 | { 75 | dos2unix_main(); 76 | } 77 | -------------------------------------------------------------------------------- /tests/sh.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | shellit() 8 | { 9 | EVAL="bash -c" testing "$2" "$1 printf %s $2" "$3" "$4" "$5" 10 | } 11 | 12 | # $'' expands special chars but doesn't do so inside double quotes. 13 | 14 | shellit "" "\$'a\\tb'" "a\tb" "" "" 15 | shellit "" "\"\$'a\\tb'\"" '$'"'"'a\\tb'"'" "" "" 16 | 17 | # $(( )) tests 18 | 19 | shellit 'x=1;' '$((-x))' '-1' '' '' 20 | shellit 'x=0;' '$((x++)); echo $x' '01\n' '' '' 21 | shellit 'x=0;' '$((++x))' '1' '' '' 22 | shellit 'x=0;' '$((~x))' '-1' '' '' 23 | shellit 'x=1;' '$((!x))' '0' '' '' 24 | shellit 'x=0;' '$((!x))' '1' '' '' 25 | shellit 'x=2;' '$((2*x))' '4' '' '' 26 | shellit 'x=9;' '$((x/4))' '2' '' '' 27 | shellit 'x=9;' '$((x%4))' '1' '' '' 28 | shellit 'x=4;' '$((x+2))' '6' '' '' 29 | shellit 'x=4;' '$((x-2))' '2' '' '' 30 | shellit 'x=4;' '$((1<>1))' '2' '' '' 32 | shellit '' '$((3**4))' '81' '' '' 33 | shellit '' '$((3<=4))' '1' '' '' 34 | shellit '' '$((3>=4))' '0' '' '' 35 | shellit '' '$((3<4))' '1' '' '' 36 | shellit '' '$((3>4))' '0' '' '' 37 | shellit '' '$((3==4))' '0' '' '' 38 | shellit '' '$((3!=4))' '1' '' '' 39 | shellit '' '$((6&4))' '4' '' '' 40 | shellit '' '$((4|2))' '6' '' '' 41 | shellit '' '$((6&&2))' '1' '' '' 42 | shellit '' '$((6||4))' '1' '' '' 43 | shellit '' '$((1?2:3))' '2' '' '' 44 | shellit 'x=2;' '$((x=3)); echo $x' '33\n' '' '' 45 | shellit 'x=2;' '$((x*=3)); echo $x' '66\n' '' '' 46 | shellit 'x=5;' '$((x/=2)); echo $x' '22\n' '' '' 47 | shellit 'x=9;' '$((x%=5)); echo $x' '44\n' '' '' 48 | shellit 'x=9;' '$((x-=3)); echo $x' '66\n' '' '' 49 | shellit 'x=3;' '$((x+=2)); echo $x' '55\n' '' '' 50 | shellit 'x=7;' '$((x&=13)); echo $x' '55\n' '' '' 51 | shellit 'x=5;' '$((x|=12)); echo $x' '1313\n' '' '' 52 | shellit 'x=5;' '$((x^=12)); echo $x' '99\n' '' '' 53 | shellit 'x=2;' '$((x<<=2)); echo $x' '88\n' '' '' 54 | shellit 'x=12;' '$((x>>=2)); echo $x' '33\n' '' '' 55 | shellit 'x=2;' '$((x++,5)); echo $x' '53\n' '' '' 56 | -------------------------------------------------------------------------------- /tests/cut.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2013 Robin Mittal 4 | # Copyright 2013 Divya Kothari 5 | # Copyright 2013 Kyungwan.Han 6 | 7 | [ -f testing.sh ] && . testing.sh 8 | 9 | #testing "name" "command" "result" "infile" "stdin" 10 | #set -x 11 | 12 | # Creating test file for testing cut 13 | echo "one:two:three:four:five:six:seven 14 | alpha:beta:gamma:delta:epsilon:zeta:eta:teta:iota:kappa:lambda:mu 15 | the quick brown fox jumps over the lazy dog" >abc.txt 16 | 17 | testing "with -c (a-b)" "cut -c 4-10 abc.txt" ":two:th\nha:beta\n quick \n" "" "" 18 | testing "with -f (a-)" "cut -d ':' -f 5- abc.txt" "five:six:seven\nepsilon:zeta:eta:teta:iota:kappa:lambda:mu\nthe quick brown fox jumps over the lazy dog\n" "" "" 19 | 20 | testing "with -f (a)" "cut -d ' ' -f 3 abc.txt" "one:two:three:four:five:six:seven\nalpha:beta:gamma:delta:epsilon:zeta:eta:teta:iota:kappa:lambda:mu\nbrown\n" "" "" 21 | 22 | testing "with echo, -c (a-b)" "echo 'ref_categorie=test' | cut -c 1-15 " "ref_categorie=t\n" "" "" 23 | testing "with echo, -c (a)" "echo 'ref_categorie=test' | cut -c 14" "=\n" "" "" 24 | 25 | # Modifying abc.txt data as per new testcase 26 | echo "abcdefghijklmnopqrstuvwxyz" >abc.txt 27 | 28 | testing "with -c (a,b,c)" "cut -c 4,5,20 abc.txt" "det\n" "" "" 29 | 30 | testing "with -b (a,b,c)" "cut -b 4,5,20 abc.txt" "det\n" "" "" 31 | 32 | # Modifying abc.txt data as per testcase 33 | echo "406378:Sales:Itorre:Jan 34 | 031762:Marketing:Nasium:Jim 35 | 636496:Research:Ancholie:Mel 36 | 396082:Sales:Jucacion:Ed" >abc.txt 37 | 38 | testing "with -d -f(:) -s" "cut -d: -f3 -s abc.txt" "Itorre\nNasium\nAncholie\nJucacion\n" "" "" 39 | 40 | testing "with -d -f( ) -s" "cut -d' ' -f3 -s abc.txt && echo yes" "yes\n" "" "" 41 | 42 | testing "with -d -f(a) -s" "cut -da -f3 -s abc.txt" "n\nsium:Jim\n\ncion:Ed\n" "" "" 43 | 44 | testing "with -d -f(a) -s -n" "cut -da -f3 -s -n abc.txt" "n\nsium:Jim\n\ncion:Ed\n" "" "" 45 | 46 | # Removing abc.txt file for cleanup purpose 47 | rm abc.txt 48 | -------------------------------------------------------------------------------- /toys/other/blockdev.c: -------------------------------------------------------------------------------- 1 | /* blockdev.c -show/set blockdev information. 2 | * 3 | * Copyright 2014 Sameer Prakash Pradhan 4 | * 5 | * No Standard. 6 | 7 | USE_BLOCKDEV(NEWTOY(blockdev, "<1>1(setro)(setrw)(getro)(getss)(getbsz)(setbsz)#<0(getsz)(getsize)(getsize64)(flushbufs)(rereadpt)",TOYFLAG_USR|TOYFLAG_BIN)) 8 | 9 | config BLOCKDEV 10 | bool "blockdev" 11 | default y 12 | help 13 | usage: blockdev --OPTION... BLOCKDEV... 14 | 15 | Call ioctl(s) on each listed block device 16 | 17 | OPTIONs: 18 | --setro Set read only 19 | --setrw Set read write 20 | --getro Get read only 21 | --getss Get sector size 22 | --getbsz Get block size 23 | --setbsz BYTES Set block size 24 | --getsz Get device size in 512-byte sectors 25 | --getsize Get device size in sectors (deprecated) 26 | --getsize64 Get device size in bytes 27 | --flushbufs Flush buffers 28 | --rereadpt Reread partition table 29 | */ 30 | 31 | #define FOR_blockdev 32 | #include "toys.h" 33 | #include 34 | 35 | GLOBALS( 36 | long bsz; 37 | ) 38 | 39 | void blockdev_main(void) 40 | { 41 | int cmds[] = {BLKRRPART, BLKFLSBUF, BLKGETSIZE64, BLKGETSIZE, BLKGETSIZE64, 42 | BLKBSZSET, BLKBSZGET, BLKSSZGET, BLKROGET, BLKROSET, BLKROSET}; 43 | char **ss; 44 | long long val = 0; 45 | 46 | if (!toys.optflags) help_exit("need --option"); 47 | 48 | for (ss = toys.optargs; *ss; ss++) { 49 | int fd = xopenro(*ss), i; 50 | 51 | // Command line order discarded so perform multiple operations in flag order 52 | for (i = 0; i < 32; i++) { 53 | long flag = toys.optflags & (1<> 9: val); 64 | } 65 | xclose(fd); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /toys/pending/logger.c: -------------------------------------------------------------------------------- 1 | /* logger.c - Log messages. 2 | * 3 | * Copyright 2013 Ilya Kuzmich 4 | * 5 | * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/logger.html 6 | 7 | USE_LOGGER(NEWTOY(logger, "st:p:", TOYFLAG_USR|TOYFLAG_BIN)) 8 | 9 | config LOGGER 10 | bool "logger" 11 | depends on SYSLOGD 12 | default n 13 | help 14 | usage: logger [-s] [-t tag] [-p [facility.]priority] [message] 15 | 16 | Log message (or stdin) to syslog. 17 | */ 18 | 19 | #define FOR_logger 20 | #include "toys.h" 21 | 22 | GLOBALS( 23 | char *priority_arg; 24 | char *ident; 25 | ) 26 | 27 | extern int logger_lookup(int where, char *key); 28 | 29 | void logger_main(void) 30 | { 31 | int facility = LOG_USER, priority = LOG_NOTICE; 32 | char *message = NULL; 33 | 34 | if (toys.optflags & FLAG_p) { 35 | char *sep = strchr(TT.priority_arg, '.'); 36 | 37 | if (sep) { 38 | *sep = '\0'; 39 | if ((facility = logger_lookup(0, TT.priority_arg)) == -1) 40 | error_exit("bad facility: %s", TT.priority_arg); 41 | TT.priority_arg = sep+1; 42 | } 43 | 44 | if ((priority = logger_lookup(1, TT.priority_arg)) == -1) 45 | error_exit("bad priority: %s", TT.priority_arg); 46 | } 47 | 48 | if (!(toys.optflags & FLAG_t)) { 49 | struct passwd *pw = getpwuid(geteuid()); 50 | 51 | if (!pw) perror_exit("getpwuid"); 52 | TT.ident = xstrdup(pw->pw_name); 53 | } 54 | 55 | if (toys.optc) { 56 | int length = 0, pos = 0; 57 | 58 | for (;*toys.optargs; toys.optargs++) { 59 | length += strlen(*(toys.optargs)) + 1; // plus one for the args spacing 60 | message = xrealloc(message, length + 1); // another one for the null byte 61 | 62 | sprintf(message + pos, "%s ", *toys.optargs); 63 | pos = length; 64 | } 65 | } else { 66 | toybuf[readall(0, toybuf, 4096-1)] = '\0'; 67 | message = toybuf; 68 | } 69 | 70 | openlog(TT.ident, (toys.optflags & FLAG_s ? LOG_PERROR : 0) , facility); 71 | syslog(priority, "%s", message); 72 | closelog(); 73 | } 74 | -------------------------------------------------------------------------------- /toys/posix/chmod.c: -------------------------------------------------------------------------------- 1 | /* chmod.c - Change file mode bits 2 | * 3 | * Copyright 2012 Rob Landley 4 | * 5 | * See http://opengroup.org/onlinepubs/9699919799/utilities/chmod.html 6 | 7 | USE_CHMOD(NEWTOY(chmod, "<2?vRf[-vf]", TOYFLAG_BIN)) 8 | 9 | config CHMOD 10 | bool "chmod" 11 | default y 12 | help 13 | usage: chmod [-R] MODE FILE... 14 | 15 | Change mode of listed file[s] (recursively with -R). 16 | 17 | MODE can be (comma-separated) stanzas: [ugoa][+-=][rwxstXugo] 18 | 19 | Stanzas are applied in order: For each category (u = user, 20 | g = group, o = other, a = all three, if none specified default is a), 21 | set (+), clear (-), or copy (=), r = read, w = write, x = execute. 22 | s = u+s = suid, g+s = sgid, o+s = sticky. (+t is an alias for o+s). 23 | suid/sgid: execute as the user/group who owns the file. 24 | sticky: can't delete files you don't own out of this directory 25 | X = x for directories or if any category already has x set. 26 | 27 | Or MODE can be an octal value up to 7777 ug uuugggooo top + 28 | bit 1 = o+x, bit 1<<8 = u+w, 1<<11 = g+1 sstrwxrwxrwx bottom 29 | 30 | Examples: 31 | chmod u+w file - allow owner of "file" to write to it. 32 | chmod 744 file - user can read/write/execute, everyone else read only 33 | */ 34 | 35 | #define FOR_chmod 36 | #include "toys.h" 37 | 38 | GLOBALS( 39 | char *mode; 40 | ) 41 | 42 | static int do_chmod(struct dirtree *try) 43 | { 44 | mode_t mode; 45 | 46 | if (!dirtree_notdotdot(try)) return 0; 47 | 48 | mode = string_to_mode(TT.mode, try->st.st_mode); 49 | if (toys.optflags & FLAG_v) { 50 | char *s = dirtree_path(try, 0); 51 | printf("chmod '%s' to %04o\n", s, mode); 52 | free(s); 53 | } 54 | wfchmodat(dirtree_parentfd(try), try->name, mode); 55 | 56 | return (toys.optflags & FLAG_R) ? DIRTREE_RECURSE : 0; 57 | } 58 | 59 | void chmod_main(void) 60 | { 61 | TT.mode = *toys.optargs; 62 | char **file; 63 | 64 | for (file = toys.optargs+1; *file; file++) dirtree_read(*file, do_chmod); 65 | } 66 | -------------------------------------------------------------------------------- /tests/mkdir.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | testing "mkdir" "mkdir one && [ -d one ] && echo yes" "yes\n" "" "" 8 | rmdir one 9 | 10 | touch existing 11 | testing "existing" \ 12 | "mkdir existing 2> /dev/null || [ -f existing ] && echo yes" "yes\n" "" "" 13 | rm existing 14 | 15 | testing "one two" \ 16 | "mkdir one two && [ -d one ] && [ -d two ] && echo yes" "yes\n" "" "" 17 | rmdir one two 18 | 19 | testing "missing/one" \ 20 | "mkdir missing/one 2> /dev/null || [ ! -d missing ] && echo yes" "yes\n" "" "" 21 | 22 | testing "-p" \ 23 | "mkdir -p one/two/three && [ -d one/two/three ] && echo yes" "yes\n" "" "" 24 | rm -rf one 25 | 26 | mkdir existing 27 | testing "-p existing" "mkdir -p existing && echo yes" "yes\n" "" "" 28 | rmdir existing 29 | 30 | umask 123 31 | testing "(default permissions)" \ 32 | "mkdir one && stat -c %a one" "654\n" "" "" 33 | rmdir one 34 | 35 | testing "-m 124" \ 36 | "mkdir -m 124 one && stat -c %a one" "124\n" "" "" 37 | rmdir one 38 | 39 | umask 000 40 | testing "-p -m 653" \ 41 | "mkdir -p -m 653 one/two && stat -c %a one && stat -c %a one/two" \ 42 | "777\n653\n" "" "" 43 | rm -rf one 44 | 45 | testing "-p one/two/ (trailing slash)" \ 46 | "mkdir -p one/two/ && [ -d one/two ] && echo yes" "yes\n" "" "" 47 | rm -rf one 48 | 49 | umask 022 50 | testing "-p -m 777 (022 umask)" \ 51 | "mkdir -p -m 777 one/two && stat -c %a one && stat -c %a one/two" \ 52 | "755\n777\n" "" "" 53 | rm -rf one 54 | 55 | umask 377 56 | testing "-p -m 777 (377 umask)" \ 57 | "mkdir -p -m 777 one/two && stat -c %a one && stat -c %a one/two" \ 58 | "700\n777\n" "" "" 59 | umask 002 60 | rm -rf one 61 | 62 | testing "-vp" "mkdir -vp walrus 2>&1" \ 63 | "mkdir: created directory 'walrus'\n" "" "" 64 | 65 | testing "-vp exists" "mkdir -vp walrus 2>&1" \ 66 | "" "" "" 67 | rm -rf walrus 68 | 69 | touch two 70 | testing "continue after fail" \ 71 | "mkdir -m 777 one two three 2>/dev/null || stat -c %a three" \ 72 | "777\n" "" "" 73 | rm -rf one two three 74 | -------------------------------------------------------------------------------- /toys/other/help.c: -------------------------------------------------------------------------------- 1 | /* help.c - Show help for toybox commands 2 | * 3 | * Copyright 2007 Rob Landley 4 | * 5 | * Often a shell builtin. 6 | 7 | USE_HELP(NEWTOY(help, ""USE_HELP_EXTRAS("ah"), TOYFLAG_BIN)) 8 | 9 | config HELP 10 | bool "help" 11 | default y 12 | depends on TOYBOX_HELP 13 | help 14 | usage: help [command] 15 | 16 | Show usage information for toybox commands. 17 | Run "toybox" with no arguments for a list of available commands. 18 | 19 | config HELP_EXTRAS 20 | bool "help -ah" 21 | default y 22 | depends on TOYBOX 23 | depends on HELP 24 | help 25 | usage: help [-ah] 26 | 27 | -a All commands 28 | -h HTML output 29 | */ 30 | 31 | #define FOR_help 32 | #include "toys.h" 33 | 34 | static void do_help(struct toy_list *t) 35 | { 36 | if (toys.optflags & FLAG_h) 37 | xprintf("

%s

\n", t->name, t->name);
38 | 
39 |   toys.which = t;
40 |   show_help(stdout);
41 | 
42 |   if (toys.optflags & FLAG_h) xprintf("
\n"); 43 | } 44 | 45 | // The simple help is just toys.which = toy_find("name"); show_help(stdout); 46 | // But iterating through html output and all commands is a big more 47 | 48 | void help_main(void) 49 | { 50 | int i; 51 | 52 | if (!(toys.optflags & FLAG_a)) { 53 | struct toy_list *t = toys.which; 54 | 55 | if (*toys.optargs && !(t = toy_find(*toys.optargs))) 56 | error_exit("Unknown command '%s'", *toys.optargs); 57 | do_help(t); 58 | return; 59 | } 60 | 61 | if (toys.optflags & FLAG_h) { 62 | xprintf("\nToybox command list\n\n

\n"); 63 | for (i=0; i < toys.toycount; i++) 64 | xprintf("%s\n", toy_list[i].name, 65 | toy_list[i].name); 66 | xprintf("

\n"); 67 | } 68 | 69 | for (i = 0; i < toys.toycount; i++) { 70 | if (toys.optflags & FLAG_h) xprintf("
\n
\n");
71 |     do_help(toy_list+i);
72 |     if (toys.optflags & FLAG_h) xprintf("
\n"); 73 | } 74 | 75 | if (toys.optflags & FLAG_h) xprintf(""); 76 | } 77 | -------------------------------------------------------------------------------- /toys/other/mix.c: -------------------------------------------------------------------------------- 1 | /* mix.c - A very basic mixer. 2 | * 3 | * Copyright 2014 Brad Conroy, dedicated to the Public Domain. 4 | * 5 | 6 | USE_MIX(NEWTOY(mix, "c:d:l#r#", TOYFLAG_USR|TOYFLAG_BIN)) 7 | 8 | config MIX 9 | bool "mix" 10 | default y 11 | help 12 | usage: mix [-d DEV] [-c CHANNEL] [-l VOL] [-r RIGHT] 13 | 14 | List OSS sound channels (module snd-mixer-oss), or set volume(s). 15 | 16 | -c CHANNEL Set/show volume of CHANNEL (default first channel found) 17 | -d DEV Device node (default /dev/mixer) 18 | -l VOL Volume level 19 | -r RIGHT Volume of right stereo channel (with -r, -l sets left volume) 20 | */ 21 | 22 | #define FOR_mix 23 | #include "toys.h" 24 | #include 25 | 26 | GLOBALS( 27 | long right; 28 | long level; 29 | char *dev; 30 | char *chan; 31 | ) 32 | 33 | void mix_main(void) 34 | { 35 | const char *channels[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES; 36 | int mask, channel = -1, level, fd; 37 | 38 | if (!TT.dev) TT.dev = "/dev/mixer"; 39 | fd = xopen(TT.dev, O_RDWR|O_NONBLOCK); 40 | xioctl(fd, SOUND_MIXER_READ_DEVMASK, &mask); 41 | 42 | for (channel = 0; channel < SOUND_MIXER_NRDEVICES; channel++) { 43 | if ((1< 0xFF) 57 | xprintf("%s:%s = left:%d\t right:%d\n", 58 | TT.dev, channels[channel], level>>8, level & 0xFF); 59 | else xprintf("%s:%s = %d\n", TT.dev, channels[channel], level); 60 | } else { 61 | level = TT.level; 62 | if (!(toys.optflags & FLAG_r)) level = TT.right | (level<<8); 63 | 64 | xioctl(fd, MIXER_WRITE(channel), &level); 65 | } 66 | 67 | if (CFG_TOYBOX_FREE) close(fd); 68 | } 69 | -------------------------------------------------------------------------------- /toys/other/mountpoint.c: -------------------------------------------------------------------------------- 1 | /* mountpoint.c - Check if a directory is a mountpoint. 2 | * 3 | * Copyright 2012 Elie De Brauwer 4 | 5 | USE_MOUNTPOINT(NEWTOY(mountpoint, "<1qdx[-dx]", TOYFLAG_BIN)) 6 | 7 | config MOUNTPOINT 8 | bool "mountpoint" 9 | default y 10 | help 11 | usage: mountpoint [-q] [-d] directory 12 | mountpoint [-q] [-x] device 13 | 14 | -q Be quiet, return zero if directory is a mountpoint 15 | -d Print major/minor device number of the directory 16 | -x Print major/minor device number of the block device 17 | */ 18 | 19 | #define FOR_mountpoint 20 | #include "toys.h" 21 | 22 | static void die(char *gripe) 23 | { 24 | if (!(toys.optflags & FLAG_q)) printf("%s: not a %s\n", *toys.optargs, gripe); 25 | 26 | toys.exitval++; 27 | xexit(); 28 | } 29 | 30 | void mountpoint_main(void) 31 | { 32 | struct stat st1, st2; 33 | char *arg = *toys.optargs; 34 | int quiet = toys.optflags & FLAG_q; 35 | 36 | if (lstat(arg, &st1)) perror_exit_raw(arg); 37 | 38 | if (toys.optflags & FLAG_x) { 39 | if (S_ISBLK(st1.st_mode)) { 40 | if (!quiet) 41 | printf("%u:%u\n", dev_major(st1.st_rdev), dev_minor(st1.st_rdev)); 42 | 43 | return; 44 | } 45 | die("block device"); 46 | } 47 | 48 | // TODO: Ignore the fact a file can be a mountpoint for --bind mounts. 49 | if (!S_ISDIR(st1.st_mode)) die("directory"); 50 | 51 | arg = xmprintf("%s/..", arg); 52 | xstat(arg, &st2); 53 | if (CFG_TOYBOX_FREE) free(arg); 54 | 55 | // If the device is different, it's a mount point. If the device _and_ 56 | // inode are the same, it's probably "/". This misses --bind mounts from 57 | // elsewhere in the same filesystem, but so does the other one and in the 58 | // absence of a spec I guess that's the expected behavior? 59 | toys.exitval = !(st1.st_dev != st2.st_dev || st1.st_ino == st2.st_ino); 60 | if (toys.optflags & FLAG_d) 61 | printf("%u:%u\n", dev_major(st1.st_dev), dev_minor(st1.st_dev)); 62 | else if (!quiet) 63 | printf("%s is %sa mountpoint\n", *toys.optargs, toys.exitval ? "not " : ""); 64 | } 65 | -------------------------------------------------------------------------------- /toys/other/timeout.c: -------------------------------------------------------------------------------- 1 | /* timeout.c - Run command line with a timeout 2 | * 3 | * Copyright 2013 Rob Landley 4 | * 5 | * No standard 6 | 7 | USE_TIMEOUT(NEWTOY(timeout, "<2^vk:s: ", TOYFLAG_BIN)) 8 | 9 | config TIMEOUT 10 | bool "timeout" 11 | default y 12 | depends on TOYBOX_FLOAT 13 | help 14 | usage: timeout [-k LENGTH] [-s SIGNAL] LENGTH COMMAND... 15 | 16 | Run command line as a child process, sending child a signal if the 17 | command doesn't exit soon enough. 18 | 19 | Length can be a decimal fraction. An optional suffix can be "m" 20 | (minutes), "h" (hours), "d" (days), or "s" (seconds, the default). 21 | 22 | -s Send specified signal (default TERM) 23 | -k Send KILL signal if child still running this long after first signal. 24 | -v Verbose 25 | */ 26 | 27 | #define FOR_timeout 28 | #include "toys.h" 29 | 30 | GLOBALS( 31 | char *s_signal; 32 | char *k_timeout; 33 | 34 | int nextsig; 35 | pid_t pid; 36 | struct timeval ktv; 37 | struct itimerval itv; 38 | ) 39 | 40 | static void handler(int i) 41 | { 42 | if (toys.optflags & FLAG_v) 43 | fprintf(stderr, "timeout pid %d signal %d\n", TT.pid, TT.nextsig); 44 | kill(TT.pid, TT.nextsig); 45 | 46 | if (TT.k_timeout) { 47 | TT.k_timeout = 0; 48 | TT.nextsig = SIGKILL; 49 | xsignal(SIGALRM, handler); 50 | TT.itv.it_value = TT.ktv; 51 | setitimer(ITIMER_REAL, &TT.itv, (void *)toybuf); 52 | } 53 | } 54 | 55 | void timeout_main(void) 56 | { 57 | // Parse early to get any errors out of the way. 58 | TT.itv.it_value.tv_sec = xparsetime(*toys.optargs, 1000000, &TT.itv.it_value.tv_usec); 59 | 60 | if (TT.k_timeout) 61 | TT.ktv.tv_sec = xparsetime(TT.k_timeout, 1000000, &TT.ktv.tv_usec); 62 | TT.nextsig = SIGTERM; 63 | if (TT.s_signal && -1 == (TT.nextsig = sig_to_num(TT.s_signal))) 64 | error_exit("bad -s: '%s'", TT.s_signal); 65 | 66 | if (!(TT.pid = XVFORK())) xexec(toys.optargs+1); 67 | else { 68 | xsignal(SIGALRM, handler); 69 | setitimer(ITIMER_REAL, &TT.itv, (void *)toybuf); 70 | toys.exitval = xwaitpid(TT.pid); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /tests/seq.test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -f testing.sh ] && . testing.sh 4 | 5 | #testing "name" "command" "result" "infile" "stdin" 6 | 7 | testing "(exit with error)" "seq 2> /dev/null || echo yes" "yes\n" "" "" 8 | testing "(exit with error)" "seq 1 2 3 4 2> /dev/null || echo yes" \ 9 | "yes\n" "" "" 10 | testing "one argument" "seq 3" "1\n2\n3\n" "" "" 11 | testing "two arguments" "seq 5 7" "5\n6\n7\n" "" "" 12 | testing "two arguments reversed" "seq 7 5" "" "" "" 13 | testing "two arguments equal" "seq 3 3" "3\n" "" "" 14 | testing "two arguments equal, arbitrary negative step" "seq 1 -15 1" \ 15 | "1\n" "" "" 16 | testing "two arguments equal, arbitrary positive step" "seq 1 +15 1" \ 17 | "1\n" "" "" 18 | testing "count up by 2" "seq 4 2 8" "4\n6\n8\n" "" "" 19 | testing "count down by 2" "seq 8 -2 4" "8\n6\n4\n" "" "" 20 | testing "count wrong way #1" "seq 4 -2 8" "" "" "" 21 | testing "count wrong way #2" "seq 8 2 4" "" "" "" 22 | testing "count by .3" "seq 3 .3 4" "3\n3.3\n3.6\n3.9\n" "" "" 23 | testing "count by -.9" "seq .7 -.9 -2.2" "0.7\n-0.2\n-1.1\n-2\n" "" "" 24 | testing "count by zero" "seq 4 0 8 | head -n 10" "" "" "" 25 | testing "separator -" "seq -s - 1 3" "1-2-3\n" "" "" 26 | testing "format string" 'seq -f %+01g -10 5 10' "-10\n-5\n+0\n+5\n+10\n" \ 27 | "" "" 28 | testing "separator and format string" "seq -f \%03g -s \; 5 -1 0" "005;004;003;002;001;000\n" "" "" 29 | testing "padding" "seq -s, -w -2 19 120" "-02,017,036,055,074,093,112\n" \ 30 | "" "" 31 | testing "padding" "seq -s, -w -2 3 12" "-2,01,04,07,10\n" "" "" 32 | testing "padding" "seq -s, -w -2.2 3.3 12" "-2.2,01.1,04.4,07.7,11.0\n" \ 33 | "" "" 34 | 35 | # Test -f format filtering 36 | for i in %f %e %g "boo %f yah" "% f" %-1.2f %+-f "%+ - f" %.2f %3.f "%'.2f" \ 37 | %%%f%% 38 | do 39 | testing "filter -f \"$i\"" "seq -f \"$i\" 1 3 > /dev/null && echo yes" \ 40 | "yes\n" "" "" 41 | done 42 | # Test -f format filtering failures 43 | for i in %d %s "" "boo %f %f yah" "%*f" %-1.2.3f '%2$f' %1-f "%1 f" \ 44 | %2..2f %%%f%%% 45 | do 46 | testing "filter reject -f '$i'" \ 47 | "seq -f '$i' 1 3 2>/dev/null || echo no" "no\n" "" "" 48 | done 49 | -------------------------------------------------------------------------------- /toys/posix/cksum.c: -------------------------------------------------------------------------------- 1 | /* cksum.c - produce crc32 checksum value for each input 2 | * 3 | * Copyright 2008 Rob Landley 4 | * 5 | * See http://opengroup.org/onlinepubs/9699919799/utilities/cksum.html 6 | 7 | USE_CKSUM(NEWTOY(cksum, "HIPLN", TOYFLAG_BIN)) 8 | 9 | config CKSUM 10 | bool "cksum" 11 | default y 12 | help 13 | usage: cksum [-IPLN] [file...] 14 | 15 | For each file, output crc32 checksum value, length and name of file. 16 | If no files listed, copy from stdin. Filename "-" is a synonym for stdin. 17 | 18 | -H Hexadecimal checksum (defaults to decimal) 19 | -L Little endian (defaults to big endian) 20 | -P Pre-inversion 21 | -I Skip post-inversion 22 | -N Do not include length in CRC calculation 23 | */ 24 | 25 | #define FOR_cksum 26 | #include "toys.h" 27 | 28 | GLOBALS( 29 | unsigned crc_table[256]; 30 | ) 31 | 32 | static unsigned cksum_be(unsigned crc, unsigned char c) 33 | { 34 | return (crc<<8)^TT.crc_table[(crc>>24)^c]; 35 | } 36 | 37 | static unsigned cksum_le(unsigned crc, unsigned char c) 38 | { 39 | return TT.crc_table[(crc^c)&0xff] ^ (crc>>8); 40 | } 41 | 42 | static void do_cksum(int fd, char *name) 43 | { 44 | unsigned crc = (toys.optflags & FLAG_P) ? 0xffffffff : 0; 45 | uint64_t llen = 0, llen2; 46 | unsigned (*cksum)(unsigned crc, unsigned char c); 47 | 48 | cksum = (toys.optflags & FLAG_L) ? cksum_le : cksum_be; 49 | // CRC the data 50 | 51 | for (;;) { 52 | int len, i; 53 | 54 | len = read(fd, toybuf, sizeof(toybuf)); 55 | if (len<0) perror_msg_raw(name); 56 | if (len<1) break; 57 | 58 | llen += len; 59 | for (i=0; i>= 8; 69 | } 70 | } 71 | 72 | printf((toys.optflags & FLAG_H) ? "%x" : "%u", 73 | (toys.optflags & FLAG_I) ? crc : ~crc); 74 | printf(" %"PRIu64, llen2); 75 | if (strcmp("-", name)) printf(" %s", name); 76 | xputc('\n'); 77 | } 78 | 79 | void cksum_main(void) 80 | { 81 | crc_init(TT.crc_table, toys.optflags & FLAG_L); 82 | loopfiles(toys.optargs, do_cksum); 83 | } 84 | --------------------------------------------------------------------------------