7 F_ALLEXPORT
, // -a or -o allexport
8 F_ERREXIT
, // -e or -o errexit
9 F_IGNOREEOF
, // -o ignoreeof
10 F_MONITOR
, // -m or -o monitor
11 F_NOCLOBBER
, // -C or -o noclobb
12 F_NOGLOB
, // -f or -o noglob
14 F_NOEXEC
, // -n or -o noexec
16 F_NOTIFY
, // -b or -o notify
17 F_NOUNSET
, // -u or -o nounset
18 F_VERBOSE
, // -v or -o verbose
20 F_XTRACE
, // -x or -o xtrace
22 F_D_ALLEXPORT
, // +a or +o allexport
23 F_D_ERREXIT
, // +e or +o errexit
24 F_D_IGNOREEOF
, // +o ignoreeof
25 F_D_MONITOR
, // +m or +o monitor
26 F_D_NOCLOBBER
, // +C or +o noclobber
27 F_D_NOGLOB
, // +f or +o noglob
29 F_D_NOEXEC
, // +n or +o noexec
30 F_D_NOLOG
, // +o nolog
31 F_D_NOTIFY
, // +b or +o notify
32 F_D_NOUNSET
, // +u or +o nounset
33 F_D_VERBOSE
, // +v or +o verbose
35 F_D_XTRACE
, // +x or +o xtrace
46 struct FlagList_
*next
;
49 typedef struct FlagList_ FlagList
;
51 const char *progname
= "sh";
53 static FlagList
*cons_flag(Flag f
, FlagList
*l
);
54 static FlagList
*parse_argv();
55 static void usage(void);
57 /* used to build flag list */
58 FlagList
*cons_flag(Flag f
, FlagList
*l
)
60 FlagList
*node
= malloc(sizeof(FlagList
));
68 /* mostly for debugging at this point */
69 void print_flaglist(FlagList
*l
)
74 printf("allexport\n");
80 printf("ignoreeof\n");
86 printf("noclobber\n");
116 printf("d_allexport\n");
119 printf("d_errexit\n");
122 printf("d_ignoreeof\n");
125 printf("d_monitor\n");
128 printf("d_noclobber\n");
131 printf("d_noglob\n");
134 printf("d_remember\n");
137 printf("d_noexec\n");
143 printf("d_notify\n");
146 printf("d_nounset\n");
149 printf("d_verbose\n");
155 printf("d_xtrace\n");
161 printf("cmdstdin\n");
164 printf("interactive\n");
171 /* this function modifies the argc and argv so that when
172 * it returns, argv points to the 1st non-option and
173 * argc is the _actual_ count. We also assume that the
174 * caller decremented the argc and pointed argv to its
175 * second field before calling */
176 FlagList
*parse_argv(int *argc
, char *argv
[])
182 FlagList
*list
= NULL
;
189 /* if not a flag, stop parsing flags */
190 if(str
[0] != '-' && str
[0] != '+')
193 /* if its a single '-', discard and stop parsing */
194 if(str
[0] == '-' && len
== 1) {
200 /* if we get to this point, we can start analyzing
201 the string. First, we want to know if we enable
203 enable
= str
[0] == '-';
205 /* the -o <option> case is a little more complicated,
206 so let's treat it first */
208 /* we are unforgiving on bad input format */
210 fprintf(stderr
,"ERROR: unrecognized flag: %s\n", str
);
215 /* we need an option string */
217 fprintf(stderr
,"ERROR: option string needed for %s\n", str
);
221 /* now we are sure we have one, let's jump to it */
226 /* let's try to identify it. hold tight, it's gonna be ugly */
227 if(strcmp(str
, "allexport") == 0) {
228 flag
= enable
? F_ALLEXPORT
: F_D_ALLEXPORT
;
229 } else if(strcmp(str
, "errexit") == 0) {
230 flag
= enable
? F_ERREXIT
: F_D_ERREXIT
;
231 } else if(strcmp(str
, "ignoreeof") == 0) {
232 flag
= enable
? F_IGNOREEOF
: F_D_IGNOREEOF
;
233 } else if(strcmp(str
, "monitor") == 0) {
234 flag
= enable
? F_MONITOR
: F_D_MONITOR
;
235 } else if(strcmp(str
, "noclobber") == 0) {
236 flag
= enable
? F_NOCLOBBER
: F_D_NOCLOBBER
;
237 } else if(strcmp(str
, "noglob") == 0) {
238 flag
= enable
? F_NOGLOB
: F_D_NOGLOB
;
239 } else if(strcmp(str
, "noexec") == 0) {
240 flag
= enable
? F_NOEXEC
: F_D_NOEXEC
;
241 } else if(strcmp(str
, "nolog") == 0) {
242 flag
= enable
? F_NOLOG
: F_D_NOLOG
;
243 } else if(strcmp(str
, "notify") == 0) {
244 flag
= enable
? F_NOTIFY
: F_D_NOTIFY
;
245 } else if(strcmp(str
, "nounset") == 0) {
246 flag
= enable
? F_NOUNSET
: F_D_NOUNSET
;
247 } else if(strcmp(str
, "verbose") == 0) {
248 flag
= enable
? F_VERBOSE
: F_D_VERBOSE
;
249 } else if(strcmp(str
, "vi") == 0) {
250 flag
= enable
? F_VI
: F_D_VI
;
251 } else if(strcmp(str
, "xtrace") == 0) {
252 flag
= enable
? F_XTRACE
: F_D_XTRACE
;
254 /* ohoh, bad input! */
255 fprintf(stderr
, "ERROR: invalid option string: %s\n", str
);
259 /* well, that wasn't fun. lets add the flag to list of known flag
261 list
= cons_flag(flag
,list
);
267 /* if we get here, we are looking for single character options.
268 we loop over all characters in the string. */
269 for(j
= 1; j
< len
; j
++)
271 /* try to identify char at position */
274 flag
= enable
? F_ALLEXPORT
: F_D_ALLEXPORT
;
277 flag
= enable
? F_ERREXIT
: F_D_ERREXIT
;
280 flag
= enable
? F_MONITOR
: F_D_MONITOR
;
283 flag
= enable
? F_NOCLOBBER
: F_D_NOCLOBBER
;
286 flag
= enable
? F_NOGLOB
: F_D_NOGLOB
;
289 flag
= enable
? F_REMEMBER
: F_D_REMEMBER
;
292 flag
= enable
? F_NOEXEC
: F_D_NOEXEC
;
295 flag
= enable
? F_NOTIFY
: F_D_NOTIFY
;
298 flag
= enable
? F_NOUNSET
: F_D_NOUNSET
;
301 flag
= enable
? F_VERBOSE
: F_D_VERBOSE
;
304 flag
= enable
? F_XTRACE
: F_D_XTRACE
;
313 flag
= F_INTERACTIVE
;
316 /* oops, bad input! */
317 fprintf(stderr
,"ERROR: unrecognized flag: %c\n", str
[j
]);
322 /* add it to the list of known flags */
323 list
= cons_flag(flag
,list
);
326 /* we successfuly parsed the whole string! lets
327 decrement the argc, point the argv to the next
328 string and try again. */
333 /* at last, we are done! */
338 /* print usage text */
341 printf("usage: %s [-/+ abCefhimnuvz][-/+ o <option>] [<non-options>]\n"
342 "where <non-options> can be:\n"
343 " <command file> [<argument>...]\n"
344 " -c <command string> [<command name> [argument...]]\n"
345 " -s [argument]\n", progname
);
348 int main(int argc
, char *argv
[])
350 /* Welcome to main! */
353 /* our first task is parsing the argv.
354 the function parse_argv() requires us
355 to decrement argc and point argv to
356 its second field, so lets do that */
359 flags
= parse_argv(&argc
, argv
);
361 print_flaglist(flags
);