xref: /freebsd/contrib/diff/lib/quotesys.c (revision 396c556d77189a5c474d35cec6f44a762e310b7d)
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 
32 size_t
33 quote_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