From 438b4ac2860f4aec5b5fb82c47f75a0cb80d9cb4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 16 Mar 2014 12:34:53 +0100 Subject: script: make it work even if fd 0 is closed Testcase: script -q -c "echo hey" /dev/null 0>&- Signed-off-by: Denys Vlasenko --- libbb/getpty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libbb') diff --git a/libbb/getpty.c b/libbb/getpty.c index 435e4d09f..391d729f2 100644 --- a/libbb/getpty.c +++ b/libbb/getpty.c @@ -16,7 +16,7 @@ int FAST_FUNC xgetpty(char *line) #if ENABLE_FEATURE_DEVPTS p = open("/dev/ptmx", O_RDWR); - if (p > 0) { + if (p >= 0) { grantpt(p); /* chmod+chown corresponding slave pty */ unlockpt(p); /* (what does this do?) */ # ifndef HAVE_PTSNAME_R -- cgit v1.2.3-55-g6feb From c50493854a78b28b3642a402d1a0bbd57c1b3c1b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 16 Mar 2014 20:53:40 +0100 Subject: libbb: fix a bad check for uclibc >= 0.9.31 Signed-off-by: Denys Vlasenko --- libbb/xreadlink.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'libbb') diff --git a/libbb/xreadlink.c b/libbb/xreadlink.c index bb63da08c..7d4cb60a5 100644 --- a/libbb/xreadlink.c +++ b/libbb/xreadlink.c @@ -1,14 +1,14 @@ /* vi: set sw=4 ts=4: */ /* * xreadlink.c - safe implementation of readlink. - * Returns a NULL on failure... + * Returns a NULL on failure. * * Licensed under GPLv2, see file LICENSE in this source tree. */ #include "libbb.h" -/* some systems (eg Hurd) does not have MAXSYMLINKS definition, +/* Some systems (eg Hurd) do not have MAXSYMLINKS definition, * set it to some reasonable value if it isn't defined */ #ifndef MAXSYMLINKS # define MAXSYMLINKS 20 @@ -108,8 +108,11 @@ char* FAST_FUNC xmalloc_readlink_or_warn(const char *path) char* FAST_FUNC xmalloc_realpath(const char *path) { -#if defined(__GLIBC__) || \ - (defined(__UCLIBC__) && UCLIBC_VERSION >= KERNEL_VERSION(0, 9, 31)) +/* NB: uclibc also defines __GLIBC__ + * Therefore the test "if glibc, or uclibc >= 0.9.31" looks a bit weird: + */ +#if defined(__GLIBC__) && \ + (!defined(__UCLIBC__) || UCLIBC_VERSION >= KERNEL_VERSION(0, 9, 31)) /* glibc provides a non-standard extension */ /* new: POSIX.1-2008 specifies this behavior as well */ return realpath(path, NULL); -- cgit v1.2.3-55-g6feb From ad16741ccd8a8587644d88fb8fdfc41ada1928a6 Mon Sep 17 00:00:00 2001 From: Bernhard Reutner-Fischer Date: Sun, 13 Apr 2014 16:37:57 +0200 Subject: libbb: provide usleep() fallback implementation POSIX.1-2008 removed the usleep function, provide a fallback implementaion using the recommended nanosleep(). Signed-off-by: Bernhard Reutner-Fischer Signed-off-by: Denys Vlasenko --- include/platform.h | 16 ++++++++++++++-- libbb/platform.c | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) (limited to 'libbb') diff --git a/include/platform.h b/include/platform.h index bd11ad69a..92f775551 100644 --- a/include/platform.h +++ b/include/platform.h @@ -373,6 +373,7 @@ typedef unsigned smalluint; #define HAVE_STRSIGNAL 1 #define HAVE_STRVERSCMP 1 #define HAVE_VASPRINTF 1 +#define HAVE_USLEEP 1 #define HAVE_UNLOCKED_STDIO 1 #define HAVE_UNLOCKED_LINE_OPS 1 #define HAVE_GETLINE 1 @@ -381,8 +382,15 @@ typedef unsigned smalluint; #define HAVE_NET_ETHERNET_H 1 #define HAVE_SYS_STATFS_H 1 -#if defined(__UCLIBC__) && UCLIBC_VERSION < KERNEL_VERSION(0, 9, 32) -# undef HAVE_STRVERSCMP +#if defined(__UCLIBC__) +# if UCLIBC_VERSION < KERNEL_VERSION(0, 9, 32) +# undef HAVE_STRVERSCMP +# endif +# if UCLIBC_VERSION >= KERNEL_VERSION(0, 9, 30) +# ifndef __UCLIBC_SUSV3_LEGACY__ +# undef HAVE_USLEEP +# endif +# endif #endif #if defined(__WATCOMC__) @@ -519,6 +527,10 @@ extern char *strsep(char **stringp, const char *delim) FAST_FUNC; # define strsignal(sig) get_signame(sig) #endif +#ifndef HAVE_USLEEP +extern int usleep(unsigned) FAST_FUNC; +#endif + #ifndef HAVE_VASPRINTF extern int vasprintf(char **string_ptr, const char *format, va_list p) FAST_FUNC; #endif diff --git a/libbb/platform.c b/libbb/platform.c index 19734517b..8d90ca4e9 100644 --- a/libbb/platform.c +++ b/libbb/platform.c @@ -17,6 +17,24 @@ char* FAST_FUNC strchrnul(const char *s, int c) } #endif +#ifndef HAVE_USLEEP +int FAST_FUNC usleep(unsigned usec) +{ + struct timespec ts; + ts.tv_sec = usec / 1000000u; + ts.tv_nsec = (usec % 1000000u) * 1000u; + /* + * If a signal has non-default handler, nanosleep returns early. + * Our version of usleep doesn't return early + * if interrupted by such signals: + * + */ + while (nanosleep(&ts, &ts) != 0) + continue; + return 0; +} +#endif + #ifndef HAVE_VASPRINTF int FAST_FUNC vasprintf(char **string_ptr, const char *format, va_list p) { -- cgit v1.2.3-55-g6feb From eb9f485b07b1823efbfddc773c899bd35dee62a6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 16 Apr 2014 19:51:34 +0200 Subject: libbb/obscure.c: code shrink. Suggested by Tito. function old new delta string_checker 97 92 -5 Signed-off-by: Denys Vlasenko --- libbb/obscure.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libbb') diff --git a/libbb/obscure.c b/libbb/obscure.c index 9ecc1f672..24c4ac917 100644 --- a/libbb/obscure.c +++ b/libbb/obscure.c @@ -76,7 +76,7 @@ static int string_checker(const char *p1, const char *p2) ret |= string_checker_helper(p, p2); /* clean up */ - memset(p, 0, size); + nuke_str(p); free(p); return ret; -- cgit v1.2.3-55-g6feb From 3dfe0ae5a8c4f3a75f61df157db157ac0e044a51 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 30 Apr 2014 14:48:28 +0200 Subject: libbb: make syslog level for bb_error_msg's configurable. use it in crond function old new delta bb_verror_msg 380 386 +6 syslog_level - 1 +1 crondlog 165 108 -57 Signed-off-by: Denys Vlasenko --- include/libbb.h | 1 + libbb/verror_msg.c | 3 ++- miscutils/crond.c | 23 ++++++++--------------- 3 files changed, 11 insertions(+), 16 deletions(-) (limited to 'libbb') diff --git a/include/libbb.h b/include/libbb.h index 1cbe2c8b4..29cf6bc6d 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1074,6 +1074,7 @@ enum { LOGMODE_BOTH = LOGMODE_SYSLOG + LOGMODE_STDIO, }; extern const char *msg_eol; +extern smallint syslog_level; extern smallint logmode; extern int die_sleep; extern uint8_t xfunc_error_retval; diff --git a/libbb/verror_msg.c b/libbb/verror_msg.c index ee95be3e3..87efb56b3 100644 --- a/libbb/verror_msg.c +++ b/libbb/verror_msg.c @@ -11,6 +11,7 @@ # include #endif +smallint syslog_level = LOG_ERR; smallint logmode = LOGMODE_STDIO; const char *msg_eol = "\n"; @@ -70,7 +71,7 @@ void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr) } #if ENABLE_FEATURE_SYSLOG if (logmode & LOGMODE_SYSLOG) { - syslog(LOG_ERR, "%s", msg + applet_len); + syslog(syslog_level, "%s", msg + applet_len); } #endif free(msg); diff --git a/miscutils/crond.c b/miscutils/crond.c index 995ed9e0a..8441b6cc5 100644 --- a/miscutils/crond.c +++ b/miscutils/crond.c @@ -163,28 +163,21 @@ static void crondlog(const char *ctl, ...) __attribute__ ((format (printf, 1, 2) static void crondlog(const char *ctl, ...) { va_list va; - int level = (ctl[0] & 0x1f); + unsigned level = (ctl[0] & 0x1f); va_start(va, ctl); - if (level >= (int)G.log_level) { - /* Debug mode: all to (non-redirected) stderr, */ - /* Syslog mode: all to syslog (logmode = LOGMODE_SYSLOG), */ - if (!DebugOpt && G.log_filename) { - /* Otherwise (log to file): we reopen log file at every write: */ + if (level >= G.log_level) { + if (G.log_filename) { + /* If log to file, reopen log file at every write: */ int logfd = open_or_warn(G.log_filename, O_WRONLY | O_CREAT | O_APPEND); if (logfd >= 0) xmove_fd(logfd, STDERR_FILENO); } /* When we log to syslog, level > 8 is logged at LOG_ERR - * syslog level, level <= 8 is logged at LOG_INFO. */ - if (level > 8) { - bb_verror_msg(ctl + 1, va, /* strerr: */ NULL); - } else { - char *msg = NULL; - vasprintf(&msg, ctl + 1, va); - bb_info_msg("%s: %s", applet_name, msg); - free(msg); - } + * syslog level, level <= 8 is logged at LOG_INFO. + */ + syslog_level = (level > 8) ? LOG_ERR : LOG_INFO; + bb_verror_msg(ctl + 1, va, /* strerr: */ NULL); } va_end(va); if (ctl[0] & 0x80) -- cgit v1.2.3-55-g6feb From fe33683c8bad841a1b5e947fcc6a502b85ca53cf Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 2 May 2014 07:18:55 +0200 Subject: Fix compile failures Signed-off-by: Denys Vlasenko --- libbb/verror_msg.c | 2 ++ miscutils/less.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'libbb') diff --git a/libbb/verror_msg.c b/libbb/verror_msg.c index 87efb56b3..0ef2a311f 100644 --- a/libbb/verror_msg.c +++ b/libbb/verror_msg.c @@ -11,7 +11,9 @@ # include #endif +#if ENABLE_FEATURE_SYSLOG smallint syslog_level = LOG_ERR; +#endif smallint logmode = LOGMODE_STDIO; const char *msg_eol = "\n"; diff --git a/miscutils/less.c b/miscutils/less.c index 36d0a0bd9..d84df469c 100644 --- a/miscutils/less.c +++ b/miscutils/less.c @@ -456,7 +456,7 @@ static void read_lines(void) readeof = eof_error; if (eof_error <= 0) goto reached_eof; - had_progress = 1; + IF_FEATURE_LESS_REGEXP(had_progress = 1;) } c = readbuf[readpos]; /* backspace? [needed for manpages] */ -- cgit v1.2.3-55-g6feb From 528808fa7b0778931fb624e95c38cf8cbc2fff90 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 2 May 2014 09:05:03 +0200 Subject: libbb: make rtc_xopen try harder on EBUSY function old new delta rtc_xopen 77 139 +62 Signed-off-by: Denys Vlasenko --- libbb/rtc.c | 52 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 10 deletions(-) (limited to 'libbb') diff --git a/libbb/rtc.c b/libbb/rtc.c index 97455e86a..f84da09bb 100644 --- a/libbb/rtc.c +++ b/libbb/rtc.c @@ -33,23 +33,55 @@ int FAST_FUNC rtc_adjtime_is_utc(void) return utc; } +/* rtc opens are exclusive. + * Try to run two "hwclock -w" at the same time to see it. + * Users wouldn't expect that to fail merely because /dev/rtc + * was momentarily busy, let's try a bit harder on errno == EBUSY. + */ +static int open_loop_on_busy(const char *name, int flags) +{ + int rtc; + /* + * Tested with two parallel "hwclock -w" loops. + * With try = 10, no failures with 2x1000000 loop iterations. + */ + int try = 1000 / 20; + again: + errno = 0; + rtc = open(name, flags); + if (errno == EBUSY) { + usleep(20 * 1000); + if (--try != 0) + goto again; + /* EBUSY. Last try, exit on error instead of returning -1 */ + return xopen(name, flags); + } + return rtc; +} + +/* Never fails */ int FAST_FUNC rtc_xopen(const char **default_rtc, int flags) { int rtc; + const char *name = + "/dev/rtc""\0" + "/dev/rtc0""\0" + "/dev/misc/rtc""\0"; - if (!*default_rtc) { - *default_rtc = "/dev/rtc"; - rtc = open(*default_rtc, flags); - if (rtc >= 0) - return rtc; - *default_rtc = "/dev/rtc0"; - rtc = open(*default_rtc, flags); + if (!*default_rtc) + goto try_name; + name = ""; /*else: we have rtc name, don't try other names */ + + for (;;) { + rtc = open_loop_on_busy(*default_rtc, flags); if (rtc >= 0) return rtc; - *default_rtc = "/dev/misc/rtc"; + name += strlen(name) + 1; + if (!name[0]) + return xopen(*default_rtc, flags); + try_name: + *default_rtc = name; } - - return xopen(*default_rtc, flags); } void FAST_FUNC rtc_read_tm(struct tm *ptm, int fd) -- cgit v1.2.3-55-g6feb From d8290c2ef039c389b2f39704543277865f3693fb Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 2 May 2014 09:07:16 +0200 Subject: libbb: fix thinko in rtc_xopen() Signed-off-by: Denys Vlasenko --- libbb/rtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libbb') diff --git a/libbb/rtc.c b/libbb/rtc.c index f84da09bb..6d06d57f9 100644 --- a/libbb/rtc.c +++ b/libbb/rtc.c @@ -76,11 +76,11 @@ int FAST_FUNC rtc_xopen(const char **default_rtc, int flags) rtc = open_loop_on_busy(*default_rtc, flags); if (rtc >= 0) return rtc; - name += strlen(name) + 1; if (!name[0]) return xopen(*default_rtc, flags); try_name: *default_rtc = name; + name += strlen(name) + 1; } } -- cgit v1.2.3-55-g6feb From 15a357e5962634c94ee322fee4da897312090a89 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 2 May 2014 17:08:29 +0200 Subject: libbb: fix empty PATH components handling function old new delta find_execable 81 86 +5 exists_execable 71 66 -5 Signed-off-by: Denys Vlasenko --- libbb/execable.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) (limited to 'libbb') diff --git a/libbb/execable.c b/libbb/execable.c index 178a00a5f..a3caea6f9 100644 --- a/libbb/execable.c +++ b/libbb/execable.c @@ -30,6 +30,14 @@ int FAST_FUNC execable_file(const char *name) */ 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; @@ -37,14 +45,15 @@ char* FAST_FUNC find_execable(const char *filename, char **PATHp) n = strchr(p, ':'); if (n) *n++ = '\0'; - if (*p != '\0') { /* it's not a PATH="foo::bar" situation */ - p = concat_path_file(p, filename); - if (execable_file(p)) { - *PATHp = n; - return p; - } - free(p); + 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; @@ -60,11 +69,8 @@ int FAST_FUNC exists_execable(const char *filename) char *tmp = path; char *ret = find_execable(filename, &tmp); free(path); - if (ret) { - free(ret); - return 1; - } - return 0; + free(ret); + return ret != NULL; } #if ENABLE_FEATURE_PREFER_APPLETS -- 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 'libbb') 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