aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--toys/pending/sh.c184
1 files changed, 89 insertions, 95 deletions
diff --git a/toys/pending/sh.c b/toys/pending/sh.c
index 68004ce4..b461a6a4 100644
--- a/toys/pending/sh.c
+++ b/toys/pending/sh.c
@@ -157,8 +157,67 @@ GLOBALS(
struct sh_arg *arg;
)
+// Can't yet avoid this prototype. Fundamental problem is $($($(blah))) nests,
+// leading to function loop with run->parse->run
+static int sh_run(char *new);
+
+// Pipeline segments
+struct sh_pipeline {
+ struct sh_pipeline *next, *prev;
+ int count, here, type;
+ struct sh_arg arg[1];
+};
+
+// scratch space (state held between calls). Don't want to make it global yet
+// because this could be reentrant.
+struct sh_function {
+ char *name;
+ struct sh_pipeline *pipeline;
+ struct double_list *expect;
+// TODO: lifetime rules for arg? remember "shift" command.
+ struct sh_arg *arg; // arguments to function call
+ char *end;
+};
+
#define BUGBUG 0
+static void dump_state(struct sh_function *sp)
+{
+ struct sh_pipeline *pl;
+ long i;
+ int q = 0, fd = open("/proc/self/fd", O_RDONLY);
+ DIR *dir = fdopendir(fd);
+ char buf[256];
+
+ if (sp->expect) {
+ struct double_list *dl;
+
+ for (dl = sp->expect; dl; dl = (dl->next == sp->expect) ? 0 : dl->next)
+ dprintf(255, "expecting %s\n", dl->data);
+ if (sp->pipeline)
+ dprintf(255, "pipeline count=%d here=%d\n", sp->pipeline->prev->count,
+ sp->pipeline->prev->here);
+ }
+
+ for (pl = sp->pipeline; pl ; pl = (pl->next == sp->pipeline) ? 0 : pl->next) {
+ for (i = 0; i<pl->arg->c; i++)
+ dprintf(255, "arg[%d][%ld]=%s\n", q, i, pl->arg->v[i]);
+ if (pl->arg->c<0) dprintf(255, "argc=%d\n", pl->arg->c);
+ else dprintf(255, "type=%d term[%d]=%s\n", pl->type, q++, pl->arg->v[pl->arg->c]);
+ }
+
+ if (dir) {
+ struct dirent *dd;
+
+ while ((dd = readdir(dir))) {
+ if (atoi(dd->d_name)!=fd && 0<readlinkat(fd, dd->d_name, buf,sizeof(buf)))
+ dprintf(2, "OPEN %d: %s = %s\n", getpid(), dd->d_name, buf);
+ }
+ closedir(dir);
+ }
+ close(fd);
+}
+
// ordered for greedy matching, so >&; becomes >& ; not > &;
// making these const means I need to typecast the const away later to
// avoid endless warnings.
@@ -181,7 +240,7 @@ static void syntax_err(char *msg, ...)
}
// append to array with null terminator and realloc as necessary
-void array_add(char ***list, unsigned count, char *data)
+static void array_add(char ***list, unsigned count, char *data)
{
if (!(count&31)) *list = xrealloc(*list, sizeof(char *)*(count+33));
(*list)[count] = data;
@@ -189,7 +248,7 @@ void array_add(char ***list, unsigned count, char *data)
}
// add argument to an arg_list
-void add_arg(struct arg_list **list, char *arg)
+static void add_arg(struct arg_list **list, char *arg)
{
struct arg_list *al;
@@ -200,7 +259,7 @@ void add_arg(struct arg_list **list, char *arg)
*list = al;
}
-void array_add_del(char ***list, unsigned count, char *data,
+static void array_add_del(char ***list, unsigned count, char *data,
struct arg_list **delete)
{
if (delete) add_arg(delete, data);
@@ -269,7 +328,7 @@ static char *getvar(char *s)
// TODO: make parse_word use this?
// returns length of current quote context. Handles \ '' "" `` $()
-int skip_quote(char *s)
+static int skip_quote(char *s)
{
int i, q = 0;
@@ -301,7 +360,7 @@ int skip_quote(char *s)
}
// Return next available high (>=10) file descriptor
-int next_hfd()
+static int next_hfd()
{
int hfd;
@@ -318,7 +377,7 @@ int next_hfd()
// Perform a redirect, saving displaced filehandle to a high (>10) fd
// rd is an int array: [0] = count, followed by from/to pairs to restore later.
// If from == -1 just save to, else dup from->to after saving to.
-int save_redirect(int **rd, int from, int to)
+static int save_redirect(int **rd, int from, int to)
{
int cnt, hfd, *rr;
@@ -357,11 +416,6 @@ static void subshell_callback(void)
// TODO check every caller of run_subshell for error, or syntax_error() here
// from pipe() failure
-// TODO eliminate prototypes
-static int sh_run(char *new);
-static void unredirect(int *urd);
-
-
// Pass environment and command string to child shell, return PID of child
static int run_subshell(char *str, int len)
{
@@ -403,8 +457,26 @@ static int run_subshell(char *str, int len)
return pid;
}
+// restore displaced filehandles, closing high filehandles they were copied to
+static void unredirect(int *urd)
+{
+ int *rr = urd+1, i;
+
+ if (!urd) return;
+
+ for (i = 0; i<*urd; i++, rr += 2) {
+if (BUGBUG) dprintf(255, "urd %d %d\n", rr[0], rr[1]);
+ if (rr[1] != -1) {
+ // No idea what to do about fd exhaustion here, so Steinbach's Guideline.
+ dup2(rr[0], rr[1]);
+ close(rr[0]);
+ }
+ }
+ free(urd);
+}
+
// Call subshell with either stdin/stdout redirected, return other end of pipe
-int pipe_subshell(char *s, int len, int out)
+static int pipe_subshell(char *s, int len, int out)
{
int pipes[2], *uu = 0, in = !out;
@@ -836,42 +908,6 @@ static int redir_prefix(char *word)
// TODO |&
-// restore displaced filehandles, closing high filehandles they were copied to
-static void unredirect(int *urd)
-{
- int *rr = urd+1, i;
-
- if (!urd) return;
-
- for (i = 0; i<*urd; i++, rr += 2) {
-if (BUGBUG) dprintf(255, "urd %d %d\n", rr[0], rr[1]);
- if (rr[1] != -1) {
- // No idea what to do about fd exhaustion here, so Steinbach's Guideline.
- dup2(rr[0], rr[1]);
- close(rr[0]);
- }
- }
- free(urd);
-}
-
-// Pipeline segments
-struct sh_pipeline {
- struct sh_pipeline *next, *prev;
- int count, here, type;
- struct sh_arg arg[1];
-};
-
-// scratch space (state held between calls). Don't want to make it global yet
-// because this could be reentrant.
-struct sh_function {
- char *name;
- struct sh_pipeline *pipeline;
- struct double_list *expect;
-// TODO: lifetime rules for arg? remember "shift" command.
- struct sh_arg *arg; // arguments to function call
- char *end;
-};
-
// turn a parsed pipeline back into a string.
static char *pl2str(struct sh_pipeline *pl)
{
@@ -1282,7 +1318,7 @@ static char *parse_word(char *start)
// if then fi for while until select done done case esac break continue return
// Free one pipeline segment.
-void free_pipeline(void *pipeline)
+static void free_pipeline(void *pipeline)
{
struct sh_pipeline *pl = pipeline;
int i, j;
@@ -1295,7 +1331,7 @@ void free_pipeline(void *pipeline)
}
// Return end of current block, or NULL if we weren't in block and fell off end.
-struct sh_pipeline *block_end(struct sh_pipeline *pl)
+static struct sh_pipeline *block_end(struct sh_pipeline *pl)
{
int i = 0;
@@ -1311,7 +1347,7 @@ struct sh_pipeline *block_end(struct sh_pipeline *pl)
return pl;
}
-void free_function(struct sh_function *sp)
+static void free_function(struct sh_function *sp)
{
llist_traverse(sp->pipeline, free_pipeline);
llist_traverse(sp->expect, free);
@@ -1319,7 +1355,7 @@ void free_function(struct sh_function *sp)
}
// TODO this has to add to a namespace context. Functions within functions...
-struct sh_pipeline *add_function(char *name, struct sh_pipeline *pl)
+static struct sh_pipeline *add_function(char *name, struct sh_pipeline *pl)
{
dprintf(2, "stub add_function");
@@ -1642,48 +1678,6 @@ flush:
return 0-!!s;
}
-static void dump_state(struct sh_function *sp)
-{
- struct sh_pipeline *pl;
- int q = 0;
- long i;
-
- if (sp->expect) {
- struct double_list *dl;
-
- for (dl = sp->expect; dl; dl = (dl->next == sp->expect) ? 0 : dl->next)
- dprintf(255, "expecting %s\n", dl->data);
- if (sp->pipeline)
- dprintf(255, "pipeline count=%d here=%d\n", sp->pipeline->prev->count,
- sp->pipeline->prev->here);
- }
-
- for (pl = sp->pipeline; pl ; pl = (pl->next == sp->pipeline) ? 0 : pl->next) {
- for (i = 0; i<pl->arg->c; i++)
- dprintf(255, "arg[%d][%ld]=%s\n", q, i, pl->arg->v[i]);
- if (pl->arg->c<0) dprintf(255, "argc=%d\n", pl->arg->c);
- else dprintf(255, "type=%d term[%d]=%s\n", pl->type, q++, pl->arg->v[pl->arg->c]);
- }
-}
-
-void dump_filehandles(char *when)
-{
- int fd = open("/proc/self/fd", O_RDONLY);
- DIR *dir = fdopendir(fd);
- char buf[256];
-
- if (dir) {
- struct dirent *dd;
-
- while ((dd = readdir(dir))) {
- if (atoi(dd->d_name)!=fd && 0<readlinkat(fd, dd->d_name, buf,sizeof(buf)))
- dprintf(2, "OPEN %s %d: %s = %s\n", when, getpid(), dd->d_name, buf);
- }
- closedir(dir);
- }
- close(fd);
-}
-
/* Flow control statements:
if/then/elif/else/fi, for select while until/do/done, case/esac,
@@ -2090,7 +2084,7 @@ static void setonlylocal(char ***to, char *name, char *val)
}
// init locals, sanitize environment, handle nommu subshell handoff
-void subshell_setup(void)
+static void subshell_setup(void)
{
struct passwd *pw = getpwuid(getuid());
int to, from, pid = 0, ppid = 0, mypid, myppid, len;