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