diff options
Diffstat (limited to 'findutils')
-rw-r--r-- | findutils/xargs.c | 207 |
1 files changed, 91 insertions, 116 deletions
diff --git a/findutils/xargs.c b/findutils/xargs.c index d067a3f48..b6a154f15 100644 --- a/findutils/xargs.c +++ b/findutils/xargs.c @@ -45,54 +45,52 @@ #endif /* - This function have special algorithm. - Don`t use fork and include to main! + This function has special algorithm. + Don't use fork and include to main! */ static int xargs_exec(char *const *args) { pid_t p; volatile int exec_errno = 0; /* shared vfork stack */ + int status; - if ((p = vfork()) >= 0) { - if (p == 0) { - /* vfork -- child */ - execvp(args[0], args); - exec_errno = errno; /* set error to shared stack */ - _exit(1); - } else { - /* vfork -- parent */ - int status; - - while (wait(&status) == (pid_t) - 1) - if (errno != EINTR) - break; - if (exec_errno) { - errno = exec_errno; - bb_perror_msg("%s", args[0]); - return exec_errno == ENOENT ? 127 : 126; - } else { - if (WEXITSTATUS(status) == 255) { - bb_error_msg("%s: exited with status 255; aborting", args[0]); - return 124; - } - if (WIFSTOPPED(status)) { - bb_error_msg("%s: stopped by signal %d", - args[0], WSTOPSIG(status)); - return 125; - } - if (WIFSIGNALED(status)) { - bb_error_msg("%s: terminated by signal %d", - args[0], WTERMSIG(status)); - return 125; - } - if (WEXITSTATUS(status) != 0) - return 123; - return 0; - } - } - } else { + p = vfork(); + if (p < 0) bb_perror_msg_and_die("vfork"); + + if (p == 0) { + /* vfork -- child */ + execvp(args[0], args); + exec_errno = errno; /* set error to shared stack */ + _exit(1); + } + + /* vfork -- parent */ + while (wait(&status) == (pid_t) -1) + if (errno != EINTR) + break; + if (exec_errno) { + errno = exec_errno; + bb_perror_msg("%s", args[0]); + return exec_errno == ENOENT ? 127 : 126; } + if (WEXITSTATUS(status) == 255) { + bb_error_msg("%s: exited with status 255; aborting", args[0]); + return 124; + } + if (WIFSTOPPED(status)) { + bb_error_msg("%s: stopped by signal %d", + args[0], WSTOPSIG(status)); + return 125; + } + if (WIFSIGNALED(status)) { + bb_error_msg("%s: terminated by signal %d", + args[0], WTERMSIG(status)); + return 125; + } + if (WEXITSTATUS(status)) + return 123; + return 0; } @@ -105,7 +103,7 @@ typedef struct xlist_s { static int eof_stdin_detected; #define ISBLANK(c) ((c) == ' ' || (c) == '\t') -#define ISSPACE(c) (ISBLANK (c) || (c) == '\n' || (c) == '\r' \ +#define ISSPACE(c) (ISBLANK(c) || (c) == '\n' || (c) == '\r' \ || (c) == '\f' || (c) == '\v') #ifdef CONFIG_FEATURE_XARGS_SUPPORT_QUOTES @@ -304,19 +302,10 @@ static int xargs_ask_confirmation(void) return 1; return 0; } - -# define OPT_INC_P 1 #else -# define OPT_INC_P 0 # define xargs_ask_confirmation() 1 #endif /* CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION */ -#ifdef CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT -# define OPT_INC_X 1 -#else -# define OPT_INC_X 0 -#endif - #ifdef CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM static xlist_t *process0_stdin(xlist_t * list_arg, const char *eof_str ATTRIBUTE_UNUSED, size_t mc, char *buf) @@ -371,35 +360,37 @@ static xlist_t *process0_stdin(xlist_t * list_arg, const char *eof_str ATTRIBUTE } return list_arg; } - -# define READ_ARGS(l, e, nmc, mc) (*read_args)(l, e, nmc, mc) -# define OPT_INC_0 1 /* future use */ -#else -# define OPT_INC_0 0 /* future use */ -# define READ_ARGS(l, e, nmc, mc) process_stdin(l, e, nmc, mc) #endif /* CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM */ - -#define OPT_VERBOSE (1<<0) -#define OPT_NO_EMPTY (1<<1) -#define OPT_UPTO_NUMBER (1<<2) -#define OPT_UPTO_SIZE (1<<3) -#define OPT_EOF_STRING (1<<4) -#ifdef CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION -#define OPT_INTERACTIVE (1<<5) -#else -#define OPT_INTERACTIVE (0) /* require for algorithm &| */ -#endif -#define OPT_TERMINATE (1<<(5+OPT_INC_P)) -#define OPT_ZEROTERM (1<<(5+OPT_INC_P+OPT_INC_X)) -/* next future -#define OPT_NEXT_OTHER (1<<(5+OPT_INC_P+OPT_INC_X+OPT_INC_0)) -*/ +/* Correct regardless of combination of CONFIG_xxx */ +enum { + OPTBIT_VERBOSE = 0, + OPTBIT_NO_EMPTY, + OPTBIT_UPTO_NUMBER, + OPTBIT_UPTO_SIZE, + OPTBIT_EOF_STRING, + USE_FEATURE_XARGS_SUPPORT_CONFIRMATION(OPTBIT_INTERACTIVE,) + USE_FEATURE_XARGS_SUPPORT_TERMOPT( OPTBIT_TERMINATE ,) + USE_FEATURE_XARGS_SUPPORT_ZERO_TERM( OPTBIT_ZEROTERM ,) + + OPT_VERBOSE = 1<<OPTBIT_VERBOSE , + OPT_NO_EMPTY = 1<<OPTBIT_NO_EMPTY , + OPT_UPTO_NUMBER = 1<<OPTBIT_UPTO_NUMBER, + OPT_UPTO_SIZE = 1<<OPTBIT_UPTO_SIZE , + OPT_EOF_STRING = 1<<OPTBIT_EOF_STRING , + OPT_INTERACTIVE = USE_FEATURE_XARGS_SUPPORT_CONFIRMATION((1<<OPTBIT_INTERACTIVE)) + 0, + OPT_TERMINATE = USE_FEATURE_XARGS_SUPPORT_TERMOPT( (1<<OPTBIT_TERMINATE )) + 0, + OPT_ZEROTERM = USE_FEATURE_XARGS_SUPPORT_ZERO_TERM( (1<<OPTBIT_ZEROTERM )) + 0, +}; +#define OPTION_STR "+trn:s:e::" \ + USE_FEATURE_XARGS_SUPPORT_CONFIRMATION("p") \ + USE_FEATURE_XARGS_SUPPORT_TERMOPT( "x") \ + USE_FEATURE_XARGS_SUPPORT_ZERO_TERM( "0") int xargs_main(int argc, char **argv) { char **args; - int i, a, n; + int i, n; xlist_t *list = NULL; xlist_t *cur; int child_error = 0; @@ -410,42 +401,33 @@ int xargs_main(int argc, char **argv) const char *eof_str = "_"; unsigned long opt; size_t n_max_chars; - -#ifdef CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM - xlist_t *(*read_args) (xlist_t *, const char *, size_t, char *) = process_stdin; +#if ENABLE_FEATURE_XARGS_SUPPORT_ZERO_TERM + xlist_t* (*read_args)(xlist_t*, const char*, size_t, char*) = process_stdin; +#else +#define read_args process_stdin #endif -#ifdef CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION - bb_opt_complementally = "pt"; -#endif + opt = bb_getopt_ulflags(argc, argv, OPTION_STR, &max_args, &max_chars, &eof_str); - opt = bb_getopt_ulflags(argc, argv, "+trn:s:e::" -#ifdef CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION - "p" -#endif -#ifdef CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT - "x" -#endif -#ifdef CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM - "0" -#endif - ,&max_args, &max_chars, &eof_str); + if (opt & OPT_ZEROTERM) + USE_FEATURE_XARGS_SUPPORT_ZERO_TERM(read_args = process0_stdin); - a = argc - optind; + argc -= optind; argv += optind; - if (a == 0) { + if (!argc) { /* default behavior is to echo all the filenames */ *argv = "echo"; - a++; + argc++; } orig_arg_max = ARG_MAX; if (orig_arg_max == -1) orig_arg_max = LONG_MAX; - orig_arg_max -= 2048; /* POSIX.2 requires subtracting 2048. */ - if ((opt & OPT_UPTO_SIZE)) { + orig_arg_max -= 2048; /* POSIX.2 requires subtracting 2048 */ + + if (opt & OPT_UPTO_SIZE) { n_max_chars = bb_xgetularg10_bnd(max_chars, 1, orig_arg_max); - for (i = 0; i < a; i++) { + for (i = 0; i < argc; i++) { n_chars += strlen(*argv) + 1; } if (n_max_chars < n_chars) { @@ -463,19 +445,14 @@ int xargs_main(int argc, char **argv) } max_chars = xmalloc(n_max_chars); - if ((opt & OPT_UPTO_NUMBER)) { + if (opt & OPT_UPTO_NUMBER) { n_max_arg = bb_xgetularg10_bnd(max_args, 1, INT_MAX); } else { n_max_arg = n_max_chars; } -#ifdef CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM - if (opt & OPT_ZEROTERM) - read_args = process0_stdin; -#endif - - while ((list = READ_ARGS(list, eof_str, n_max_chars, max_chars)) != NULL || - (opt & OPT_NO_EMPTY) == 0) + while ((list = read_args(list, eof_str, n_max_chars, max_chars)) != NULL || + !(opt & OPT_NO_EMPTY)) { opt |= OPT_NO_EMPTY; n = 0; @@ -501,13 +478,13 @@ int xargs_main(int argc, char **argv) } #endif /* CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT */ - /* allocating pointers for execvp: - a*arg, n*arg from stdin, NULL */ - args = xzalloc((n + a + 1) * sizeof(char *)); + /* allocate pointers for execvp: + argc*arg, n*arg from stdin, NULL */ + args = xzalloc((n + argc + 1) * sizeof(char *)); - /* Store the command to be executed + /* store the command to be executed (taken from the command line) */ - for (i = 0; i < a; i++) + for (i = 0; i < argc; i++) args[i] = argv[i]; /* (taken from stdin) */ for (cur = list; n; cur = cur->link) { @@ -515,21 +492,21 @@ int xargs_main(int argc, char **argv) n--; } - if ((opt & (OPT_INTERACTIVE | OPT_VERBOSE))) { + if (opt & (OPT_INTERACTIVE | OPT_VERBOSE)) { for (i = 0; args[i]; i++) { if (i) fputc(' ', stderr); fputs(args[i], stderr); } - if ((opt & OPT_INTERACTIVE) == 0) + if (!(opt & OPT_INTERACTIVE)) fputc('\n', stderr); } - if ((opt & OPT_INTERACTIVE) == 0 || xargs_ask_confirmation() != 0) { + if (!(opt & OPT_INTERACTIVE) || xargs_ask_confirmation()) { child_error = xargs_exec(args); } /* clean up */ - for (i = a; args[i]; i++) { + for (i = argc; args[i]; i++) { cur = list; list = list->link; free(cur); @@ -539,9 +516,7 @@ int xargs_main(int argc, char **argv) break; } } -#ifdef CONFIG_FEATURE_CLEAN_UP - free(max_chars); -#endif + if (ENABLE_FEATURE_CLEAN_UP) free(max_chars); return child_error; } |