| 1 | /* buildcmd.c -- build command lines from a list of arguments.
|
|---|
| 2 | Copyright (C) 1990, 91, 92, 93, 94, 2000, 2003, 2005 Free Software Foundation, Inc.
|
|---|
| 3 |
|
|---|
| 4 | This program is free software; you can redistribute it and/or modify
|
|---|
| 5 | it under the terms of the GNU General Public License as published by
|
|---|
| 6 | the Free Software Foundation; either version 2, or (at your option)
|
|---|
| 7 | any later version.
|
|---|
| 8 |
|
|---|
| 9 | This program is distributed in the hope that it will be useful,
|
|---|
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|---|
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|---|
| 12 | GNU General Public License for more details.
|
|---|
| 13 |
|
|---|
| 14 | You should have received a copy of the GNU General Public License
|
|---|
| 15 | along with this program; if not, write to the Free Software
|
|---|
| 16 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
|---|
| 17 | USA.
|
|---|
| 18 | */
|
|---|
| 19 |
|
|---|
| 20 | #include <config.h>
|
|---|
| 21 |
|
|---|
| 22 | # ifndef PARAMS
|
|---|
| 23 | # if defined PROTOTYPES || (defined __STDC__ && __STDC__)
|
|---|
| 24 | # define PARAMS(Args) Args
|
|---|
| 25 | # else
|
|---|
| 26 | # define PARAMS(Args) ()
|
|---|
| 27 | # endif
|
|---|
| 28 | # endif
|
|---|
| 29 |
|
|---|
| 30 | #if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
|
|---|
| 31 | #include <string.h>
|
|---|
| 32 | #endif
|
|---|
| 33 |
|
|---|
| 34 |
|
|---|
| 35 | #if DO_MULTIBYTE
|
|---|
| 36 | # if HAVE_MBRLEN
|
|---|
| 37 | # include <wchar.h>
|
|---|
| 38 | # else
|
|---|
| 39 | /* Simulate mbrlen with mblen as best we can. */
|
|---|
| 40 | # define mbstate_t int
|
|---|
| 41 | # define mbrlen(s, n, ps) mblen (s, n)
|
|---|
| 42 | # endif
|
|---|
| 43 | #endif
|
|---|
| 44 |
|
|---|
| 45 | #ifdef HAVE_LOCALE_H
|
|---|
| 46 | #include <locale.h>
|
|---|
| 47 | #endif
|
|---|
| 48 | #if ENABLE_NLS
|
|---|
| 49 | # include <libintl.h>
|
|---|
| 50 | # define _(Text) gettext (Text)
|
|---|
| 51 | #else
|
|---|
| 52 | # define _(Text) Text
|
|---|
| 53 | #define textdomain(Domain)
|
|---|
| 54 | #define bindtextdomain(Package, Directory)
|
|---|
| 55 | #endif
|
|---|
| 56 | #ifdef gettext_noop
|
|---|
| 57 | # define N_(String) gettext_noop (String)
|
|---|
| 58 | #else
|
|---|
| 59 | /* See locate.c for explanation as to why not use (String) */
|
|---|
| 60 | # define N_(String) String
|
|---|
| 61 | #endif
|
|---|
| 62 |
|
|---|
| 63 | #ifndef _POSIX_SOURCE
|
|---|
| 64 | #include <sys/param.h>
|
|---|
| 65 | #endif
|
|---|
| 66 |
|
|---|
| 67 | #ifdef HAVE_LIMITS_H
|
|---|
| 68 | #include <limits.h>
|
|---|
| 69 | #endif
|
|---|
| 70 |
|
|---|
| 71 | /* The presence of unistd.h is assumed by gnulib these days, so we
|
|---|
| 72 | * might as well assume it too.
|
|---|
| 73 | */
|
|---|
| 74 | /* for sysconf() */
|
|---|
| 75 | #include <unistd.h>
|
|---|
| 76 |
|
|---|
| 77 | #include <assert.h>
|
|---|
| 78 |
|
|---|
| 79 | /* COMPAT: SYSV version defaults size (and has a max value of) to 470.
|
|---|
| 80 | We try to make it as large as possible. */
|
|---|
| 81 | #if !defined(ARG_MAX) && defined(_SC_ARG_MAX)
|
|---|
| 82 | #define ARG_MAX sysconf (_SC_ARG_MAX)
|
|---|
| 83 | #endif
|
|---|
| 84 | #ifndef ARG_MAX
|
|---|
| 85 | #define ARG_MAX NCARGS
|
|---|
| 86 | #endif
|
|---|
| 87 |
|
|---|
| 88 |
|
|---|
| 89 |
|
|---|
| 90 | #include <xalloc.h>
|
|---|
| 91 | #include <error.h>
|
|---|
| 92 |
|
|---|
| 93 | #include "buildcmd.h"
|
|---|
| 94 |
|
|---|
| 95 |
|
|---|
| 96 | extern char **environ;
|
|---|
| 97 |
|
|---|
| 98 |
|
|---|
| 99 | static char *mbstrstr PARAMS ((const char *haystack, const char *needle));
|
|---|
| 100 |
|
|---|
| 101 | /* Replace all instances of `replace_pat' in ARG with `linebuf',
|
|---|
| 102 | and add the resulting string to the list of arguments for the command
|
|---|
| 103 | to execute.
|
|---|
| 104 | ARGLEN is the length of ARG, not including the null.
|
|---|
| 105 | LBLEN is the length of LINEBUF, not including the null.
|
|---|
| 106 | PFXLEN is the length of PREFIX. Substitution is not performed on
|
|---|
| 107 | the prefix. The prefix is used if the argument contains replace_pat.
|
|---|
| 108 |
|
|---|
| 109 | COMPAT: insertions on the SYSV version are limited to 255 chars per line,
|
|---|
| 110 | and a max of 5 occurrences of replace_pat in the initial-arguments.
|
|---|
| 111 | Those restrictions do not exist here. */
|
|---|
| 112 |
|
|---|
| 113 | void
|
|---|
| 114 | bc_do_insert (const struct buildcmd_control *ctl,
|
|---|
| 115 | struct buildcmd_state *state,
|
|---|
| 116 | char *arg, size_t arglen,
|
|---|
| 117 | const char *prefix, size_t pfxlen,
|
|---|
| 118 | const char *linebuf, size_t lblen,
|
|---|
| 119 | int initial_args)
|
|---|
| 120 | {
|
|---|
| 121 | /* Temporary copy of each arg with the replace pattern replaced by the
|
|---|
| 122 | real arg. */
|
|---|
| 123 | static char *insertbuf;
|
|---|
| 124 | char *p;
|
|---|
| 125 | size_t bytes_left = ctl->arg_max - 1; /* Bytes left on the command line. */
|
|---|
| 126 | int need_prefix;
|
|---|
| 127 |
|
|---|
| 128 | /* XXX: on systems lacking an upper limit for exec args, ctl->arg_max
|
|---|
| 129 | * may have been set to LONG_MAX (see bc_get_arg_max()). Hence
|
|---|
| 130 | * this xmalloc call may be a bad idea, especially since we are
|
|---|
| 131 | * adding 1 to it...
|
|---|
| 132 | */
|
|---|
| 133 | if (!insertbuf)
|
|---|
| 134 | insertbuf = (char *) xmalloc (ctl->arg_max + 1);
|
|---|
| 135 | p = insertbuf;
|
|---|
| 136 |
|
|---|
| 137 | do
|
|---|
| 138 | {
|
|---|
| 139 | size_t len; /* Length in ARG before `replace_pat'. */
|
|---|
| 140 | char *s = mbstrstr (arg, ctl->replace_pat);
|
|---|
| 141 | if (s)
|
|---|
| 142 | {
|
|---|
| 143 | len = s - arg;
|
|---|
| 144 | }
|
|---|
| 145 | else
|
|---|
| 146 | {
|
|---|
| 147 | len = arglen;
|
|---|
| 148 | }
|
|---|
| 149 |
|
|---|
| 150 | if (bytes_left <= len)
|
|---|
| 151 | break;
|
|---|
| 152 | else
|
|---|
| 153 | bytes_left -= len;
|
|---|
| 154 |
|
|---|
| 155 | strncpy (p, arg, len);
|
|---|
| 156 | p += len;
|
|---|
| 157 | arg += len;
|
|---|
| 158 | arglen -= len;
|
|---|
| 159 |
|
|---|
| 160 | if (s)
|
|---|
| 161 | {
|
|---|
| 162 | if (bytes_left <= (lblen + pfxlen))
|
|---|
| 163 | break;
|
|---|
| 164 | else
|
|---|
| 165 | bytes_left -= (lblen + pfxlen);
|
|---|
| 166 |
|
|---|
| 167 | if (prefix)
|
|---|
| 168 | {
|
|---|
| 169 | strcpy (p, prefix);
|
|---|
| 170 | p += pfxlen;
|
|---|
| 171 | }
|
|---|
| 172 | strcpy (p, linebuf);
|
|---|
| 173 | p += lblen;
|
|---|
| 174 |
|
|---|
| 175 | arg += ctl->rplen;
|
|---|
| 176 | arglen -= ctl->rplen;
|
|---|
| 177 | }
|
|---|
| 178 | }
|
|---|
| 179 | while (*arg);
|
|---|
| 180 | if (*arg)
|
|---|
| 181 | error (1, 0, _("command too long"));
|
|---|
| 182 | *p++ = '\0';
|
|---|
| 183 |
|
|---|
| 184 | bc_push_arg (ctl, state,
|
|---|
| 185 | insertbuf, p - insertbuf,
|
|---|
| 186 | NULL, 0,
|
|---|
| 187 | initial_args);
|
|---|
| 188 | }
|
|---|
| 189 |
|
|---|
| 190 | static
|
|---|
| 191 | void do_exec(const struct buildcmd_control *ctl,
|
|---|
| 192 | struct buildcmd_state *state)
|
|---|
| 193 | {
|
|---|
| 194 | (ctl->exec_callback)(ctl, state);
|
|---|
| 195 | }
|
|---|
| 196 |
|
|---|
| 197 |
|
|---|
| 198 | /* Return nonzero if there would not be enough room for an additional
|
|---|
| 199 | * argument. We check the total number of arguments only, not the space
|
|---|
| 200 | * occupied by those arguments.
|
|---|
| 201 | *
|
|---|
| 202 | * If we return zero, there still may not be enough room for the next
|
|---|
| 203 | * argument, depending on its length.
|
|---|
| 204 | */
|
|---|
| 205 | static int
|
|---|
| 206 | bc_argc_limit_reached(int initial_args,
|
|---|
| 207 | const struct buildcmd_control *ctl,
|
|---|
| 208 | struct buildcmd_state *state)
|
|---|
| 209 | {
|
|---|
| 210 | /* Check to see if we about to exceed a limit set by xargs' -n option */
|
|---|
| 211 | if (!initial_args && ctl->args_per_exec &&
|
|---|
| 212 | ( (state->cmd_argc - ctl->initial_argc) == ctl->args_per_exec))
|
|---|
| 213 | return 1;
|
|---|
| 214 |
|
|---|
| 215 | /* We deliberately use an equality test here rather than >= in order
|
|---|
| 216 | * to force a software failure if the code is modified in such a way
|
|---|
| 217 | * that it fails to call this function for every new argument.
|
|---|
| 218 | */
|
|---|
| 219 | return state->cmd_argc == ctl->max_arg_count;
|
|---|
| 220 | }
|
|---|
| 221 |
|
|---|
| 222 |
|
|---|
| 223 | /* Add ARG to the end of the list of arguments `cmd_argv' to pass
|
|---|
| 224 | to the command.
|
|---|
| 225 | LEN is the length of ARG, including the terminating null.
|
|---|
| 226 | If this brings the list up to its maximum size, execute the command.
|
|---|
| 227 | */
|
|---|
| 228 |
|
|---|
| 229 | void
|
|---|
| 230 | bc_push_arg (const struct buildcmd_control *ctl,
|
|---|
| 231 | struct buildcmd_state *state,
|
|---|
| 232 | const char *arg, size_t len,
|
|---|
| 233 | const char *prefix, size_t pfxlen,
|
|---|
| 234 | int initial_args)
|
|---|
| 235 | {
|
|---|
| 236 | if (!initial_args)
|
|---|
| 237 | state->todo = 1;
|
|---|
| 238 |
|
|---|
| 239 | if (arg)
|
|---|
| 240 | {
|
|---|
| 241 | if (state->cmd_argv_chars + len > ctl->arg_max)
|
|---|
| 242 | {
|
|---|
| 243 | if (initial_args || state->cmd_argc == ctl->initial_argc)
|
|---|
| 244 | error (1, 0, _("can not fit single argument within argument list size limit"));
|
|---|
| 245 | /* xargs option -i (replace_pat) implies -x (exit_if_size_exceeded) */
|
|---|
| 246 | if (ctl->replace_pat
|
|---|
| 247 | || (ctl->exit_if_size_exceeded &&
|
|---|
| 248 | (ctl->lines_per_exec || ctl->args_per_exec)))
|
|---|
| 249 | error (1, 0, _("argument list too long"));
|
|---|
| 250 | do_exec (ctl, state);
|
|---|
| 251 | }
|
|---|
| 252 |
|
|---|
| 253 | if (bc_argc_limit_reached(initial_args, ctl, state))
|
|---|
| 254 | do_exec (ctl, state);
|
|---|
| 255 | }
|
|---|
| 256 |
|
|---|
| 257 | if (state->cmd_argc >= state->cmd_argv_alloc)
|
|---|
| 258 | {
|
|---|
| 259 | if (!state->cmd_argv)
|
|---|
| 260 | {
|
|---|
| 261 | state->cmd_argv_alloc = 64;
|
|---|
| 262 | state->cmd_argv = (char **) xmalloc (sizeof (char *) * state->cmd_argv_alloc);
|
|---|
| 263 | }
|
|---|
| 264 | else
|
|---|
| 265 | {
|
|---|
| 266 | state->cmd_argv_alloc *= 2;
|
|---|
| 267 | state->cmd_argv = (char **) xrealloc (state->cmd_argv,
|
|---|
| 268 | sizeof (char *) * state->cmd_argv_alloc);
|
|---|
| 269 | }
|
|---|
| 270 | }
|
|---|
| 271 |
|
|---|
| 272 | if (!arg)
|
|---|
| 273 | state->cmd_argv[state->cmd_argc++] = NULL;
|
|---|
| 274 | else
|
|---|
| 275 | {
|
|---|
| 276 | state->cmd_argv[state->cmd_argc++] = state->argbuf + state->cmd_argv_chars;
|
|---|
| 277 | if (prefix)
|
|---|
| 278 | {
|
|---|
| 279 | strcpy (state->argbuf + state->cmd_argv_chars, prefix);
|
|---|
| 280 | state->cmd_argv_chars += pfxlen;
|
|---|
| 281 | }
|
|---|
| 282 |
|
|---|
| 283 | strcpy (state->argbuf + state->cmd_argv_chars, arg);
|
|---|
| 284 | state->cmd_argv_chars += len;
|
|---|
| 285 |
|
|---|
| 286 | /* If we have now collected enough arguments,
|
|---|
| 287 | * do the exec immediately. This must be
|
|---|
| 288 | * conditional on arg!=NULL, since do_exec()
|
|---|
| 289 | * actually calls bc_push_arg(ctl, state, NULL, 0, false).
|
|---|
| 290 | */
|
|---|
| 291 | if (bc_argc_limit_reached(initial_args, ctl, state))
|
|---|
| 292 | do_exec (ctl, state);
|
|---|
| 293 | }
|
|---|
| 294 |
|
|---|
| 295 | /* If this is an initial argument, set the high-water mark. */
|
|---|
| 296 | if (initial_args)
|
|---|
| 297 | {
|
|---|
| 298 | state->cmd_initial_argv_chars = state->cmd_argv_chars;
|
|---|
| 299 | }
|
|---|
| 300 | }
|
|---|
| 301 |
|
|---|
| 302 |
|
|---|
| 303 | /* Finds the first occurrence of the substring NEEDLE in the string
|
|---|
| 304 | HAYSTACK. Both strings can be multibyte strings. */
|
|---|
| 305 |
|
|---|
| 306 | static char *
|
|---|
| 307 | mbstrstr (const char *haystack, const char *needle)
|
|---|
| 308 | {
|
|---|
| 309 | #if DO_MULTIBYTE
|
|---|
| 310 | if (MB_CUR_MAX > 1)
|
|---|
| 311 | {
|
|---|
| 312 | size_t hlen = strlen (haystack);
|
|---|
| 313 | size_t nlen = strlen (needle);
|
|---|
| 314 | mbstate_t mbstate;
|
|---|
| 315 | size_t step;
|
|---|
| 316 |
|
|---|
| 317 | memset (&mbstate, 0, sizeof (mbstate_t));
|
|---|
| 318 | while (hlen >= nlen)
|
|---|
| 319 | {
|
|---|
| 320 | if (memcmp (haystack, needle, nlen) == 0)
|
|---|
| 321 | return (char *) haystack;
|
|---|
| 322 | step = mbrlen (haystack, hlen, &mbstate);
|
|---|
| 323 | if (step <= 0)
|
|---|
| 324 | break;
|
|---|
| 325 | haystack += step;
|
|---|
| 326 | hlen -= step;
|
|---|
| 327 | }
|
|---|
| 328 | return NULL;
|
|---|
| 329 | }
|
|---|
| 330 | #endif
|
|---|
| 331 | return strstr (haystack, needle);
|
|---|
| 332 | }
|
|---|
| 333 |
|
|---|
| 334 | static size_t
|
|---|
| 335 | get_line_max(void)
|
|---|
| 336 | {
|
|---|
| 337 | long val;
|
|---|
| 338 | #ifdef _SC_LINE_MAX
|
|---|
| 339 | val = sysconf(_SC_LINE_MAX);
|
|---|
| 340 | #else
|
|---|
| 341 | val = -1;
|
|---|
| 342 | #endif
|
|---|
| 343 |
|
|---|
| 344 | if (val > 0)
|
|---|
| 345 | return val;
|
|---|
| 346 |
|
|---|
| 347 | /* either _SC_LINE_MAX was not available or
|
|---|
| 348 | * there is no particular limit.
|
|---|
| 349 | */
|
|---|
| 350 | #ifdef LINE_MAX
|
|---|
| 351 | val = LINE_MAX;
|
|---|
| 352 | #endif
|
|---|
| 353 |
|
|---|
| 354 | if (val > 0)
|
|---|
| 355 | return val;
|
|---|
| 356 |
|
|---|
| 357 | return 2048L; /* a reasonable guess. */
|
|---|
| 358 | }
|
|---|
| 359 |
|
|---|
| 360 |
|
|---|
| 361 | size_t
|
|---|
| 362 | bc_get_arg_max(void)
|
|---|
| 363 | {
|
|---|
| 364 | long val;
|
|---|
| 365 |
|
|---|
| 366 | /* We may resort to using LONG_MAX, so check it fits. */
|
|---|
| 367 | /* XXX: better to do a compile-time check */
|
|---|
| 368 | assert( (~(size_t)0) >= LONG_MAX);
|
|---|
| 369 |
|
|---|
| 370 | #ifdef _SC_ARG_MAX
|
|---|
| 371 | val = sysconf(_SC_ARG_MAX);
|
|---|
| 372 | #else
|
|---|
| 373 | val = -1;
|
|---|
| 374 | #endif
|
|---|
| 375 |
|
|---|
| 376 | if (val > 0)
|
|---|
| 377 | return val;
|
|---|
| 378 |
|
|---|
| 379 | /* either _SC_ARG_MAX was not available or
|
|---|
| 380 | * there is no particular limit.
|
|---|
| 381 | */
|
|---|
| 382 | #ifdef ARG_MAX
|
|---|
| 383 | val = ARG_MAX;
|
|---|
| 384 | #endif
|
|---|
| 385 |
|
|---|
| 386 | if (val > 0)
|
|---|
| 387 | return val;
|
|---|
| 388 |
|
|---|
| 389 | /* The value returned by this function bounds the
|
|---|
| 390 | * value applied as the ceiling for the -s option.
|
|---|
| 391 | * Hence it the system won't tell us what its limit
|
|---|
| 392 | * is, we allow the user to specify more or less
|
|---|
| 393 | * whatever value they like.
|
|---|
| 394 | */
|
|---|
| 395 | return LONG_MAX;
|
|---|
| 396 | }
|
|---|
| 397 |
|
|---|
| 398 |
|
|---|
| 399 | static int cb_exec_noop(const struct buildcmd_control *ctl,
|
|---|
| 400 | struct buildcmd_state *state)
|
|---|
| 401 | {
|
|---|
| 402 | /* does nothing. */
|
|---|
| 403 | (void) ctl;
|
|---|
| 404 | (void) state;
|
|---|
| 405 |
|
|---|
| 406 | return 0;
|
|---|
| 407 | }
|
|---|
| 408 |
|
|---|
| 409 |
|
|---|
| 410 | /* Return how much of ARG_MAX is used by the environment. */
|
|---|
| 411 | size_t
|
|---|
| 412 | bc_size_of_environment (void)
|
|---|
| 413 | {
|
|---|
| 414 | size_t len = 0u;
|
|---|
| 415 | char **envp = environ;
|
|---|
| 416 |
|
|---|
| 417 | while (*envp)
|
|---|
| 418 | len += strlen (*envp++) + 1;
|
|---|
| 419 |
|
|---|
| 420 | return len;
|
|---|
| 421 | }
|
|---|
| 422 |
|
|---|
| 423 |
|
|---|
| 424 | enum BC_INIT_STATUS
|
|---|
| 425 | bc_init_controlinfo(struct buildcmd_control *ctl)
|
|---|
| 426 | {
|
|---|
| 427 | size_t size_of_environment = bc_size_of_environment();
|
|---|
| 428 | size_t arg_max;
|
|---|
| 429 |
|
|---|
| 430 | ctl->posix_arg_size_min = get_line_max();
|
|---|
| 431 | arg_max = bc_get_arg_max();
|
|---|
| 432 |
|
|---|
| 433 | /* POSIX.2 requires subtracting 2048. */
|
|---|
| 434 | assert(arg_max > 2048u); /* XXX: this is an external condition, should not check it with assert. */
|
|---|
| 435 | ctl->posix_arg_size_max = (arg_max - 2048);
|
|---|
| 436 |
|
|---|
| 437 | ctl->exit_if_size_exceeded = 0;
|
|---|
| 438 |
|
|---|
| 439 | /* Take the size of the environment into account. */
|
|---|
| 440 | if (size_of_environment > ctl->posix_arg_size_max)
|
|---|
| 441 | {
|
|---|
| 442 | return BC_INIT_ENV_TOO_BIG;
|
|---|
| 443 | }
|
|---|
| 444 | else
|
|---|
| 445 | {
|
|---|
| 446 | ctl->posix_arg_size_max - size_of_environment;
|
|---|
| 447 | }
|
|---|
| 448 |
|
|---|
| 449 | /* need to subtract 2 on the following line - for Linux/PPC */
|
|---|
| 450 | ctl->max_arg_count = (ctl->posix_arg_size_max / sizeof(char*)) - 2u;
|
|---|
| 451 | assert(ctl->max_arg_count > 0);
|
|---|
| 452 | ctl->rplen = 0u;
|
|---|
| 453 | ctl->replace_pat = NULL;
|
|---|
| 454 | ctl->initial_argc = 0;
|
|---|
| 455 | ctl->exec_callback = cb_exec_noop;
|
|---|
| 456 | ctl->lines_per_exec = 0;
|
|---|
| 457 | ctl->args_per_exec = 0;
|
|---|
| 458 |
|
|---|
| 459 | /* Set the initial value of arg_max to the largest value we can
|
|---|
| 460 | * tolerate.
|
|---|
| 461 | */
|
|---|
| 462 | ctl->arg_max = ctl->posix_arg_size_max;
|
|---|
| 463 |
|
|---|
| 464 | return BC_INIT_OK;
|
|---|
| 465 | }
|
|---|
| 466 |
|
|---|
| 467 | void
|
|---|
| 468 | bc_use_sensible_arg_max(struct buildcmd_control *ctl)
|
|---|
| 469 | {
|
|---|
| 470 | size_t env_size = bc_size_of_environment();
|
|---|
| 471 | const size_t arg_size = (128u * 1024u) + env_size;
|
|---|
| 472 |
|
|---|
| 473 | /* Check against the upper and lower limits. */
|
|---|
| 474 | if (arg_size > ctl->posix_arg_size_max)
|
|---|
| 475 | ctl->arg_max = ctl->posix_arg_size_max - env_size;
|
|---|
| 476 | else if (arg_size < ctl->posix_arg_size_min)
|
|---|
| 477 | ctl->arg_max = ctl->posix_arg_size_min;
|
|---|
| 478 | else
|
|---|
| 479 | ctl->arg_max = arg_size;
|
|---|
| 480 | }
|
|---|
| 481 |
|
|---|
| 482 |
|
|---|
| 483 |
|
|---|
| 484 |
|
|---|
| 485 | void
|
|---|
| 486 | bc_init_state(const struct buildcmd_control *ctl,
|
|---|
| 487 | struct buildcmd_state *state,
|
|---|
| 488 | void *context)
|
|---|
| 489 | {
|
|---|
| 490 | state->cmd_argc = 0;
|
|---|
| 491 | state->cmd_argv_chars = 0;
|
|---|
| 492 | state->cmd_argv = NULL;
|
|---|
| 493 | state->cmd_argv_alloc = 0;
|
|---|
| 494 |
|
|---|
| 495 | /* XXX: the following memory allocation is inadvisable on systems
|
|---|
| 496 | * with no ARG_MAX, because ctl->arg_max may actually be close to
|
|---|
| 497 | * LONG_MAX. Adding one to it is safe though because earlier we
|
|---|
| 498 | * subtracted 2048.
|
|---|
| 499 | */
|
|---|
| 500 | assert(ctl->arg_max <= (LONG_MAX - 2048L));
|
|---|
| 501 | state->argbuf = (char *) xmalloc (ctl->arg_max + 1u);
|
|---|
| 502 |
|
|---|
| 503 | state->cmd_argv_chars = state->cmd_initial_argv_chars = 0;
|
|---|
| 504 | state->todo = 0;
|
|---|
| 505 | state->usercontext = context;
|
|---|
| 506 | }
|
|---|
| 507 |
|
|---|
| 508 | void
|
|---|
| 509 | bc_clear_args(const struct buildcmd_control *ctl,
|
|---|
| 510 | struct buildcmd_state *state)
|
|---|
| 511 | {
|
|---|
| 512 | state->cmd_argc = ctl->initial_argc;
|
|---|
| 513 | state->cmd_argv_chars = state->cmd_initial_argv_chars;
|
|---|
| 514 | state->todo = 0;
|
|---|
| 515 | }
|
|---|
| 516 |
|
|---|