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.
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)
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.
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,
23 # if defined PROTOTYPES || (defined __STDC__ && __STDC__)
24 # define PARAMS(Args) Args
26 # define PARAMS(Args) ()
30 #if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
39 /* Simulate mbrlen with mblen as best we can. */
40 # define mbstate_t int
41 # define mbrlen(s, n, ps) mblen (s, n)
50 # define _(Text) gettext (Text)
53 #define textdomain(Domain)
54 #define bindtextdomain(Package, Directory)
57 # define N_(String) gettext_noop (String)
59 /* See locate.c for explanation as to why not use (String) */
60 # define N_(String) String
64 #include <sys/param.h>
71 /* The presence of unistd.h is assumed by gnulib these days, so we
72 * might as well assume it too.
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)
85 #define ARG_MAX NCARGS
97 extern char **environ
;
100 static char *mbstrstr
PARAMS ((const char *haystack
, const char *needle
));
102 /* Replace all instances of `replace_pat' in ARG with `linebuf',
103 and add the resulting string to the list of arguments for the command
105 ARGLEN is the length of ARG, not including the null.
106 LBLEN is the length of LINEBUF, not including the null.
107 PFXLEN is the length of PREFIX. Substitution is not performed on
108 the prefix. The prefix is used if the argument contains replace_pat.
110 COMPAT: insertions on the SYSV version are limited to 255 chars per line,
111 and a max of 5 occurrences of replace_pat in the initial-arguments.
112 Those restrictions do not exist here. */
115 bc_do_insert (const struct buildcmd_control
*ctl
,
116 struct buildcmd_state
*state
,
117 char *arg
, size_t arglen
,
118 const char *prefix
, size_t pfxlen
,
119 const char *linebuf
, size_t lblen
,
122 /* Temporary copy of each arg with the replace pattern replaced by the
124 static char *insertbuf
;
126 size_t bytes_left
= ctl
->arg_max
- 1; /* Bytes left on the command line. */
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
134 insertbuf
= (char *) xmalloc (ctl
->arg_max
+ 1);
139 size_t len
; /* Length in ARG before `replace_pat'. */
140 char *s
= mbstrstr (arg
, ctl
->replace_pat
);
150 if (bytes_left
<= len
)
155 strncpy (p
, arg
, len
);
162 if (bytes_left
<= (lblen
+ pfxlen
))
165 bytes_left
-= (lblen
+ pfxlen
);
176 arglen
-= ctl
->rplen
;
181 error (1, 0, _("command too long"));
184 bc_push_arg (ctl
, state
,
185 insertbuf
, p
- insertbuf
,
191 void do_exec(const struct buildcmd_control
*ctl
,
192 struct buildcmd_state
*state
)
194 (ctl
->exec_callback
)(ctl
, state
);
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.
202 * If we return zero, there still may not be enough room for the next
203 * argument, depending on its length.
206 bc_argc_limit_reached(int initial_args
,
207 const struct buildcmd_control
*ctl
,
208 struct buildcmd_state
*state
)
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
))
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.
219 return state
->cmd_argc
== ctl
->max_arg_count
;
223 /* Add ARG to the end of the list of arguments `cmd_argv' to pass
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.
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
,
243 if (state
->cmd_argv_chars
+ len
> ctl
->arg_max
)
245 if (initial_args
|| state
->cmd_argc
== ctl
->initial_argc
)
246 error (1, 0, _("can not fit single argument within argument list size limit"));
247 /* xargs option -i (replace_pat) implies -x (exit_if_size_exceeded) */
249 || (ctl
->exit_if_size_exceeded
&&
250 (ctl
->lines_per_exec
|| ctl
->args_per_exec
)))
251 error (1, 0, _("argument list too long"));
252 do_exec (ctl
, state
);
255 if (bc_argc_limit_reached(initial_args
, ctl
, state
))
256 do_exec (ctl
, state
);
259 if (state
->cmd_argc
>= state
->cmd_argv_alloc
)
261 if (!state
->cmd_argv
)
263 state
->cmd_argv_alloc
= 64;
264 state
->cmd_argv
= (char **) xmalloc (sizeof (char *) * state
->cmd_argv_alloc
);
268 state
->cmd_argv_alloc
*= 2;
269 state
->cmd_argv
= (char **) xrealloc (state
->cmd_argv
,
270 sizeof (char *) * state
->cmd_argv_alloc
);
275 state
->cmd_argv
[state
->cmd_argc
++] = NULL
;
278 state
->cmd_argv
[state
->cmd_argc
++] = state
->argbuf
+ state
->cmd_argv_chars
;
281 strcpy (state
->argbuf
+ state
->cmd_argv_chars
, prefix
);
282 state
->cmd_argv_chars
+= pfxlen
;
285 strcpy (state
->argbuf
+ state
->cmd_argv_chars
, arg
);
286 state
->cmd_argv_chars
+= len
;
288 /* If we have now collected enough arguments,
289 * do the exec immediately. This must be
290 * conditional on arg!=NULL, since do_exec()
291 * actually calls bc_push_arg(ctl, state, NULL, 0, false).
293 if (bc_argc_limit_reached(initial_args
, ctl
, state
))
294 do_exec (ctl
, state
);
297 /* If this is an initial argument, set the high-water mark. */
300 state
->cmd_initial_argv_chars
= state
->cmd_argv_chars
;
305 /* Finds the first occurrence of the substring NEEDLE in the string
306 HAYSTACK. Both strings can be multibyte strings. */
309 mbstrstr (const char *haystack
, const char *needle
)
314 size_t hlen
= strlen (haystack
);
315 size_t nlen
= strlen (needle
);
319 memset (&mbstate
, 0, sizeof (mbstate_t));
322 if (memcmp (haystack
, needle
, nlen
) == 0)
323 return (char *) haystack
;
324 step
= mbrlen (haystack
, hlen
, &mbstate
);
333 return strstr (haystack
, needle
);
341 val
= sysconf(_SC_LINE_MAX
);
349 /* either _SC_LINE_MAX was not available or
350 * there is no particular limit.
359 return 2048L; /* a reasonable guess. */
368 /* We may resort to using LONG_MAX, so check it fits. */
369 /* XXX: better to do a compile-time check */
370 assert( (~(size_t)0) >= LONG_MAX
);
373 val
= sysconf(_SC_ARG_MAX
);
381 /* either _SC_ARG_MAX was not available or
382 * there is no particular limit.
391 /* The value returned by this function bounds the
392 * value applied as the ceiling for the -s option.
393 * Hence it the system won't tell us what its limit
394 * is, we allow the user to specify more or less
395 * whatever value they like.
401 static int cb_exec_noop(const struct buildcmd_control
*ctl
,
402 struct buildcmd_state
*state
)
412 /* Return how much of ARG_MAX is used by the environment. */
414 bc_size_of_environment (void)
417 char **envp
= environ
;
420 len
+= strlen (*envp
++) + 1;
427 bc_init_controlinfo(struct buildcmd_control
*ctl
)
429 size_t size_of_environment
= bc_size_of_environment();
432 ctl
->posix_arg_size_min
= get_line_max();
433 arg_max
= bc_get_arg_max();
435 /* POSIX.2 requires subtracting 2048. */
436 assert(arg_max
> 2048u); /* XXX: this is an external condition, should not check it with assert. */
437 ctl
->posix_arg_size_max
= (arg_max
- 2048);
439 ctl
->exit_if_size_exceeded
= 0;
441 /* Take the size of the environment into account. */
442 if (size_of_environment
> ctl
->posix_arg_size_max
)
444 return BC_INIT_ENV_TOO_BIG
;
448 #warning the next line is probably a bug.
449 ctl
->posix_arg_size_max
- size_of_environment
;
452 /* need to subtract 2 on the following line - for Linux/PPC */
453 ctl
->max_arg_count
= (ctl
->posix_arg_size_max
/ sizeof(char*)) - 2u;
454 assert(ctl
->max_arg_count
> 0);
456 ctl
->replace_pat
= NULL
;
457 ctl
->initial_argc
= 0;
458 ctl
->exec_callback
= cb_exec_noop
;
459 ctl
->lines_per_exec
= 0;
460 ctl
->args_per_exec
= 0;
462 /* Set the initial value of arg_max to the largest value we can
465 ctl
->arg_max
= ctl
->posix_arg_size_max
;
471 bc_use_sensible_arg_max(struct buildcmd_control
*ctl
)
473 size_t env_size
= bc_size_of_environment();
474 const size_t arg_size
= (128u * 1024u) + env_size
;
476 /* Check against the upper and lower limits. */
477 if (arg_size
> ctl
->posix_arg_size_max
)
478 ctl
->arg_max
= ctl
->posix_arg_size_max
- env_size
;
479 else if (arg_size
< ctl
->posix_arg_size_min
)
480 ctl
->arg_max
= ctl
->posix_arg_size_min
;
482 ctl
->arg_max
= arg_size
;
489 bc_init_state(const struct buildcmd_control
*ctl
,
490 struct buildcmd_state
*state
,
494 state
->cmd_argv_chars
= 0;
495 state
->cmd_argv
= NULL
;
496 state
->cmd_argv_alloc
= 0;
498 /* XXX: the following memory allocation is inadvisable on systems
499 * with no ARG_MAX, because ctl->arg_max may actually be close to
500 * LONG_MAX. Adding one to it is safe though because earlier we
503 assert(ctl
->arg_max
<= (LONG_MAX
- 2048L));
504 state
->argbuf
= (char *) xmalloc (ctl
->arg_max
+ 1u);
506 state
->cmd_argv_chars
= state
->cmd_initial_argv_chars
= 0;
509 state
->usercontext
= context
;
513 bc_clear_args(const struct buildcmd_control
*ctl
,
514 struct buildcmd_state
*state
)
516 state
->cmd_argc
= ctl
->initial_argc
;
517 state
->cmd_argv_chars
= state
->cmd_initial_argv_chars
;