xref: /plan9/sys/src/ape/cmd/patch/quotearg.c (revision 0b459c2cb92b7c9d88818e9a2f72e678e5bc4553)
1*0b459c2cSDavid du Colombier /* Shell command argument quoting.
2*0b459c2cSDavid du Colombier    Copyright (C) 1994, 1995, 1997 Free Software Foundation, Inc.
3*0b459c2cSDavid du Colombier 
4*0b459c2cSDavid du Colombier    This program is free software; you can redistribute it and/or modify
5*0b459c2cSDavid du Colombier    it under the terms of the GNU General Public License as published by
6*0b459c2cSDavid du Colombier    the Free Software Foundation; either version 2, or (at your option)
7*0b459c2cSDavid du Colombier    any later version.
8*0b459c2cSDavid du Colombier 
9*0b459c2cSDavid du Colombier    This program is distributed in the hope that it will be useful,
10*0b459c2cSDavid du Colombier    but WITHOUT ANY WARRANTY; without even the implied warranty of
11*0b459c2cSDavid du Colombier    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12*0b459c2cSDavid du Colombier    GNU General Public License for more details.
13*0b459c2cSDavid du Colombier 
14*0b459c2cSDavid du Colombier    You should have received a copy of the GNU General Public License
15*0b459c2cSDavid du Colombier    along with this program; see the file COPYING.
16*0b459c2cSDavid du Colombier    If not, write to the Free Software Foundation,
17*0b459c2cSDavid du Colombier    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
18*0b459c2cSDavid du Colombier 
19*0b459c2cSDavid du Colombier /* Written by Paul Eggert <eggert@twinsun.com> */
20*0b459c2cSDavid du Colombier 
21*0b459c2cSDavid du Colombier #if HAVE_CONFIG_H
22*0b459c2cSDavid du Colombier # include <config.h>
23*0b459c2cSDavid du Colombier #endif
24*0b459c2cSDavid du Colombier 
25*0b459c2cSDavid du Colombier #include <sys/types.h>
26*0b459c2cSDavid du Colombier #include <quotearg.h>
27*0b459c2cSDavid du Colombier 
28*0b459c2cSDavid du Colombier /* Place into QUOTED a quoted version of ARG suitable for `system'.
29*0b459c2cSDavid du Colombier    Return the length of the resulting string (which is not null-terminated).
30*0b459c2cSDavid du Colombier    If QUOTED is null, return the length without any side effects.  */
31*0b459c2cSDavid du Colombier 
32*0b459c2cSDavid du Colombier size_t
quote_system_arg(quoted,arg)33*0b459c2cSDavid du Colombier quote_system_arg (quoted, arg)
34*0b459c2cSDavid du Colombier      char *quoted;
35*0b459c2cSDavid du Colombier      char const *arg;
36*0b459c2cSDavid du Colombier {
37*0b459c2cSDavid du Colombier   char const *a;
38*0b459c2cSDavid du Colombier   size_t len = 0;
39*0b459c2cSDavid du Colombier 
40*0b459c2cSDavid du Colombier   /* Scan ARG, copying it to QUOTED if QUOTED is not null,
41*0b459c2cSDavid du Colombier      looking for shell metacharacters.  */
42*0b459c2cSDavid du Colombier 
43*0b459c2cSDavid du Colombier   for (a = arg; ; a++)
44*0b459c2cSDavid du Colombier     {
45*0b459c2cSDavid du Colombier       char c = *a;
46*0b459c2cSDavid du Colombier       switch (c)
47*0b459c2cSDavid du Colombier 	{
48*0b459c2cSDavid du Colombier 	case 0:
49*0b459c2cSDavid du Colombier 	  /* ARG has no shell metacharacters.  */
50*0b459c2cSDavid du Colombier 	  return len;
51*0b459c2cSDavid du Colombier 
52*0b459c2cSDavid du Colombier 	case '=':
53*0b459c2cSDavid du Colombier 	  if (*arg == '-')
54*0b459c2cSDavid du Colombier 	    break;
55*0b459c2cSDavid du Colombier 	  /* Fall through.  */
56*0b459c2cSDavid du Colombier 	case '\t': case '\n': case ' ':
57*0b459c2cSDavid du Colombier 	case '!': case '"': case '#': case '$': case '%': case '&': case '\'':
58*0b459c2cSDavid du Colombier 	case '(': case ')': case '*': case ';':
59*0b459c2cSDavid du Colombier 	case '<': case '>': case '?': case '[': case '\\':
60*0b459c2cSDavid du Colombier 	case '^': case '`': case '|': case '~':
61*0b459c2cSDavid du Colombier 	  {
62*0b459c2cSDavid du Colombier 	    /* ARG has a shell metacharacter.
63*0b459c2cSDavid du Colombier 	       Start over, quoting it this time.  */
64*0b459c2cSDavid du Colombier 
65*0b459c2cSDavid du Colombier 	    len = 0;
66*0b459c2cSDavid du Colombier 	    c = *arg++;
67*0b459c2cSDavid du Colombier 
68*0b459c2cSDavid du Colombier 	    /* If ARG is an option, quote just its argument.
69*0b459c2cSDavid du Colombier 	       This is not necessary, but it looks nicer.  */
70*0b459c2cSDavid du Colombier 	    if (c == '-'  &&  arg < a)
71*0b459c2cSDavid du Colombier 	      {
72*0b459c2cSDavid du Colombier 		c = *arg++;
73*0b459c2cSDavid du Colombier 
74*0b459c2cSDavid du Colombier 		if (quoted)
75*0b459c2cSDavid du Colombier 		  {
76*0b459c2cSDavid du Colombier 		    quoted[len] = '-';
77*0b459c2cSDavid du Colombier 		    quoted[len + 1] = c;
78*0b459c2cSDavid du Colombier 		  }
79*0b459c2cSDavid du Colombier 		len += 2;
80*0b459c2cSDavid du Colombier 
81*0b459c2cSDavid du Colombier 		if (c == '-')
82*0b459c2cSDavid du Colombier 		  while (arg < a)
83*0b459c2cSDavid du Colombier 		    {
84*0b459c2cSDavid du Colombier 		      c = *arg++;
85*0b459c2cSDavid du Colombier 		      if (quoted)
86*0b459c2cSDavid du Colombier 			quoted[len] = c;
87*0b459c2cSDavid du Colombier 		      len++;
88*0b459c2cSDavid du Colombier 		      if (c == '=')
89*0b459c2cSDavid du Colombier 			break;
90*0b459c2cSDavid du Colombier 		    }
91*0b459c2cSDavid du Colombier 		c = *arg++;
92*0b459c2cSDavid du Colombier 	      }
93*0b459c2cSDavid du Colombier 
94*0b459c2cSDavid du Colombier 	    if (quoted)
95*0b459c2cSDavid du Colombier 	      quoted[len] = '\'';
96*0b459c2cSDavid du Colombier 	    len++;
97*0b459c2cSDavid du Colombier 
98*0b459c2cSDavid du Colombier 	    for (;  c;  c = *arg++)
99*0b459c2cSDavid du Colombier 	      {
100*0b459c2cSDavid du Colombier 		if (c == '\'')
101*0b459c2cSDavid du Colombier 		  {
102*0b459c2cSDavid du Colombier 		    if (quoted)
103*0b459c2cSDavid du Colombier 		      {
104*0b459c2cSDavid du Colombier 			quoted[len] = '\'';
105*0b459c2cSDavid du Colombier 			quoted[len + 1] = '\\';
106*0b459c2cSDavid du Colombier 			quoted[len + 2] = '\'';
107*0b459c2cSDavid du Colombier 		      }
108*0b459c2cSDavid du Colombier 		    len += 3;
109*0b459c2cSDavid du Colombier 		  }
110*0b459c2cSDavid du Colombier 		if (quoted)
111*0b459c2cSDavid du Colombier 		  quoted[len] = c;
112*0b459c2cSDavid du Colombier 		len++;
113*0b459c2cSDavid du Colombier 	      }
114*0b459c2cSDavid du Colombier 
115*0b459c2cSDavid du Colombier 	    if (quoted)
116*0b459c2cSDavid du Colombier 	      quoted[len] = '\'';
117*0b459c2cSDavid du Colombier 	    return len + 1;
118*0b459c2cSDavid du Colombier 	  }
119*0b459c2cSDavid du Colombier 	}
120*0b459c2cSDavid du Colombier 
121*0b459c2cSDavid du Colombier       if (quoted)
122*0b459c2cSDavid du Colombier 	quoted[len] = c;
123*0b459c2cSDavid du Colombier       len++;
124*0b459c2cSDavid du Colombier     }
125*0b459c2cSDavid du Colombier }
126