Ron Yorston | 31a04d9 | 2018-11-27 10:45:30 +0000 | [diff] [blame] | 1 | Embedded Shell Scripts in BusyBox |
| 2 | ================================= |
| 3 | |
| 4 | BusyBox allows applets to be implemented as shell scripts. Since |
| 5 | this obviously requires a shell to interpret the scripts the feature |
Ron Yorston | 71df2d3 | 2018-11-27 14:34:25 +0000 | [diff] [blame] | 6 | depends on having a shell built into the binary. Either ash or hush |
| 7 | will do. If both are present ash will be used. Support for embedded |
| 8 | scripts also has to be enabled. |
Ron Yorston | 31a04d9 | 2018-11-27 10:45:30 +0000 | [diff] [blame] | 9 | |
| 10 | It's unlikely that your applet will be implemented as a pure shell |
| 11 | script: it will probably need some external commands. If these are |
| 12 | to be provided by BusyBox you'll need to ensure they're enabled too. |
| 13 | |
| 14 | There are two ways to include scripts in BusyBox: the quick-and-dirty |
| 15 | custom script and the full-featured scripted applet. |
| 16 | |
| 17 | Custom Scripts |
| 18 | -------------- |
| 19 | |
| 20 | When embedded script support is enabled the BusyBox build process |
| 21 | assumes that any files in the directory 'embed' at the top level of |
| 22 | the source tree are scripts to be embedded. |
| 23 | |
| 24 | The embed directory isn't present in the BusyBox source tree and |
| 25 | BusyBox itself will never put anything there: it's entirely for the |
| 26 | use of third parties. |
| 27 | |
| 28 | Adding a custom script is as simple as running the following sequence |
| 29 | of commands in the BusyBox source directory: |
| 30 | |
| 31 | mkdir embed |
| 32 | echo 'echo foo' >embed/foo |
| 33 | make defconfig |
| 34 | make |
| 35 | |
| 36 | The resulting binary includes the new applet foo! |
| 37 | |
| 38 | Custom scripts have limited opportunities for configuration: the only |
| 39 | control developers have is to put them in the embed directory, or not. |
| 40 | Everything else takes default values. For more control you need the |
| 41 | additional features provided by scripted applets. |
| 42 | |
| 43 | Scripted Applets |
| 44 | ---------------- |
| 45 | |
| 46 | Suppose we want to make a shell script version of the sample applet |
| 47 | from the New Applet HOWTO. First we'd have to write a script (vaguely) |
| 48 | equivalent to the C code: |
| 49 | |
| 50 | return $(($RANDOM%256)) |
| 51 | |
| 52 | This should be placed in the file applets_sh/mu in the source tree. |
| 53 | |
| 54 | Next we need the configuration data. This is very similar to the example |
| 55 | code for the native applet: |
| 56 | |
| 57 | //config:config MU |
Denys Vlasenko | 00d10cb | 2021-12-17 21:38:02 +0100 | [diff] [blame] | 58 | //config: bool "MU" |
| 59 | //config: default y |
| 60 | //config: help |
| 61 | //config: Returns an indeterminate value. |
Ron Yorston | 31a04d9 | 2018-11-27 10:45:30 +0000 | [diff] [blame] | 62 | |
| 63 | //applet:IF_MU(APPLET_SCRIPTED(mu, scripted, BB_DIR_USR_BIN, BB_SUID_DROP, mu)) |
| 64 | |
| 65 | //usage:#define mu_trivial_usage |
Denys Vlasenko | 00d10cb | 2021-12-17 21:38:02 +0100 | [diff] [blame] | 66 | //usage: "[-abcde] FILE..." |
Ron Yorston | 31a04d9 | 2018-11-27 10:45:30 +0000 | [diff] [blame] | 67 | //usage:#define mu_full_usage |
Denys Vlasenko | 00d10cb | 2021-12-17 21:38:02 +0100 | [diff] [blame] | 68 | //usage: "Returns an indeterminate value\n" |
| 69 | //usage: "\n -a First function" |
| 70 | //usage: "\n -b Second function" |
Ron Yorston | 31a04d9 | 2018-11-27 10:45:30 +0000 | [diff] [blame] | 71 | |
| 72 | The only difference is that the applet is specified as being of type |
| 73 | APPLET_SCRIPTED. It would also be useful to include details of any |
Ron Yorston | 71df2d3 | 2018-11-27 14:34:25 +0000 | [diff] [blame] | 74 | dependencies the script has. No external commands are used by our mu |
| 75 | script, but it does depend on optional shell features. We can ensure |
| 76 | these are selected by adding this to the configuration: |
Ron Yorston | 31a04d9 | 2018-11-27 10:45:30 +0000 | [diff] [blame] | 77 | |
| 78 | //config:config MU_DEPENDENCIES |
| 79 | //config: bool "Enable dependencies for mu" |
| 80 | //config: default y |
| 81 | //config: depends on MU |
| 82 | //config: select ASH_RANDOM_SUPPORT |
| 83 | //config: select FEATURE_SH_MATH |
| 84 | //config: help |
Ron Yorston | 71df2d3 | 2018-11-27 14:34:25 +0000 | [diff] [blame] | 85 | //config: mu is implemented as a shell script. It requires support |
| 86 | //config: for $RANDOM and arithmetic. |
Ron Yorston | 31a04d9 | 2018-11-27 10:45:30 +0000 | [diff] [blame] | 87 | |
| 88 | The configuration data should be placed in a C file in an appropriate |
| 89 | subdirectory. There isn't any C code, though! In this case the file |
| 90 | could be miscutils/mu.c. |
| 91 | |
| 92 | Scripted applets are just as configurable as applets written in C. |
| 93 | They can be enabled or disabled using the configuration menu; their |
| 94 | install directory can be specified and their usage messages are stored |
| 95 | along with those of all other applets. |
| 96 | |
| 97 | Additional Notes |
| 98 | ---------------- |
| 99 | |
| 100 | The source for embedded scripts can be displayed by running: |
| 101 | |
| 102 | busybox --show SCRIPT |
| 103 | |
| 104 | This can be disabled by turning off FEATURE_SHOW_SCRIPT in the |
| 105 | configuration, though it won't prevent a determined user from |
| 106 | extracting the source code. |
| 107 | |
| 108 | It can be argued that embedded scripts are linked into the BusyBox |
| 109 | binary and are therefore not subject to the 'mere aggregation' |
| 110 | exception in the GPL. If this is the case embedded scripts should |
| 111 | have a licence compatible with BusyBox's GPL v2-only licence. |