xref: /onnv-gate/usr/src/lib/krb5/ss/parse.c (revision 8093:d2fc11f7c4e7)
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  
ss_parse(sci_idx,line_ptr,argc_ptr,argv_ptr,quiet)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