fixed canonicalize_pathname() breakage: fixed str_move() function (memmove semantics...
[midnight-commander.git] / mhl / escape.h
blobefc0aac52caf0172d5408fd4e2fbac2e2dd30cee
1 #ifndef __MHL_SHELL_ESCAPE_H
2 #define __MHL_SHELL_ESCAPE_H
4 /* Micro helper library: shell escaping functions */
6 #include <string.h>
7 #include <stdlib.h>
9 #include <mhl/types.h>
11 #define mhl_shell_escape_toesc(x) \
12 (((x)==' ')||((x)=='!')||((x)=='#')||((x)=='$')||((x)=='%')|| \
13 ((x)=='(')||((x)==')')||((x)=='\'')||((x)=='&')||((x)=='~')|| \
14 ((x)=='{')||((x)=='}')||((x)=='[')||((x)==']')||((x)=='`')|| \
15 ((x)=='?')||((x)=='|')||((x)=='<')||((x)=='>')||((x)==';')|| \
16 ((x)=='*')||((x)=='\\')||((x)=='"'))
18 #define mhl_shell_escape_nottoesc(x) \
19 (((x)!=0) && (!mhl_shell_escape_toesc((x))))
21 /* type for escaped string - just for a bit more type safety ;-p */
22 typedef struct { char* s; } SHELL_ESCAPED_STR;
24 /** To be compatible with the general posix command lines we have to escape
25 strings for the command line
27 /params const char * in
28 string for escaping
29 /returns
30 return escaped string (later need to free)
32 static inline SHELL_ESCAPED_STR mhl_shell_escape_dup(const char* src)
34 if ((src==NULL)||(!(*src)))
35 return (SHELL_ESCAPED_STR){ .s = strdup("") };
37 char* buffer = calloc(1, strlen(src)*2+2);
38 char* ptr = buffer;
40 /* look for the first char to escape */
41 while (1)
43 char c;
44 /* copy over all chars not to escape */
45 while ((c=(*src)) && mhl_shell_escape_nottoesc(c))
47 *ptr = c;
48 ptr++;
49 src++;
52 /* at this point we either have an \0 or an char to escape */
53 if (!c)
54 return (SHELL_ESCAPED_STR){ .s = buffer };
56 *ptr = '\\';
57 ptr++;
58 *ptr = c;
59 ptr++;
60 src++;
64 /** Unescape paths or other strings for e.g the internal cd
65 shell-unescape within a given buffer (writing to it!)
67 /params const char * in
68 string for unescaping
69 /returns
70 return unescaped string
72 static inline char* mhl_shell_unescape_buf(char* text)
74 if (!text)
75 return NULL;
77 /* look for the first \ - that's quick skipover if there's nothing to escape */
78 char* readptr = text;
79 while ((*readptr) && ((*readptr)!='\\')) readptr++;
80 if (!(*readptr)) return text;
82 /* if we're here, we're standing on the first '\' */
83 char* writeptr = readptr;
84 char c;
85 while ((c = *readptr))
87 if (c=='\\')
89 readptr++;
90 switch ((c = *readptr))
92 case 'n': (*writeptr) = '\n'; writeptr++; break;
93 case 'r': (*writeptr) = '\r'; writeptr++; break;
94 case 't': (*writeptr) = '\t'; writeptr++; break;
96 case ' ':
97 case '\\':
98 case '#':
99 case '$':
100 case '%':
101 case '(':
102 case ')':
103 case '[':
104 case ']':
105 case '{':
106 case '}':
107 case '<':
108 case '>':
109 case '!':
110 case '*':
111 case '?':
112 case '~':
113 case '`':
114 case '"':
115 case ';':
116 default:
117 (*writeptr) = c; writeptr++; break;
120 else /* got a normal character */
122 (*writeptr) = *readptr;
123 writeptr++;
125 readptr++;
127 *writeptr = 0;
129 return text;
132 /** Check if char in pointer contain escape'd chars
134 /params const char * in
135 string for checking
136 /returns
137 return TRUE if string contain escaped chars
138 otherwise return FALSE
140 static inline bool
141 mhl_shell_is_char_escaped ( const char *in )
143 if (in == NULL || !*in || in[0] != '\\')
144 return false;
145 if (mhl_shell_escape_toesc(in[1]))
146 return true;
147 return false;
150 #endif