From 9dbe4d054703ac96355c90bd7794d14d206e10c5 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 12 Mar 2014 22:43:50 +0100 Subject: docs: update new-applet-HOWTO.txt This patch adds some information about the gen_build_files.sh script and how it allows to keep the Kbuild, Config.in etc. declarations in .c files. Signed-off-by: Bartosz Golaszewski Signed-off-by: Denys Vlasenko --- docs/new-applet-HOWTO.txt | 97 ++++++++++++++++++++++++++++++----------------- 1 file changed, 62 insertions(+), 35 deletions(-) (limited to 'docs') diff --git a/docs/new-applet-HOWTO.txt b/docs/new-applet-HOWTO.txt index 6a8054d0e..28970a50a 100644 --- a/docs/new-applet-HOWTO.txt +++ b/docs/new-applet-HOWTO.txt @@ -16,10 +16,10 @@ Initial Write First, write your applet. Be sure to include copyright information at the top, such as who you stole the code from and so forth. Also include the mini-GPL -boilerplate. Be sure to name the main function _main instead of main. -And be sure to put it in .c. Usage does not have to be taken care of by -your applet. -Make sure to #include "libbb.h" as the first include file in your applet. +boilerplate and Config.in/Kbuild/usage/applet.h snippets (more on that below +in this document). Be sure to name the main function _main instead +of main. And be sure to put it in .c. Make sure to #include "libbb.h" +as the first include file in your applet. For a new applet mu, here is the code that would go in mu.c: @@ -41,6 +41,23 @@ For a new applet mu, here is the code that would go in mu.c: #include "libbb.h" #include "other.h" +//config:config MU +//config: bool "MU" +//config: default n +//config: help +//config: Returns an indeterminate value. + +//kbuild:lib-$(CONFIG_MU) += mu.o +//applet:IF_MU(APPLET(mu, BB_DIR_USR_BIN, BB_SUID_DROP)) + +//usage:#define mu_trivial_usage +//usage: "-[abcde] FILES" +//usage:#define mu_full_usage +//usage: "Returns an indeterminate value.\n\n" +//usage: "Options:\n" +//usage: "\t-a\t\tfirst function\n" +//usage: "\t-b\t\tsecond function\n" + int mu_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int mu_main(int argc, char **argv) { @@ -90,6 +107,8 @@ Make a new file named .c #include "libbb.h" #include "other.h" +//kbuild:lib-y += function.o + int function(char *a) { return *a; @@ -97,9 +116,7 @@ int function(char *a) ----end example code------ -Add .o in the right alphabetically sorted place -in libbb/Kbuild.src. You should look at the conditional part of -libbb/Kbuild.src as well. +Remember about the kbuild snippet. You should also try to find a suitable place in include/libbb.h for the function declaration. If not, add it somewhere anyway, with or without @@ -109,41 +126,55 @@ You can look at libbb/Config.src and try to find out if the function is tunable and add it there if it is. +Kbuild/Config.in/usage/applets.h snippets in .c files +----------------------------------------------------- + +The old way of adding new applets was to put all the information needed by the +configuration and build system into appropriate files (namely: Kbuild.src and +Config.src in new applet's directory) and to add the applet declaration and +usage info text to include/applets.src.h and include/usage.src.h respectively. + +Since the scripts/gen_build_files.sh script had been introduced, the preferred +way is to have all these declarations contained within the applet .c files. + +Every line intended to be processed by gen_build_files.sh should start as a +comment without any preceding whitespaces and be followed by an appropriate +keyword - kbuild, config, usage or applet - and a colon, just like shown in the +first example above. + + Placement / Directory --------------------- Find the appropriate directory for your new applet. -Make sure you find the appropriate places in the files, the applets are -sorted alphabetically. +Add the kbuild snippet to the .c file: -Add the applet to Kbuild.src in the chosen directory: +//kbuild:lib-$(CONFIG_MU) += mu.o -lib-$(CONFIG_MU) += mu.o +Add the config snippet to the .c file: -Add the applet to Config.src in the chosen directory: - -config MU - bool "MU" - default n - help - Returns an indeterminate value. +//config:config MU +//config: bool "MU" +//config: default n +//config: help +//config: Returns an indeterminate value. Usage String(s) --------------- -Next, add usage information for you applet to include/usage.src.h. +Next, add usage information for your applet to the .c file. This should look like the following: - #define mu_trivial_usage \ - "-[abcde] FILES" - #define mu_full_usage \ - "Returns an indeterminate value.\n\n" \ - "Options:\n" \ - "\t-a\t\tfirst function\n" \ - "\t-b\t\tsecond function\n" \ - ... +//usage:#define mu_trivial_usage +//usage: "-[abcde] FILES" +//usage:#define mu_full_usage +//usage: "Returns an indeterminate value.\n\n" +//usage: "Options:\n" +//usage: "\t-a\t\tfirst function\n" +//usage: "\t-b\t\tsecond function\n" +//usage: ... If your program supports flags, the flags should be mentioned on the first line (-[abcde]) and a detailed description of each flag should go in the @@ -154,15 +185,11 @@ currently exist in usage.src.h.) Header Files ------------ -Next, add an entry to include/applets.src.h. Be *sure* to keep the list -in alphabetical order, or else it will break the binary-search lookup -algorithm in busybox.c and the Gods of BusyBox smite you. Yea, verily: - -Be sure to read the top of applets.src.h before adding your applet. +Finally add the applet declaration snippet. Be sure to read the top of +applets.src.h before adding your applet - it contains important info +on applet macros and conventions. - /* all programs above here are alphabetically "less than" 'mu' */ - IF_MU(APPLET(mu, BB_DIR_USR_BIN, BB_SUID_DROP)) - /* all programs below here are alphabetically "greater than" 'mu' */ +//applet:IF_MU(APPLET(mu, BB_DIR_USR_BIN, BB_SUID_DROP)) The Grand Announcement -- cgit v1.2.3-55-g6feb From f332617fbd9248f34cff183a2a4caa961730625d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 17 Mar 2014 15:06:29 +0100 Subject: docs/new-applet-HOWTO.txt: tweak a bit Signed-off-by: Denys Vlasenko --- docs/new-applet-HOWTO.txt | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) (limited to 'docs') diff --git a/docs/new-applet-HOWTO.txt b/docs/new-applet-HOWTO.txt index 28970a50a..078e77bce 100644 --- a/docs/new-applet-HOWTO.txt +++ b/docs/new-applet-HOWTO.txt @@ -6,7 +6,7 @@ This document details the steps you must take to add a new applet to BusyBox. Credits: Matt Kraai - initial writeup Mark Whitley - the remix -Thomas Lundquist - Trying to keep it updated. +Thomas Lundquist - trying to keep it updated When doing this you should consider using the latest git HEAD. This is a good thing if you plan to getting it committed into mainline. @@ -23,7 +23,7 @@ as the first include file in your applet. For a new applet mu, here is the code that would go in mu.c: -(busybox.h already includes most usual header files. You do not need +(libbb.h already includes most usual header files. You do not need #include etc...) @@ -43,7 +43,7 @@ For a new applet mu, here is the code that would go in mu.c: //config:config MU //config: bool "MU" -//config: default n +//config: default y //config: help //config: Returns an indeterminate value. @@ -51,12 +51,11 @@ For a new applet mu, here is the code that would go in mu.c: //applet:IF_MU(APPLET(mu, BB_DIR_USR_BIN, BB_SUID_DROP)) //usage:#define mu_trivial_usage -//usage: "-[abcde] FILES" +//usage: "[-abcde] FILE..." //usage:#define mu_full_usage -//usage: "Returns an indeterminate value.\n\n" -//usage: "Options:\n" -//usage: "\t-a\t\tfirst function\n" -//usage: "\t-b\t\tsecond function\n" +//usage: "Returns an indeterminate value\n" +//usage: "\n -a First function" +//usage: "\n -b Second function" int mu_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int mu_main(int argc, char **argv) @@ -150,13 +149,13 @@ Find the appropriate directory for your new applet. Add the kbuild snippet to the .c file: -//kbuild:lib-$(CONFIG_MU) += mu.o +//kbuild:lib-$(CONFIG_MU) += mu.o Add the config snippet to the .c file: //config:config MU //config: bool "MU" -//config: default n +//config: default y //config: help //config: Returns an indeterminate value. @@ -168,18 +167,16 @@ Next, add usage information for your applet to the .c file. This should look like the following: //usage:#define mu_trivial_usage -//usage: "-[abcde] FILES" +//usage: "[-abcde] FILE..." //usage:#define mu_full_usage -//usage: "Returns an indeterminate value.\n\n" -//usage: "Options:\n" -//usage: "\t-a\t\tfirst function\n" -//usage: "\t-b\t\tsecond function\n" +//usage: "Returns an indeterminate value\n" +//usage: "\n -a First function" +//usage: "\n -b Second function" //usage: ... If your program supports flags, the flags should be mentioned on the first -line (-[abcde]) and a detailed description of each flag should go in the -mu_full_usage section, one flag per line. (Numerous examples of this -currently exist in usage.src.h.) +line ([-abcde]) and a detailed description of each flag should go in the +mu_full_usage section, one flag per line. Header Files -- cgit v1.2.3-55-g6feb From e765b5ac349a8f9305e52b3ab2c3ac78c17bf283 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 2 May 2014 17:15:58 +0200 Subject: libbb: rename execable -> executable. No code changes English speakers complained that it sounded awfully broken. Signed-off-by: Denys Vlasenko --- debianutils/which.c | 10 +++--- docs/ifupdown_design.txt | 2 +- include/libbb.h | 6 ++-- libbb/Kbuild.src | 2 +- libbb/execable.c | 92 ------------------------------------------------ libbb/executable.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++ networking/ifupdown.c | 4 +-- 7 files changed, 104 insertions(+), 104 deletions(-) delete mode 100644 libbb/execable.c create mode 100644 libbb/executable.c (limited to 'docs') diff --git a/debianutils/which.c b/debianutils/which.c index 15fd598b7..760bcdcad 100644 --- a/debianutils/which.c +++ b/debianutils/which.c @@ -46,7 +46,7 @@ int which_main(int argc UNUSED_PARAM, char **argv) #if ENABLE_DESKTOP /* Much bloat just to support -a */ if (strchr(*argv, '/')) { - if (execable_file(*argv)) { + if (file_is_executable(*argv)) { puts(*argv); continue; } @@ -55,7 +55,7 @@ int which_main(int argc UNUSED_PARAM, char **argv) char *path2 = xstrdup(path); char *tmp = path2; - p = find_execable(*argv, &tmp); + p = find_executable(*argv, &tmp); if (!p) status = EXIT_FAILURE; else { @@ -65,7 +65,7 @@ int which_main(int argc UNUSED_PARAM, char **argv) if (opt) { /* -a: show matches in all PATH components */ if (tmp) { - p = find_execable(*argv, &tmp); + p = find_executable(*argv, &tmp); if (p) goto print; } @@ -76,14 +76,14 @@ int which_main(int argc UNUSED_PARAM, char **argv) #else /* Just ignoring -a */ if (strchr(*argv, '/')) { - if (execable_file(*argv)) { + if (file_is_executable(*argv)) { puts(*argv); continue; } } else { char *path2 = xstrdup(path); char *tmp = path2; - p = find_execable(*argv, &tmp); + p = find_executable(*argv, &tmp); free(path2); if (p) { puts(p); diff --git a/docs/ifupdown_design.txt b/docs/ifupdown_design.txt index 8ab4e51ad..39e28a9f4 100644 --- a/docs/ifupdown_design.txt +++ b/docs/ifupdown_design.txt @@ -21,7 +21,7 @@ static int dhcp_down(struct interface_defn_t *ifd, execfn *exec) #if ENABLE_FEATURE_IFUPDOWN_EXTERNAL_DHCP int i ; for (i = 0; i < ARRAY_SIZE(ext_dhcp_clients); i++) { - if (exists_execable(ext_dhcp_clients[i].name)) + if (executable_exists(ext_dhcp_clients[i].name)) return execute(ext_dhcp_clients[i].stopcmd, ifd, exec); } bb_error_msg("no dhcp clients found, using static interface shutdown"); diff --git a/include/libbb.h b/include/libbb.h index 29cf6bc6d..afdee38c4 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -912,9 +912,9 @@ void FAST_FUNC update_utmp(pid_t pid, int new_type, const char *tty_name, const #endif -int execable_file(const char *name) FAST_FUNC; -char *find_execable(const char *filename, char **PATHp) FAST_FUNC; -int exists_execable(const char *filename) FAST_FUNC; +int file_is_executable(const char *name) FAST_FUNC; +char *find_executable(const char *filename, char **PATHp) FAST_FUNC; +int executable_exists(const char *filename) FAST_FUNC; /* BB_EXECxx always execs (it's not doing NOFORK/NOEXEC stuff), * but it may exec busybox and call applet instead of searching PATH. diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src index a6468f171..6578d1171 100644 --- a/libbb/Kbuild.src +++ b/libbb/Kbuild.src @@ -30,7 +30,7 @@ lib-y += crc32.o lib-y += default_error_retval.o lib-y += device_open.o lib-y += dump.o -lib-y += execable.o +lib-y += executable.o lib-y += fclose_nonstdin.o lib-y += fflush_stdout_and_exit.o lib-y += fgets_str.o diff --git a/libbb/execable.c b/libbb/execable.c deleted file mode 100644 index a3caea6f9..000000000 --- a/libbb/execable.c +++ /dev/null @@ -1,92 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* - * Utility routines. - * - * Copyright (C) 2006 Gabriel Somlo - * - * Licensed under GPLv2 or later, see file LICENSE in this source tree. - */ - -#include "libbb.h" - -/* check if path points to an executable file; - * return 1 if found; - * return 0 otherwise; - */ -int FAST_FUNC execable_file(const char *name) -{ - struct stat s; - return (!access(name, X_OK) && !stat(name, &s) && S_ISREG(s.st_mode)); -} - -/* search (*PATHp) for an executable file; - * return allocated string containing full path if found; - * PATHp points to the component after the one where it was found - * (or NULL), - * you may call find_execable again with this PATHp to continue - * (if it's not NULL). - * return NULL otherwise; (PATHp is undefined) - * in all cases (*PATHp) contents will be trashed (s/:/NUL/). - */ -char* FAST_FUNC find_execable(const char *filename, char **PATHp) -{ - /* About empty components in $PATH: - * http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html - * 8.3 Other Environment Variables - PATH - * A zero-length prefix is a legacy feature that indicates the current - * working directory. It appears as two adjacent colons ( "::" ), as an - * initial colon preceding the rest of the list, or as a trailing colon - * following the rest of the list. - */ - char *p, *n; - - p = *PATHp; - while (p) { - n = strchr(p, ':'); - if (n) - *n++ = '\0'; - p = concat_path_file( - p[0] ? p : ".", /* handle "::" case */ - filename - ); - if (execable_file(p)) { - *PATHp = n; - return p; - } - free(p); - p = n; - } /* on loop exit p == NULL */ - return p; -} - -/* search $PATH for an executable file; - * return 1 if found; - * return 0 otherwise; - */ -int FAST_FUNC exists_execable(const char *filename) -{ - char *path = xstrdup(getenv("PATH")); - char *tmp = path; - char *ret = find_execable(filename, &tmp); - free(path); - free(ret); - return ret != NULL; -} - -#if ENABLE_FEATURE_PREFER_APPLETS -/* just like the real execvp, but try to launch an applet named 'file' first */ -int FAST_FUNC BB_EXECVP(const char *file, char *const argv[]) -{ - if (find_applet_by_name(file) >= 0) - execvp(bb_busybox_exec_path, argv); - return execvp(file, argv); -} -#endif - -int FAST_FUNC BB_EXECVP_or_die(char **argv) -{ - BB_EXECVP(argv[0], argv); - /* SUSv3-mandated exit codes */ - xfunc_error_retval = (errno == ENOENT) ? 127 : 126; - bb_perror_msg_and_die("can't execute '%s'", argv[0]); -} diff --git a/libbb/executable.c b/libbb/executable.c new file mode 100644 index 000000000..85ecc3e6c --- /dev/null +++ b/libbb/executable.c @@ -0,0 +1,92 @@ +/* vi: set sw=4 ts=4: */ +/* + * Utility routines. + * + * Copyright (C) 2006 Gabriel Somlo + * + * Licensed under GPLv2 or later, see file LICENSE in this source tree. + */ + +#include "libbb.h" + +/* check if path points to an executable file; + * return 1 if found; + * return 0 otherwise; + */ +int FAST_FUNC file_is_executable(const char *name) +{ + struct stat s; + return (!access(name, X_OK) && !stat(name, &s) && S_ISREG(s.st_mode)); +} + +/* search (*PATHp) for an executable file; + * return allocated string containing full path if found; + * PATHp points to the component after the one where it was found + * (or NULL), + * you may call find_executable again with this PATHp to continue + * (if it's not NULL). + * return NULL otherwise; (PATHp is undefined) + * in all cases (*PATHp) contents will be trashed (s/:/NUL/). + */ +char* FAST_FUNC find_executable(const char *filename, char **PATHp) +{ + /* About empty components in $PATH: + * http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html + * 8.3 Other Environment Variables - PATH + * A zero-length prefix is a legacy feature that indicates the current + * working directory. It appears as two adjacent colons ( "::" ), as an + * initial colon preceding the rest of the list, or as a trailing colon + * following the rest of the list. + */ + char *p, *n; + + p = *PATHp; + while (p) { + n = strchr(p, ':'); + if (n) + *n++ = '\0'; + p = concat_path_file( + p[0] ? p : ".", /* handle "::" case */ + filename + ); + if (file_is_executable(p)) { + *PATHp = n; + return p; + } + free(p); + p = n; + } /* on loop exit p == NULL */ + return p; +} + +/* search $PATH for an executable file; + * return 1 if found; + * return 0 otherwise; + */ +int FAST_FUNC executable_exists(const char *filename) +{ + char *path = xstrdup(getenv("PATH")); + char *tmp = path; + char *ret = find_executable(filename, &tmp); + free(path); + free(ret); + return ret != NULL; +} + +#if ENABLE_FEATURE_PREFER_APPLETS +/* just like the real execvp, but try to launch an applet named 'file' first */ +int FAST_FUNC BB_EXECVP(const char *file, char *const argv[]) +{ + if (find_applet_by_name(file) >= 0) + execvp(bb_busybox_exec_path, argv); + return execvp(file, argv); +} +#endif + +int FAST_FUNC BB_EXECVP_or_die(char **argv) +{ + BB_EXECVP(argv[0], argv); + /* SUSv3-mandated exit codes */ + xfunc_error_retval = (errno == ENOENT) ? 127 : 126; + bb_perror_msg_and_die("can't execute '%s'", argv[0]); +} diff --git a/networking/ifupdown.c b/networking/ifupdown.c index e1ea351a4..c35d97a1a 100644 --- a/networking/ifupdown.c +++ b/networking/ifupdown.c @@ -555,7 +555,7 @@ static int FAST_FUNC dhcp_up(struct interface_defn_t *ifd, execfn *exec) return 0; # endif for (i = 0; i < ARRAY_SIZE(ext_dhcp_clients); i++) { - if (exists_execable(ext_dhcp_clients[i].name)) + if (executable_exists(ext_dhcp_clients[i].name)) return execute(ext_dhcp_clients[i].startcmd, ifd, exec); } bb_error_msg("no dhcp clients found"); @@ -592,7 +592,7 @@ static int FAST_FUNC dhcp_down(struct interface_defn_t *ifd, execfn *exec) unsigned i; for (i = 0; i < ARRAY_SIZE(ext_dhcp_clients); i++) { - if (exists_execable(ext_dhcp_clients[i].name)) { + if (executable_exists(ext_dhcp_clients[i].name)) { result = execute(ext_dhcp_clients[i].stopcmd, ifd, exec); if (result) break; -- cgit v1.2.3-55-g6feb