summaryrefslogtreecommitdiff
path: root/execute_cmd.c
diff options
context:
space:
mode:
authorChet Ramey <chet.ramey@case.edu>2011-12-07 09:26:30 -0500
committerChet Ramey <chet.ramey@case.edu>2011-12-07 09:26:30 -0500
commit8e1a6eaa95d16cc9ec67523b9e9cb4a599ae4ace (patch)
tree607ef4058688250093e130daddac5f2278a77998 /execute_cmd.c
parent547ef91456587b9d98629c56ff241799b5cae2d6 (diff)
downloadbash-8e1a6eaa95d16cc9ec67523b9e9cb4a599ae4ace.tar.gz
commit bash-20080724 snapshot
Diffstat (limited to 'execute_cmd.c')
-rw-r--r--execute_cmd.c214
1 files changed, 204 insertions, 10 deletions
diff --git a/execute_cmd.c b/execute_cmd.c
index 8499dab2..6443c90e 100644
--- a/execute_cmd.c
+++ b/execute_cmd.c
@@ -1312,7 +1312,7 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close)
do_piping (pipe_in, pipe_out);
#if defined (COPROCESS_SUPPORT)
- coproc_close (&sh_coproc);
+ coproc_closeall ();
#endif
/* If this is a user subshell, set a flag if stdin was redirected.
@@ -1404,10 +1404,183 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close)
}
#if defined (COPROCESS_SUPPORT)
+#define COPROC_MAX 16
+
+typedef struct cpelement
+ {
+ struct cpelement *next;
+ struct coproc *coproc;
+ }
+cpelement_t;
+
+typedef struct cplist
+ {
+ struct cpelement *head;
+ struct cpelement *tail;
+ int ncoproc;
+ }
+cplist_t;
+
+static struct cpelement *cpe_alloc __P((struct coproc *));
+static void cpe_dispose __P((struct cpelement *));
+static struct cpelement *cpl_add __P((struct coproc *));
+static struct cpelement *cpl_delete __P((pid_t));
+static void cpl_flush __P((void));
+static struct cpelement *cpl_search __P((pid_t));
+static struct cpelement *cpl_searchbyname __P((char *));
+static void cpl_prune __P((void));
+
Coproc sh_coproc = { 0, NO_PID, -1, -1, 0, 0 };
+cplist_t coproc_list = {0, 0, 0};
+
+/* Functions to manage the list of exited background pids whose status has
+ been saved. */
+
+static struct cpelement *
+cpe_alloc (cp)
+ Coproc *cp;
+{
+ struct cpelement *cpe;
+
+ cpe = (struct cpelement *)xmalloc (sizeof (struct cpelement));
+ cpe->coproc = cp;
+ cpe->next = (struct cpelement *)0;
+ return cpe;
+}
+
+static void
+cpe_dispose (cpe)
+ struct cpelement *cpe;
+{
+ free (cpe);
+}
+
+static struct cpelement *
+cpl_add (cp)
+ Coproc *cp;
+{
+ struct cpelement *cpe;
+
+ cpe = cpe_alloc (cp);
+
+ if (coproc_list.head == 0)
+ {
+ coproc_list.head = coproc_list.tail = cpe;
+ coproc_list.ncoproc = 0; /* just to make sure */
+ }
+ else
+ {
+ coproc_list.tail->next = cpe;
+ coproc_list.tail = cpe;
+ }
+ coproc_list.ncoproc++;
+
+ return cpe;
+}
+
+static struct cpelement *
+cpl_delete (pid)
+ pid_t pid;
+{
+ struct cpelement *prev, *p;
+
+ for (prev = p = coproc_list.head; p; prev = p, p = p->next)
+ if (p->coproc->c_pid == pid)
+ {
+ prev->next = p->next; /* remove from list */
+ break;
+ }
+
+ if (p == 0)
+ return 0; /* not found */
+
+#if defined (DEBUG)
+ itrace("cpl_delete: deleting %d", pid);
+#endif
+
+ /* Housekeeping in the border cases. */
+ if (p == coproc_list.head)
+ coproc_list.head = coproc_list.head->next;
+ else if (p == coproc_list.tail)
+ coproc_list.tail = prev;
+
+ coproc_list.ncoproc--;
+ if (coproc_list.ncoproc == 0)
+ coproc_list.head = coproc_list.tail = 0;
+ else if (coproc_list.ncoproc == 1)
+ coproc_list.tail = coproc_list.head; /* just to make sure */
+
+ return (p);
+}
+
+/* Clear out the list of saved statuses */
+static void
+cpl_flush ()
+{
+ struct cpelement *cpe, *p;
+
+ for (cpe = coproc_list.head; cpe; )
+ {
+ p = cpe;
+ cpe = cpe->next;
+
+ coproc_dispose (p->coproc);
+ cpe_dispose (p);
+ }
+
+ coproc_list.head = coproc_list.tail = 0;
+ coproc_list.ncoproc = 0;
+}
+
+/* Search for PID in the list of coprocs; return the cpelement struct if
+ found. If not found, return NULL. */
+static struct cpelement *
+cpl_search (pid)
+ pid_t pid;
+{
+ struct cpelement *cp;
+
+ for (cp = coproc_list.head ; cp; cp = cp->next)
+ if (cp->coproc->c_pid == pid)
+ return cp;
+ return (struct cpelement *)NULL;
+}
+
+/* Search for the coproc named NAME in the list of coprocs; return the
+ cpelement struct if found. If not found, return NULL. */
+static struct cpelement *
+cpl_searchbyname (name)
+ char *name;
+{
+ struct cpelement *cp;
+
+ for (cp = coproc_list.head ; cp; cp = cp->next)
+ if (STREQ (cp->coproc->c_name, name))
+ return cp;
+ return (struct cpelement *)NULL;
+}
+
+#if 0
+static void
+cpl_prune ()
+{
+ struct cpelement *cp;
+
+ while (coproc_list.head && coproc_list.ncoproc > COPROC_MAX)
+ {
+ cp = coproc_list.head;
+ coproc_list.head = coproc_list.head->next;
+ coproc_dispose (cp->coproc);
+ cpe_dispose (cp);
+ coproc_list.ncoproc--;
+ }
+}
+#endif
+
/* These currently use a single global "shell coproc" but are written in a
- way to not preclude additional coprocs later */
+ way to not preclude additional coprocs later (using the list management
+ package above). */
struct coproc *
getcoprocbypid (pid)
@@ -1441,7 +1614,7 @@ coproc_alloc (name, pid)
{
struct coproc *cp;
- cp = &sh_coproc;
+ cp = &sh_coproc; /* XXX */
coproc_init (cp);
cp->c_name = savestring (name);
@@ -1463,6 +1636,13 @@ coproc_dispose (cp)
coproc_init (cp);
}
+/* Placeholder for now. */
+void
+coproc_flush ()
+{
+ coproc_dispose (&sh_coproc);
+}
+
void
coproc_close (cp)
struct coproc *cp;
@@ -1481,6 +1661,12 @@ coproc_close (cp)
}
void
+coproc_closeall ()
+{
+ coproc_close (&sh_coproc);
+}
+
+void
coproc_rclose (cp, fd)
struct coproc *cp;
int fd;
@@ -1505,7 +1691,7 @@ coproc_wclose (cp, fd)
}
void
-coproc_fdchk (cp, fd)
+coproc_checkfd (cp, fd)
struct coproc *cp;
int fd;
{
@@ -1521,6 +1707,13 @@ coproc_fdchk (cp, fd)
}
void
+coproc_fdchk (fd)
+ int fd;
+{
+ coproc_checkfd (&sh_coproc, fd);
+}
+
+void
coproc_fdclose (cp, fd)
struct coproc *cp;
int fd;
@@ -1530,7 +1723,6 @@ coproc_fdclose (cp, fd)
coproc_setvars (cp);
}
-
void
coproc_fdsave (cp)
struct coproc *cp;
@@ -1554,12 +1746,13 @@ coproc_pidchk (pid)
struct coproc *cp;
cp = getcoprocbypid (pid);
+#if defined (DEBUG)
+ if (cp)
+ itrace("coproc_pidchk: pid %d has died", pid);
+#endif
if (cp)
-{
-itrace("coproc_pidchk: pid %d has died", pid);
coproc_dispose (cp);
}
-}
void
coproc_setvars (cp)
@@ -1652,6 +1845,7 @@ execute_coproc (command, pipe_in, pipe_out, fds_to_close)
Coproc *cp;
char *tcmd;
+ /* XXX -- will require changes to handle multiple coprocs */
if (sh_coproc.c_pid != NO_PID)
{
#if 0
@@ -3017,7 +3211,7 @@ execute_null_command (redirects, pipe_in, pipe_out, async)
do_piping (pipe_in, pipe_out);
#if defined (COPROCESS_SUPPORT)
- coproc_close (&sh_coproc);
+ coproc_closeall ();
#endif
subshell_environment = 0;
@@ -3223,7 +3417,7 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
do_piping (pipe_in, pipe_out);
pipe_in = pipe_out = NO_PIPE;
#if defined (COPROCESS_SUPPORT)
- coproc_close (&sh_coproc);
+ coproc_closeall ();
#endif
last_asynchronous_pid = old_last_async_pid;