1170754Sdelphij/* Shell command argument quoting.
2170754Sdelphij   Copyright (C) 1994, 1995, 1997 Free Software Foundation, Inc.
3170754Sdelphij
4170754Sdelphij   This program is free software; you can redistribute it and/or modify
5170754Sdelphij   it under the terms of the GNU General Public License as published by
6170754Sdelphij   the Free Software Foundation; either version 2, or (at your option)
7170754Sdelphij   any later version.
8170754Sdelphij
9170754Sdelphij   This program is distributed in the hope that it will be useful,
10170754Sdelphij   but WITHOUT ANY WARRANTY; without even the implied warranty of
11170754Sdelphij   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12170754Sdelphij   GNU General Public License for more details.
13170754Sdelphij
14170754Sdelphij   You should have received a copy of the GNU General Public License
15170754Sdelphij   along with this program; see the file COPYING.
16170754Sdelphij   If not, write to the Free Software Foundation,
17170754Sdelphij   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
18170754Sdelphij
19170754Sdelphij/* Written by Paul Eggert <eggert@twinsun.com> */
20170754Sdelphij
21170754Sdelphij#if HAVE_CONFIG_H
22170754Sdelphij# include <config.h>
23170754Sdelphij#endif
24170754Sdelphij
25170754Sdelphij#include <sys/types.h>
26170754Sdelphij#include <quotesys.h>
27170754Sdelphij
28170754Sdelphij/* Place into QUOTED a quoted version of ARG suitable for `system'.
29170754Sdelphij   Return the length of the resulting string (which is not null-terminated).
30170754Sdelphij   If QUOTED is null, return the length without any side effects.  */
31170754Sdelphij
32170754Sdelphijsize_t
33170754Sdelphijquote_system_arg (quoted, arg)
34170754Sdelphij     char *quoted;
35170754Sdelphij     char const *arg;
36170754Sdelphij{
37170754Sdelphij  char const *a;
38170754Sdelphij  size_t len = 0;
39170754Sdelphij
40170754Sdelphij  /* Scan ARG, copying it to QUOTED if QUOTED is not null,
41170754Sdelphij     looking for shell metacharacters.  */
42170754Sdelphij
43170754Sdelphij  for (a = arg; ; a++)
44170754Sdelphij    {
45170754Sdelphij      char c = *a;
46170754Sdelphij      switch (c)
47170754Sdelphij	{
48170754Sdelphij	case 0:
49170754Sdelphij	  /* ARG has no shell metacharacters.  */
50170754Sdelphij	  return len;
51170754Sdelphij
52170754Sdelphij	case '=':
53170754Sdelphij	  if (*arg == '-')
54170754Sdelphij	    break;
55170754Sdelphij	  /* Fall through.  */
56170754Sdelphij	case '\t': case '\n': case ' ':
57170754Sdelphij	case '!': case '"': case '#': case '$': case '%': case '&': case '\'':
58170754Sdelphij	case '(': case ')': case '*': case ';':
59170754Sdelphij	case '<': case '>': case '?': case '[': case '\\':
60170754Sdelphij	case '^': case '`': case '|': case '~':
61170754Sdelphij	  {
62170754Sdelphij	    /* ARG has a shell metacharacter.
63170754Sdelphij	       Start over, quoting it this time.  */
64170754Sdelphij
65170754Sdelphij	    len = 0;
66170754Sdelphij	    c = *arg++;
67170754Sdelphij
68170754Sdelphij	    /* If ARG is an option, quote just its argument.
69170754Sdelphij	       This is not necessary, but it looks nicer.  */
70170754Sdelphij	    if (c == '-'  &&  arg < a)
71170754Sdelphij	      {
72170754Sdelphij		c = *arg++;
73170754Sdelphij
74170754Sdelphij		if (quoted)
75170754Sdelphij		  {
76170754Sdelphij		    quoted[len] = '-';
77170754Sdelphij		    quoted[len + 1] = c;
78170754Sdelphij		  }
79170754Sdelphij		len += 2;
80170754Sdelphij
81170754Sdelphij		if (c == '-')
82170754Sdelphij		  while (arg < a)
83170754Sdelphij		    {
84170754Sdelphij		      c = *arg++;
85170754Sdelphij		      if (quoted)
86170754Sdelphij			quoted[len] = c;
87170754Sdelphij		      len++;
88170754Sdelphij		      if (c == '=')
89170754Sdelphij			break;
90170754Sdelphij		    }
91170754Sdelphij		c = *arg++;
92170754Sdelphij	      }
93170754Sdelphij
94170754Sdelphij	    if (quoted)
95170754Sdelphij	      quoted[len] = '\'';
96170754Sdelphij	    len++;
97170754Sdelphij
98170754Sdelphij	    for (;  c;  c = *arg++)
99170754Sdelphij	      {
100170754Sdelphij		if (c == '\'')
101170754Sdelphij		  {
102170754Sdelphij		    if (quoted)
103170754Sdelphij		      {
104170754Sdelphij			quoted[len] = '\'';
105170754Sdelphij			quoted[len + 1] = '\\';
106170754Sdelphij			quoted[len + 2] = '\'';
107170754Sdelphij		      }
108170754Sdelphij		    len += 3;
109170754Sdelphij		  }
110170754Sdelphij		if (quoted)
111170754Sdelphij		  quoted[len] = c;
112170754Sdelphij		len++;
113170754Sdelphij	      }
114170754Sdelphij
115170754Sdelphij	    if (quoted)
116170754Sdelphij	      quoted[len] = '\'';
117170754Sdelphij	    return len + 1;
118170754Sdelphij	  }
119170754Sdelphij	}
120170754Sdelphij
121170754Sdelphij      if (quoted)
122170754Sdelphij	quoted[len] = c;
123170754Sdelphij      len++;
124170754Sdelphij    }
125170754Sdelphij}
126