Whamcloud - gitweb
This commit was generated by cvs2svn to compensate for changes in r46154,
[fs/lustre-release.git] / libsysio / tests / test_driver.c
1 #ifndef _BSD_SOURCE
2 #define _BSD_SOURCE
3 #endif
4 #ifndef _XOPEN_SOURCE
5 #define _XOPEN_SOURCE 500
6 #endif
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <getopt.h>
12 #include <errno.h>
13 #include <sys/types.h>
14 #include <sys/stat.h>
15 #include <sys/uio.h>
16 #include <sys/statvfs.h>
17 #include <fcntl.h>
18 #include <dirent.h>
19 #include <unistd.h>
20 #include <ctype.h>
21 #include <sys/uio.h>
22 #include <sys/queue.h>
23
24 #include "xtio.h"
25 #include "mount.h"
26 #include "test.h"
27 #include "test_driver.h"
28
29
30 struct queue_t;
31     
32 typedef struct cmd_tree_t {
33   char *res_name;
34   char *val;
35   int arg_count;
36   struct queue_t *children;
37 } cmd_tree;
38
39 struct queue_t {
40     char *val;
41     cmd_tree *cmd;
42     struct queue_t *next;
43 };
44
45 struct cmd_t cmd_list[] = {
46   {"alloc", get_buffer, usage_get_buffer},
47   {"chdir", test_do_chdir, usage_chdir},
48   {"checkbuf", do_checkbuf, usage_checkbuf},
49   {"chmod", test_do_chmod, usage_chmod},
50   {"chown", test_do_chown, usage_chown},
51   {"clear", test_do_clear, usage_clear},
52   {"close", test_do_close, usage_close},
53   {"cmpstr", cmp_bufs, usage_cmpbufs},
54   {"creat", test_do_creat, usage_creat},
55   {"debug", test_do_setdebug, usage_setdebug},
56   {"dup", test_do_dup, usage_dup},
57   {"dup2", test_do_dup2, usage_dup2},
58   {"endian", get_endian, usage_endian},
59   {"exit", test_do_exit, usage_exit},
60   {"fcntl", test_do_fcntl, usage_fcntl},
61   {"fdatasync", test_do_fdatasync, usage_fdatasync},
62   {"fill", test_do_fillbuff, usage_do_fillbuff},
63   {"free", free_buffer, usage_free_buffer},
64   {"fstat", test_do_fstat, usage_fstat},
65   {"fstatvfs", test_do_fstatvfs, usage_fstatvfs},
66   {"fsync", test_do_fsync, usage_fsync},
67   {"ftruncate", test_do_ftruncate, usage_ftruncate},
68   {"getcwd", test_do_getcwd, usage_getcwd},
69   {"getdirentries", test_do_getdirentries, usage_getdirentries},
70   {"init", test_do_init, usage_init},
71   {"init_iovec", test_do_init_iovec, usage_init_iovec},
72   {"init_xtvec", test_do_init_xtvec, usage_init_xtvec}, 
73   {"ioctl", test_do_ioctl, usage_ioctl},
74   {"iodone", test_do_iodone, usage_iodone},
75   {"iowait", test_do_iowait, usage_iowait},
76   {"ipread", test_do_ipread, usage_ipread},
77   {"ipreadv", test_do_ipreadv, usage_ipreadv},
78   {"ipwrite", test_do_ipwrite, usage_ipwrite},
79   {"ipwritev", test_do_ipwritev, usage_ipwritev},
80   {"iread", test_do_iread, usage_iread},
81   {"ireadv", test_do_ireadv, usage_ireadv},
82         {"ireadx", test_do_ireadx, usage_ireadx},
83   {"iwrite", test_do_iwrite, usage_iwrite},
84   {"iwritev", test_do_iwritev, usage_iwritev},
85   {"iwritex", test_do_iwritex, usage_iwritex},
86   {"list", test_do_list, usage_list},
87   {"lseek", test_do_lseek, usage_lseek},
88   {"lstat", test_do_lstat, usage_lstat},
89   {"mkdir", test_do_mkdir, usage_mkdir},
90   {"mknod", test_do_mknod, usage_mknod},
91   {"mount", test_do_mount, usage_mount},
92   {"open", test_do_open, usage_open},
93   {"printbuf", test_do_printbuf, usage_do_printbuf},
94   {"printline", test_do_printline, usage_printline},
95   {"pread", test_do_pread, usage_pread},
96   {"preadv", test_do_preadv, usage_preadv},
97   {"pwritev", test_do_pwritev, usage_pwritev},
98   {"pwrite", test_do_pwrite, usage_pwrite},
99   {"quit", test_do_exit, usage_exit},
100   {"read", test_do_read, usage_read},
101   {"readv", test_do_readv, usage_readv},
102         {"readx", test_do_readx, usage_readx},
103   {"rmdir", test_do_rmdir, usage_rmdir},
104   {"setbuf", do_setbuf, usage_setbuf},
105   {"sizeof", get_sizeof, usage_sizeof},
106   /*  {"setoutput", test_do_setoutput, usage_setoutput}, */
107   {"stat", test_do_stat, usage_stat},
108   {"statvfs", test_do_statvfs, usage_statvfs},
109   {"symlink", test_do_symlink, usage_symlink},
110   {"truncate", test_do_truncate, usage_truncate},
111   {"umask", test_do_umask, usage_umask},
112   {"umount", test_do_umount, usage_umount},
113   {"unlink", test_do_unlink, usage_unlink},
114   {"write", test_do_write, usage_write},
115   {"writev", test_do_writev, usage_writev},
116   {"writex", test_do_writex, usage_writex},
117   {NULL, NULL, NULL}
118 };
119
120 int run_cmd(cmd_tree *cmd_arg);
121 cmd_tree* build_tree(char **cmd, int *length, int total);
122 /*
123  * ##################################################
124  * # Memory functions                               #
125  * #  Intended to allow users to gain access to     #
126  * #  buffers of memory to be manipulated later     #
127  * ##################################################
128  */
129
130 void * alloc_buff32(unsigned int size, int align)
131 {
132   void* buf;
133   long buf_ptr;
134
135   /*
136   if ((err = memalign(&buf, align, size)) != 0) {
137     perror("memalign");
138     return 0;
139   }
140   */
141   size += align;
142   buf = malloc(size);
143   align--;
144   DBG(3, fprintf(outfp, "Buf is at %p\n", (void *)buf));
145   buf_ptr = (long)buf + ((long)buf & align);
146
147   DBG(3, fprintf(outfp, "Buf is at %p\n", (void *)buf_ptr));
148   return (void *)buf_ptr;
149 }
150
151 void free_buf32(void * ptr)
152 {
153   free(ptr);
154 }
155
156 long alloc_buff64(unsigned int size, int align)
157 {
158   char * buf;
159   long ret_value;
160
161   /*  
162       if (memalign((void **)&buf, align, size))
163       return 0;
164   */
165   size += align;
166   buf = malloc(size);
167   align--;
168   ret_value = (long)buf  + ((long)buf & align);
169   return ret_value;
170 }
171
172 void free_buf64(long ptr)
173 {
174   free((char *)ptr);
175 }
176
177   
178 /* 
179  * Hash function for variables. Shamelessly stolen
180  * from the ext3 code
181  */
182 unsigned int dx_hack_hash (const char *name, int len)
183 {
184   unsigned int hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9;
185   while (len--)
186     {
187       unsigned int hash = hash1 + (hash0 ^ (*name++ * 7152373));
188       if (hash & 0x80000000) hash -= 0x7fffffff;
189       hash1 = hash0;
190       hash0 = hash;
191     }
192   return hash0;
193 }
194
195 struct var_mapping *get_map(char *var_name)
196 {
197   int index;
198   struct var_mapping_list *curr;
199   
200
201  if (var_name[0] == '$') {
202     /* It is a name--chop off the initial and get the mapping $ */
203     var_name++;
204   }
205    
206   index = dx_hack_hash(var_name, strlen(var_name));
207   index %= MAX_VARS -1;
208
209   DBG(5, fprintf(outfp, "Got index of %d for %s\n", index, var_name));
210   curr = &map[index];
211   
212   while ((curr) && (curr->map.obj != -1) ) {
213     if ( (curr->map.name == NULL) || (strcmp(curr->map.name, var_name)) )
214       curr = curr->next;
215     else
216       return &curr->map;
217   }
218
219   return NULL;
220 }
221
222 char *get_str(char *var_name) 
223 {
224   /* See if it is a quoted string */
225   if (var_name[0] == '"') {
226     /* Chop off the beginning and end quotes and return the string */
227     int len = strlen(var_name);
228     var_name[len-1] = '\0';
229     var_name++;
230   }
231
232   return var_name;
233 }
234
235 static char* 
236 get_or_part(char **str, int* did_alloc)
237 {
238         char *tmp_str = *str;
239         int i, norm_str=0;
240
241         if (tmp_str == NULL)
242                 return NULL;
243
244         if (tmp_str[0] == '|') {
245                 tmp_str++;
246                 norm_str=1;
247         }
248
249         for (i=0; (unsigned int)i < strlen(tmp_str); i++) {
250                 if (tmp_str[i] == '|') {
251                         char *new_str = (char *)malloc(i+1);
252                         memcpy(new_str, tmp_str, i);
253                         new_str[i] = '\0';
254                         *did_alloc = 1;
255                         *str = &tmp_str[i];
256                         return new_str;
257                 }
258         }
259
260         if (norm_str) {
261                 *did_alloc = 0;
262                 *str = NULL;
263                 return tmp_str;
264         } 
265
266         return NULL;
267 }
268
269 int get_obj(char *var_name) 
270 {
271         char** str = &var_name;
272         char *str1;
273   struct var_mapping *var_map;
274   int did_alloc=0;
275         int obj=0, got_obj=0;
276
277   DBG(5, fprintf(outfp, "Getting object for %s\n", var_name));
278   
279   /* If var_name is a digit, we assume it is a literal */
280   if (isdigit(var_name[0])) 
281     return atoi(var_name); 
282  
283   /* 
284    * Check for '|', indicates that one or more values are or'd
285    * together
286    */
287         while ((str1 = get_or_part(str, &did_alloc)) != NULL) {
288
289                 if (isdigit(str1[0])) {
290                         if (str1[0] == '0') {
291                                 /* Assume octal format */
292                                 obj |= strtol(str1, NULL, 8);
293                         } else 
294                                 obj |= atoi(str1);
295                 } else {
296                         var_map = get_map(str1);
297                         if (!var_map) {
298                                 if (did_alloc)
299                                         free(str1);
300                                 return -1;
301                         }
302                         obj |= var_map->obj;
303                 }
304
305                 if (did_alloc) {
306                         did_alloc = 0;
307                         free(str1);
308                 }
309                 got_obj++;
310         }
311
312         if (got_obj)
313                 return obj;
314  
315   var_map = get_map(var_name);
316   if (!var_map)
317     return -1;
318   else
319     return var_map->obj;
320 }
321
322      
323 void store_result(char *var_name, int result)
324 {
325   int index = dx_hack_hash(var_name, strlen(var_name));
326   struct var_mapping_list *map_obj;
327   struct var_mapping_list *new_map;
328   index %= MAX_VARS -1 ;
329
330   if (map[index].map.obj >= 0) {
331
332     /* Got a collision --just chain it*/ 
333     new_map = malloc(sizeof(struct var_mapping_list));
334                      
335     map_obj = &map[index];
336     while (map_obj->next != NULL)
337       map_obj = map_obj->next;
338     
339     map_obj->next = new_map;
340   } else
341     new_map = &map[index];
342
343   new_map->map.name = malloc(strlen(var_name) + 1);
344   strcpy(new_map->map.name, var_name);
345   new_map->map.obj = result;
346   new_map->map.type = last_type;
347   new_map->next = NULL;
348   DBG(3, fprintf(outfp, "Stored %d in index %d hashed with %s\n",
349                 result, index, var_name));
350 }
351
352 void free_obj(char *obj_name)
353 {
354   int index;
355   struct var_mapping_list *prev, *curr;
356
357
358   /* See if it is a variable name */
359   if (obj_name[0] == '$') {
360     /* It is a name--chop off the initial $ */
361     obj_name++;
362   }
363   index = dx_hack_hash(obj_name, strlen(obj_name));
364   index %= MAX_VARS -1;
365
366   DBG(5, fprintf(outfp, "Got index of %d\n", index));
367   curr = &map[index];
368
369   prev = NULL;
370
371   while ((curr) && (curr->map.obj != -1) ) {
372     if (strcmp(curr->map.name, obj_name)) {
373       prev = curr;
374       curr = curr->next;
375     } else
376       break;
377   }
378
379   /* Remove the object from the chain */
380   if (prev) 
381     prev->next = curr->next;
382   
383   curr->map.obj = -1;
384   free(curr->map.name);
385   if (prev) 
386     free(curr);
387 }
388
389
390 /*
391  * Given a long string, returns the string divided into
392  * whitespace seperated words in list.  Returns the number
393  * of words
394  */
395 int parser(char *str, char** list)
396 {
397   int len, i=0, j=0, counter=-1;
398   int in_quotes = 0;
399   char *new_str;
400
401
402   len = strlen(str);
403   DBG(5, fprintf(outfp, "str is %s len is %d\n", str, len));
404   while (i < len) {
405    
406     if ((i==0) || ((str[i] == ' ') && (in_quotes == 0)) ) {
407       if (i != 0) {
408         new_str[j] = '\0';
409         DBG(5, fprintf(outfp, "Got word %s\n", list[counter]));
410         i++;
411       } 
412       while ((str[i] == ' ') && (in_quotes == 0))
413         i++;
414       counter++;
415       new_str = list[counter] = malloc(MAX_WORD);
416       j = 0;
417       
418     }
419     
420     new_str[j] = str[i];
421     if (str[i] == '"') {
422       if (in_quotes)
423         in_quotes = 0;
424       else
425         in_quotes = 1;
426     }
427     if ((str[i] == ' ') && (in_quotes==0)){
428       while (str[i+1] == ' ')
429                                 i++;
430       new_str[j] = '\0';
431     }
432     i++;
433     j++;
434
435   }
436   new_str[j] = '\0';
437   DBG(5, fprintf(outfp, "Got word %s\n", list[counter]));
438   return counter +1;
439 }
440
441
442 int execute_cmd(char *cmd, char **args, int arg_count)
443 {
444   int i = 0;
445
446   if (!strcmp(cmd, "help")) {
447     if (arg_count > 0) {
448                         while(cmd_list[i].cmd != NULL) {
449                                 if (!strcmp(cmd_list[i].cmd, args[0])) {
450                                         (cmd_list[i].usage)();
451                                         return 0;
452                                 }
453                                 i++;
454       }
455     } else {
456       do_help();
457       return 0;
458     }
459     return -1;
460   } 
461   while(cmd_list[i].cmd != NULL) {
462     if (!strcmp(cmd_list[i].cmd, cmd)) {
463       return (cmd_list[i].func)(arg_count, args);
464                 }
465     i++;
466   }
467   DBG(2, fprintf(outfp, "Command %s was invalid\n", cmd));
468   return INVALID_CMD;
469 }
470
471 int get_args(struct queue_t *child, char** list, int num_args, int argnum)
472 {
473   char *argval;
474
475   if (child->val != NULL) {
476     argval = child->val;
477   } else if (child->cmd != NULL) {
478     run_cmd(child->cmd);
479     if (child->cmd->res_name != NULL)
480       argval = child->cmd->res_name;
481     else {
482       char tmpstr[50];
483       int val = last_ret_val;
484       sprintf(tmpstr, "%x", val);
485       argval = tmpstr;
486     }
487   } else {
488     DBG(2, fprintf(outfp, "I am confused\n"));
489     return INVALID_ARGS;
490   }
491   
492   list[argnum] = malloc(strlen(argval) + 1);
493   strcpy(list[argnum], argval);
494   argnum++;
495
496   if (argnum == num_args)
497     return SUCCESS;
498   else if (child->next == NULL) {
499     DBG(2, fprintf(outfp, "Only on arg number %d out of %d, but ran out of children\n",
500                    argnum, num_args));
501     return INVALID_ARGS;
502   } else 
503     return get_args(child->next, list, num_args, argnum);
504
505   return SUCCESS;
506 }
507
508 int run_cmd(cmd_tree *cmd_arg)
509 {
510   char cmdstr[MAX_COMMAND];
511   char *cmdptr;
512   char **args;
513   int res, i;
514   struct buf_t *buf;
515   char *cmd;
516   struct queue_t *child;
517
518   if (cmd_arg == NULL)
519     return INVALID_CMD;
520
521   cmd = cmd_arg->val;
522   cmdptr = cmdstr;
523   child = cmd_arg->children;
524   if ( (!strcmp("exit", cmd)) || (!strcmp("quit", cmd)) ||
525        (!strcmp("EXIT", cmd)) || (!strcmp("QUIT", cmd)) )
526     strcpy(cmdstr, "exit");
527   else if (!strcmp("ALLOC", cmd)) 
528     strcpy(cmdstr, "alloc");
529   else if (!strcmp("FREE", cmd))
530     strcpy(cmdstr, "free");
531  else if (!strcmp("HELP", cmd))
532     strcpy(cmdstr, "help");
533   else if (!strcmp("CALL", cmd)) {
534     if (cmd_arg->arg_count < 1) {
535       DBG(2, fprintf(outfp, "Need at least one command\n"));
536       return INVALID_CMD;
537     }
538
539     cmd_arg->arg_count--;
540     if (child->val != NULL) 
541       cmdptr = child->val;
542     else {
543       DBG(2, fprintf(outfp, "Need to specify command\n"));
544       return INVALID_CMD;
545     }
546
547     DBG(3, fprintf(outfp, "Got cmd %s\n", child->val));
548     if (cmd_arg->arg_count != 0)
549       child = child->next;
550
551    
552   } else if (!strcmp("DEPOSIT", cmd))
553     strcpy(cmdstr, "fill");
554   else if (!strcmp("PRINT", cmd))
555     strcpy(cmdstr, "printbuf");
556   else {
557     if (cmd_arg->res_name != NULL) {
558       /* 
559        * If the cmd is not a valid command, just store it
560        */
561       res = get_obj(cmd_arg->children->val);
562       last_type = UINT;
563       if (res < 0) {
564                                 /* Just store it as a string */
565                                 buf = (struct buf_t *)malloc(sizeof(struct buf_t));
566                                 buf->len = strlen(cmd);
567                                 buf->buf = (char *)malloc(buf->len+1);
568                                 strcpy(buf->buf, cmd_arg->children->val);
569                                 buflist[next] = buf;
570                                 res = next;
571                                 DBG(3, fprintf(outfp, "Stored %s in index %d\n", (char *)buf->buf, next));
572                                 next++;
573                                 last_type = STR;
574       }
575       store_result(cmd_arg->res_name, res);
576       return SUCCESS;
577     } else
578       return INVALID_CMD;
579   }
580
581
582   if (cmd_arg->arg_count == 0)
583     args = NULL;
584   else {
585     args = (char **)malloc(sizeof(char *)*cmd_arg->arg_count);
586     get_args(child, args, cmd_arg->arg_count, 0);
587   } 
588
589   DBG(3, fprintf(outfp, "CMD: %s\n ARGS: ",cmdptr));
590   for (i=0; i < cmd_arg->arg_count; i++)
591     DBG(3, fprintf(outfp, "%s ", args[i]));
592   DBG(3, fprintf(outfp, "\n"));
593   res = execute_cmd(cmdptr, args, cmd_arg->arg_count);
594   if (cmd_arg->res_name != NULL)
595     store_result(cmd_arg->res_name, last_ret_val);
596
597   return res;
598
599
600
601 int is_command(char *name)
602 {
603     if ( (strcmp(name, "CALL"))  && (strcmp(name, "FILL"))  &&
604          (strcmp(name, "ALLOC")) && (strcmp(name, "PRINT")) &&
605          (strcmp(name, "FREE"))  && (strcmp(name, "exit"))  && 
606          (strcmp(name, "HELP"))  && (strcmp(name, "help"))  && 
607          (strcmp(name, "quit"))  && (strcmp(name, "EXIT"))  &&
608          (strcmp(name, "QUIT"))  && (strcmp(name, "DEPOSIT")) )
609         return 0;
610
611     return 1;
612 }
613
614 #define ARGS 1
615 int get_type(char *arg0)
616 {
617     if ((arg0[0] == '(') || (is_command(arg0)) ){
618         return 2;
619     }
620
621     return ARGS;
622 }
623                      
624         
625 int add_args(char **cmd, int length, int total, cmd_tree *tree)
626 {
627     int new_len, type;
628     struct queue_t *old, *new;
629
630     old = tree->children;
631     while ((old) && (old->next))
632         old = old->next;
633     new = (struct queue_t *)malloc(sizeof(struct queue_t));
634     if (old)
635         old->next = new;
636     else
637         tree->children = new;
638     new->next = NULL;
639
640     type = get_type(cmd[0]);
641     if (type < 0) {
642         DBG(2, fprintf(outfp, "Don't understand %s\n", cmd[0]));
643         return INVALID_CMD;
644     }
645     if (type == ARGS) {
646         new->val = (char *)malloc(strlen(cmd[0])+1);
647         strcpy(new->val, cmd[0]);
648         new->cmd = NULL;
649         total = 1;
650     } else {
651         new_len = length;
652         if (cmd[0][0] == '(') {
653             new_len--;
654         }
655
656         new->val = NULL;
657         new->cmd = build_tree(&cmd[1], &new_len, total);
658         if (new->cmd == NULL) { /* Invalid command */
659           return length; /* Pretend we used everything up */
660         }
661         total = (length - new_len);
662         DBG(4, fprintf(outfp, "Used %d bytes\n", total));
663     }
664  
665     return total;
666 }
667
668 void free_tree(cmd_tree* tree) 
669 {
670   if (!tree)
671     return;
672
673   if (tree->children) {
674    struct queue_t *child = tree->children;
675    struct queue_t *next;
676    do {
677      next = child->next;  
678      if (child->cmd) 
679        free_tree(child->cmd);
680      free(child->val);
681      free(child);
682      child = next;
683    } while (child);
684  }
685
686  if (tree->res_name)
687    free(tree->res_name);
688
689  if (tree->val)
690    free(tree->val);
691
692  free(tree);
693 }
694
695 cmd_tree* build_tree(char **cmd, int *length, int total)
696 {
697     int index = 0, used_args = 0;
698     cmd_tree *tree;
699     if ((*length < 0) || (!cmd) || (*cmd == NULL)) 
700                         return NULL;
701
702    
703     DBG(4, fprintf(outfp, "length is %d\n", *length));
704     tree = (cmd_tree *)malloc(sizeof(cmd_tree));
705     tree->res_name = NULL;
706     tree->children = NULL;
707     if (cmd[index][0] == '$') {
708                         tree->res_name = (char *)malloc(strlen(cmd[index])+1);
709                         strcpy(tree->res_name, (char*)(cmd[index]+1));
710                         index++;
711                         if (cmd[index][0] == '=')
712                                 index++;
713     } else
714       tree->res_name = NULL;
715
716     if (is_command(cmd[index]) == 0) {
717       if (tree->res_name == NULL) {
718                                 DBG(2, fprintf(outfp, "command %s is invalid \n", cmd[index]));
719         return NULL;
720       }
721     }
722
723     tree->val = (char *)malloc(strlen(cmd[index])+1);
724     strcpy(tree->val, cmd[index]);    
725     index++;
726     *length -= index;
727     tree->arg_count = 0;
728
729     if (*length == 0) {
730                         /* All done! */
731                         return tree;
732     }
733     
734     /* Got to get the arguments */
735     while (*length > 0) {
736
737                         if (cmd[index][0] == ')') {
738                                 *length = *length-1;
739                                 DBG(4, fprintf(outfp, "and now len is %d\n", *length));
740                                 return tree;
741                         }
742                         
743                         used_args = add_args(&cmd[index], *length, total, tree);
744                         tree->arg_count++;
745                         *length -= used_args;
746                         index += used_args;
747     }
748         
749     return tree;
750 }
751
752 char *line;
753 char *getline(char *prompt)
754 {
755   int i=-1;
756   int count=0;
757
758   line = malloc(MAX_LINE);
759   if ((do_prompt) && (infp == stdin)) 
760     printf(prompt);
761
762   do {
763     /* If we get an end of file, just wait */
764     if (feof(infp)) {
765       while (feof(infp) && (line[i] != '\n')) {
766                                 clearerr(infp);
767                                 count++;
768                                 fseek(infp, 0, SEEK_CUR);
769       }
770     } else {
771       i++;
772     }
773     fread(&line[i], 1, 1, infp);
774   } while(line[i] != '\n');
775
776   line[i] = '\0';
777
778   /*  fprintf(stderr, "Got word %s\n", line); */
779   DBG(5, fprintf(outfp, "Got word %s\n", line));
780   return line;
781 }
782
783 void my_perror(char *msg) 
784 {
785   char *errmsg = strerror(errno);
786   
787   DBG(2, fprintf(outfp, "%s: %s\n", msg, errmsg));
788 }
789   
790 /* Static list of flag names */
791 struct var_mapping flags_map[] = {
792   {"O_RDONLY", O_RDONLY, UINT },
793   {"O_WRONLY", O_WRONLY, UINT },
794   {"O_RDWR", O_RDWR, UINT },
795   {"O_CREAT", O_CREAT, UINT },
796   {"O_EXCL", O_EXCL, UINT },
797   {"O_NOCTTY", O_NOCTTY, UINT },
798   {"O_TRUNC", O_TRUNC, UINT },
799   {"O_APPEND", O_APPEND, UINT },
800   {"O_SYNC", O_NONBLOCK, UINT },
801   {"O_NDELAY", O_NDELAY, UINT },
802   {"O_SYNC", O_SYNC, UINT },
803   {"O_FSYNC", O_FSYNC, UINT },
804   {"O_ASYNC", O_ASYNC, UINT },
805   {"SEEK_SET", SEEK_SET, UINT },
806   {"SEEK_CUR", SEEK_CUR, UINT },
807   {"SEEK_END", SEEK_END, UINT },
808   {"S_ISUID", S_ISUID, UINT },
809   {"S_ISGID", S_ISGID, UINT },
810   {"S_ISVTX", S_ISVTX, UINT },
811   {"S_IRWXU", S_IRWXU, UINT },
812   {"S_IRUSR", S_IRUSR, UINT },
813   {"S_IREAD", S_IREAD, UINT },
814   {"S_IWUSR", S_IWUSR, UINT },
815   {"S_IWRITE", S_IWRITE, UINT },
816   {"S_IXUSR", S_IXUSR, UINT },
817   {"S_IEXEC", S_IEXEC, UINT },
818   {"S_IRWXG", S_IRWXG, UINT },
819   {"S_IRGRP", S_IRGRP, UINT },
820   {"S_IWGRP", S_IWGRP, UINT },
821   {"S_IXGRP", S_IXGRP, UINT },
822   {"S_IRWXO", S_IRWXO, UINT },
823   {"S_IROTH", S_IROTH, UINT },
824   {"S_IWOTH", S_IWOTH, UINT },
825   {"S_IXOTH", S_IXOTH, UINT },
826   {"S_IFCHR", S_IFCHR, UINT },
827   {"S_IFMT", S_IFMT, UINT },
828   {"S_IFBLK", S_IFBLK, UINT },
829   {"S_IFREG", S_IFREG, UINT },
830   {"S_IFIFO", S_IFIFO, UINT },
831   {"S_IFLNK", S_IFLNK, UINT },
832   { NULL, -1, SINT }
833 };
834  
835 void init_map()
836 {
837   int index = 0;
838
839   while (flags_map[index].obj != -1) {
840     store_result(flags_map[index].name, flags_map[index].obj);
841     index++;
842   }
843 }
844
845 int getquotedlen(char *str)
846 {
847         int i;
848         
849         if (str[0] != '"' && str[0] != '\'')
850                 return -1;
851         
852         for (i=1; str[i] != '\0' && str[i] != '"' && str[i] != '\''; i++);
853
854         return i;
855 }
856
857 int perform_op(int num1, int num2, char op) 
858 {
859         switch(op) {
860                 
861         case '+':
862                 return num1 + num2;
863                 break;
864
865         case '*':
866                 return num1 * num2;
867                 break;
868
869         case '/':
870                 return num1 / num2;
871                 break;
872
873         case '-':
874                 return num1 - num2;
875                 break;
876                 
877         case '%':
878                 return num1%num2;
879                 break;
880                 
881         default:
882                 return num1;
883         }
884         return 0;
885 }
886
887 int get_constant_val(char **str_ptr, int type)
888 {
889         struct buf_t *buf;
890         char *buf_ptr;
891         char *str = *str_ptr;
892         char ch;
893         int i, j, num1, num2, size;
894
895         printf("Getting constant val from %s\n", str);
896         switch(type) {
897         case 1:
898                 size = getquotedlen(str);
899                 buf = (struct buf_t *)malloc(sizeof(struct buf_t));
900                 buf->buf = alloc_buff32(size, 8);
901                 buf->len = size;
902                 buf_ptr = buf->buf;
903                 buflist[next] = buf;
904                 j=0;
905                 for (i=1; i < size; i++) {
906                         buf_ptr[j] = str[i];
907                         j++;
908                 }
909                 buf_ptr[j] = '\0';
910
911                 DBG(3, fprintf(outfp, "Your buffer (%p) (%p) is at index %d\n",
912                                                                          (void *)buf, buf->buf, next));
913                 next++;
914
915                 last_type = PTR;
916                 last_ret_val = next-1;
917                 return last_ret_val;
918                 break;
919
920         case 2:
921                 if (str[0] == '$') {
922                         num1 = get_obj(str);
923                 } else {        
924                         num1 = atoi(str);
925                 }
926                 str = str_ptr[1];
927                 ch = str_ptr[1][0];
928                 if ((ch == '+') || (ch == '/') || (ch == '*') || 
929                                 (ch == '-') || (ch == '%')) {
930                         if (str_ptr[2][0] == '$') 
931                                 num2 = get_obj(str_ptr[2]);
932                         else
933                                 num2 = atoi(str_ptr[2]);
934                         num1 = perform_op(num1, num2, ch);
935                 }
936
937                 last_type = UINT;
938                 last_ret_val = num1;
939
940                 break;
941
942         default:
943                 DBG(2, fprintf(outfp, "Can't understand type of %d\n", type));
944                 return INVALID_ARGS;
945         }
946
947         return last_ret_val;
948 }
949
950 int is_constant(char *str) 
951 {
952         if ((str[0] == '"') || (str[0] == '\''))
953                 return 1;
954
955         
956         if ( (str[0] == '$') || 
957                          ( ((int)str[0] > 47) && ((int)str[0] < 57) ) ) 
958                 return 2;
959
960         return 0;
961 }
962
963 int main(int argc, char *argv[])
964 {
965   int count, err, i, orig_count;
966   char *input, *name;
967   char **cmd;
968   cmd_tree *tree;
969         extern int _test_sysio_startup(void);
970
971   /*
972    * Init sysio lib.
973    */
974   err = _test_sysio_startup();
975   
976   infp = stdin;
977   outfp = stdout;
978
979   do_prompt = 1;
980
981   errno = 0;
982   /* Get the input/output streams */
983   for (i = 1; i < argc; i++) {
984     if (!strcmp(argv[i], "--input")) {
985       i++;
986       infp = fopen(argv[i], "r");
987       if (!infp) {
988                                 fprintf(outfp, "Unable to open file %s for reading\n", argv[i]);
989                                 return -1;
990       }
991     } else if (!strcmp(argv[i], "--output")) {
992       i++;
993       outfp = fopen(argv[i], "w");
994       if (!outfp) {
995                                 fprintf(stderr, "Unable to open file %s for writing\n", argv[i]);
996                                 return -1;
997       }
998     } else if (!strcmp(argv[i], "--np")) {
999       do_prompt = 0;
1000     } else {
1001       fprintf(stderr, "%s: Invalid arg\n", argv[i]);
1002       return -1;
1003     }
1004   }
1005   /* Initilize the mapping */
1006   for (i=0; i < MAX_VARS; i++)
1007     map[i].map.obj = -1;
1008   
1009   /* Debug defaults */
1010   debug_level = 1;
1011   print_line = 0;
1012
1013
1014 #if 0
1015   /* sysio defaults */
1016   strcpy(root_driver, DEFAULT_DRIVER);
1017   strcpy(mntpath, "/");
1018   mntflgs = 0;
1019 #endif
1020
1021   my_errno = 0;
1022
1023   /* Set up line buffering */
1024   setlinebuf(outfp);
1025   setlinebuf(infp);
1026
1027   /* 
1028    * This sets up some common flags so that the string
1029    * names can be used (for instance 0_RDWR, SEEK_SET, etc
1030    */
1031   init_map();
1032   i=0;
1033   next = 0;
1034   while (1) {
1035     bzero(output, 4096);
1036
1037     input = getline("> ");
1038     cmd = malloc(MAX_COMMAND * sizeof(char *));
1039     count = orig_count = parser(input, cmd);
1040     name = NULL;
1041     if ((!count) || (count > MAX_COMMAND)){
1042       fprintf(outfp, "%s: invalid command\n", input);
1043     } else {
1044       i = 0;
1045       if (cmd[0][0] == '$') {
1046                                 /* Need to store output of command in var name */
1047                                 name = cmd[0]+1;
1048                                 DBG(4, fprintf(outfp, "name is %s\n", name));
1049                                 count--;
1050                                 /* The '=' is not necessary, but available */
1051                                 if (!strcmp(cmd[1], "=")){
1052                                         i++;
1053                                         count--;
1054                                 }
1055                                 i++;
1056                                 if ((err=is_constant(cmd[i])) != 0) {
1057                                         store_result((char *)(&cmd[0][1]), get_constant_val(&cmd[i], err));
1058                                         tree = NULL;
1059                                         err = 0;
1060                                 } else {
1061
1062                                         tree = build_tree(&cmd[i], &count, 0);
1063                                         if (tree != NULL) {
1064                                                 err = run_cmd(tree);
1065                                                 store_result((char *)(&cmd[0][1]), last_ret_val);
1066                                         }
1067                                 }
1068                         } else {
1069                                 
1070                                 tree = build_tree(cmd, &count, 0);
1071                                 if (tree != NULL)
1072                                         err = run_cmd(tree);
1073       }
1074       /* Print out return code and any string from command */
1075       fprintf(outfp, "%#04x %s\n", err, output);
1076       if (tree)
1077                                 free_tree(tree);
1078       /* fprintf(stderr, "%#04x %s\n", err, output); */
1079       for (i=0; i < count; i++)
1080                                 free(cmd[i]);
1081     }
1082     free(cmd);
1083     free(line);
1084   }
1085 }