#include #include #include #include #include "sh.h" #include "shio.h" #include "shvar.h" #include "util.h" /* * this could have been an instance of the dynamically sized array * with an iterator function. */ extern char **environ; struct var { char *name, *value; int is_env; } *var_tbl = 0; int var_tbl_used = 0, var_tbl_sz = 0; /* invariant: var_tbl_used <= var_tbl_sz */ /* ownership of malloc'd name/value pair is passed to var_tbl */ void dollar_set_var(char *name, char *value) { int i; struct var *ntbl; int newsize; /* has old value? */ for (i = 0; i < var_tbl_used; i++) { if (!strcmp(var_tbl[i].name,name)) { /* overwrite */ free(var_tbl[i].value); var_tbl[i].value = value; free(name); /* BUGFIX */ return; } } if (var_tbl_used == var_tbl_sz) { newsize = 2 * var_tbl_sz; ntbl = realloc(var_tbl,newsize * sizeof *ntbl); if (!ntbl) { perror(SHNAME ": dollar_set_var"); desc_printf(2,SHNAME ": cannot set %s to %s\n",name,value); return; } var_tbl = ntbl; } /* var_tbl_used < var_tbl_sz */ var_tbl[var_tbl_used].name = name; var_tbl[var_tbl_used].value = value; var_tbl[var_tbl_used].is_env = 0; var_tbl_used++; /* BUGFIX */ } int dollar_mark_exported(char *name) { int i; for (i = 0; i < var_tbl_used; i++) { if (!strcmp(var_tbl[i].name,name)) { var_tbl[i].is_env = 1; return 1; } } return 0; } /* NEW FN */ void dollar_on_fork(void) { char pidbuf[16]; (void) sprintf(pidbuf,"%d",getpid()); dollar_set_var(dupstr("$"),dupstr(pidbuf)); } void dollar_init(void) { char **ep = environ, *var, *eq; /* copy the environment to the shell variable list */ var_tbl = malloc((var_tbl_sz = 64) * sizeof *var_tbl); if (!var_tbl) { perror(SHNAME ": dollar_init"); exit(1); } while ((var = *ep) != 0) { eq = strchr(var,'='); if (!eq) { desc_printf(2,SHNAME ": badly formatted environment entry \"%s\"\n",*ep); exit(1); } /* XXX -- hack */ *eq = '\0'; dollar_set_var(dupstr(var),dupstr(eq+1)); (void) dollar_mark_exported(var); *eq = '='; ep++; } dollar_set_var(dupstr("?"),dupstr("0")); dollar_on_fork(); } /* * dollar module still owns value; user can copy out. */ const char *dollar_value(char *name) { int i; for (i = 0; i < var_tbl_used; i++) { if (!strcmp(var_tbl[i].name,name)) { return var_tbl[i].value; } } return 0; } int dollar_unset(char *name) { int i; for (i = 0; i < var_tbl_used; i++) { if (!strcmp(var_tbl[i].name,name)) { free(var_tbl[i].value); free(var_tbl[i].name); var_tbl[i] = var_tbl[--var_tbl_used]; return 1; } } return 0; } /* * ownership of the newly constructed environment template is passed * to caller, who is responsible for freeing it if needed. */ char **dollar_construct_envp(void) { char **newenv, *envdata, *cp, ch; int env_size, strsize; int i, j; for (strsize = env_size = i = 0; i < var_tbl_used; i++) { if (!var_tbl[i].is_env) continue; ++env_size; strsize += strlen(var_tbl[i].name) + strlen(var_tbl[i].value) + 2; } newenv = malloc((env_size + 1) * sizeof(*newenv) + strsize); if (!newenv) { perror(SHNAME ": dollar_construct_envp"); desc_printf(2,SHNAME ": no memory for constructing environment table\n"); exit(1); } envdata = (char *) (newenv + env_size + 1); for (j = i = 0; i < var_tbl_used; i++) { if (!var_tbl[i].is_env) continue; newenv[j++] = envdata; for (cp = var_tbl[i].name; (ch = *cp++) != 0;) *envdata++ = ch; *envdata++ = '='; for (cp = var_tbl[i].value; (ch = *cp++) != 0;) *envdata++ = ch; *envdata++ = '\0'; } newenv[j] = 0; return newenv; } void dollar_free_envp(char **envp) { free(envp); }