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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
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>
76 /* COMPAT: SYSV version defaults size (and has a max value of) to 470.
77 We try to make it as large as possible. */
78 #if !defined(ARG_MAX) && defined(_SC_ARG_MAX)
79 #define ARG_MAX sysconf (_SC_ARG_MAX)
82 #define ARG_MAX NCARGS
92 static char *mbstrstr
PARAMS ((const char *haystack
, const char *needle
));
94 /* Replace all instances of `replace_pat' in ARG with `linebuf',
95 and add the resulting string to the list of arguments for the command
97 ARGLEN is the length of ARG, not including the null.
98 LBLEN is the length of LINEBUF, not including the null.
100 COMPAT: insertions on the SYSV version are limited to 255 chars per line,
101 and a max of 5 occurrences of replace_pat in the initial-arguments.
102 Those restrictions do not exist here. */
105 bc_do_insert (const struct buildcmd_control
*ctl
,
106 struct buildcmd_state
*state
,
113 /* Temporary copy of each arg with the replace pattern replaced by the
115 static char *insertbuf
;
117 int bytes_left
= ctl
->arg_max
- 1; /* Bytes left on the command line. */
120 insertbuf
= (char *) xmalloc (ctl
->arg_max
+ 1);
125 size_t len
; /* Length in ARG before `replace_pat'. */
126 char *s
= mbstrstr (arg
, ctl
->replace_pat
);
135 strncpy (p
, arg
, len
);
147 arglen
-= ctl
->rplen
;
153 error (1, 0, _("command too long"));
155 bc_push_arg (ctl
, state
, insertbuf
, p
- insertbuf
, initial_args
);
159 void do_exec(const struct buildcmd_control
*ctl
,
160 struct buildcmd_state
*state
)
162 (ctl
->exec_callback
)(ctl
, state
);
166 /* Add ARG to the end of the list of arguments `cmd_argv' to pass
168 LEN is the length of ARG, including the terminating null.
169 If this brings the list up to its maximum size, execute the command. */
172 bc_push_arg (const struct buildcmd_control
*ctl
,
173 struct buildcmd_state
*state
,
181 if (state
->cmd_argv_chars
+ len
> ctl
->arg_max
)
183 if (initial_args
|| state
->cmd_argc
== ctl
->initial_argc
)
184 error (1, 0, _("can not fit single argument within argument list size limit"));
185 /* option -i (replace_pat) implies -x (exit_if_size_exceeded) */
187 || (ctl
->exit_if_size_exceeded
&&
188 (ctl
->lines_per_exec
|| ctl
->args_per_exec
)))
189 error (1, 0, _("argument list too long"));
190 do_exec (ctl
, state
);
192 if (!initial_args
&& ctl
->args_per_exec
&&
193 state
->cmd_argc
- ctl
->initial_argc
== ctl
->args_per_exec
)
194 do_exec (ctl
, state
);
197 if (state
->cmd_argc
>= state
->cmd_argv_alloc
)
199 if (!state
->cmd_argv
)
201 state
->cmd_argv_alloc
= 64;
202 state
->cmd_argv
= (char **) xmalloc (sizeof (char *) * state
->cmd_argv_alloc
);
206 state
->cmd_argv_alloc
*= 2;
207 state
->cmd_argv
= (char **) xrealloc (state
->cmd_argv
,
208 sizeof (char *) * state
->cmd_argv_alloc
);
213 state
->cmd_argv
[state
->cmd_argc
++] = NULL
;
216 state
->cmd_argv
[state
->cmd_argc
++] = state
->argbuf
+ state
->cmd_argv_chars
;
217 strcpy (state
->argbuf
+ state
->cmd_argv_chars
, arg
);
218 state
->cmd_argv_chars
+= len
;
220 /* If we have now collected enough arguments,
221 * do the exec immediately. This must be
222 * conditional on arg!=NULL, since do_exec()
223 * actually calls bc_push_arg(ctl, state, NULL, 0, false).
226 && ctl
->args_per_exec
227 && (state
->cmd_argc
- ctl
->initial_argc
) == ctl
->args_per_exec
)
228 do_exec (ctl
, state
);
231 /* If this is an initial argument, set the high-water mark. */
234 state
->cmd_initial_argv_chars
= state
->cmd_argv_chars
;
239 /* Finds the first occurrence of the substring NEEDLE in the string
240 HAYSTACK. Both strings can be multibyte strings. */
243 mbstrstr (const char *haystack
, const char *needle
)
248 size_t hlen
= strlen (haystack
);
249 size_t nlen
= strlen (needle
);
253 memset (&mbstate
, 0, sizeof (mbstate_t));
256 if (memcmp (haystack
, needle
, nlen
) == 0)
257 return (char *) haystack
;
258 step
= mbrlen (haystack
, hlen
, &mbstate
);
267 return strstr (haystack
, needle
);
276 val
= sysconf(_SC_ARG_MAX
);
284 /* either _SC_ARG_MAX was not available or
285 * there is no particular limit.
294 /* The value returned by this function bounds the
295 * value applied as the ceiling for the -s option.
296 * Hence it the system won't tell us what its limit
297 * is, we allow the user to specify more or less
298 * whatever value they like.
304 static int cb_exec_noop(const struct buildcmd_control
*ctl
,
305 struct buildcmd_state
*state
)
315 bc_init_controlinfo(struct buildcmd_control
*ctl
)
317 ctl
->exit_if_size_exceeded
= 0;
318 ctl
->arg_max
= bc_get_arg_max() - 2048; /* a la xargs */
320 ctl
->replace_pat
= NULL
;
321 ctl
->initial_argc
= 0;
322 ctl
->exec_callback
= cb_exec_noop
;
323 ctl
->lines_per_exec
= 0;
324 ctl
->args_per_exec
= 0;
328 bc_init_state(const struct buildcmd_control
*ctl
,
329 struct buildcmd_state
*state
)
332 state
->cmd_argv_chars
= 0;
333 state
->cmd_argv
= NULL
;
334 state
->cmd_argv_alloc
= 0;
335 state
->argbuf
= (char *) xmalloc (ctl
->arg_max
+ 1);
336 state
->cmd_argv_chars
= 0;
338 state
->usercontext
= NULL
;
342 bc_clear_args(const struct buildcmd_control
*ctl
,
343 struct buildcmd_state
*state
)
345 state
->cmd_argc
= ctl
->initial_argc
;
346 state
->cmd_argv_chars
= state
->cmd_initial_argv_chars
;