Prefer the word 'Invalid' or the phrase 'not allowed' over 'Illegal', as per the...
[findutils.git] / lib / buildcmd.c
blob03af0b723b2b6dd5954a5cca817b5a60d08bab22
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)
7 any later version.
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,
17 USA.
20 #include <config.h>
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
30 #if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
31 #include <string.h>
32 #endif
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
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
63 #ifndef _POSIX_SOURCE
64 #include <sys/param.h>
65 #endif
67 #ifdef HAVE_LIMITS_H
68 #include <limits.h>
69 #endif
71 /* The presence of unistd.h is assumed by gnulib these days, so we
72 * might as well assume it too.
74 /* for sysconf() */
75 #include <unistd.h>
77 #include <assert.h>
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
90 #include <xalloc.h>
91 #include <error.h>
93 #include "buildcmd.h"
95 static char *mbstrstr PARAMS ((const char *haystack, const char *needle));
97 /* Replace all instances of `replace_pat' in ARG with `linebuf',
98 and add the resulting string to the list of arguments for the command
99 to execute.
100 ARGLEN is the length of ARG, not including the null.
101 LBLEN is the length of LINEBUF, not including the null.
102 PFXLEN is the length of PREFIX. Substitution is not performed on
103 the prefix. The prefix is used if the argument contains replace_pat.
105 COMPAT: insertions on the SYSV version are limited to 255 chars per line,
106 and a max of 5 occurrences of replace_pat in the initial-arguments.
107 Those restrictions do not exist here. */
109 void
110 bc_do_insert (const struct buildcmd_control *ctl,
111 struct buildcmd_state *state,
112 char *arg, size_t arglen,
113 const char *prefix, size_t pfxlen,
114 const char *linebuf, size_t lblen,
115 int initial_args)
117 /* Temporary copy of each arg with the replace pattern replaced by the
118 real arg. */
119 static char *insertbuf;
120 char *p;
121 int bytes_left = ctl->arg_max - 1; /* Bytes left on the command line. */
122 int need_prefix;
124 /* XXX: on systems lacking an upper limit for exec args, ctl->arg_max
125 * may have been set to LONG_MAX (see bc_get_arg_max()). Hence
126 * this xmalloc call may be a bad idea, especially since we are
127 * adding 1 to it...
129 if (!insertbuf)
130 insertbuf = (char *) xmalloc (ctl->arg_max + 1);
131 p = insertbuf;
133 need_prefix = 0;
136 size_t len; /* Length in ARG before `replace_pat'. */
137 char *s = mbstrstr (arg, ctl->replace_pat);
138 if (s)
140 need_prefix = 1;
141 len = s - arg;
143 else
145 len = arglen;
148 bytes_left -= len;
149 if (bytes_left <= 0)
150 break;
152 strncpy (p, arg, len);
153 p += len;
154 arg += len;
155 arglen -= len;
157 if (s)
159 bytes_left -= lblen;
160 if (bytes_left <= 0)
161 break;
162 strcpy (p, linebuf);
163 arg += ctl->rplen;
164 arglen -= ctl->rplen;
165 p += lblen;
168 while (*arg);
169 if (*arg)
170 error (1, 0, _("command too long"));
171 *p++ = '\0';
173 if (!need_prefix)
175 prefix = NULL;
176 pfxlen = 0;
179 bc_push_arg (ctl, state,
180 insertbuf, p - insertbuf,
181 prefix, pfxlen,
182 initial_args);
185 static
186 void do_exec(const struct buildcmd_control *ctl,
187 struct buildcmd_state *state)
189 (ctl->exec_callback)(ctl, state);
193 /* Return nonzero if there would not be enough room for an additional
194 * argument. We check the total number of arguments only, not the space
195 * occupied by those arguments.
197 * If we return zero, there still may not be enough room for the next
198 * argument, depending on its length.
200 static int
201 bc_argc_limit_reached(int initial_args,
202 const struct buildcmd_control *ctl,
203 struct buildcmd_state *state)
205 /* Check to see if we about to exceed a limit set by xargs' -n option */
206 if (!initial_args && ctl->args_per_exec &&
207 ( (state->cmd_argc - ctl->initial_argc) == ctl->args_per_exec))
208 return 1;
210 /* We deliberately use an equality test here rather than >= in order
211 * to force a software failure if the code is modified in such a way
212 * that it fails to call this function for every new argument.
214 return state->cmd_argc == ctl->max_arg_count;
218 /* Add ARG to the end of the list of arguments `cmd_argv' to pass
219 to the command.
220 LEN is the length of ARG, including the terminating null.
221 If this brings the list up to its maximum size, execute the command. */
223 void
224 bc_push_arg (const struct buildcmd_control *ctl,
225 struct buildcmd_state *state,
226 const char *arg, size_t len,
227 const char *prefix, size_t pfxlen,
228 int initial_args)
230 if (!initial_args)
231 state->todo = 1;
233 if (arg)
235 if (state->cmd_argv_chars + len > ctl->arg_max)
237 if (initial_args || state->cmd_argc == ctl->initial_argc)
238 error (1, 0, _("can not fit single argument within argument list size limit"));
239 /* option -i (replace_pat) implies -x (exit_if_size_exceeded) */
240 if (ctl->replace_pat
241 || (ctl->exit_if_size_exceeded &&
242 (ctl->lines_per_exec || ctl->args_per_exec)))
243 error (1, 0, _("argument list too long"));
244 do_exec (ctl, state);
247 if (bc_argc_limit_reached(initial_args, ctl, state))
248 do_exec (ctl, state);
251 if (state->cmd_argc >= state->cmd_argv_alloc)
253 if (!state->cmd_argv)
255 state->cmd_argv_alloc = 64;
256 state->cmd_argv = (char **) xmalloc (sizeof (char *) * state->cmd_argv_alloc);
258 else
260 state->cmd_argv_alloc *= 2;
261 state->cmd_argv = (char **) xrealloc (state->cmd_argv,
262 sizeof (char *) * state->cmd_argv_alloc);
266 if (!arg)
267 state->cmd_argv[state->cmd_argc++] = NULL;
268 else
270 state->cmd_argv[state->cmd_argc++] = state->argbuf + state->cmd_argv_chars;
271 if (prefix)
273 strcpy (state->argbuf + state->cmd_argv_chars, prefix);
274 state->cmd_argv_chars += pfxlen;
277 strcpy (state->argbuf + state->cmd_argv_chars, arg);
278 state->cmd_argv_chars += len;
280 /* If we have now collected enough arguments,
281 * do the exec immediately. This must be
282 * conditional on arg!=NULL, since do_exec()
283 * actually calls bc_push_arg(ctl, state, NULL, 0, false).
285 if (bc_argc_limit_reached(initial_args, ctl, state))
286 do_exec (ctl, state);
289 /* If this is an initial argument, set the high-water mark. */
290 if (initial_args)
292 state->cmd_initial_argv_chars = state->cmd_argv_chars;
297 /* Finds the first occurrence of the substring NEEDLE in the string
298 HAYSTACK. Both strings can be multibyte strings. */
300 static char *
301 mbstrstr (const char *haystack, const char *needle)
303 #if DO_MULTIBYTE
304 if (MB_CUR_MAX > 1)
306 size_t hlen = strlen (haystack);
307 size_t nlen = strlen (needle);
308 mbstate_t mbstate;
309 size_t step;
311 memset (&mbstate, 0, sizeof (mbstate_t));
312 while (hlen >= nlen)
314 if (memcmp (haystack, needle, nlen) == 0)
315 return (char *) haystack;
316 step = mbrlen (haystack, hlen, &mbstate);
317 if (step <= 0)
318 break;
319 haystack += step;
320 hlen -= step;
322 return NULL;
324 #endif
325 return strstr (haystack, needle);
329 long
330 bc_get_arg_max(void)
332 long val;
333 #ifdef _SC_ARG_MAX
334 val = sysconf(_SC_ARG_MAX);
335 #else
336 val = -1;
337 #endif
339 if (val > 0)
340 return val;
342 /* either _SC_ARG_MAX was not available or
343 * there is no particular limit.
345 #ifdef ARG_MAX
346 val = ARG_MAX;
347 #endif
349 if (val > 0)
350 return val;
352 /* The value returned by this function bounds the
353 * value applied as the ceiling for the -s option.
354 * Hence it the system won't tell us what its limit
355 * is, we allow the user to specify more or less
356 * whatever value they like.
358 return LONG_MAX;
362 static int cb_exec_noop(const struct buildcmd_control *ctl,
363 struct buildcmd_state *state)
365 /* does nothing. */
366 (void) ctl;
367 (void) state;
369 return 0;
372 void
373 bc_init_controlinfo(struct buildcmd_control *ctl)
375 long arg_max = bc_get_arg_max();
376 assert(arg_max > 0);
378 ctl->exit_if_size_exceeded = 0;
379 ctl->arg_max = arg_max - 2048; /* a la xargs */
380 /* need to subtract 2 on the following line - for Linux/PPC */
381 ctl->max_arg_count = (arg_max / sizeof(void*)) - 2;
382 assert(ctl->max_arg_count > 0);
383 ctl->rplen = 0u;
384 ctl->replace_pat = NULL;
385 ctl->initial_argc = 0;
386 ctl->exec_callback = cb_exec_noop;
387 ctl->lines_per_exec = 0;
388 ctl->args_per_exec = 0;
391 void
392 bc_init_state(const struct buildcmd_control *ctl,
393 struct buildcmd_state *state,
394 void *context)
396 state->cmd_argc = 0;
397 state->cmd_argv_chars = 0;
398 state->cmd_argv = NULL;
399 state->cmd_argv_alloc = 0;
401 /* XXX: the following memory allocation is inadvisable on systems
402 * with no ARG_MAX, because ctl->arg_max may actually be LONG_MAX.
403 * Also, adding one to that is a bad idea.
405 state->argbuf = (char *) xmalloc (ctl->arg_max + 1);
407 state->cmd_argv_chars = state->cmd_initial_argv_chars = 0;
408 state->todo = 0;
409 state->usercontext = context;
412 void
413 bc_clear_args(const struct buildcmd_control *ctl,
414 struct buildcmd_state *state)
416 state->cmd_argc = ctl->initial_argc;
417 state->cmd_argv_chars = state->cmd_initial_argv_chars;
418 state->todo = 0;