4 /* Micro helper library: shell escaping functions */
10 #define mhl_shell_escape_toesc(x) \
11 (((x)==' ')||((x)=='!')||((x)=='#')||((x)=='$')||((x)=='%')|| \
12 ((x)=='(')||((x)==')')||((x)=='\'')||((x)=='&')||((x)=='~')|| \
13 ((x)=='{')||((x)=='}')||((x)=='[')||((x)==']')||((x)=='`')|| \
14 ((x)=='?')||((x)=='|')||((x)=='<')||((x)=='>')||((x)==';')|| \
15 ((x)=='*')||((x)=='\\')||((x)=='"'))
17 #define mhl_shell_escape_nottoesc(x) \
18 (((x)!=0) && (!mhl_shell_escape_toesc((x))))
20 /* type for escaped string - just for a bit more type safety ;-p */
21 typedef struct { char* s
; } SHELL_ESCAPED_STR
;
23 /** To be compatible with the general posix command lines we have to escape
24 strings for the command line
26 /params const char * in
29 return escaped string (later need to free)
31 static inline SHELL_ESCAPED_STR
mhl_shell_escape_dup(const char* src
)
33 if ((src
==NULL
)||(!(*src
)))
34 return (SHELL_ESCAPED_STR
){ .s
= strdup("") };
36 char* buffer
= calloc(1, strlen(src
)*2+2);
39 /* look for the first char to escape */
43 /* copy over all chars not to escape */
44 while ((c
=(*src
)) && mhl_shell_escape_nottoesc(c
))
51 /* at this point we either have an \0 or an char to escape */
53 return (SHELL_ESCAPED_STR
){ .s
= buffer
};
63 /** Unescape paths or other strings for e.g the internal cd
64 shell-unescape within a given buffer (writing to it!)
66 /params const char * src
69 return unescaped string
71 static inline char* mhl_shell_unescape_buf(char* text
)
76 /* look for the first \ - that's quick skipover if there's nothing to escape */
78 while ((*readptr
) && ((*readptr
)!='\\')) readptr
++;
79 if (!(*readptr
)) return text
;
81 /* if we're here, we're standing on the first '\' */
82 char* writeptr
= readptr
;
84 while ((c
= *readptr
))
89 switch ((c
= *readptr
))
91 case 'n': (*writeptr
) = '\n'; writeptr
++; break;
92 case 'r': (*writeptr
) = '\r'; writeptr
++; break;
93 case 't': (*writeptr
) = '\t'; writeptr
++; break;
115 case '\0': /* end of string! malformed escape string */
118 (*writeptr
) = c
; writeptr
++; break;
121 else /* got a normal character */
123 (*writeptr
) = *readptr
;
134 /** Check if char in pointer contain escape'd chars
136 /params const char * in
139 return TRUE if string contain escaped chars
140 otherwise return FALSE
143 mhl_shell_is_char_escaped ( const char *in
)
145 if (in
== NULL
|| !*in
|| in
[0] != '\\')
147 if (mhl_shell_escape_toesc(in
[1]))