diff options
author | Rob Landley <rob@landley.net> | 2012-10-08 00:02:30 -0500 |
---|---|---|
committer | Rob Landley <rob@landley.net> | 2012-10-08 00:02:30 -0500 |
commit | c0e56edaf256adb6c60c5a052525a1ffbb927901 (patch) | |
tree | d6bcc5c181ca46910a12d4dece4b26d6c71be3e1 | |
parent | dc7a77d1940858495f76998f4d13cac9f73e0226 (diff) | |
download | toybox-c0e56edaf256adb6c60c5a052525a1ffbb927901.tar.gz |
New build infrastructure to generate FLAG_ macros and TT alias, #define FOR_commandname before #including toys.h to trigger it. Rename DEFINE_GLOBALS() to just GLOBALS() (because I could never remember if it was DECLARE_GLOBALS). Convert existing commands to use new infrastructure, and replace optflag constants with FLAG_ macros where appropriate.
56 files changed, 294 insertions, 434 deletions
diff --git a/scripts/make.sh b/scripts/make.sh index af56e6d1..6c1672e3 100755 --- a/scripts/make.sh +++ b/scripts/make.sh @@ -10,6 +10,33 @@ then exit 1 fi +echo "Make generated/config.h from .config." + +# This long and roundabout sed invocation is to make old versions of sed happy. +# New ones have '\n' so can replace one line with two without all the branches +# and tedious mucking about with hold space. + +sed -n \ + -e 's/^# CONFIG_\(.*\) is not set.*/\1/' \ + -e 't notset' \ + -e 's/^CONFIG_\(.*\)=y.*/\1/' \ + -e 't isset' \ + -e 's/^CONFIG_\([^=]*\)=\(.*\)/#define CFG_\1 \2/p' \ + -e 'd' \ + -e ':notset' \ + -e 'h' \ + -e 's/.*/#define CFG_& 0/p' \ + -e 'g' \ + -e 's/.*/#define USE_&(...)/p' \ + -e 'd' \ + -e ':isset' \ + -e 'h' \ + -e 's/.*/#define CFG_& 1/p' \ + -e 'g' \ + -e 's/.*/#define USE_&(...) __VA_ARGS__/p' \ + .config > generated/config.h || exit 1 + + echo "Extract configuration information from toys/*.c files..." scripts/genconfig.sh @@ -22,47 +49,41 @@ echo "Generate headers from toys/*/*.c..." echo "generated/newtoys.h" -function newtoys() -{ - for i in toys/*/*.c - do - sed -n -e '1,/^config [A-Z]/s/^USE_/&/p' $i || exit 1 - done -} echo "NEWTOY(toybox, NULL, TOYFLAG_STAYROOT)" > generated/newtoys.h -newtoys | sed 's/\(.*TOY(\)\([^,]*\),\(.*\)/\2 \1\2,\3/' | sort -k 1,1 \ +sed -n -e 's/^USE_[A-Z0-9_]*(/&/p' toys/*/*.c \ + | sed 's/\(.*TOY(\)\([^,]*\),\(.*\)/\2 \1\2,\3/' | sort -k 1,1 \ | sed 's/[^ ]* //' >> generated/newtoys.h # Extract global structure definitions and flag definitions from toys/*/*.c function getglobals() { + NEWTOYS="$(cat generated/config.h generated/newtoys.h | gcc -E - | sed 's/" *"//g')" for i in toys/*/*.c do NAME="$(echo $i | sed 's@.*/\(.*\)\.c@\1@')" echo -e "// $i\n" - sed -n -e '/^DEFINE_GLOBALS(/,/^)/b got;b;:got' \ - -e 's/^DEFINE_GLOBALS(/struct '"$NAME"'_data {/' \ + sed -n -e '/^GLOBALS(/,/^)/b got;b;:got' \ + -e 's/^GLOBALS(/struct '"$NAME"'_data {/' \ -e 's/^)/};/' -e 'p' $i # And get flag definitions - FLAGS="$(sed -n \ + FLAGS="$(echo "$NEWTOYS" | sed -n \ -e "s/.*TOY($NAME"',[ \t]*"\([^"]*\)"[ \t]*,.*)/\1/' \ - -e 't keep;d;:keep' \ - -e 's/[><=][0-9][0-9]*//g' \ - -e 's/+.//g' \ - -e 's/([^)]*)//g' \ - -e 's/[-?^:&#|@*]//g' \ - -e 'p' \ - generated/newtoys.h)" + -e 't keep;d;:keep' -e 's/^[<>=][0-9]//' -e 's/[?&^]//' \ + -e 't keep' -e 's/[><=][0-9][0-9]*//g' -e 's/+.//g' \ + -e 's/([^)]*)//g' -e 's/[-?^:&#|@*]//g' -e 'p')" + echo "#ifdef FOR_${NAME}" X=0 while [ $X -lt ${#FLAGS} ] do - echo -ne "#define OPTFLAG_${NAME}_${FLAGS:$X:1}\t" + echo -ne "#define FLAG_${FLAGS:$X:1}\t" X=$(($X+1)) echo "(1<<$((${#FLAGS}-$X)))" done + echo "#define TT this.${NAME}" + echo "#endif" done } @@ -85,32 +106,6 @@ then scripts/config2help.py Config.in > generated/help.h || exit 1 fi -echo "Make generated/config.h from .config." - -# This long and roundabout sed invocation is to make old versions of sed happy. -# New ones have '\n' so can replace one line with two without all the branches -# and tedious mucking about with hold space. - -sed -n \ - -e 's/^# CONFIG_\(.*\) is not set.*/\1/' \ - -e 't notset' \ - -e 's/^CONFIG_\(.*\)=y.*/\1/' \ - -e 't isset' \ - -e 's/^CONFIG_\([^=]*\)=\(.*\)/#define CFG_\1 \2/p' \ - -e 'd' \ - -e ':notset' \ - -e 'h' \ - -e 's/.*/#define CFG_& 0/p' \ - -e 'g' \ - -e 's/.*/#define USE_&(...)/p' \ - -e 'd' \ - -e ':isset' \ - -e 'h' \ - -e 's/.*/#define CFG_& 1/p' \ - -e 'g' \ - -e 's/.*/#define USE_&(...) __VA_ARGS__/p' \ - .config > generated/config.h || exit 1 - # Extract a list of toys/*/*.c files to compile from the data in ".config": # 1) Get a list of C files in toys/* and glue them together into a regex we can @@ -107,6 +107,6 @@ extern struct toy_context { extern char toybuf[4096]; -#define DEFINE_GLOBALS(...) +#define GLOBALS(...) #define ARRAY_LEN(array) (sizeof(array)/sizeof(*array)) diff --git a/toys/lsb/dmesg.c b/toys/lsb/dmesg.c index e54a9e11..8d73513b 100644 --- a/toys/lsb/dmesg.c +++ b/toys/lsb/dmesg.c @@ -21,16 +21,15 @@ config DMESG -c Clear the ring buffer after printing. */ +#define FOR_dmesg #include "toys.h" #include <sys/klog.h> -DEFINE_GLOBALS( +GLOBALS( long level; long size; ) -#define TT this.dmesg - void dmesg_main(void) { // For -n just tell kernel to which messages to keep. diff --git a/toys/lsb/hostname.c b/toys/lsb/hostname.c index bd319188..ca436833 100644 --- a/toys/lsb/hostname.c +++ b/toys/lsb/hostname.c @@ -17,6 +17,7 @@ config HOSTNAME Get/Set the current hostname */ +#define FOR_hostname #include "toys.h" void hostname_main(void) diff --git a/toys/lsb/killall.c b/toys/lsb/killall.c index 80f0253c..ec9df62e 100644 --- a/toys/lsb/killall.c +++ b/toys/lsb/killall.c @@ -20,15 +20,12 @@ config KILLALL -q don't print any warnings or error messages */ +#define FOR_killall #include "toys.h" -#define FLAG_q 1 -#define FLAG_l 2 - -DEFINE_GLOBALS( +GLOBALS( int signum; ) -#define TT this.killall static void kill_process(pid_t pid) { diff --git a/toys/lsb/mknod.c b/toys/lsb/mknod.c index fbdc8800..c1d78b10 100644 --- a/toys/lsb/mknod.c +++ b/toys/lsb/mknod.c @@ -20,6 +20,7 @@ config MKNOD p named pipe (ignores MAJOR/MINOR) */ +#define FOR_mknod #include "toys.h" void mknod_main(void) diff --git a/toys/lsb/mktemp.c b/toys/lsb/mktemp.c index c42588ab..1b2222c0 100644 --- a/toys/lsb/mktemp.c +++ b/toys/lsb/mktemp.c @@ -22,18 +22,13 @@ config MKTEMP -q Quiet */ +#define FOR_mktemp #include "toys.h" -DEFINE_GLOBALS( +GLOBALS( char * tmpdir; ) -#define FLAG_p 1 -#define FLAG_d 2 -#define FLAG_q 4 - -#define TT this.mktemp - void mktemp_main(void) { int d_flag = toys.optflags & FLAG_d; diff --git a/toys/lsb/passwd.c b/toys/lsb/passwd.c index 348c9c21..ef119c5d 100644 --- a/toys/lsb/passwd.c +++ b/toys/lsb/passwd.c @@ -24,21 +24,14 @@ config PASSWD */ +#define FOR_passwd #include "toys.h" #include <time.h> - -DEFINE_GLOBALS( +GLOBALS( char *algo; ) -#define TT this.passwd - -#define FLAG_u (1 << 0) -#define FLAG_l (1 << 1) -#define FLAG_d (1 << 2) -#define FLAG_a (1 << 3) - #define MAX_SALT_LEN 20 //3 for id, 16 for key, 1 for '\0' #define URANDOM_PATH "/dev/urandom" diff --git a/toys/other/catv.c b/toys/other/catv.c index 221549f3..a0790a9b 100644 --- a/toys/other/catv.c +++ b/toys/other/catv.c @@ -23,12 +23,9 @@ config CATV -v Don't use ^x or M-x escapes. */ +#define FOR_catv #include "toys.h" -#define FLAG_v 4 -#define FLAG_t 2 -#define FLAG_e 1 - // Callback function for loopfiles() static void do_catv(int fd, char *name) diff --git a/toys/other/dos2unix.c b/toys/other/dos2unix.c index 07e68055..15cc1706 100644 --- a/toys/other/dos2unix.c +++ b/toys/other/dos2unix.c @@ -17,14 +17,13 @@ config DOS2UNIX If no files listed copy from stdin, "-" is a synonym for stdin. */ +#define FOR_dos2unix #include "toys.h" -DEFINE_GLOBALS( +GLOBALS( char *tempfile; ) -#define TT this.dos2unix - static void do_dos2unix(int fd, char *name) { char c = toys.which->name[0]; diff --git a/toys/other/free.c b/toys/other/free.c index b009b8b0..aa344928 100644 --- a/toys/other/free.c +++ b/toys/other/free.c @@ -18,6 +18,7 @@ config FREE -bkmg Output in bytes (default), KB, MB or GB */ +#define FOR_free #include "toys.h" static unsigned long long convert(unsigned long d, unsigned int iscale, @@ -34,10 +35,10 @@ void free_main(void) sysinfo(&info); if (info.mem_unit) iscale = info.mem_unit; - if (toys.optflags & 1) oscale = 0; - if (toys.optflags & 2) oscale = 10; - if (toys.optflags & 4) oscale = 20; - if (toys.optflags & 8) oscale = 30; + if (toys.optflags & FLAG_b) oscale = 0; + if (toys.optflags & FLAG_k) oscale = 10; + if (toys.optflags & FLAG_m) oscale = 20; + if (toys.optflags & FLAG_g) oscale = 30; xprintf("\t\ttotal used free shared buffers\n"); xprintf("Mem:%17llu%12llu%12llu%12llu%12llu\n", diff --git a/toys/other/hello.c b/toys/other/hello.c index cfab40df..2b469591 100644 --- a/toys/other/hello.c +++ b/toys/other/hello.c @@ -21,11 +21,12 @@ config HELLO occasionally nice to test kernel booting via "init=/bin/hello". */ +#define FOR_hello #include "toys.h" // Hello doesn't use these globals, they're here for example/skeleton purposes. -DEFINE_GLOBALS( +GLOBALS( char *b_string; long c_number; struct arg_list *d_list; @@ -34,14 +35,6 @@ DEFINE_GLOBALS( int more_globals; ) -#define TT this.hello - -#define FLAG_a 1 -#define FLAG_b 2 -#define FLAG_c 4 -#define FLAG_d 8 -#define FLAG_e 16 - void hello_main(void) { printf("Hello world\n"); diff --git a/toys/other/login.c b/toys/other/login.c index 8c542a7e..a9e7562c 100644 --- a/toys/other/login.c +++ b/toys/other/login.c @@ -21,6 +21,7 @@ config LOGIN -f Do not perform authentication */ +#define FOR_login #include "toys.h" #define LOGIN_TIMEOUT 60 @@ -28,10 +29,9 @@ config LOGIN #define USER_NAME_MAX_SIZE 32 #define HOSTNAME_SIZE 32 -DEFINE_GLOBALS( +GLOBALS( char *hostname; ) -#define TT this.login static void login_timeout_handler(int sig __attribute__((unused))) { @@ -162,9 +162,8 @@ void setup_environment(const struct passwd *pwd, int clear_env) void login_main(void) { - int f_flag = (toys.optflags & 4) >> 2; - int p_flag = (toys.optflags & 2) >> 1; - int h_flag = toys.optflags & 1; + int f_flag = toys.optflags & FLAG_f; + int h_flag = toys.optflags & FLAG_h; char username[USER_NAME_MAX_SIZE+1], *pass = NULL, **ss; struct passwd * pwd = NULL; struct spwd * spwd = NULL; @@ -215,7 +214,7 @@ query_pass: f_flag = 0; syslog(LOG_WARNING, "invalid password for '%s' on %s %s %s", username, - ttyname(0), (h_flag)?"from":"", (h_flag)?TT.hostname:""); + ttyname(0), h_flag?"from":"", h_flag?TT.hostname:""); sleep(LOGIN_FAIL_TIMEOUT); puts("Login incorrect"); @@ -234,12 +233,12 @@ query_pass: if (change_identity(pwd)) error_exit("Failed to change identity"); - setup_environment(pwd, !p_flag); + setup_environment(pwd, !(toys.optflags & FLAG_p)); handle_motd(); syslog(LOG_INFO, "%s logged in on %s %s %s", pwd->pw_name, - ttyname(0), (h_flag)?"from":"", (h_flag)?TT.hostname:""); + ttyname(0), h_flag?"from":"", h_flag?TT.hostname:""); spawn_shell(pwd->pw_shell); } diff --git a/toys/other/mke2fs.c b/toys/other/mke2fs.c index 837ea214..5745d519 100644 --- a/toys/other/mke2fs.c +++ b/toys/other/mke2fs.c @@ -73,9 +73,10 @@ config MKE2FS_EXTENDED sparse_super Don't allocate huge numbers of redundant superblocks */ +#define FOR_mke2fs #include "toys.h" -DEFINE_GLOBALS( +GLOBALS( // Command line arguments. long blocksize; long bytes_per_inode; @@ -102,9 +103,6 @@ DEFINE_GLOBALS( struct ext2_superblock sb; ) -// Shortcut to our global data structure, since we use it so much. -#define TT this.mke2fs - #define INODES_RESERVED 10 static uint32_t div_round_up(uint32_t a, uint32_t b) diff --git a/toys/other/modinfo.c b/toys/other/modinfo.c index c878fc4e..0c5f177f 100644 --- a/toys/other/modinfo.c +++ b/toys/other/modinfo.c @@ -14,14 +14,12 @@ config MODINFO usage: modinfo [-0] [-F field] [modulename...] */ +#define FOR_modinfo #include "toys.h" -#define FLAG_0 (1 << 0) - -DEFINE_GLOBALS( +GLOBALS( char *field; ) -#define TT this.modinfo static const char *modinfo_tags[] = { "alias", "license", "description", "author", "vermagic", diff --git a/toys/other/mountpoint.c b/toys/other/mountpoint.c index 1bb0b3a7..fe63b725 100644 --- a/toys/other/mountpoint.c +++ b/toys/other/mountpoint.c @@ -17,19 +17,20 @@ config MOUNTPOINT -x Print major/minor device number of the block device */ +#define FOR_mountpoint #include "toys.h" void mountpoint_main(void) { struct stat st1, st2; int res = 0; - int quiet = toys.optflags & 0x4; + int quiet = toys.optflags & FLAG_q; toys.exitval = 1; // be pessimistic strncpy(toybuf, toys.optargs[0], sizeof(toybuf)); - if (((toys.optflags & 0x1) && lstat(toybuf, &st1)) || stat(toybuf, &st1)) + if (((toys.optflags & FLAG_x) && lstat(toybuf, &st1)) || stat(toybuf, &st1)) perror_exit("%s", toybuf); - if (toys.optflags & 0x1){ + if (toys.optflags & FLAG_x){ if (S_ISBLK(st1.st_mode)) { if (!quiet) printf("%u:%u\n", major(st1.st_rdev), minor(st1.st_rdev)); toys.exitval = 0; @@ -48,7 +49,7 @@ void mountpoint_main(void) res = (st1.st_dev != st2.st_dev) || (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino); if (!quiet) printf("%s is %sa mountpoint\n", toys.optargs[0], res ? "" : "not "); - if (toys.optflags & 0x2) + if (toys.optflags & FLAG_d) printf("%u:%u\n", major(st1.st_dev), minor(st1.st_dev)); toys.exitval = res ? 0 : 1; } diff --git a/toys/other/netcat.c b/toys/other/netcat.c index 6442c09b..2e90737d 100644 --- a/toys/other/netcat.c +++ b/toys/other/netcat.c @@ -3,6 +3,9 @@ * netcat.c - Forward stdin/stdout to a file or network connection. * * Copyright 2007 Rob Landley <rob@landley.net> + * + * TODO: udp, ipv6, genericize for telnet/microcom/tail-f + USE_NETCAT(OLDTOY(nc, netcat, USE_NETCAT_LISTEN("tl^L^")"w#p#s:q#f:", TOYFLAG_BIN)) USE_NETCAT(NEWTOY(netcat, USE_NETCAT_LISTEN("tl^L^")"w#p#s:q#f:", TOYFLAG_BIN)) @@ -40,10 +43,11 @@ config NETCAT_LISTEN netcat -s 127.0.0.1 -p 1234 -tL /bin/bash -l */ +#define FOR_netcat #include "toys.h" #include "toynet.h" -DEFINE_GLOBALS( +GLOBALS( char *filename; // -f read from filename instead of network long quit_delay; // -q Exit after EOF from stdin after # seconds. char *source_address; // -s Bind to a specific source address. @@ -51,13 +55,6 @@ DEFINE_GLOBALS( long wait; // -w Wait # seconds for a connection. ) -#define TT this.netcat - -#define FLAG_f 1 -#define FLAG_L 32 -#define FLAG_l 64 -#define FLAG_t 128 - static void timeout(int signum) { if (TT.wait) error_exit("Timeout"); diff --git a/toys/other/oneit.c b/toys/other/oneit.c index ff7aa914..8bb482da 100644 --- a/toys/other/oneit.c +++ b/toys/other/oneit.c @@ -24,15 +24,14 @@ config ONEIT which point it reboots (or with -p, powers off) the system. */ +#define FOR_oneit #include "toys.h" #include <sys/reboot.h> -DEFINE_GLOBALS( +GLOBALS( char *console; ) -#define TT this.oneit - // The minimum amount of work necessary to get ctrl-c and such to work is: // // - Fork a child (PID 1 is special: can't exit, has various signals blocked). @@ -59,7 +58,8 @@ void oneit_main(void) // PID 1 can't call reboot() because it kills the task that calls it, // which causes the kernel to panic before the actual reboot happens. - if (!vfork()) reboot((toys.optflags&1) ? RB_POWER_OFF : RB_AUTOBOOT); + if (!vfork()) + reboot((toys.optflags & FLAG_p) ? RB_POWER_OFF : RB_AUTOBOOT); sleep(5); _exit(1); } diff --git a/toys/other/rmmod.c b/toys/other/rmmod.c index cfc978ab..18ace3fa 100644 --- a/toys/other/rmmod.c +++ b/toys/other/rmmod.c @@ -18,6 +18,7 @@ config RMMOD */ +#define FOR_rmmod #include "toys.h" #include <sys/syscall.h> @@ -41,8 +42,8 @@ void rmmod_main(void) if (len > 3 && !strcmp(&mod_name[len-3], ".ko" )) mod_name[len-3] = 0; - if (toys.optflags & 1) flags |= O_TRUNC; - if (toys.optflags & 2) flags &= ~O_NONBLOCK; + if (toys.optflags & FLAG_f) flags |= O_TRUNC; + if (toys.optflags & FLAG_w) flags &= ~O_NONBLOCK; if (delete_module(mod_name, flags)) perror_exit("failed to unload %s", mod_name); diff --git a/toys/other/sha1sum.c b/toys/other/sha1sum.c index 3165effc..8833c8de 100644 --- a/toys/other/sha1sum.c +++ b/toys/other/sha1sum.c @@ -18,9 +18,10 @@ config SHA1SUM Calculate sha1 hash of files (or stdin). */ +#define FOR_sha1sum #include <toys.h> -DEFINE_GLOBALS( +GLOBALS( uint32_t state[5]; uint32_t oldstate[5]; uint64_t count; @@ -30,8 +31,6 @@ DEFINE_GLOBALS( } buffer; ) -#define TT this.sha1sum - #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) // blk0() and blk() perform the initial expand. diff --git a/toys/other/swapon.c b/toys/other/swapon.c index 4b9734e4..db7c45b0 100644 --- a/toys/other/swapon.c +++ b/toys/other/swapon.c @@ -15,19 +15,18 @@ config SWAPON Enable swapping on a given device/file. */ +#define FOR_swapon #include "toys.h" -DEFINE_GLOBALS( +GLOBALS( long priority; ) -#define TT this.swapon - void swapon_main(void) { int flags = 0; - if (toys.optflags & 1) + if (toys.optflags) flags = SWAP_FLAG_PREFER | (TT.priority << SWAP_FLAG_PRIO_SHIFT); if (swapon(*toys.optargs, flags)) diff --git a/toys/other/switch_root.c b/toys/other/switch_root.c index b4c0b7dd..6451ec15 100644 --- a/toys/other/switch_root.c +++ b/toys/other/switch_root.c @@ -17,20 +17,16 @@ config SWITCH_ROOT -h Hang instead of exiting on failure (avoids kernel panic) */ +#define FOR_switch_root #include "toys.h" #include <sys/vfs.h> -DEFINE_GLOBALS( +GLOBALS( char *console; dev_t rootdev; ) -#define TT this.switch_root - -#define FLAG_h (1<<0) -#define FLAG_c (1<<1) - static int del_node(struct dirtree *node) { if (node->st.st_dev == TT.rootdev && dirtree_notdotdot(node)) { diff --git a/toys/other/taskset.c b/toys/other/taskset.c index 9b219044..74cbfffa 100644 --- a/toys/other/taskset.c +++ b/toys/other/taskset.c @@ -22,11 +22,9 @@ config TASKSET -a Set/get the affinity of all threads of the PID. */ +#define FOR_taskset #include "toys.h" -#define FLAG_a 0x1 -#define FLAG_p 0x2 - // Prototype for syscall wrappers sched.h refuses to give us int sched_setaffinity(pid_t pid, size_t size, void *cpuset); int sched_getaffinity(pid_t pid, size_t size, void *cpuset); diff --git a/toys/other/truncate.c b/toys/other/truncate.c index aa952b16..47b07583 100644 --- a/toys/other/truncate.c +++ b/toys/other/truncate.c @@ -17,14 +17,13 @@ config TRUNCATE -s New size */ +#define FOR_truncate #include "toys.h" -DEFINE_GLOBALS( +GLOBALS( long size; ) -#define TT this.truncate - static void do_truncate(int fd, char *name) { if (fd<0) return; diff --git a/toys/other/vmstat.c b/toys/other/vmstat.c index b4858227..1c348f2a 100644 --- a/toys/other/vmstat.c +++ b/toys/other/vmstat.c @@ -122,7 +122,7 @@ void vmstat_main(void) unsigned long io_pages_in[2], io_pages_out[2], swap_bytes_in[2], swap_bytes_out[2]; uint64_t sys_irq[2], sys_ctxt[2], cpu_user[2], cpu_sys[2], cpu_idle[2], cpu_wait[2]; int first_run = 1; - int no_header = toys.optflags & 0x1; + int no_header = toys.optflags; unsigned num_rows = 22; if (toys.optc >= 1) diff --git a/toys/posix/chgrp.c b/toys/posix/chgrp.c index 892e78d7..48ce6751 100644 --- a/toys/posix/chgrp.c +++ b/toys/posix/chgrp.c @@ -30,25 +30,16 @@ config CHGRP -v verbose output. */ +#define FOR_chgrp #include "toys.h" -#define FLAG_v 1 -#define FLAG_f 2 -#define FLAG_R 4 -#define FLAG_H 8 -#define FLAG_L 16 -#define FLAG_P 32 -#define FLAG_h 64 - -DEFINE_GLOBALS( +GLOBALS( uid_t owner; gid_t group; char *owner_name, *group_name; int symfollow; ) -#define TT this.chgrp - static int do_chgrp(struct dirtree *node) { int fd, ret, flags = toys.optflags; diff --git a/toys/posix/chmod.c b/toys/posix/chmod.c index 2a32db10..dcef9751 100644 --- a/toys/posix/chmod.c +++ b/toys/posix/chmod.c @@ -34,17 +34,13 @@ config CHMOD chmod 744 file - user can read/write/execute, everyone else read only */ +#define FOR_chmod #include "toys.h" -DEFINE_GLOBALS( +GLOBALS( char *mode; ) -#define TT this.chmod - -#define FLAG_R 1 -#define FLAG_v 2 - int do_chmod(struct dirtree *try) { mode_t mode; diff --git a/toys/posix/cksum.c b/toys/posix/cksum.c index f0aedfd0..3e27b4cb 100644 --- a/toys/posix/cksum.c +++ b/toys/posix/cksum.c @@ -23,14 +23,13 @@ config CKSUM -N Do not include length in CRC calculation */ +#define FOR_cksum #include "toys.h" -DEFINE_GLOBALS( +GLOBALS( unsigned crc_table[256]; ) -#define TT this.cksum - static unsigned cksum_be(unsigned crc, unsigned char c) { return (crc<<8)^TT.crc_table[(crc>>24)^c]; diff --git a/toys/posix/cmp.c b/toys/posix/cmp.c index c41f98b8..4bbd3f30 100644 --- a/toys/posix/cmp.c +++ b/toys/posix/cmp.c @@ -20,18 +20,14 @@ config CMP -s silent */ +#define FOR_cmp #include "toys.h" -#define FLAG_s 1 -#define FLAG_l 2 - -DEFINE_GLOBALS( +GLOBALS( int fd; char *name; ) -#define TT this.cmp - // This handles opening the file and void do_cmp(int fd, char *name) diff --git a/toys/posix/comm.c b/toys/posix/comm.c index 761a62b2..477d5160 100644 --- a/toys/posix/comm.c +++ b/toys/posix/comm.c @@ -24,12 +24,9 @@ config COMM -3 suppress the output column of lines duplicated in FILE1 and FILE2 */ +#define FOR_comm #include "toys.h" -#define FLAG_1 1 -#define FLAG_2 2 -#define FLAG_3 4 - static void writeline(const char *line, int col) { if (col == 0 && toys.optflags & FLAG_1) return; diff --git a/toys/posix/cp.c b/toys/posix/cp.c index 232d8fab..b7834e86 100644 --- a/toys/posix/cp.c +++ b/toys/posix/cp.c @@ -6,53 +6,53 @@ * * See http://opengroup.org/onlinepubs/9699919799/utilities/cp.html * - * "R+ra+d+p+r" -USE_CP(NEWTOY(cp, "<2vslrRdpaHLPif", TOYFLAG_BIN)) + * TODO: "R+ra+d+p+r" sHLPR + +USE_CP(NEWTOY(cp, "<2"USE_CP_MORE("rdavsl")"RHLPfip", TOYFLAG_BIN)) config CP bool "cp (broken by dirtree changes)" default n help - usage: cp -fiprdal SOURCE... DEST + usage: cp [-fipRHLP] SOURCE... DEST - Copy files from SOURCE to DEST. If more than one SOURCE, DEST must - be a directory. + Copy files from SOURCE to DEST. If more than one SOURCE, DEST must + be a directory. -f force copy by deleting destination file -i interactive, prompt before overwriting existing DEST -p preserve timestamps, ownership, and permissions - -r recurse into subdirectories (DEST must be a directory) + -R recurse into subdirectories (DEST must be a directory) + -H Follow symlinks listed on command line + -L Follow all symlinks + -P Do not follow symlinks [default] + +config CP_MORE + bool "cp -rdavsl options" + default y + depends on CP + help + usage: cp [-rdavsl] + + -r synonym for -R -d don't dereference symlinks -a same as -dpr - -l hard link instead of copying + -l hard link instead of copy + -s symlink instead of copy -v verbose */ +#define FOR_cp #include "toys.h" -#define FLAG_f 1 -#define FLAG_i 2 -#define FLAG_P 4 // todo -#define FLAG_L 8 // todo -#define FLAG_H 16 // todo -#define FLAG_a 32 -#define FLAG_p 64 -#define FLAG_d 128 // todo -#define FLAG_R 256 -#define FLAG_r 512 -#define FLAG_l 1024 // todo -#define FLAG_s 2048 // todo -#define FLAG_v 4098 - -DEFINE_GLOBALS( +// TODO: PLHlsd + +GLOBALS( char *destname; int destisdir; - int destisnew; int keep_symlinks; ) -#define TT this.cp - // Copy an individual file or directory to target. void cp_file(char *src, char *dst, struct stat *srcst) @@ -156,42 +156,36 @@ int cp_node(struct dirtree *node) void cp_main(void) { - struct stat st; + char *dpath = NULL; + struct stat st, std; int i; - // Grab target argument. (Guaranteed to be there due to "<2" above.) - - TT.destname = toys.optargs[--toys.optc]; + // Identify destination - // If destination doesn't exist, are we ok with that? + if (!stat(TT.destname, &std) && S_ISDIR(std.st_mode)) TT.destisdir++; + else if (toys.optc>1) error_exit("'%s' not directory", TT.destname); - if (stat(TT.destname, &st)) { - if (toys.optc>1) goto error_notdir; - TT.destisnew++; + // TODO: This is too early: we haven't created it yet if we need to + if (toys.optflags & (FLAG_R|FLAG_r|FLAG_a)) + dpath = realpath(TT.destname = toys.optargs[--toys.optc], NULL); - // If destination exists... - - } else { - if (S_ISDIR(st.st_mode)) TT.destisdir++; - else if (toys.optc > 1) goto error_notdir; - } - - // Handle sources + // Loop through sources for (i=0; i<toys.optc; i++) { - char *src = toys.optargs[i]; - char *dst; + char *dst, *src = toys.optargs[i]; // Skip src==dest (TODO check inodes to catch "cp blah ./blah"). - if (!strcmp(src, TT.destname)) continue; + if (!strncmp(src, TT.destname)) continue; // Skip nonexistent sources. TT.keep_symlinks = toys.optflags & (FLAG_d|FLAG_a); - if (TT.keep_symlinks ? lstat(src, &st) : stat(src, &st)) + if (TT.keep_symlinks ? lstat(src, &st) : stat(src, &st) + || (st.st_dev = dst.st_dev && st.st_ino == dst.dst_ino)) { - perror_msg("'%s'", src); +objection: + perror_msg("bad '%s'", src); toys.exitval = 1; continue; } @@ -199,26 +193,35 @@ void cp_main(void) // Copy directory or file. if (TT.destisdir) { + char *s; + + // Catch "cp -R .. ." and friends that would go on forever + if (dpath && (s = realpath(src, NULL)) { + int i = strlen(s); + i = (!strncmp(s, dst, i) && (!s[i] || s[i]=='/')); + free(s); + + if (i) goto objection; + } + + // Create destination filename within directory dst = strrchr(src, '/'); if (dst) dst++; else dst=src; dst = xmsprintf("%s/%s", TT.destname, dst); } else dst = TT.destname; + if (S_ISDIR(st.st_mode)) { if (toys.optflags & (FLAG_r|FLAG_R|FLAG_a)) { cp_file(src, dst, &st); TT.keep_symlinks++; - strncpy(toybuf, src, sizeof(toybuf)-1); - toybuf[sizeof(toybuf)-1]=0; - dirtree_read(toybuf, cp_node); + dirtree_read(src, cp_node); } else error_msg("Skipped dir '%s'", src); } else cp_file(src, dst, &st); if (TT.destisdir) free(dst); } + if (CFG_TOYBOX_FREE) free(dpath); return; - -error_notdir: - error_exit("'%s' isn't a directory", TT.destname); } diff --git a/toys/posix/date.c b/toys/posix/date.c index 07d8c1d6..9beaaa1a 100644 --- a/toys/posix/date.c +++ b/toys/posix/date.c @@ -17,17 +17,13 @@ config DATE Set/get the current date/time */ +#define FOR_date #include "toys.h" -DEFINE_GLOBALS( +GLOBALS( char *file; ) -#define TT this.date - -#define FLAG_u 1 -#define FLAG_r 2 - void date_main(void) { const char *format_string = "%a %b %e %H:%M:%S %Z %Y"; diff --git a/toys/posix/df.c b/toys/posix/df.c index e889907d..dc87fda3 100644 --- a/toys/posix/df.c +++ b/toys/posix/df.c @@ -37,16 +37,15 @@ config DF_PEDANTIC -k Sets units back to 1024 bytes (the default without -P) */ +#define FOR_df #include "toys.h" -DEFINE_GLOBALS( +GLOBALS( struct arg_list *fstype; long units; ) -#define TT this.df - static void show_mt(struct mtab_list *mt) { int len; @@ -67,7 +66,7 @@ static void show_mt(struct mtab_list *mt) } // If we don't have -a, skip synthetic filesystems - if (!(toys.optflags & 1) && !mt->statvfs.f_blocks) return; + if (!(toys.optflags & FLAG_a) && !mt->statvfs.f_blocks) return; // Figure out how much total/used/free space this filesystem has, // forcing 64-bit math because filesystems are big now. @@ -83,7 +82,7 @@ static void show_mt(struct mtab_list *mt) // Figure out appropriate spacing len = 25 - strlen(mt->device); if (len < 1) len = 1; - if (CFG_DF_PEDANTIC && (toys.optflags & 8)) { + if (CFG_DF_PEDANTIC && (toys.optflags & FLAG_P)) { printf("%s %ld %ld %ld %ld%% %s\n", mt->device, size, used, avail, percent, mt->dir); } else { @@ -98,9 +97,9 @@ void df_main(void) // Handle -P and -k TT.units = 1024; - if (CFG_DF_PEDANTIC && (toys.optflags & 8)) { + if (CFG_DF_PEDANTIC && (toys.optflags & FLAG_P)) { // Units are 512 bytes if you select "pedantic" without "kilobytes". - if ((toys.optflags&3) == 1) TT.units = 512; + if ((toys.optflags&(FLAG_P|FLAG_k)) == FLAG_P) TT.units = 512; printf("Filesystem %ld-blocks Used Available Capacity Mounted on\n", TT.units); } else puts("Filesystem\t1K-blocks\tUsed Available Use% Mounted on"); diff --git a/toys/posix/du.c b/toys/posix/du.c index 83aa88ec..8013810c 100644 --- a/toys/posix/du.c +++ b/toys/posix/du.c @@ -28,9 +28,10 @@ config DU -m Sizes in megabytes */ +#define FOR_du #include "toys.h" -DEFINE_GLOBALS( +GLOBALS( long maxdepth; long depth; long *dirsum; @@ -39,20 +40,6 @@ DEFINE_GLOBALS( struct arg_list *inodes; ) -#define TT this.du - -#define FLAG_x 1 -#define FLAG_s 2 -#define FLAG_L 4 -#define FLAG_k 8 -#define FLAG_H 16 -#define FLAG_a 32 -#define FLAG_c 64 -#define FLAG_l 128 -#define FLAG_m 256 -#define FLAG_h 512 -#define FLAG_d 1024 - typedef struct node_size { struct dirtree *node; long size; diff --git a/toys/posix/echo.c b/toys/posix/echo.c index 576cad70..1bf4d399 100644 --- a/toys/posix/echo.c +++ b/toys/posix/echo.c @@ -32,12 +32,9 @@ config ECHO \xHH hexadecimal values (1 to 2 digits) */ -#define THIS echo +#define FOR_echo #include "toys.h" -#define FLAG_e (1<<1) -#define FLAG_n (1<<0) - void echo_main(void) { int i = 0, out; diff --git a/toys/posix/env.c b/toys/posix/env.c index 4427d01e..32272799 100644 --- a/toys/posix/env.c +++ b/toys/posix/env.c @@ -29,7 +29,7 @@ void env_main(void) char **command = NULL; char *del = "="; - if (toys.optflags & 1) clearenv(); + if (toys.optflags) clearenv(); for (ev = toys.optargs; *ev != NULL; ev++) { char *env, *val = NULL; diff --git a/toys/posix/head.c b/toys/posix/head.c index a7271cd5..77978f74 100644 --- a/toys/posix/head.c +++ b/toys/posix/head.c @@ -20,15 +20,14 @@ config HEAD -n Number of lines to copy. */ +#define FOR_head #include "toys.h" -DEFINE_GLOBALS( +GLOBALS( long lines; int file_no; ) -#define TT this.head - static void do_head(int fd, char *name) { int i, len, lines=TT.lines, size=sizeof(toybuf); diff --git a/toys/posix/id.c b/toys/posix/id.c index d93bc2bc..523d4f3a 100644 --- a/toys/posix/id.c +++ b/toys/posix/id.c @@ -25,14 +25,9 @@ config ID -u Show only the effective user ID */ +#define FOR_id #include "toys.h" -#define FLAG_n (1<<4) -#define FLAG_G (1<<3) -#define FLAG_g (1<<2) -#define FLAG_r (1<<1) -#define FLAG_u 1 - static void s_or_u(char *s, unsigned u, int done) { if (toys.optflags & FLAG_n) printf("%s", s); diff --git a/toys/posix/kill.c b/toys/posix/kill.c index e64a146b..7810b899 100644 --- a/toys/posix/kill.c +++ b/toys/posix/kill.c @@ -18,14 +18,13 @@ config KILL */ +#define FOR_kill #include "toys.h" -DEFINE_GLOBALS( +GLOBALS( char *signame; ) -#define TT this.kill - void kill_main(void) { int signum; @@ -33,7 +32,7 @@ void kill_main(void) pid_t pid; // list signal(s) - if (toys.optflags & 1) { + if (toys.optflags & FLAG_l) { if (*args) { int signum = sig_to_num(*args); char *s = NULL; diff --git a/toys/posix/ln.c b/toys/posix/ln.c index ec3317d2..a83df7f6 100644 --- a/toys/posix/ln.c +++ b/toys/posix/ln.c @@ -22,12 +22,9 @@ config LN -n Symlink at destination treated as file */ +#define FOR_ln #include "toys.h" -#define FLAG_s 1 -#define FLAG_f 2 -#define FLAG_n 4 - void ln_main(void) { char *dest = toys.optargs[--toys.optc], *new; diff --git a/toys/posix/ls.c b/toys/posix/ls.c index a68533ff..6492fb9e 100644 --- a/toys/posix/ls.c +++ b/toys/posix/ls.c @@ -50,40 +50,14 @@ config LS -S size */ +#define FOR_ls #include "toys.h" -#define FLAG_1 (1<<0) -#define FLAG_x (1<<1) -#define FLAG_u (1<<2) -#define FLAG_t (1<<3) -#define FLAG_s (1<<4) -#define FLAG_r (1<<5) -#define FLAG_q (1<<6) -#define FLAG_p (1<<7) -#define FLAG_n (1<<8) -#define FLAG_m (1<<9) -#define FLAG_l (1<<10) -#define FLAG_k (1<<11) -#define FLAG_i (1<<12) -#define FLAG_f (1<<13) -#define FLAG_d (1<<14) -#define FLAG_c (1<<15) -#define FLAG_a (1<<16) -#define FLAG_S (1<<17) -#define FLAG_R (1<<18) -#define FLAG_L (1<<19) -#define FLAG_H (1<<20) -#define FLAG_F (1<<21) -#define FLAG_C (1<<22) -#define FLAG_A (1<<23) -#define FLAG_o (1<<24) -#define FLAG_g (1<<25) - // test sst output (suid/sticky in ls flaglist) // ls -lR starts .: then ./subdir: -DEFINE_GLOBALS( +GLOBALS( struct dirtree *files; unsigned screen_width; @@ -93,8 +67,6 @@ DEFINE_GLOBALS( char uid_buf[12]; ) -#define TT this.ls - void dlist_to_dirtree(struct dirtree *parent) { // Turn double_list into dirtree diff --git a/toys/posix/mkdir.c b/toys/posix/mkdir.c index c3bbb636..e4e591d7 100644 --- a/toys/posix/mkdir.c +++ b/toys/posix/mkdir.c @@ -20,14 +20,13 @@ config MKDIR -p make parent directories as needed. */ +#define FOR_mkdir #include "toys.h" -DEFINE_GLOBALS( +GLOBALS( long mode; ) -#define TT this.mkdir - static int do_mkdir(char *dir) { struct stat buf; diff --git a/toys/posix/mkfifo.c b/toys/posix/mkfifo.c index e5c15389..44775788 100644 --- a/toys/posix/mkfifo.c +++ b/toys/posix/mkfifo.c @@ -19,16 +19,14 @@ config MKFIFO Create FIFOs (named pipes). */ +#define FOR_mkfifo #include "toys.h" -DEFINE_GLOBALS( +GLOBALS( char *m_string; mode_t mode; ) -#define TT this.mkfifo -#define FLAG_m (1) - void mkfifo_main(void) { char **s; diff --git a/toys/posix/nice.c b/toys/posix/nice.c index 4f522aa7..d45429f8 100644 --- a/toys/posix/nice.c +++ b/toys/posix/nice.c @@ -22,14 +22,13 @@ config NICE priority. Only root can set a negative niceness level. */ +#define FOR_nice #include "toys.h" -DEFINE_GLOBALS( +GLOBALS( long priority; ) -#define TT this.nice - void nice_main(void) { if (!toys.optflags) TT.priority = 10; diff --git a/toys/posix/od.c b/toys/posix/od.c index 3c84cb51..ef420b87 100644 --- a/toys/posix/od.c +++ b/toys/posix/od.c @@ -19,20 +19,10 @@ config OD -t output type(s) a (ascii) c (char) d (decimal) foux */ +#define FOR_od #include "toys.h" -#define FLAG_t (1 << 0) -#define FLAG_A (1 << 1) -#define FLAG_b (1 << 2) -#define FLAG_c (1 << 3) -#define FLAG_d (1 << 4) -#define FLAG_o (1 << 5) -#define FLAG_s (1 << 6) -#define FLAG_x (1 << 7) -#define FLAG_N (1 << 8) -#define FLAG_v (1 << 9) - -DEFINE_GLOBALS( +GLOBALS( struct arg_list *output_base; char *address_base; long max_count; @@ -44,8 +34,6 @@ DEFINE_GLOBALS( off_t pos; ) -#define TT this.od - static char *ascii = "nulsohstxetxeotenqackbel bs ht nl vt ff cr so si" "dledc1dc2dc3dc4naksynetbcan emsubesc fs gs rs us sp"; diff --git a/toys/posix/patch.c b/toys/posix/patch.c index a19cc8d3..fae908db 100644 --- a/toys/posix/patch.c +++ b/toys/posix/patch.c @@ -45,9 +45,10 @@ config PATCH created/deleted as appropriate. */ +#define FOR_patch #include "toys.h" -DEFINE_GLOBALS( +GLOBALS( char *infile; long prefix; @@ -58,14 +59,6 @@ DEFINE_GLOBALS( char *tempname; ) -#define TT this.patch - -#define FLAG_R (1<<0) -#define FLAG_i (1<<1) -#define FLAG_l (1<<2) -#define FLAG_p (1<<3) -#define FLAG_u (1<<4) - // Dispose of a line of input, either by writing it out or discarding it. // state < 2: just free diff --git a/toys/posix/sed.c b/toys/posix/sed.c index 4097585e..a3ba9e38 100644 --- a/toys/posix/sed.c +++ b/toys/posix/sed.c @@ -18,15 +18,14 @@ config SED of input. */ +#define FOR_sed #include "toys.h" #include "lib/xregcomp.h" -DEFINE_GLOBALS( +GLOBALS( struct arg_list *commands; ) -#define TT this.sed - struct sed_command { // Doubly linked list of commands. struct sed_command *next, *prev; diff --git a/toys/posix/sh.c b/toys/posix/sh.c index f0bcdc38..44c39119 100644 --- a/toys/posix/sh.c +++ b/toys/posix/sh.c @@ -176,14 +176,13 @@ config CD_P -L Cancel previous -P and restore default behavior. */ +#define FOR_sh #include "toys.h" -DEFINE_GLOBALS( +GLOBALS( char *command; ) -#define TT this.sh - // A single executable, its arguments, and other information we know about it. #define SH_FLAG_EXIT 1 #define SH_FLAG_SUSPEND 2 diff --git a/toys/posix/sort.c b/toys/posix/sort.c index 27aeb777..8f26f5d3 100644 --- a/toys/posix/sort.c +++ b/toys/posix/sort.c @@ -60,9 +60,10 @@ config SORT_FLOAT */ +#define FOR_sort #include "toys.h" -DEFINE_GLOBALS( +GLOBALS( char *key_separator; struct arg_list *raw_keys; char *outfile; @@ -73,30 +74,11 @@ DEFINE_GLOBALS( char **lines; ) -#define TT this.sort - // The sort types are n, g, and M. // u, c, s, and z apply to top level only, not to keys. // b at top level implies bb. // The remaining options can be applied to search keys. -#define FLAG_n (1<<0) // Sort type: numeric -#define FLAG_u (1<<1) // Unique -#define FLAG_r (1<<2) // Reverse output order - -#define FLAG_i (1<<3) // Ignore !isprint() -#define FLAG_f (1<<4) // Force uppercase -#define FLAG_d (1<<5) // Ignore !(isalnum()|isspace()) -#define FLAG_z (1<<6) // Input is null terminated, not \n -#define FLAG_s (1<<7) // Stable sort, no ascii fallback at end -#define FLAG_c (1<<8) // Check only. No output, exit(!ordered) -#define FLAG_M (1<<9) // Sort type: date -#define FLAG_b (1<<10) // Ignore leading blanks -#define FLAG_x (1<<11) // Hex sort -#define FLAG_g (1<<18) // Sort type: strtod() - -// Left off dealing with FLAG_b/FLAG_bb logic... - #define FLAG_bb (1<<31) // Ignore trailing blanks struct sort_key diff --git a/toys/posix/tail.c b/toys/posix/tail.c index 83a47674..d0711c0c 100644 --- a/toys/posix/tail.c +++ b/toys/posix/tail.c @@ -29,21 +29,16 @@ config TAIL_SEEK This version uses lseek, which is faster on large files. */ +#define FOR_tail #include "toys.h" -DEFINE_GLOBALS( +GLOBALS( long lines; long bytes; int file_no; ) -#define TT this.tail - -#define FLAG_n 1 -#define FLAG_c 2 -#define FLAG_f 4 - struct line_list { struct line_list *next, *prev; char *data; diff --git a/toys/posix/tee.c b/toys/posix/tee.c index 15a40fe7..e6342f4c 100644 --- a/toys/posix/tee.c +++ b/toys/posix/tee.c @@ -21,14 +21,13 @@ config TEE -i ignore SIGINT. */ +#define FOR_tee #include "toys.h" -DEFINE_GLOBALS( +GLOBALS( void *outputs; ) -#define TT this.tee - struct fd_list { struct fd_list *next; int fd; @@ -48,12 +47,12 @@ static void do_tee_open(int fd, char *name) void tee_main(void) { - if (toys.optflags&2) signal(SIGINT, SIG_IGN); + if (toys.optflags & FLAG_i) signal(SIGINT, SIG_IGN); // Open output files loopfiles_rw(toys.optargs, - O_RDWR|O_CREAT|((toys.optflags&1)?O_APPEND:O_TRUNC), 0666, 0, - do_tee_open); + O_RDWR|O_CREAT|((toys.optflags & FLAG_a)?O_APPEND:O_TRUNC), + 0666, 0, do_tee_open); for (;;) { struct fd_list *fdl; diff --git a/toys/posix/uname.c b/toys/posix/uname.c index c1f2b490..3c774b3c 100644 --- a/toys/posix/uname.c +++ b/toys/posix/uname.c @@ -24,6 +24,7 @@ config UNAME -a All of the above */ +#define FOR_uname #include "toys.h" // If a 32 bit x86 build environment working in a chroot under an x86-64 @@ -39,15 +40,13 @@ config UNAME #define GROSS "i386" #endif -#define FLAG_a (1<<5) - void uname_main(void) { int i, flags = toys.optflags, needspace=0; uname((void *)toybuf); - if (!flags) flags=1; + if (!flags) flags = FLAG_s; for (i=0; i<5; i++) { char *c = toybuf+(65*i); diff --git a/toys/posix/uniq.c b/toys/posix/uniq.c index 1418904a..f42b7293 100644 --- a/toys/posix/uniq.c +++ b/toys/posix/uniq.c @@ -26,23 +26,16 @@ config UNIQ -s ignore first X chars */ +#define FOR_uniq #include "toys.h" -DEFINE_GLOBALS( +GLOBALS( long maxchars; long nchars; long nfields; long repeats; ) -#define TT this.uniq - -#define FLAG_z 16 -#define FLAG_i 8 -#define FLAG_c 4 -#define FLAG_d 2 -#define FLAG_u 1 - static char *skip(char *str) { long nchars = TT.nchars, nfields; diff --git a/toys/posix/wc.c b/toys/posix/wc.c index 9d11577c..7a5e5a30 100644 --- a/toys/posix/wc.c +++ b/toys/posix/wc.c @@ -24,14 +24,13 @@ config WC argument (or from stdin if none). */ +#define FOR_wc #include "toys.h" -DEFINE_GLOBALS( +GLOBALS( unsigned long totals[3]; ) -#define TT this.wc - static void show_lengths(unsigned long *lengths, char *name) { int i, nospace = 1; diff --git a/toys/posix/xargs.c b/toys/posix/xargs.c index 0d513253..8f19d07f 100644 --- a/toys/posix/xargs.c +++ b/toys/posix/xargs.c @@ -29,9 +29,10 @@ config XARGS -E stop at line matching string */ +#define FOR_xargs #include "toys.h" -DEFINE_GLOBALS( +GLOBALS( long max_bytes; long max_entries; long L; @@ -42,8 +43,6 @@ DEFINE_GLOBALS( char delim; ) -#define TT this.xargs - // If out==NULL count TT.bytes and TT.entries, stopping at max. // Otherwise, fill out out[] @@ -105,7 +104,7 @@ void xargs_main(void) int entries, bytes, done = 0, status; char *data = NULL; - if (!(toys.optflags&1)) TT.delim = '\n'; + if (!(toys.optflags & FLAG_0)) TT.delim = '\n'; // If no optargs, call echo. if (!toys.optc) { diff --git a/www/code.html b/www/code.html index 3a77a3ce..73348ca0 100644 --- a/www/code.html +++ b/www/code.html @@ -74,7 +74,8 @@ multiple commands:</li> <li><a href="#lib_dirtree">lib/dirtree.c</a></li> </ul> <li>The <a href="#toys">toys directory</a> contains the C files implementating -each command.</li> +each command. Currently it contains three subdirectories: +posix, lsb, and other.</li> <li>The <a href="#scripts">scripts directory</a> contains the build and test infrastructure.</li> <li>The <a href="#kconfig">kconfig directory</a> contains the configuration @@ -85,13 +86,18 @@ files generated from other parts of the source code.</li> <a name="adding" /> <p><h1>Adding a new command</h1></p> -<p>To add a new command to toybox, add a C file implementing that command to +<p>To add a new command to toybox, add a C file implementing that command under the toys directory. No other files need to be modified; the build extracts all the information it needs (such as command line arguments) from specially formatted comments and macros in the C file. (See the description of the <a href="#generated">"generated" directory</a> for details.)</p> -<p>An easy way to start a new command is copy the file "hello.c" to +<p>Currently there are three subdirectories under "toys", one for commands +defined by the POSIX standard, one for commands defined by the Linux Standard +Base, and one for all other commands. (This is just for developer convenience +sorting them, the directories are otherwise functionally identical.)</p> + +<p>An easy way to start a new command is copy the file "toys/other/hello.c" to the name of the new command, and modify this copy to implement the new command. This file is an example command meant to be used as a "skeleton" for new commands (more or less by turning every instance of "hello" into the @@ -104,7 +110,7 @@ variables that a "hello world" program doesn't strictly need).</p> <p>Here's a checklist of steps to turn hello.c into another command:</p> <ul> -<li><p>First "cd toys" and "cp hello.c yourcommand.c". Note that the name +<li><p>First "cd toys/other" and "cp hello.c yourcommand.c". Note that the name of this file is significant, it's the name of the new command you're adding to toybox. Open your new file in your favorite editor.</p></li> @@ -114,12 +120,9 @@ to toybox. Open your new file in your favorite editor.</p></li> <li><p>Change the copyright notice to your name, email, and the current year.</p></li> -<li><p>Give a URL to the relevant standards document, or say "Not in SUSv4" if -there is no relevant standard. (Currently both lines are there, delete -whichever is inappropriate.) The existing link goes to the directory of SUSv4 -command line utility standards on the Open Group's website, where there's often -a relevant commandname.html file. Feel free to link to other documentation or -standards as appropriate.</p></li> +<li><p>Give a URL to the relevant standards document, where applicable. +(Sample links to SUSv4 and LSB are provided, feel free to link to other +documentation or standards as appropriate.)</p></li> <li><p>Update the USE_YOURCOMMAND(NEWTOY(yourcommand,"blah",0)) line. The NEWTOY macro fills out this command's <a href="#toy_list">toy_list</a> @@ -153,24 +156,29 @@ collates these usage lines for commands with multiple configuration options when producing generated/help.h.</p> </li> -<li><p>Update the DEFINE_GLOBALS() macro to contain your command's global -variables, and also change the name "hello" in the #define TT line afterwards -to the name of your command. If your command has no global variables, delete -this macro (and the #define TT line afterwards). Note that if you specified -two-character command line arguments in NEWTOY(), the first few global -variables will be initialized by the automatic argument parsing logic, and -the type and order of these variables must correspond to the arguments -specified in NEWTOY(). See [TODO] for details.</p></li> - -<li><p>If you didn't delete the DEFINE_GLOBALS macro, change the "#define TT -this.hello" line to use your command name in place of the "hello". This is a -shortcut to access your global variables as if they were members of the global -struct "TT". (Access these members with a period ".", not a right arrow -"->".)</p></li> +<li><p>Change the "#define FOR_hello" line to "#define FOR_yourcommand" right +before the "#include <toys.h>". (This selects the appropriate FLAG_ macros and +does a "#define TT this.yourcommand" so you can access the global variables +out of the space-saving union of structures. If you aren't using any command +flag bits and aren't defining a GLOBAL block, you can delete this line.)</p></li> + +<li><p>Update the GLOBALS() macro to contain your command's global +variables. If your command has no global variables, delete this macro.</p> + +<p>Variables in the GLOBALS() block are are stored in a space saving +<a href="#toy_union">union of structures</a> format, which may be accessed +using the TT macro as if TT were a global structure (so TT.membername). +If you specified two-character command line arguments in +NEWTOY(), the first few global variables will be initialized by the automatic +argument parsing logic, and the type and order of these variables must +correspond to the arguments specified in NEWTOY(). +(See <a href="#lib_args">lib/args.c</a> for details.)</p></li> <li><p>Rename hello_main() to yourcommand_main(). This is the main() function -where execution of your command starts. See [TODO] to figure out what -happened to your command line arguments and how to access them.</p></li> +where execution of your command starts. Your command line options are +already sorted into this.optflags, this.optargs, this.optc, and the GLOBALS() +as appropriate by the time this function is called. (See +<a href="#lib_args">get_optflags()</a> for details.</p></li> </ul> <p><a name="top" /><h2>Top level directory.</h2></p> @@ -178,7 +186,9 @@ happened to your command line arguments and how to access them.</p></li> <p>This directory contains global infrastructure.</p> <h3>toys.h</h3> -<p>Each command #includes "toys.h" as part of its standard prolog.</p> +<p>Each command #includes "toys.h" as part of its standard prolog. It +may "#define FOR_commandname" before doing so to get some extra entries +specific to this command.</p> <p>This file sucks in most of the commonly used standard #includes, so individual files can just #include "toys.h" and not have to worry about @@ -233,7 +243,7 @@ defining macros and #including generated/newtoys.h.</p> command.</p></li> <li><p>char *<b>options</b> - command line option string (used by get_optflags() in lib/args.c to intialize toys.optflags, toys.optargs, and -entries in the toy's DEFINE_GLOBALS struct). When this is NULL, no option +entries in the toy's GLOBALS struct). When this is NULL, no option parsing is done before calling toy_main().</p></li> <li><p>int <b>flags</b> - Behavior flags for this command. The following flags are currently understood:</p> @@ -269,7 +279,7 @@ unmodified string array passed in to main(). Note that modifying this changes "ps" output, and is not recommended. This array is null terminated; a NULL entry indicates the end of the array.</p> <p>Most commands don't use this field, instead the use optargs, optflags, -and the fields in the DEFINE_GLOBALS struct initialized by get_optflags().</p> +and the fields in the GLOBALS struct initialized by get_optflags().</p> </li> <li><p>unsigned <b>optflags</b> - Command line option flags, set by <a href="#lib_args">get_optflags()</a>. Indicates which of the command line options listed in @@ -282,8 +292,15 @@ the option string "abcd" would parse the command line "-c" to set optflags to 2, "-a" would set optflags to 8, and "-bd" would set optflags to 6 (4|2).</p> <p>Only letters are relevant to optflags. In the string "a*b:c#d", d=1, c=2, -b=4, a=8. The punctuation after a letter initializes global variables -(see [TODO] DECLARE_GLOBALS() for details).</p> +b=4, a=8. Punctuation after a letter initializes global variables at the +start of the GLOBALS() block (see <a href="#toy_union">union toy_union this</a> +for details).</p> + +<p>The build infrastructure creates FLAG_ macros for each option letter, +corresponding to the bit position, so you can check (toys.optflags & FLAG_x) +to see if a flag was specified. (The correct set of FLAG_ macros is selected +by defining FOR_mycommand before #including toys.h. The macros live in +toys/globals.h which is generated by scripts/make.sh.)</p> <p>For more information on option parsing, see <a href="#lib_args">get_optflags()</a>.</p> @@ -299,6 +316,7 @@ via help_main() before exiting. (True during option parsing, defaults to false afterwards.)</p></li> </ul> +<a name="toy_union" /> <li><p><b>union toy_union this</b> - Union of structures containing each command's global variables.</p> @@ -313,11 +331,12 @@ running would be wasteful.</p> <p>Toybox handles this by encapsulating each command's global variables in a structure, and declaring a union of those structures with a single global -instance (called "this"). The DEFINE_GLOBALS() macro contains the global +instance (called "this"). The GLOBALS() macro contains the global variables that should go in the current command's global structure. Each variable can then be accessed as "this.commandname.varname". -Generally, the macro TT is #defined to this.commandname so the variable -can then be accessed as "TT.variable". See toys/hello.c for an example.</p> +If you #defined FOR_commandname before including toys.h, the macro TT is +#defined to this.commandname so the variable can then be accessed as +"TT.variable". See toys/hello.c for an example.</p> <p>A command that needs global variables should declare a structure to contain them all, and add that structure to this union. A command should never @@ -664,17 +683,16 @@ available to command_main(): <p>If the command's globals are:</p> <blockquote><pre> -DECLARE_GLOBALS( +GLOBALS( char *c; char *b; long a; ) -#define TT this.command </pre></blockquote> <p>That would mean TT.c == NULL, TT.b == "fruit", and TT.a == 42. (Remember, each entry that receives an argument must be a long or pointer, to line up with the array position. Right to left in the optflags string corresponds to -top to bottom in DECLARE_GLOBALS().</p> +top to bottom in GLOBALS().</p> <p><b>long toys.optflags</b></p> @@ -940,6 +958,28 @@ from elsewhere in the program. This gives ls -lR manual control of traversal order, which is neither depth first nor breadth first but instead a sort of FIFO order requried by the ls standard.</p> +<a name="#toys"> +<h2>Directory toys/</h2> + +<p>This directory contains command implementations. Each command is a single +self-contained file. Adding a new command involves adding a single +file, and removing a command involves removing that file. Commands use +shared infrastructure from the lib/ and generated/ directories.</p> + +<p>Currently there are three subdirectories under "toys/" containing commands +described in POSIX-2008, the Linux Standard Base 4.1, or "other". The only +difference this makes is which menu the command shows up in during "make +menuconfig", the directories are otherwise identical. Note that they commands +exist within a single namespace at runtime, so you can't have the same +command in multiple subdirectories.</p> + +<p>(There are actually four sub-menus in "make menuconfig", the fourth +contains global configuration options for toybox, and lives in Config.in at +the top level.)</p> + +<p>See <a href="#adding">adding a new command</a> for details on the +layout of a command file.</p> + <h2>Directory scripts/</h2> <h3>scripts/cfg2files.sh</h3> |