📄 execute_cmd.c
字号:
close_fd_bitmap (fds_to_close); do_piping (pipe_in, pipe_out);#if defined (COPROCESS_SUPPORT) coproc_closeall ();#endif /* If this is a user subshell, set a flag if stdin was redirected. This is used later to decide whether to redirect fd 0 to /dev/null for async commands in the subshell. This adds more sh compatibility, but I'm not sure it's the right thing to do. */ if (user_subshell) { stdin_redir = stdin_redirects (command->redirects); restore_default_signal (0); } /* If this is an asynchronous command (command &), we want to redirect the standard input from /dev/null in the absence of any specific redirection involving stdin. */ if (should_redir_stdin && stdin_redir == 0) async_redirect_stdin (); /* Do redirections, then dispose of them before recursive call. */ if (command->redirects) { if (do_redirections (command->redirects, RX_ACTIVE) != 0) exit (invert ? EXECUTION_SUCCESS : EXECUTION_FAILURE); dispose_redirects (command->redirects); command->redirects = (REDIRECT *)NULL; } if (command->type == cm_subshell) tcom = command->value.Subshell->command; else if (user_coproc) tcom = command->value.Coproc->command; else tcom = command; if (command->flags & CMD_TIME_PIPELINE) tcom->flags |= CMD_TIME_PIPELINE; if (command->flags & CMD_TIME_POSIX) tcom->flags |= CMD_TIME_POSIX; /* Make sure the subshell inherits any CMD_IGNORE_RETURN flag. */ if ((command->flags & CMD_IGNORE_RETURN) && tcom != command) tcom->flags |= CMD_IGNORE_RETURN; /* If this is a simple command, tell execute_disk_command that it might be able to get away without forking and simply exec. This means things like ( sleep 10 ) will only cause one fork. If we're timing the command or inverting its return value, however, we cannot do this optimization. */ if ((user_subshell || user_coproc) && (tcom->type == cm_simple || tcom->type == cm_subshell) && ((tcom->flags & CMD_TIME_PIPELINE) == 0) && ((tcom->flags & CMD_INVERT_RETURN) == 0)) { tcom->flags |= CMD_NO_FORK; if (tcom->type == cm_simple) tcom->value.Simple->flags |= CMD_NO_FORK; } invert = (tcom->flags & CMD_INVERT_RETURN) != 0; tcom->flags &= ~CMD_INVERT_RETURN; result = setjmp (top_level); /* If we're inside a function while executing this subshell, we need to handle a possible `return'. */ function_value = 0; if (return_catch_flag) function_value = setjmp (return_catch); /* If we're going to exit the shell, we don't want to invert the return status. */ if (result == EXITPROG) invert = 0, return_code = last_command_exit_value; else if (result) return_code = EXECUTION_FAILURE; else if (function_value) return_code = return_catch_value; else return_code = execute_command_internal (tcom, asynchronous, NO_PIPE, NO_PIPE, fds_to_close); /* If we are asked to, invert the return value. */ if (invert) return_code = (return_code == EXECUTION_SUCCESS) ? EXECUTION_FAILURE : EXECUTION_SUCCESS; /* If we were explicitly placed in a subshell with (), we need to do the `shell cleanup' things, such as running traps[0]. */ if (user_subshell && signal_is_trapped (0)) { last_command_exit_value = return_code; return_code = run_exit_trap (); } subshell_level--; return (return_code); /* NOTREACHED */}#if defined (COPROCESS_SUPPORT)#define COPROC_MAX 16typedef 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_reap __P((void));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, 0, 0 };cplist_t coproc_list = {0, 0, 0};/* Functions to manage the list of coprocs */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 voidcpe_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);}static voidcpl_reap (){ struct cpelement *prev, *p; for (prev = p = coproc_list.head; p; prev = p, p = p->next) if (p->coproc->c_flags & COPROC_DEAD) { prev->next = p->next; /* remove from list */ /* 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 */#if defined (DEBUG) itrace("cpl_reap: deleting %d", p->coproc->c_pid);#endif coproc_dispose (p->coproc); cpe_dispose (p); }}/* Clear out the list of saved statuses */static voidcpl_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 0static voidcpl_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 (using the list management package above). */struct coproc *getcoprocbypid (pid) pid_t pid;{ return (pid == sh_coproc.c_pid ? &sh_coproc : 0);}struct coproc *getcoprocbyname (name) const char *name;{ return ((sh_coproc.c_name && STREQ (sh_coproc.c_name, name)) ? &sh_coproc : 0);}voidcoproc_init (cp) struct coproc *cp;{ cp->c_name = 0; cp->c_pid = NO_PID; cp->c_rfd = cp->c_wfd = -1; cp->c_rsave = cp->c_wsave = -1; cp->c_flags = cp->c_status = 0; }struct coproc *coproc_alloc (name, pid) char *name; pid_t pid;{ struct coproc *cp; cp = &sh_coproc; /* XXX */ coproc_init (cp); cp->c_name = savestring (name); cp->c_pid = pid; return (cp);}voidcoproc_dispose (cp) struct coproc *cp;{ if (cp == 0) return; coproc_unsetvars (cp); FREE (cp->c_name); coproc_close (cp); coproc_init (cp);}/* Placeholder for now. */voidcoproc_flush (){ coproc_dispose (&sh_coproc);}voidcoproc_close (cp) struct coproc *cp;{ if (cp->c_rfd >= 0) { close (cp->c_rfd); cp->c_rfd = -1; } if (cp->c_wfd >= 0) { close (cp->c_wfd); cp->c_wfd = -1; } cp->c_rsave = cp->c_wsave = -1;}voidcoproc_closeall (){ coproc_close (&sh_coproc);}voidcoproc_reap (){ struct coproc *cp; cp = &sh_coproc; if (cp && (cp->c_flags & COPROC_DEAD)) coproc_dispose (cp);}voidcoproc_rclose (cp, fd) struct coproc *cp; int fd;{ if (cp->c_rfd >= 0 && cp->c_rfd == fd) { close (cp->c_rfd); cp->c_rfd = -1; }}voidcoproc_wclose (cp, fd) struct coproc *cp; int fd;{ if (cp->c_wfd >= 0 && cp->c_wfd == fd) { close (cp->c_wfd); cp->c_wfd = -1; }}voidcoproc_checkfd (cp, fd) struct coproc *cp; int fd;{ int update; update = 0; if (cp->c_rfd >= 0 && cp->c_rfd == fd) update = cp->c_rfd = -1; if (cp->c_wfd >= 0 && cp->c_wfd == fd) update = cp->c_wfd = -1; if (update) coproc_setvars (cp);}voidcoproc_fdchk (fd) int fd;{ coproc_checkfd (&sh_coproc, fd);}voidcoproc_fdclose (cp, fd) struct coproc *cp; int fd;{ coproc_rclose (cp, fd); coproc_wclose (cp, fd); coproc_setvars (cp);}voidcoproc_fdsave (cp) struct coproc *cp;{ cp->c_rsave = cp->c_rfd; cp->c_wsave = cp->c_wfd;}void
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -