2 * Until FreeBSD gets their act together;
3 * http://www.mail-archive.com/freebsd-hackers@freebsd.org/msg69469.html
15 #ifdef HAVE_BSD_STRING_H
16 #include <bsd/string.h>
33 static DFA mtable
[9][6] = {
34 {{3, 1}, {0, 0}, {4, 0}, {1, 0}, {8, 0}, {6, 0}},
35 {{1, 1}, {1, 1}, {2, 0}, {3, 0}, {5, 0}, {1, 1}},
36 {{1, 1}, {1, 1}, {1, 1}, {1, 1}, {5, 0}, {1, 1}},
37 {{3, 1}, {5, 0}, {4, 0}, {1, 0}, {5, 0}, {6, 0}},
38 {{3, 1}, {3, 1}, {3, 1}, {3, 1}, {5, 0}, {3, 1}},
39 {{-1, -1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, /* final state */
40 {{6, 1}, {6, 1}, {7, 0}, {6, 1}, {5, 0}, {3, 0}},
41 {{6, 1}, {6, 1}, {6, 1}, {6, 1}, {5, 0}, {6, 1}},
42 {{-1, -1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, /* final state */
45 char *wtokennext(char *word
, char **next
)
51 t
= ret
= wmalloc(strlen(word
) + 1);
58 else if (*ptr
== '\\')
62 else if (*ptr
== '\'')
64 else if (*ptr
== ' ' || *ptr
== '\t')
69 if (mtable
[state
][ctype
].output
) {
74 state
= mtable
[state
][ctype
].nstate
;
76 if (mtable
[state
][0].output
< 0) {
94 /* separate a string in tokens, taking " and ' into account */
95 void wtokensplit(char *command
, char ***argv
, int *argc
)
103 token
= wtokennext(line
, &line
);
106 *argv
= wmalloc(sizeof(**argv
));
108 *argv
= wrealloc(*argv
, (count
+ 1) * sizeof(**argv
));
109 (*argv
)[count
++] = token
;
111 } while (token
!= NULL
&& line
!= NULL
);
116 char *wtokenjoin(char **list
, int count
)
119 char *flat_string
, *wspace
;
122 for (i
= 0; i
< count
; i
++) {
123 if (list
[i
] != NULL
&& list
[i
][0] != 0) {
124 j
+= strlen(list
[i
]);
125 if (strpbrk(list
[i
], " \t"))
130 flat_string
= wmalloc(j
+ count
+ 1);
132 for (i
= 0; i
< count
; i
++) {
133 if (list
[i
] != NULL
&& list
[i
][0] != 0) {
135 wstrlcat(flat_string
, " ", j
+ count
+ 1) >= j
+ count
+ 1)
138 wspace
= strpbrk(list
[i
], " \t");
141 wstrlcat(flat_string
, "\"", j
+ count
+ 1) >= j
+ count
+ 1)
144 if (wstrlcat(flat_string
, list
[i
], j
+ count
+ 1) >= j
+ count
+ 1)
148 wstrlcat(flat_string
, "\"", j
+ count
+ 1) >= j
+ count
+ 1)
161 void wtokenfree(char **tokens
, int count
)
164 wfree(tokens
[count
]);
168 char *wtrimspace(const char *s
)
175 while (isspace(*s
) && *s
)
177 t
= s
+ strlen(s
) - 1;
178 while (t
> s
&& isspace(*t
))
181 return wstrndup(s
, t
- s
+ 1);
184 char *wstrdup(const char *str
)
188 return strcpy(wmalloc(strlen(str
) + 1), str
);
191 char *wstrndup(const char *str
, size_t len
)
197 len
= WMIN(len
, strlen(str
));
198 copy
= strncpy(wmalloc(len
+ 1), str
, len
);
204 char *wstrconcat(const char *str1
, const char *str2
)
210 return wstrdup(str2
);
211 else if (str1
&& !str2
)
212 return wstrdup(str1
);
213 else if (!str1
&& !str2
)
216 slen
= strlen(str1
) + strlen(str2
) + 1;
218 if (wstrlcpy(str
, str1
, slen
) >= slen
||
219 wstrlcat(str
, str2
, slen
) >= slen
) {
227 char *wstrappend(char *dst
, const char *src
)
231 if (!src
|| *src
== 0)
236 slen
= strlen(dst
) + strlen(src
) + 1;
237 dst
= wrealloc(dst
, slen
);
246 wstrlcat(char *dst
, const char *src
, size_t siz
)
248 return strlcat(dst
, src
, siz
);
251 /* $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */
254 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
256 * Permission to use, copy, modify, and distribute this software for any
257 * purpose with or without fee is hereby granted, provided that the above
258 * copyright notice and this permission notice appear in all copies.
260 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
261 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
262 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
263 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
264 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
265 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
266 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
270 * Appends src to string dst of size siz (unlike strncat, siz is the
271 * full size of dst, not space left). At most siz-1 characters
272 * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
273 * Returns strlen(src) + MIN(siz, strlen(initial dst)).
274 * If retval >= siz, truncation occurred.
277 wstrlcat(char *dst
, const char *src
, size_t siz
)
284 /* Find the end of dst and adjust bytes left but don't go past end */
285 while (n
-- != 0 && *d
!= '\0')
291 return(dlen
+ strlen(s
));
301 return(dlen
+ (s
- src
)); /* count does not include NUL */
303 #endif /* HAVE_STRLCAT */
307 wstrlcpy(char *dst
, const char *src
, size_t siz
)
309 return strlcpy(dst
, src
, siz
);
313 /* $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ */
316 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
318 * Permission to use, copy, modify, and distribute this software for any
319 * purpose with or without fee is hereby granted, provided that the above
320 * copyright notice and this permission notice appear in all copies.
322 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
323 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
324 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
325 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
326 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
327 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
328 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
332 * Copy src to string dst of size siz. At most siz-1 characters
333 * will be copied. Always NUL terminates (unless siz == 0).
334 * Returns strlen(src); if retval >= siz, truncation occurred.
337 wstrlcpy(char *dst
, const char *src
, size_t siz
)
343 /* Copy as many bytes as will fit */
346 if ((*d
++ = *s
++) == '\0')
351 /* Not enough room in dst, add NUL and traverse rest of src */
354 *d
= '\0'; /* NUL-terminate dst */
359 return(s
- src
- 1); /* count does not include NUL */
361 #endif /* HAVE_STRLCPY */
363 /* transform `s' so that the result is safe to pass to the shell as an argument.
364 * returns a newly allocated string.
365 * with very heavy inspirations from NetBSD's shquote(3).
367 char *wshellquote(const char *s
)
369 char *p
, *r
, *last
, *ret
;
376 needs_quoting
= !*s
; /* the empty string does need quoting */
378 /* do not quote if consists only of the following characters */
379 for (p
= (char *)s
; *p
&& !needs_quoting
; p
++) {
380 needs_quoting
= !(isalnum(*p
) || (*p
== '+') || (*p
== '/') ||
381 (*p
== '.') || (*p
== ',') || (*p
== '-'));
387 for (slen
= 0, p
= (char *)s
; *p
; p
++) /* count space needed (worst case) */
388 slen
+= *p
== '\'' ? 4 : 1; /* every single ' becomes ''\' */
390 slen
+= 2 /* leading + trailing "'" */ + 1 /* NULL */;
392 ret
= r
= wmalloc(slen
);
396 if (*p
!= '\'') /* if string doesn't already begin with "'" */
397 *r
++ ='\''; /* start putting it in quotes */
401 if (*p
== '\'') { /* turn each ' into ''\' */
402 if (p
!= s
) /* except if it's the first ', in which case */
403 *r
++ = '\''; /* only escape it */
406 while (*++p
&& *p
== '\'') { /* keep turning each consecutive 's into \' */
410 if (*p
) /* if more input follows, terminate */
411 *r
++ = '\''; /* what we have so far */
417 if (*last
!= '\'') /* if the last one isn't already a ' */
418 *r
++ = '\''; /* terminate the whole shebang */
422 return ret
; /* technically, we lose (but not leak) a couple of */
423 /* bytes (twice the number of consecutive 's in the */
424 /* input or so), but since these are relatively rare */
425 /* and short-lived strings, not sure if a trip to */
426 /* wstrdup+wfree worths the gain. */