2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1997-1998 University of Maryland at College Park
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of U.M. not be used in advertising or
11 * publicity pertaining to distribution of the software without specific,
12 * written prior permission. U.M. makes no representations about the
13 * suitability of this software for any purpose. It is provided "as is"
14 * without express or implied warranty.
16 * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
18 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * Authors: the Amanda Development Team. Its members are listed in a
24 * file named AUTHORS, in the root directory of this distribution.
27 * $Id: token.c,v 1.32 2006/07/19 17:41:15 martinea Exp $
29 * token bashing routines
33 ** The quoting method used here was selected because it has the
34 ** property that quoting a string that doesn't contain funny
35 ** characters results in an unchanged string and it was easy to code.
36 ** There are probably other algorithms that are just as effective.
43 /* Split a string up into tokens.
44 ** There is exactly one separator character between tokens.
45 ** XXX Won't work too well if separator is '\'!
47 ** Inspired by awk and a routine called splitter() that I snarfed from
48 ** the net ages ago (original author long forgotten).
52 char * str, /* String to split */
53 char ** token, /* Array of token pointers */
54 int toklen, /* Size of token[] */
55 char * sep) /* Token separators - usually " " */
57 register char *pi, *po;
60 static char *buf = (char *)0; /* XXX - static buffer */
63 assert(str && token && toklen > 0 && sep);
67 for (fld = 1; fld < toklen; fld++) token[fld] = (char *)0;
71 if (*sep == '\0' || *str == '\0' || toklen == 1) return fld;
73 /* Calculate the length of the unquoted string. */
76 /* Allocate some space */
78 buf = newalloc(buf, len+1);
80 /* Copy it across and tokenise it */
85 for (pi = str; *pi && *pi != '\0'; pi++) {
86 if (*pi == '\n' && !in_quotes)
89 if (!in_quotes && strchr(sep, *pi)) {
92 * Advance to next field.
94 *po = '\0'; /* end of token */
95 if (fld+1 >= toklen) return fld; /* too many tokens */
96 token[++fld] = po + 1;
103 * Start or end of quote
104 * Emit quote in either case
106 in_quotes = !in_quotes;
107 } else if (in_quotes && *pi == '\\' && (*(pi + 1) == '"')) {
110 * emit '/' - default will pick up '"'
114 *po++ = *pi; /* Emit character */
118 assert(po == buf + len); /* Just checking! */
124 ** Quote all the funny characters in one token.
125 ** - squotef - formatted string with space separator
126 ** - quotef - formatted string with specified separators
127 ** - squote - fixed string with space separator
128 ** - quote - fixed strings with specified separators
130 printf_arglist_function(char *squotef, char *, format)
135 /* Format the token */
137 arglist_start(argp, format);
138 g_vsnprintf(linebuf, SIZEOF(linebuf), format, argp);
141 return quote(" ", linebuf);
144 printf_arglist_function1(char *quotef, char *, sep, char *, format)
149 /* Format the token */
151 arglist_start(argp, format);
152 g_vsnprintf(linebuf, SIZEOF(linebuf), format, argp);
155 return quote(sep, linebuf);
159 char * str) /* the string to quote */
161 return quote(" ", str);
166 char * sepchr, /* separators that also need quoting */
167 char * str) /* the string to quote */
169 register char *pi, *po;
172 int sep, need_quotes;
174 /* Calculate the length of the quoted token. */
178 for (pi = str; *pi; pi++) {
179 if (*pi < ' ' || *pi > '~')
181 else if (*pi == '\\' || *pi == '"')
183 else if (*sepchr && strchr(sepchr, *pi)) {
191 need_quotes = (sep != 0);
193 if (need_quotes) len = len + 2;
195 /* Allocate some space */
197 buf = alloc(len+1); /* trailing null */
203 if (need_quotes) *po++ = '"';
205 for (pi = str; *pi; pi++) {
206 if (*pi < ' ' || *pi > '~') {
208 *po++ = (char)(((*pi >> 6) & 07) + '0');
209 *po++ = (char)(((*pi >> 3) & 07) + '0');
210 *po++ = (char)(((*pi ) & 07) + '0');
212 else if (*pi == '\\' || *pi == '"') {
219 if (need_quotes) *po++ = '"';
223 assert(po == (buf + len)); /* Just checking! */
228 /* Quote a string so that it can be used as a regular expression */
231 char * str) /* the string to quote */
237 /* Calculate the length of the quoted token. */
240 for (pi = str; *pi; pi++) {
242 /* regular expression meta-characters: */
257 case '}' /* no colon */
267 /* Allocate some space */
269 buf = alloc(len+1); /* trailing null */
275 for (pi = str; *pi; pi++) {
289 assert(po == (buf + len)); /* Just checking! */
295 /* Quote a string so that it can be safely passed to a shell */
298 char * str) /* the string to quote */
304 /* Calculate the length of the quoted token. */
307 for (pi = str; *pi; pi++) {
309 /* shell meta-characters: */
333 case '}' /* no colon */
343 /* Allocate some space */
345 buf = alloc(len+1); /* trailing null */
351 for (pi = str; *pi; pi++) {
365 assert(po == (buf + len)); /* Just checking! */
378 while(table->word != (char *)0) {
379 if (*table->word == *str && strcmp(table->word, str) == 0) {
388 /* Reverse table lookup.
392 /*@keep@*/ table_t * table,
395 while(table->word != (char *)0) {
396 if (table->value == val) {
419 * Configure program for internationalization:
420 * 1) Only set the message locale for now.
421 * 2) Set textdomain for all amanda related programs to "amanda"
422 * We don't want to be forced to support dozens of message catalogs
424 setlocale(LC_MESSAGES, "C");
425 textdomain("amanda");
429 setlocale(LC_ALL, "C");
431 /* shut up compiler */
435 set_pname("token test");
439 /* Don't die when child closes pipe */
440 signal(SIGPIPE, SIG_IGN);
442 erroutput_type = ERR_INTERACTIVE;
444 g_printf(_("Testing split() with \" \" token separator\n"));
446 g_printf(_("Input string: "));
448 if ((str = agets(stdin)) == NULL) {
452 r = split(str, t, 20, " ");
453 g_printf(plural(_("%d token:\n"), _("%d token:\n"), r), r);
454 for (i=0; i <= r; i++)
455 g_printf("tok[%d] = \"%s\"\n", i, t[i]);
460 g_printf(_("Testing quote()\n"));
462 g_printf(_("Input string: "));
464 if ((str = agets(stdin)) == NULL) {
469 g_printf(_("Quoted = \"%s\"\n"), sr);
470 strncpy(str,sr,SIZEOF(str)-1);
471 str[SIZEOF(str)-1] = '\0';
472 r = split(str, t, 20, " ");
474 g_printf("split()=%d!\n", r);
475 g_printf(_("Unquoted = \"%s\"\n"), t[1]);