struct BoolExpr * BX_UnequalN(size_t n, ...) { struct BoolExpr *xs[n]; READ_ARGS(n, xs); return BX_Unequal(n, xs); }
struct BoolExpr * BX_NandN(size_t n, ...) { struct BoolExpr *xs[n]; READ_ARGS(n, xs); return BX_Nand(n, xs); }
struct BoolExpr * BX_XnorN(size_t n, ...) { struct BoolExpr *xs[n]; READ_ARGS(n, xs); return BX_Xnor(n, xs); }
int xargs_main(int argc, char **argv) { char **args; int i, a, n; xlist_t *list = NULL; xlist_t *cur; int child_error = 0; char *max_args, *max_chars; int n_max_arg; size_t n_chars = 0; long orig_arg_max; 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; #endif #ifdef CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION bb_opt_complementaly = "pt"; #endif 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); a = argc - optind; argv += optind; if (a == 0) { /* default behavior is to echo all the filenames */ *argv = "echo"; a++; } 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)) { n_max_chars = bb_xgetularg10_bnd(max_chars, 1, orig_arg_max); for (i = 0; i < a; i++) { n_chars += strlen(*argv) + 1; } if (n_max_chars < n_chars) { bb_error_msg_and_die("can not fit single argument within argument list size limit"); } n_max_chars -= n_chars; } else { /* Sanity check for systems with huge ARG_MAX defines (e.g., Suns which have it at 1 meg). Things will work fine with a large ARG_MAX but it will probably hurt the system more than it needs to; an array of this size is allocated. */ if (orig_arg_max > 20 * 1024) orig_arg_max = 20 * 1024; n_max_chars = orig_arg_max; } max_chars = xmalloc(n_max_chars); 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) { opt |= OPT_NO_EMPTY; n = 0; n_chars = 0; #ifdef CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT for (cur = list; cur;) { n_chars += cur->lenght; n++; cur = cur->link; if (n_chars > n_max_chars || (n == n_max_arg && cur)) { if (opt & OPT_TERMINATE) bb_error_msg_and_die("argument list too long"); break; } } #else for (cur = list; cur; cur = cur->link) { n_chars += cur->lenght; n++; if (n_chars > n_max_chars || n == n_max_arg) { break; } } #endif /* CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT */ /* allocating pointers for execvp: a*arg, n*arg from stdin, NULL */ args = xcalloc(n + a + 1, sizeof(char *)); /* Store the command to be executed (taken from the command line) */ for (i = 0; i < a; i++) args[i] = argv[i]; /* (taken from stdin) */ for (cur = list; n; cur = cur->link) { args[i++] = cur->data; n--; } 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) fputc('\n', stderr); } if ((opt & OPT_INTERACTIVE) == 0 || xargs_ask_confirmation() != 0) { child_error = xargs_exec(args); } /* clean up */ for (i = a; args[i]; i++) { cur = list; list = list->link; free(cur); } free(args); if (child_error > 0 && child_error != 123) { break; } } #ifdef CONFIG_FEATURE_CLEAN_UP free(max_chars); #endif return child_error; }