From 52370154121692ffe96660b675584bc1569c8c3f Mon Sep 17 00:00:00 2001
From: Rob Landley
Adding a new command
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 -"generated" directory for details.)
+To add a new command to toybox, add a C file implementing that command to +one of the subdirectories 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 "generated" directory +for details.)
Currently there are five subdirectories under "toys", one for commands defined by the POSIX standard, one for commands defined by the Linux Standard @@ -489,8 +491,9 @@ instructions.
which is for files generated at build time from other source files.generated/Config.in - Included from the top level Config.in, -contains one or more configuration entries for each command.
+generated/Config.in - Kconfig entries for each command, included +from the top level Config.in. The help text here is used to generate +help.h.
Each command has a configuration entry with an upper case version of the command name. Options to commands start with the command @@ -498,16 +501,10 @@ name followed by an underscore and the option name. Global options are attached to the "toybox" command, and thus use the prefix "TOYBOX_". This organization is used by scripts/cfg2files to select which toys/*/*.c files to compile for a given .config.
- -A command with multiple names (or multiple similar commands implemented in -the same .c file) should have config symbols prefixed with the name of their -C file. I.E. config symbol prefixes are NEWTOY() names. If OLDTOY() names -have config symbols they must be options (symbols with an underscore and -suffix) to the NEWTOY() name. (See generated/toylist.h)
generated/config.h - list of CFG_SYMBOL and USE_SYMBOL() macros, -generated from .config by a sed invocation in the top level Makefile.
+generated from .config by a sed invocation in scripts/make.sh.CFG_SYMBOL is a comple time constant set to 1 for enabled symbols and 0 for disabled symbols. This allows the use of normal if() statements to remove @@ -518,12 +515,15 @@ breaks. (See the 1992 Usenix paper #ifdef Considered Harmful for more information.)
-USE_SYMBOL(code) evaluates to the code in parentheses when the symbol -is enabled, and nothing when the symbol is disabled. This can be used -for things like varargs or variable declarations which can't always be -eliminated by a simple test on CFG_SYMBOL. Note that -(unlike CFG_SYMBOL) this is really just a variant of #ifdef, and can -still result in configuration dependent build breaks. Use with caution.
+When you can't entirely avoid an #ifdef, the USE_SYMBOL(code) macro +provides a less intrusive alternative, evaluating to the code in parentheses +when the symbol is enabled, and nothing when the symbol is disabled. This +is most commonly used around NEWTOY() declarations (so only the enabled +commands show up in toy_list), and in option strings. This can also be used +for things like varargs or structure members which can't always be +eliminated by a simple test on CFG_SYMBOL. Remember, unlike CFG_SYMBOL +this is really just a variant of #ifdef, and can still result in configuration +dependent build breaks. Use with caution.
generated/flags.h - FLAG_? macros indicating which command @@ -556,10 +556,10 @@ variables out of "this" as TT.variablename.
lib/args.c argument parsing code called from main.c.toys/help.h - -#defines two help text strings for each command: a single line -command_help and an additinal command_help_long. This is used by help_main() -in toys/help.c to display help for commands.
+toys/help.h - Help strings for use by the "help" command and +--help options. This file #defines a help_symbolname string for each +symbolname, but only the symbolnames matching command names get used +by show_help() in lib/help.c to display help for commands.
This file is created by scripts/make.sh, which compiles scripts/config2help.c into the binary generated/config2help, and then runs it against the top @@ -573,17 +573,19 @@ have their help text added to the command they depend on.
generated/newtoys.h - -All the NEWTOY() and OLDTOY() macros in alphabetical order, -each of which should be inside the appropriate USE_ macro. (Ok, not _quite_ -alphabetical orer: the "toybox" multiplexer is always the first entry.)
+All the NEWTOY() and OLDTOY() macros from toys/*/*.c. The "toybox" multiplexer +is the first entry, the rest are in alphabetical order. Each line should be +inside an appropriate USE_ macro, so code that #includes this file only sees +the currently enabled commands.By #definining NEWTOY() to various things before #including this file, it may be used to create function prototypes (in toys.h), initialize the -toy_list array (in main.c, the alphabetical order lets toy_find() do a -binary search), initialize the help_data array (in lib/help.c), and so on. -(It's even used to initialize the NEED_OPTIONS macro, which is has a 1 or 0 -for each command using command line option parsing, ORed together. -This allows compile-time dead code elimination to remove the whole of +help_data array (in lib/help.c), initialize the toy_list array (in main.c, +the alphabetical order lets toy_find() do a binary search, the exception to +the alphabetical order lets it use the multiplexer without searching), and so +on. (It's even used to initialize the NEED_OPTIONS macro, which produces a 1 +or 0 for each command using command line option parsing, which is ORed together +to allow compile-time dead code elimination to remove the whole of lib/args.c if nothing currently enabled is using it.)
Each NEWTOY and OLDTOY macro contains the command name, command line @@ -608,6 +610,163 @@ having to repeat it.
strlcpy(), xexec(), xopen()/xread(), xgetcwd(), xabspath(), find_in_path(), itoa(). + + +Functions prefixed with the letter x call perror_exit() when they hit +errors, to eliminate common error checking. This prints an error message +and the strerror() string for the errno encountered.
+ +You can intercept this exit by assigning a setjmp/longjmp buffer to +toys.rebound (set it back to zero to restore the default behavior). +If you do this, cleaning up resource leaks is your problem.
+ +int xcreate(char *path, int flags, int mode)
+int xopen(char *path, int flags)
The xopen() and xcreate() functions open an existing file (exiting if +it's not there) and create a new file (exiting if it can't).
+ +They default to O_CLOEXEC so the filehandles aren't passed on to child +processes. Feed in O_CLOEXEC to disable this.
+void xclose(int fd)
+ +Because NFS is broken, and won't necessarily perform the requested +operation (and report the error) until you close the file. Of course, this +being NFS, it's not guaranteed to report the error there either, but it +_can_.
+ +Nothing else ever reports an error on close, everywhere else it's just a +VFS operation freeing some resources. NFS is _special_, in a way that +other network filesystems like smbfs and v9fs aren't..
+size_t xread(int fd, void *buf, size_t len)
+ +Can return 0, but not -1.
+void xreadall(int fd, void *buf, size_t len)
+ +Reads the entire len-sized buffer, retrying to complete short +reads. Exits if it can't get enough data.
void xwrite(int fd, void *buf, size_t len)
+ +Retries short writes, exits if can't write the entire buffer.
char *xabspath(char *path, int exact)
+ +After several years of +wrestling +with realpath(), +I broke down and wrote +my own implementation that doesn't use the one in libc. As I explained: + +
+ +If the path ends with a broken link, +readlink -f should show where the link points to, not where the broken link +lives. (The point of readlink -f is "if I write here, where would it attempt +to create a file".) The problem is, realpath() returns NULL for a path ending +with a broken link, and I can't beat different behavior out of code locked +away in libc.
+
struct passwd *xgetpwuid(uid_t uid)
+struct group *xgetgrgid(gid_t gid)
+struct passwd *xgetpwnam(char *name)
Eight gazillion common functions:
+ +This file is automatically included from the top of toys.h, and smooths @@ -1124,16 +1283,23 @@ 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.
-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.
+Currently there are five subdirectories under "toys/" containing "posix" +commands described in POSIX-2008, "lsb" commands described in the Linux +Standard Base 4.1, "other" commands not described by either standard, +"pending" commands awaiting cleanup (which default to "n" in menuconfig +because they don't necessarily work right yet), and "example" code showing +how toybox infrastructure works and providing template/skeleton files to +start new commands.
-(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.)
+The only difference directory location makes is which menu the command +shows up in during "make menuconfig", the directories are otherwise identical. +Note that the commands exist within a single namespace at runtime, so you can't +have the same command in multiple subdirectories. (The build tries to fail +informatively when you do that.)
+ +There is one more sub-menus in "make menuconfig" containing global +configuration options for toybox. This menu is defined in the top level +Config.in.
See adding a new command for details on the layout of a command file.
@@ -1160,29 +1326,15 @@ Makefile.Menuconfig infrastructure copied from the Linux kernel. See the Linux kernel's Documentation/kbuild/kconfig-language.txt
- -All the files in this directory except the README are generated by the -build. (See scripts/make.sh)
- -config.h - CFG_COMMAND and USE_COMMAND() macros set by menuconfig via .config.
Config.in - Kconfig entries for each command. Included by top level Config.in. The help text in here is used to generated help.h
help.h - Help text strings for use by "help" command. Building -this file requires python on the host system, so the prebuilt file is shipped -in the build tarball to avoid requiring python to build toybox.