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