xref: /titanic_52/usr/src/lib/krb5/ss/parse.c (revision b9e93c10c0a2a4bb069d38bb311021a9478c4711)
1 /*
2  * Copyright 1987, 1988 by MIT Student Information Processing Board
3  *
4  * For copyright info, see copyright.h.
5  */
6 
7 /*
8  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
9  * Use is subject to license terms.
10  */
11 
12 #include "ss_internal.h"
13 #include "copyright.h"
14 #include <errno.h>
15 
16 enum parse_mode { WHITESPACE, TOKEN, QUOTED_STRING };
17 
18 
19 /*
20  * Solaris Kerberos:
21  * ss_parse has been modified slightly from the original in two ways.
22  * 1) A new parameter "quiet" has been added which is used to silence
23  *    error or warning messages.
24  * 2) ss_parse now returns an error status instead of argv - this is to
25  *    allow an error to be distinguished from no tokens when parsing an empty
26  *    string.
27  * Both of these changes allow ss_parse to be used during tab-completion.
28  */
29 
30 /*
31  * parse(line_ptr, argc_ptr)
32  *
33  * Function:
34  *      Parses line, dividing at whitespace, into tokens, returns
35  *      the "argc" and "argv" values.
36  * Arguments:
37  *      line_ptr (char *)
38  *              Pointer to text string to be parsed.
39  *      argc_ptr (int *)
40  *              Where to put the "argc" (number of tokens) value.
41  *      argv_ptr (char ***)
42  *              Where to put the series of pointers to parsed tokens.
43  * Returns:
44  *      error (0 - success, non-zero on failure)
45  */
46 
47 #define NEW_ARGV(old,n) (char **)realloc((char *)old,\
48 					 (unsigned)(n+2)*sizeof(char*))
49 
50 int ss_parse (sci_idx, line_ptr, argc_ptr, argv_ptr, quiet)
51     int sci_idx;
52     register char *line_ptr;
53     int *argc_ptr;
54     char ***argv_ptr;
55     int quiet;
56 {
57     register char **argv, *cp;
58     register int argc;
59     register enum parse_mode parse_mode;
60 
61     argv = (char **) malloc (sizeof(char *));
62     if (argv == (char **)NULL) {
63 	if (!quiet)
64 	    ss_error(sci_idx, errno, "Can't allocate storage");
65 	*argc_ptr = 0;
66 	*argv_ptr = argv;
67 	return(ENOMEM);
68     }
69     *argv = (char *)NULL;
70 
71     argc = 0;
72 
73     parse_mode = WHITESPACE;	/* flushing whitespace */
74     cp = line_ptr;		/* cp is for output */
75     while (1) {
76 #ifdef DEBUG
77 	{
78 	    printf ("character `%c', mode %d\n", *line_ptr, parse_mode);
79 	}
80 #endif
81 	while (parse_mode == WHITESPACE) {
82 	    if (*line_ptr == '\0')
83 		goto end_of_line;
84 	    if (*line_ptr == ' ' || *line_ptr == '\t') {
85 		line_ptr++;
86 		continue;
87 	    }
88 	    if (*line_ptr == '"') {
89 		/* go to quoted-string mode */
90 		parse_mode = QUOTED_STRING;
91 		cp = line_ptr++;
92 		argv = NEW_ARGV (argv, argc);
93 		argv[argc++] = cp;
94 		argv[argc] = NULL;
95 	    }
96 	    else {
97 		/* random-token mode */
98 		parse_mode = TOKEN;
99 		cp = line_ptr;
100 		argv = NEW_ARGV (argv, argc);
101 		argv[argc++] = line_ptr;
102 		argv[argc] = NULL;
103 	    }
104 	}
105 	while (parse_mode == TOKEN) {
106 	    if (*line_ptr == '\0') {
107 		*cp++ = '\0';
108 		goto end_of_line;
109 	    }
110 	    else if (*line_ptr == ' ' || *line_ptr == '\t') {
111 		*cp++ = '\0';
112 		line_ptr++;
113 		parse_mode = WHITESPACE;
114 	    }
115 	    else if (*line_ptr == '"') {
116 		line_ptr++;
117 		parse_mode = QUOTED_STRING;
118 	    }
119 	    else {
120 		*cp++ = *line_ptr++;
121 	    }
122 	}
123 	while (parse_mode == QUOTED_STRING) {
124 	    if (*line_ptr == '\0') {
125 		if (!quiet)
126 		    ss_error (sci_idx, 0,
127 			"Unbalanced quotes in command line");
128 		free (argv);
129 		*argc_ptr = 0;
130 		*argv_ptr = NULL;
131 		return (-1);
132 	    }
133 	    else if (*line_ptr == '"') {
134 		if (*++line_ptr == '"') {
135 		    *cp++ = '"';
136 		    line_ptr++;
137 		}
138 		else {
139 		    parse_mode = TOKEN;
140 		}
141 	    }
142 	    else {
143 		*cp++ = *line_ptr++;
144 	    }
145 	}
146     }
147 end_of_line:
148     *argc_ptr = argc;
149 #ifdef DEBUG
150     {
151 	int i;
152 	printf ("argc = %d\n", argc);
153 	for (i = 0; i <= argc; i++)
154 	    printf ("\targv[%2d] = `%s'\n", i,
155 		    argv[i] ? argv[i] : "<NULL>");
156     }
157 #endif
158     *argv_ptr = argv;
159     return(0);
160 }
161