xref: /freebsd/contrib/diff/lib/quotesys.c (revision 18fd37a72c3a7549d2d4f6c6ea00bdcd2bdaca01)
118fd37a7SXin LI /* Shell command argument quoting.
218fd37a7SXin LI    Copyright (C) 1994, 1995, 1997 Free Software Foundation, Inc.
318fd37a7SXin LI 
418fd37a7SXin LI    This program is free software; you can redistribute it and/or modify
518fd37a7SXin LI    it under the terms of the GNU General Public License as published by
618fd37a7SXin LI    the Free Software Foundation; either version 2, or (at your option)
718fd37a7SXin LI    any later version.
818fd37a7SXin LI 
918fd37a7SXin LI    This program is distributed in the hope that it will be useful,
1018fd37a7SXin LI    but WITHOUT ANY WARRANTY; without even the implied warranty of
1118fd37a7SXin LI    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1218fd37a7SXin LI    GNU General Public License for more details.
1318fd37a7SXin LI 
1418fd37a7SXin LI    You should have received a copy of the GNU General Public License
1518fd37a7SXin LI    along with this program; see the file COPYING.
1618fd37a7SXin LI    If not, write to the Free Software Foundation,
1718fd37a7SXin LI    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
1818fd37a7SXin LI 
1918fd37a7SXin LI /* Written by Paul Eggert <eggert@twinsun.com> */
2018fd37a7SXin LI 
2118fd37a7SXin LI #if HAVE_CONFIG_H
2218fd37a7SXin LI # include <config.h>
2318fd37a7SXin LI #endif
2418fd37a7SXin LI 
2518fd37a7SXin LI #include <sys/types.h>
2618fd37a7SXin LI #include <quotesys.h>
2718fd37a7SXin LI 
2818fd37a7SXin LI /* Place into QUOTED a quoted version of ARG suitable for `system'.
2918fd37a7SXin LI    Return the length of the resulting string (which is not null-terminated).
3018fd37a7SXin LI    If QUOTED is null, return the length without any side effects.  */
3118fd37a7SXin LI 
3218fd37a7SXin LI size_t
quote_system_arg(quoted,arg)3318fd37a7SXin LI quote_system_arg (quoted, arg)
3418fd37a7SXin LI      char *quoted;
3518fd37a7SXin LI      char const *arg;
3618fd37a7SXin LI {
3718fd37a7SXin LI   char const *a;
3818fd37a7SXin LI   size_t len = 0;
3918fd37a7SXin LI 
4018fd37a7SXin LI   /* Scan ARG, copying it to QUOTED if QUOTED is not null,
4118fd37a7SXin LI      looking for shell metacharacters.  */
4218fd37a7SXin LI 
4318fd37a7SXin LI   for (a = arg; ; a++)
4418fd37a7SXin LI     {
4518fd37a7SXin LI       char c = *a;
4618fd37a7SXin LI       switch (c)
4718fd37a7SXin LI 	{
4818fd37a7SXin LI 	case 0:
4918fd37a7SXin LI 	  /* ARG has no shell metacharacters.  */
5018fd37a7SXin LI 	  return len;
5118fd37a7SXin LI 
5218fd37a7SXin LI 	case '=':
5318fd37a7SXin LI 	  if (*arg == '-')
5418fd37a7SXin LI 	    break;
5518fd37a7SXin LI 	  /* Fall through.  */
5618fd37a7SXin LI 	case '\t': case '\n': case ' ':
5718fd37a7SXin LI 	case '!': case '"': case '#': case '$': case '%': case '&': case '\'':
5818fd37a7SXin LI 	case '(': case ')': case '*': case ';':
5918fd37a7SXin LI 	case '<': case '>': case '?': case '[': case '\\':
6018fd37a7SXin LI 	case '^': case '`': case '|': case '~':
6118fd37a7SXin LI 	  {
6218fd37a7SXin LI 	    /* ARG has a shell metacharacter.
6318fd37a7SXin LI 	       Start over, quoting it this time.  */
6418fd37a7SXin LI 
6518fd37a7SXin LI 	    len = 0;
6618fd37a7SXin LI 	    c = *arg++;
6718fd37a7SXin LI 
6818fd37a7SXin LI 	    /* If ARG is an option, quote just its argument.
6918fd37a7SXin LI 	       This is not necessary, but it looks nicer.  */
7018fd37a7SXin LI 	    if (c == '-'  &&  arg < a)
7118fd37a7SXin LI 	      {
7218fd37a7SXin LI 		c = *arg++;
7318fd37a7SXin LI 
7418fd37a7SXin LI 		if (quoted)
7518fd37a7SXin LI 		  {
7618fd37a7SXin LI 		    quoted[len] = '-';
7718fd37a7SXin LI 		    quoted[len + 1] = c;
7818fd37a7SXin LI 		  }
7918fd37a7SXin LI 		len += 2;
8018fd37a7SXin LI 
8118fd37a7SXin LI 		if (c == '-')
8218fd37a7SXin LI 		  while (arg < a)
8318fd37a7SXin LI 		    {
8418fd37a7SXin LI 		      c = *arg++;
8518fd37a7SXin LI 		      if (quoted)
8618fd37a7SXin LI 			quoted[len] = c;
8718fd37a7SXin LI 		      len++;
8818fd37a7SXin LI 		      if (c == '=')
8918fd37a7SXin LI 			break;
9018fd37a7SXin LI 		    }
9118fd37a7SXin LI 		c = *arg++;
9218fd37a7SXin LI 	      }
9318fd37a7SXin LI 
9418fd37a7SXin LI 	    if (quoted)
9518fd37a7SXin LI 	      quoted[len] = '\'';
9618fd37a7SXin LI 	    len++;
9718fd37a7SXin LI 
9818fd37a7SXin LI 	    for (;  c;  c = *arg++)
9918fd37a7SXin LI 	      {
10018fd37a7SXin LI 		if (c == '\'')
10118fd37a7SXin LI 		  {
10218fd37a7SXin LI 		    if (quoted)
10318fd37a7SXin LI 		      {
10418fd37a7SXin LI 			quoted[len] = '\'';
10518fd37a7SXin LI 			quoted[len + 1] = '\\';
10618fd37a7SXin LI 			quoted[len + 2] = '\'';
10718fd37a7SXin LI 		      }
10818fd37a7SXin LI 		    len += 3;
10918fd37a7SXin LI 		  }
11018fd37a7SXin LI 		if (quoted)
11118fd37a7SXin LI 		  quoted[len] = c;
11218fd37a7SXin LI 		len++;
11318fd37a7SXin LI 	      }
11418fd37a7SXin LI 
11518fd37a7SXin LI 	    if (quoted)
11618fd37a7SXin LI 	      quoted[len] = '\'';
11718fd37a7SXin LI 	    return len + 1;
11818fd37a7SXin LI 	  }
11918fd37a7SXin LI 	}
12018fd37a7SXin LI 
12118fd37a7SXin LI       if (quoted)
12218fd37a7SXin LI 	quoted[len] = c;
12318fd37a7SXin LI       len++;
12418fd37a7SXin LI     }
12518fd37a7SXin LI }
126