intbuiltin_command(char **args, int *resultp) /* * purpose: run a builtin command * returns: 1 if args[0] is builtin, 0 if not * details: test args[0] against all known built-ins. Call functions */ { int rv = 0;
intassign(char *str) /* * purpose: execute name = val AND ensure that name is legal * returns: -1 for illegal lval, or result of VLstore * warning: modifies the string, but restores it to normal */ { char *cp; int rv;
intok_to_execute() /* * purpose: determine the shell should execute a command * returns: 1 for yes, 0 for no * details: if in THEN_BLOCK and if_result was SUCESS then yes * if in THEN_BLOCK and if_result was FAIL then no * if in WANT_THEN then syntax error(sh is different) */ { int rv = 1;
intexecute(char *argv[]) /* * purpose: run a program passing it arguments * returns: status returned via wait, or -1 on error * errors: -1 on fork() or wait() errors */ { int pid; int child_info = -1; externchar ** environ;
/* * process.c * command processing layer * * The process(char ** arglist) function is called by the main loop * It sits in front of the execute() function. This layer handles * two main classes of processing. * a) built-in functions(e.g. exit(), set, =, read,..) * b) control structures(e.g. if, while, for) */
intprocess(char **args) /* * purpose: process user command * returns: result of proceessing command * details: if a built-in then call arrprporiate function, if not * execute() * errors: arise from subroutines, handled there */ { int rv = 0;
/* * splitline.c - command reading and parsing functions for smsh * * char * next_cmd(char *prompt, FILE *fp) - get next command * char ** splitline(char *str) - parse a string */ #include<stdio.h> #include<stdlib.h> #include<string.h> #include"smsh.h"
char * next_cmd(char * prompt, FILE * fp) /* * purpose: read next command line from fp * returns: dynamically allocated string holding command line * errors: NULL at EOF (not really an error) * calls fatal from emalloc() * notes: allocates space in BUFSIZ chunks */ { char *buf; // the buffer int bufspace = 0; // total size int pos = 0; // current position int c; // input char
/* * splitline (parse a line into an array of strings) */ char ** splitline(char * line) /* * purpose: split a line into array of white - space separated tokens * returns: a NULL-terminated array of pointers to copies of the * tokens or NULL if line if no tokens on the line * action: travers the array, locate strings, make copies * note: strtok() could work, but we may want to add quotes later */ { char * newstr(); char **args; int spots = 0; // spots in table int bufspace = 0; // bytes in table int argnum = 0; // slots used char *cp = line; // pos in string char *start; int len;
while (*cp != '\0') { while (isspace(*cp)) // skip leading spaces cp++; if (*cp == "\0") break;
// make sure the array has room(+1 for NULL) if (argnum + 1 >= spots) { args = erealloc(args, bufspace+BUFSIZ); bufspace += BUFSIZ; spots += (BUFSIZ/sizeof(char *)); } // mark start, then find end of word start = cp; len = 1; while (*++cp != '\0' && !(isspace(*cp))) { len++; } args[argnum++] = newstr(start, len); }
args[argnum] = NULL; return args; }
/* * purpose: constructor for strings * returns: a string, never NULL */ char * newstr(char *s, int l) { char * rv = emalloc(l + 1);
rv[l] = '\0'; strncpy(rv, s, l); return rv; }
voidfreelist(char ** list) /* * purpose: free the list returned by splitline * returns: nothing * action: free all strings in list and then free the list */ { char ** cp = list; while (*cp) free(*cp++); free(list); }
/* * varlib.c * * a simple storage system to store name=value pairs * with facility to mark items as part of the environment * * interface: * VLstore(name, value) return 1 for ok, 0 for no * VLlookup(name) return string or NULL if not there * VLlist() prints out current table * * environment-related functions * VLexport(name) adds name to list of env vars * VLtable2environ() copy from table to environ * VLenviron2table() copy from environ to table * * details: * the table is stored as an array of structs that * contain a flag for global and a single string of * the form name=value. This allows EZ addition to the * environment. It makes searching pretty easy, as * long as you search for "name=" * */
intVLstore(char *name, char *val) /* * traverse list, if found, replace it, else add at end * since there is no delete, a blank on is a free one * return 1 if trouble, 0 if ok(like a command) */ { structvar * itemp; char *s; int rv = 1;
// find spot to put it and make new string if ((itemp = find_item(name, 1)) != NULL && (s = new_string(name, val)) != NULL) { if (itemp->str) free(itemp->str); itemp->str = s; rv = 0; }
return rv; }
staticchar * new_string(char *name, char *val) /* * returns new string of form name=value or NULL on error */ { char * retval;
static struct var * find_item(char *name, int first_blank) /* * searches table for an item * returns ptr to struct or NULL if not found * OR if (first_blank) then ptr to first blank one */ { int i; int len = strlen(name); char *s;
for (i = 0; i < MAXVARS && tab[i].str != NULL; ++i) { s = tab[i].str; if (strncmp(s, name, len) == 0 && s[len] == '=') { // printf("%s %d\n", name, len); return &tab[i]; } } if (i < MAXVARS && first_blank) return &tab[i];
returnNULL; }
voidVLlist() /* * performs the shell's set command * Lists the contents of the variable table, marking each * exported variable with the symbol '*' */ { int i; for (i = 0; i < MAXVARS && tab[i].str != NULL; i++) { if (tab[i].global) printf(" * %s\n", tab[i].str); else printf(" %s\n", tab[i].str); } }
intVLenviron2table(char *env[]) /* * initialize the variable table by loading array of strings * return 1 for ok, 0 for not ok */ { int i; char *newstring;
for (i = 0; env[i] != NULL; i++) { if (i == MAXVARS) return0; newstring = malloc(1+strlen(env[i])); if (newstring == NULL) return0; strcpy(newstring, env[i]); tab[i].str = newstring; tab[i].global = 1; } while (i<MAXVARS) { tab[i].str = NULL; tab[i++].global = 0; } return1; }
char ** VLtable2environ() /* * build an array of pointers suitable for making a new environment * note: you need to free() this when done to avoid memory leaks */ { int i, j, n = 0; char **envtab;
// first, count the number of global variables for (i = 0; i < MAXVARS && tab[i].str != NULL; i++) if (tab[i].global == 1) n++;
// then, allocate space for that many variables envtab = (char **)malloc((n+1) * sizeof(char *)); if (envtab == NULL) returnNULL;
// then, load the array with pointers for (i = 0, j = 0; i < MAXVARS & tab[i].str != NULL; i++) if (tab[i].global == 1) { envtab[j++] = tab[i].str; // printf("%d %s\n",i, tab[i].str); } envtab[j] = NULL;