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 | #ifndef __EMX__ /* our _SC_ARG_MAX value is too low for the env logic to work. */
|
---|
371 | #ifdef _SC_ARG_MAX
|
---|
372 | val = sysconf(_SC_ARG_MAX);
|
---|
373 | #else
|
---|
374 | val = -1;
|
---|
375 | #endif
|
---|
376 |
|
---|
377 | if (val > 0)
|
---|
378 | return val;
|
---|
379 | #endif /* !__EMX__ */
|
---|
380 |
|
---|
381 | /* either _SC_ARG_MAX was not available or
|
---|
382 | * there is no particular limit.
|
---|
383 | */
|
---|
384 | #ifdef ARG_MAX
|
---|
385 | val = ARG_MAX;
|
---|
386 | #endif
|
---|
387 |
|
---|
388 | if (val > 0)
|
---|
389 | return val;
|
---|
390 |
|
---|
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.
|
---|
396 | */
|
---|
397 | return LONG_MAX;
|
---|
398 | }
|
---|
399 |
|
---|
400 |
|
---|
401 | static int cb_exec_noop(const struct buildcmd_control *ctl,
|
---|
402 | struct buildcmd_state *state)
|
---|
403 | {
|
---|
404 | /* does nothing. */
|
---|
405 | (void) ctl;
|
---|
406 | (void) state;
|
---|
407 |
|
---|
408 | return 0;
|
---|
409 | }
|
---|
410 |
|
---|
411 |
|
---|
412 | /* Return how much of ARG_MAX is used by the environment. */
|
---|
413 | size_t
|
---|
414 | bc_size_of_environment (void)
|
---|
415 | {
|
---|
416 | size_t len = 0u;
|
---|
417 | char **envp = environ;
|
---|
418 |
|
---|
419 | while (*envp)
|
---|
420 | len += strlen (*envp++) + 1;
|
---|
421 |
|
---|
422 | return len;
|
---|
423 | }
|
---|
424 |
|
---|
425 |
|
---|
426 | enum BC_INIT_STATUS
|
---|
427 | bc_init_controlinfo(struct buildcmd_control *ctl)
|
---|
428 | {
|
---|
429 | size_t size_of_environment = bc_size_of_environment();
|
---|
430 | size_t arg_max;
|
---|
431 |
|
---|
432 | ctl->posix_arg_size_min = get_line_max();
|
---|
433 | arg_max = bc_get_arg_max();
|
---|
434 |
|
---|
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);
|
---|
438 |
|
---|
439 | ctl->exit_if_size_exceeded = 0;
|
---|
440 |
|
---|
441 | /* Take the size of the environment into account. */
|
---|
442 | if (size_of_environment > ctl->posix_arg_size_max)
|
---|
443 | {
|
---|
444 | return BC_INIT_ENV_TOO_BIG;
|
---|
445 | }
|
---|
446 | else
|
---|
447 | {
|
---|
448 | ctl->posix_arg_size_max - size_of_environment;
|
---|
449 | }
|
---|
450 |
|
---|
451 | /* need to subtract 2 on the following line - for Linux/PPC */
|
---|
452 | ctl->max_arg_count = (ctl->posix_arg_size_max / sizeof(char*)) - 2u;
|
---|
453 | assert(ctl->max_arg_count > 0);
|
---|
454 | ctl->rplen = 0u;
|
---|
455 | ctl->replace_pat = NULL;
|
---|
456 | ctl->initial_argc = 0;
|
---|
457 | ctl->exec_callback = cb_exec_noop;
|
---|
458 | ctl->lines_per_exec = 0;
|
---|
459 | ctl->args_per_exec = 0;
|
---|
460 |
|
---|
461 | /* Set the initial value of arg_max to the largest value we can
|
---|
462 | * tolerate.
|
---|
463 | */
|
---|
464 | ctl->arg_max = ctl->posix_arg_size_max;
|
---|
465 |
|
---|
466 | return BC_INIT_OK;
|
---|
467 | }
|
---|
468 |
|
---|
469 | void
|
---|
470 | bc_use_sensible_arg_max(struct buildcmd_control *ctl)
|
---|
471 | {
|
---|
472 | size_t env_size = bc_size_of_environment();
|
---|
473 | const size_t arg_size = (128u * 1024u) + env_size;
|
---|
474 |
|
---|
475 | /* Check against the upper and lower limits. */
|
---|
476 | if (arg_size > ctl->posix_arg_size_max)
|
---|
477 | ctl->arg_max = ctl->posix_arg_size_max - env_size;
|
---|
478 | else if (arg_size < ctl->posix_arg_size_min)
|
---|
479 | ctl->arg_max = ctl->posix_arg_size_min;
|
---|
480 | else
|
---|
481 | ctl->arg_max = arg_size;
|
---|
482 | }
|
---|
483 |
|
---|
484 |
|
---|
485 |
|
---|
486 |
|
---|
487 | void
|
---|
488 | bc_init_state(const struct buildcmd_control *ctl,
|
---|
489 | struct buildcmd_state *state,
|
---|
490 | void *context)
|
---|
491 | {
|
---|
492 | state->cmd_argc = 0;
|
---|
493 | state->cmd_argv_chars = 0;
|
---|
494 | state->cmd_argv = NULL;
|
---|
495 | state->cmd_argv_alloc = 0;
|
---|
496 |
|
---|
497 | /* XXX: the following memory allocation is inadvisable on systems
|
---|
498 | * with no ARG_MAX, because ctl->arg_max may actually be close to
|
---|
499 | * LONG_MAX. Adding one to it is safe though because earlier we
|
---|
500 | * subtracted 2048.
|
---|
501 | */
|
---|
502 | assert(ctl->arg_max <= (LONG_MAX - 2048L));
|
---|
503 | state->argbuf = (char *) xmalloc (ctl->arg_max + 1u);
|
---|
504 |
|
---|
505 | state->cmd_argv_chars = state->cmd_initial_argv_chars = 0;
|
---|
506 | state->todo = 0;
|
---|
507 | state->usercontext = context;
|
---|
508 | }
|
---|
509 |
|
---|
510 | void
|
---|
511 | bc_clear_args(const struct buildcmd_control *ctl,
|
---|
512 | struct buildcmd_state *state)
|
---|
513 | {
|
---|
514 | state->cmd_argc = ctl->initial_argc;
|
---|
515 | state->cmd_argv_chars = state->cmd_initial_argv_chars;
|
---|
516 | state->todo = 0;
|
---|
517 | }
|
---|
518 |
|
---|