1 /******************************************************************************
2 * This file is Copyright 1992 by Philip G. Richards.  All Rights Reserved.
3 * See the file README that came with this distribution for permissions on
4 * code usage, copying, and distribution.  It comes with absolutely no warranty.
5 ******************************************************************************/
6 
7 #include "client.h"
8 #include "main.h"
9 #include "parse.h"
10 #include <ctype.h>
11 #include <stdlib.h>
12 
13 extern char **environ;
14 
15 #define ISMAGIC 0x80
16 #define ISPROT  0x40
17 
18 void
freemyargs(int argc,char ** argv)19 freemyargs(int argc, char **argv)
20 {
21     int i;
22 
23     if (argv == NULL)
24 	return;
25 
26 #ifdef MALLOCDEBUG
27   {
28     int oldlvl = malloc_debug(0);
29 #endif
30 
31     for (i = 0; i < argc && argv[i]; i++)
32 	(void)free(argv[i]);
33 
34 #ifdef MALLOCDEBUG
35     (void)malloc_debug(oldlvl);
36     if (!malloc_verify())
37     {
38         ffprintf(STDERR, "??freemyargs() has screwed up malloc()\n");
39 	abort();
40     }
41   }
42 #endif
43 }
44 
45 /**********************************************************************
46 * create an argument list from a command line; the original line is
47 * undamaged by this function, and the values returned in the pargv
48 * are all malloc'd and should be free'd with freemyargs()
49 **********************************************************************/
50 int
parsemyargs(char * comm,char *** pargv,unsigned int * pmaxargc,int gargc,char ** gargv)51 parsemyargs(char *comm, char ***pargv, unsigned int *pmaxargc, int gargc, char **gargv)
52 {
53     int j, rdsp, inquotes;
54     unsigned int argc,i;
55     char *buff, *magic;
56 
57     if ((buff = strdup(comm)) == (char*)0)
58     {
59 	ffprintf(STDERR, "??out of memory in parsemyargs()\n");
60 	return 0;
61     }
62 
63     /* count words -- ok, I know this can be done better, but I'm lazy */
64     for (i = 0, argc = 0, rdsp = 1, inquotes = 0; buff[i]; i++)
65     {
66 	/* buff[i] != 0 => next test can only succeed if inquotes != 0 */
67 	if (inquotes == '\\' || buff[i] == inquotes)
68 	{
69 	    inquotes = 0;
70 	    rdsp = 0;
71 	}
72 	else if (inquotes)
73 	{
74 	    ;
75 	}
76 	else if (isspace(buff[i]))
77 	{
78 	    if (!rdsp)
79 		buff[i] = '\0';
80 	    while (isspace(buff[i+1]))
81 		i++;
82 	    rdsp = 1;
83 	}
84 	else
85 	{
86 	    if (rdsp)
87 	    {
88 		/* check if we are starting a comment */
89 		if (buff[i] == '#')
90 		    break;
91 
92 		/***********************************************************
93 		* if we have a single character command, pretend we have
94 		* spaces after it, even if we don't (true for first word only)
95 		***********************************************************/
96 		rdsp = (argc == 0)
97 		       && (buff[i] == '!' || buff[i] == '@');
98 
99 		argc++;
100 
101 		/***********************************************************
102 		* if the first character in the word is an unquoted `|', then
103 		* consider that as the beginning of the final word (which
104 		* will take the rest of the line)
105 		***********************************************************/
106 		if (buff[i] == '|')
107 		    break;
108 	    }
109 
110 	    if (buff[i] == '"' || buff[i] == '\'' || buff[i] == '\\')
111 		inquotes = buff[i];
112 	}
113     }
114 
115     if (inquotes)
116     {
117 	ffprintf(STDERR, "?unclosed quotes\n");
118 	(void)free(buff);
119 	return 0;
120     }
121 
122     if (argc > *pmaxargc - 1)
123     {
124 	*pmaxargc = argc + 1;
125 
126 	if (*pargv == (char**)0)
127 	    *pargv = (char**)malloc(*pmaxargc * sizeof(char*));
128 	else
129 	    *pargv = (char**)realloc((char*)*pargv, *pmaxargc * sizeof(char*));
130 
131 	if (*pargv == (char**)0)
132 	{
133 	    ffprintf(STDERR, "??out of memory in parsemyargs()\n");
134 	    *pmaxargc = 0;
135 	    return 0;
136 	}
137     }
138 
139     if ((magic = strdup(comm)) == (char*)0)
140     {
141 	ffprintf(STDERR, "??out of memory in parsemyargs() for magic\n");
142 	(void)free(buff);
143 	*pmaxargc = 0;
144 	return 0;
145     }
146 
147     /* set up *pargv[] */
148     for (i = 0, j = 0; i < argc; i++, j++)
149     {
150 	int k, d;
151 
152 	while (isspace(buff[j]))
153 	    j++;
154 
155 	if (i == 0 && (buff[j] == '!' || buff[j] == '@'))
156 	    switch (buff[j])
157 	    {
158 	      case '!':
159 		(*pargv)[i] = "shell";
160 		break;
161 	      case '@':
162 		(*pargv)[i] = BUILTIN;
163 		break;
164 	      default:
165 		(*pargv)[i] = "error";
166 		break;
167 	    }
168 	else if (i == argc - 1 && buff[j] == '|')
169 	    (*pargv)[i] = buff + j;
170 	else
171 	{
172 	    (*pargv)[i] = buff + j;
173 	    k = j;
174 	    while (buff[j])
175 		j++;
176 
177 	    /***********************************************************
178 	    * at this point, (*pargv)[i] to buff+j is the word, still with
179 	    * quote characters in it; at this point we remove the quotes
180 	    * we mark magic characters (non-8bit clean) with a 0x80 top
181 	    * bit; outside of quotes, ?*{[$\ are all magic; inside `"'s
182 	    * just $\ are magic; inside "'"s nothing is magic; a magic \
183 	    * turns off the magic ability of the next character
184 	    ***********************************************************/
185 	    for (inquotes = 0, d = k; k <= j; k++)
186 		if ((inquotes & 0x7f) == '\\')
187 		{
188 		    inquotes = (inquotes & ISMAGIC)? '"': 0;
189 		    buff[d]    = buff[k];
190 		    magic[d++] = ISPROT;
191 		}
192 		else if (inquotes)
193 		{
194 		    if (inquotes == '"' && buff[k] == '\\')
195 			inquotes |= ISMAGIC;
196 		    else
197 		    {
198 			if (buff[k] != inquotes)
199 			{
200 			    buff[d]    = buff[k];
201 			    magic[d++] = (inquotes != '\''
202 					  && buff[k] == '$')? ISMAGIC: 0;
203 			}
204 			else
205 			    inquotes = 0;
206 		    }
207 		}
208 		else if (buff[k] == '"' || buff[k] == '\'' || buff[k] == '\\')
209 		    inquotes = buff[k];
210 		else
211 		{
212 		    buff[d]    = buff[k];
213 		    magic[d++] = (inquotes != '\'' &&
214 				    (buff[k] == '?' || buff[k] == '*' ||
215 				     buff[k] == '{' || buff[k] == '[' ||
216 				     buff[k] == '$'))? ISMAGIC: 0;
217 		}
218 	}
219     }
220 
221     for (i = 0; i < argc; i++)
222 	(*pargv)[i] = strdup((*pargv)[i]);
223 
224     (*pargv)[argc] = (char*)0;
225     (void)free(buff);
226     (void)free(magic);
227 
228     return argc;
229 }
230