1/* Shell command argument quoting.
2   Copyright (C) 1994, 1995, 1997 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; see the file COPYING.
16   If not, write to the Free Software Foundation,
17   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
18
19/* Written by Paul Eggert <eggert@twinsun.com> */
20
21#if HAVE_CONFIG_H
22# include <config.h>
23#endif
24
25#include <sys/types.h>
26#include <quotesys.h>
27
28/* Place into QUOTED a quoted version of ARG suitable for `system'.
29   Return the length of the resulting string (which is not null-terminated).
30   If QUOTED is null, return the length without any side effects.  */
31
32size_t
33quote_system_arg (quoted, arg)
34     char *quoted;
35     char const *arg;
36{
37  char const *a;
38  size_t len = 0;
39
40  /* Scan ARG, copying it to QUOTED if QUOTED is not null,
41     looking for shell metacharacters.  */
42
43  for (a = arg; ; a++)
44    {
45      char c = *a;
46      switch (c)
47	{
48	case 0:
49	  /* ARG has no shell metacharacters.  */
50	  return len;
51
52	case '=':
53	  if (*arg == '-')
54	    break;
55	  /* Fall through.  */
56	case '\t': case '\n': case ' ':
57	case '!': case '"': case '#': case '$': case '%': case '&': case '\'':
58	case '(': case ')': case '*': case ';':
59	case '<': case '>': case '?': case '[': case '\\':
60	case '^': case '`': case '|': case '~':
61	  {
62	    /* ARG has a shell metacharacter.
63	       Start over, quoting it this time.  */
64
65	    len = 0;
66	    c = *arg++;
67
68	    /* If ARG is an option, quote just its argument.
69	       This is not necessary, but it looks nicer.  */
70	    if (c == '-'  &&  arg < a)
71	      {
72		c = *arg++;
73
74		if (quoted)
75		  {
76		    quoted[len] = '-';
77		    quoted[len + 1] = c;
78		  }
79		len += 2;
80
81		if (c == '-')
82		  while (arg < a)
83		    {
84		      c = *arg++;
85		      if (quoted)
86			quoted[len] = c;
87		      len++;
88		      if (c == '=')
89			break;
90		    }
91		c = *arg++;
92	      }
93
94	    if (quoted)
95	      quoted[len] = '\'';
96	    len++;
97
98	    for (;  c;  c = *arg++)
99	      {
100		if (c == '\'')
101		  {
102		    if (quoted)
103		      {
104			quoted[len] = '\'';
105			quoted[len + 1] = '\\';
106			quoted[len + 2] = '\'';
107		      }
108		    len += 3;
109		  }
110		if (quoted)
111		  quoted[len] = c;
112		len++;
113	      }
114
115	    if (quoted)
116	      quoted[len] = '\'';
117	    return len + 1;
118	  }
119	}
120
121      if (quoted)
122	quoted[len] = c;
123      len++;
124    }
125}
126