1/* Create and destroy argument vectors (argv's)
2   Copyright (C) 1992, 2001, 2010, 2012 Free Software Foundation, Inc.
3   Written by Fred Fish @ Cygnus Support
4
5This file is part of the libiberty library.
6Libiberty is free software; you can redistribute it and/or
7modify it under the terms of the GNU Library General Public
8License as published by the Free Software Foundation; either
9version 2 of the License, or (at your option) any later version.
10
11Libiberty is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14Library General Public License for more details.
15
16You should have received a copy of the GNU Library General Public
17License along with libiberty; see the file COPYING.LIB.  If
18not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
19Boston, MA 02110-1301, USA.  */
20
21
22/*  Create and destroy argument vectors.  An argument vector is simply an
23    array of string pointers, terminated by a NULL pointer. */
24
25#ifdef HAVE_CONFIG_H
26#include "config.h"
27#endif
28#include "ansidecl.h"
29#include "libiberty.h"
30#include "safe-ctype.h"
31
32/*  Routines imported from standard C runtime libraries. */
33
34#include <stddef.h>
35#include <string.h>
36#include <stdlib.h>
37#include <stdio.h>
38#include <sys/types.h>
39#ifdef HAVE_UNISTD_H
40#include <unistd.h>
41#endif
42#if HAVE_SYS_STAT_H
43#include <sys/stat.h>
44#endif
45
46#ifndef NULL
47#define NULL 0
48#endif
49
50#ifndef EOS
51#define EOS '\0'
52#endif
53
54#define INITIAL_MAXARGC 8	/* Number of args + NULL in initial argv */
55
56
57/*
58
59@deftypefn Extension char** dupargv (char * const *@var{vector})
60
61Duplicate an argument vector.  Simply scans through @var{vector},
62duplicating each argument until the terminating @code{NULL} is found.
63Returns a pointer to the argument vector if successful.  Returns
64@code{NULL} if there is insufficient memory to complete building the
65argument vector.
66
67@end deftypefn
68
69*/
70
71char **
72dupargv (char * const *argv)
73{
74  int argc;
75  char **copy;
76
77  if (argv == NULL)
78    return NULL;
79
80  /* the vector */
81  for (argc = 0; argv[argc] != NULL; argc++);
82  copy = (char **) xmalloc ((argc + 1) * sizeof (char *));
83
84  /* the strings */
85  for (argc = 0; argv[argc] != NULL; argc++)
86    copy[argc] = xstrdup (argv[argc]);
87  copy[argc] = NULL;
88  return copy;
89}
90
91/*
92
93@deftypefn Extension void freeargv (char **@var{vector})
94
95Free an argument vector that was built using @code{buildargv}.  Simply
96scans through @var{vector}, freeing the memory for each argument until
97the terminating @code{NULL} is found, and then frees @var{vector}
98itself.
99
100@end deftypefn
101
102*/
103
104void freeargv (char **vector)
105{
106  register char **scan;
107
108  if (vector != NULL)
109    {
110      for (scan = vector; *scan != NULL; scan++)
111	{
112	  free (*scan);
113	}
114      free (vector);
115    }
116}
117
118static void
119consume_whitespace (const char **input)
120{
121  while (ISSPACE (**input))
122    {
123      (*input)++;
124    }
125}
126
127static int
128only_whitespace (const char* input)
129{
130  while (*input != EOS && ISSPACE (*input))
131    input++;
132
133  return (*input == EOS);
134}
135
136/*
137
138@deftypefn Extension char** buildargv (char *@var{sp})
139
140Given a pointer to a string, parse the string extracting fields
141separated by whitespace and optionally enclosed within either single
142or double quotes (which are stripped off), and build a vector of
143pointers to copies of the string for each field.  The input string
144remains unchanged.  The last element of the vector is followed by a
145@code{NULL} element.
146
147All of the memory for the pointer array and copies of the string
148is obtained from @code{xmalloc}.  All of the memory can be returned to the
149system with the single function call @code{freeargv}, which takes the
150returned result of @code{buildargv}, as it's argument.
151
152Returns a pointer to the argument vector if successful.  Returns
153@code{NULL} if @var{sp} is @code{NULL} or if there is insufficient
154memory to complete building the argument vector.
155
156If the input is a null string (as opposed to a @code{NULL} pointer),
157then buildarg returns an argument vector that has one arg, a null
158string.
159
160@end deftypefn
161
162The memory for the argv array is dynamically expanded as necessary.
163
164In order to provide a working buffer for extracting arguments into,
165with appropriate stripping of quotes and translation of backslash
166sequences, we allocate a working buffer at least as long as the input
167string.  This ensures that we always have enough space in which to
168work, since the extracted arg is never larger than the input string.
169
170The argument vector is always kept terminated with a @code{NULL} arg
171pointer, so it can be passed to @code{freeargv} at any time, or
172returned, as appropriate.
173
174*/
175
176char **buildargv (const char *input)
177{
178  char *arg;
179  char *copybuf;
180  int squote = 0;
181  int dquote = 0;
182  int bsquote = 0;
183  int argc = 0;
184  int maxargc = 0;
185  char **argv = NULL;
186  char **nargv;
187
188  if (input != NULL)
189    {
190      copybuf = (char *) xmalloc (strlen (input) + 1);
191      /* Is a do{}while to always execute the loop once.  Always return an
192	 argv, even for null strings.  See NOTES above, test case below. */
193      do
194	{
195	  /* Pick off argv[argc] */
196	  consume_whitespace (&input);
197
198	  if ((maxargc == 0) || (argc >= (maxargc - 1)))
199	    {
200	      /* argv needs initialization, or expansion */
201	      if (argv == NULL)
202		{
203		  maxargc = INITIAL_MAXARGC;
204		  nargv = (char **) xmalloc (maxargc * sizeof (char *));
205		}
206	      else
207		{
208		  maxargc *= 2;
209		  nargv = (char **) xrealloc (argv, maxargc * sizeof (char *));
210		}
211	      argv = nargv;
212	      argv[argc] = NULL;
213	    }
214	  /* Begin scanning arg */
215	  arg = copybuf;
216	  while (*input != EOS)
217	    {
218	      if (ISSPACE (*input) && !squote && !dquote && !bsquote)
219		{
220		  break;
221		}
222	      else
223		{
224		  if (bsquote)
225		    {
226		      bsquote = 0;
227		      *arg++ = *input;
228		    }
229		  else if (*input == '\\')
230		    {
231		      bsquote = 1;
232		    }
233		  else if (squote)
234		    {
235		      if (*input == '\'')
236			{
237			  squote = 0;
238			}
239		      else
240			{
241			  *arg++ = *input;
242			}
243		    }
244		  else if (dquote)
245		    {
246		      if (*input == '"')
247			{
248			  dquote = 0;
249			}
250		      else
251			{
252			  *arg++ = *input;
253			}
254		    }
255		  else
256		    {
257		      if (*input == '\'')
258			{
259			  squote = 1;
260			}
261		      else if (*input == '"')
262			{
263			  dquote = 1;
264			}
265		      else
266			{
267			  *arg++ = *input;
268			}
269		    }
270		  input++;
271		}
272	    }
273	  *arg = EOS;
274	  argv[argc] = xstrdup (copybuf);
275	  argc++;
276	  argv[argc] = NULL;
277
278	  consume_whitespace (&input);
279	}
280      while (*input != EOS);
281
282      free (copybuf);
283    }
284  return (argv);
285}
286
287/*
288
289@deftypefn Extension int writeargv (char * const *@var{argv}, FILE *@var{file})
290
291Write each member of ARGV, handling all necessary quoting, to the file
292named by FILE, separated by whitespace.  Return 0 on success, non-zero
293if an error occurred while writing to FILE.
294
295@end deftypefn
296
297*/
298
299int
300writeargv (char * const *argv, FILE *f)
301{
302  int status = 0;
303
304  if (f == NULL)
305    return 1;
306
307  while (*argv != NULL)
308    {
309      const char *arg = *argv;
310
311      while (*arg != EOS)
312        {
313          char c = *arg;
314
315          if (ISSPACE(c) || c == '\\' || c == '\'' || c == '"')
316            if (EOF == fputc ('\\', f))
317              {
318                status = 1;
319                goto done;
320              }
321
322          if (EOF == fputc (c, f))
323            {
324              status = 1;
325              goto done;
326            }
327          arg++;
328        }
329
330      if (EOF == fputc ('\n', f))
331        {
332          status = 1;
333          goto done;
334        }
335      argv++;
336    }
337
338 done:
339  return status;
340}
341
342/*
343
344@deftypefn Extension void expandargv (int *@var{argcp}, char ***@var{argvp})
345
346The @var{argcp} and @code{argvp} arguments are pointers to the usual
347@code{argc} and @code{argv} arguments to @code{main}.  This function
348looks for arguments that begin with the character @samp{@@}.  Any such
349arguments are interpreted as ``response files''.  The contents of the
350response file are interpreted as additional command line options.  In
351particular, the file is separated into whitespace-separated strings;
352each such string is taken as a command-line option.  The new options
353are inserted in place of the option naming the response file, and
354@code{*argcp} and @code{*argvp} will be updated.  If the value of
355@code{*argvp} is modified by this function, then the new value has
356been dynamically allocated and can be deallocated by the caller with
357@code{freeargv}.  However, most callers will simply call
358@code{expandargv} near the beginning of @code{main} and allow the
359operating system to free the memory when the program exits.
360
361@end deftypefn
362
363*/
364
365void
366expandargv (int *argcp, char ***argvp)
367{
368  /* The argument we are currently processing.  */
369  int i = 0;
370  /* Non-zero if ***argvp has been dynamically allocated.  */
371  int argv_dynamic = 0;
372  /* Limit the number of response files that we parse in order
373     to prevent infinite recursion.  */
374  unsigned int iteration_limit = 2000;
375  /* Loop over the arguments, handling response files.  We always skip
376     ARGVP[0], as that is the name of the program being run.  */
377  while (++i < *argcp)
378    {
379      /* The name of the response file.  */
380      const char *filename;
381      /* The response file.  */
382      FILE *f;
383      /* An upper bound on the number of characters in the response
384	 file.  */
385      long pos;
386      /* The number of characters in the response file, when actually
387	 read.  */
388      size_t len;
389      /* A dynamically allocated buffer used to hold options read from a
390	 response file.  */
391      char *buffer;
392      /* Dynamically allocated storage for the options read from the
393	 response file.  */
394      char **file_argv;
395      /* The number of options read from the response file, if any.  */
396      size_t file_argc;
397#ifdef S_ISDIR
398      struct stat sb;
399#endif
400      /* We are only interested in options of the form "@file".  */
401      filename = (*argvp)[i];
402      if (filename[0] != '@')
403	continue;
404      /* If we have iterated too many times then stop.  */
405      if (-- iteration_limit == 0)
406	{
407	  fprintf (stderr, "%s: error: too many @-files encountered\n", (*argvp)[0]);
408	  xexit (1);
409	}
410#ifdef S_ISDIR
411      if (stat (filename+1, &sb) < 0)
412	continue;
413      if (S_ISDIR(sb.st_mode))
414	{
415	  fprintf (stderr, "%s: error: @-file refers to a directory\n", (*argvp)[0]);
416	  xexit (1);
417	}
418#endif
419      /* Read the contents of the file.  */
420      f = fopen (++filename, "r");
421      if (!f)
422	continue;
423      if (fseek (f, 0L, SEEK_END) == -1)
424	goto error;
425      pos = ftell (f);
426      if (pos == -1)
427	goto error;
428      if (fseek (f, 0L, SEEK_SET) == -1)
429	goto error;
430      buffer = (char *) xmalloc (pos * sizeof (char) + 1);
431      len = fread (buffer, sizeof (char), pos, f);
432      if (len != (size_t) pos
433	  /* On Windows, fread may return a value smaller than POS,
434	     due to CR/LF->CR translation when reading text files.
435	     That does not in-and-of itself indicate failure.  */
436	  && ferror (f))
437	goto error;
438      /* Add a NUL terminator.  */
439      buffer[len] = '\0';
440      /* If the file is empty or contains only whitespace, buildargv would
441	 return a single empty argument.  In this context we want no arguments,
442	 instead.  */
443      if (only_whitespace (buffer))
444	{
445	  file_argv = (char **) xmalloc (sizeof (char *));
446	  file_argv[0] = NULL;
447	}
448      else
449	/* Parse the string.  */
450	file_argv = buildargv (buffer);
451      /* If *ARGVP is not already dynamically allocated, copy it.  */
452      if (!argv_dynamic)
453	*argvp = dupargv (*argvp);
454      /* Count the number of arguments.  */
455      file_argc = 0;
456      while (file_argv[file_argc])
457	++file_argc;
458      /* Now, insert FILE_ARGV into ARGV.  The "+1" below handles the
459	 NULL terminator at the end of ARGV.  */
460      *argvp = ((char **)
461		xrealloc (*argvp,
462			  (*argcp + file_argc + 1) * sizeof (char *)));
463      memmove (*argvp + i + file_argc, *argvp + i + 1,
464	       (*argcp - i) * sizeof (char *));
465      memcpy (*argvp + i, file_argv, file_argc * sizeof (char *));
466      /* The original option has been replaced by all the new
467	 options.  */
468      *argcp += file_argc - 1;
469      /* Free up memory allocated to process the response file.  We do
470	 not use freeargv because the individual options in FILE_ARGV
471	 are now in the main ARGV.  */
472      free (file_argv);
473      free (buffer);
474      /* Rescan all of the arguments just read to support response
475	 files that include other response files.  */
476      --i;
477    error:
478      /* We're all done with the file now.  */
479      fclose (f);
480    }
481}
482
483/*
484
485@deftypefn Extension int countargv (char * const *@var{argv})
486
487Return the number of elements in @var{argv}.
488Returns zero if @var{argv} is NULL.
489
490@end deftypefn
491
492*/
493
494int
495countargv (char * const *argv)
496{
497  int argc;
498
499  if (argv == NULL)
500    return 0;
501  for (argc = 0; argv[argc] != NULL; argc++)
502    continue;
503  return argc;
504}
505
506#ifdef MAIN
507
508/* Simple little test driver. */
509
510static const char *const tests[] =
511{
512  "a simple command line",
513  "arg 'foo' is single quoted",
514  "arg \"bar\" is double quoted",
515  "arg \"foo bar\" has embedded whitespace",
516  "arg 'Jack said \\'hi\\'' has single quotes",
517  "arg 'Jack said \\\"hi\\\"' has double quotes",
518  "a b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9",
519
520  /* This should be expanded into only one argument.  */
521  "trailing-whitespace ",
522
523  "",
524  NULL
525};
526
527int
528main (void)
529{
530  char **argv;
531  const char *const *test;
532  char **targs;
533
534  for (test = tests; *test != NULL; test++)
535    {
536      printf ("buildargv(\"%s\")\n", *test);
537      if ((argv = buildargv (*test)) == NULL)
538	{
539	  printf ("failed!\n\n");
540	}
541      else
542	{
543	  for (targs = argv; *targs != NULL; targs++)
544	    {
545	      printf ("\t\"%s\"\n", *targs);
546	    }
547	  printf ("\n");
548	}
549      freeargv (argv);
550    }
551
552  return 0;
553}
554
555#endif	/* MAIN */
556