/*----------------------------------------------------------- */ int clish_shell_execute(clish_context_t *context, char **out) { clish_shell_t *this = clish_context__get_shell(context); const clish_command_t *cmd = clish_context__get_cmd(context); int result = 0; const char *lock_path = clish_shell__get_lockfile(this); int lock_fd = -1; clish_view_t *cur_view = clish_shell__get_view(this); unsigned int saved_wdog_timeout = this->wdog_timeout; assert(cmd); /* Pre-change view if the command is from another depth/view */ { clish_view_restore_e restore = clish_command__get_restore(cmd); if ((CLISH_RESTORE_VIEW == restore) && (clish_command__get_pview(cmd) != cur_view)) { clish_view_t *view = clish_command__get_pview(cmd); clish_shell__set_pwd(this, NULL, view, NULL, context); } else if ((CLISH_RESTORE_DEPTH == restore) && (clish_command__get_depth(cmd) < this->depth)) { this->depth = clish_command__get_depth(cmd); } } /* Lock the lockfile */ if (lock_path && clish_action__get_lock(clish_command__get_action(cmd))) { lock_fd = clish_shell_lock(lock_path); if (-1 == lock_fd) { result = -1; goto error; /* Can't set lock */ } } /* Execute ACTION */ clish_context__set_action(context, clish_command__get_action(cmd)); result = clish_shell_exec_action(context, out); /* Call config callback */ if (!result) clish_shell_exec_config(context); /* Call logging callback */ if (clish_shell__get_log(this) && clish_shell_check_hook(context, CLISH_SYM_TYPE_LOG)) { char *full_line = clish_shell__get_full_line(context); clish_shell_exec_log(context, full_line, result); lub_string_free(full_line); } if (clish_shell__get_canon_out(this) && !clish_command__get_internal(cmd)) { char *space = NULL; char *full_line = clish_shell__get_full_line(context); if (this->depth > 0) { space = malloc(this->depth + 1); memset(space, ' ', this->depth); space[this->depth] = '\0'; } printf("%s%s\n", space ? space : "", full_line); lub_string_free(full_line); if (space) free(space); } /* Unlock the lockfile */ if (lock_fd != -1) clish_shell_unlock(lock_fd); /* Move into the new view */ if (!result) { char *viewname = clish_shell_expand(clish_command__get_viewname(cmd), SHELL_VAR_NONE, context); if (viewname) { /* Search for the view */ clish_view_t *view = clish_shell_find_view(this, viewname); if (!view) fprintf(stderr, "System error: Can't " "change view to %s\n", viewname); lub_string_free(viewname); /* Save the PWD */ if (view) { char *line = clish_shell__get_line(context); clish_shell__set_pwd(this, line, view, clish_command__get_viewid(cmd), context); lub_string_free(line); } } } /* Set appropriate timeout. Workaround: Don't turn on watchdog on the "set watchdog <timeout>" command itself. */ if (this->wdog_timeout && saved_wdog_timeout) { tinyrl__set_timeout(this->tinyrl, this->wdog_timeout); this->wdog_active = BOOL_TRUE; fprintf(stderr, "Warning: The watchdog is active. Timeout is %u " "seconds.\nWarning: Press any key to stop watchdog.\n", this->wdog_timeout); } else tinyrl__set_timeout(this->tinyrl, this->idle_timeout); error: return result; }
/*----------------------------------------------------------- */ int clish_shell_execute(clish_context_t *context, char **out) { clish_shell_t *this = clish_context__get_shell(context); const clish_command_t *cmd = clish_context__get_cmd(context); int result = 0; char *lock_path = clish_shell__get_lockfile(this); int lock_fd = -1; sigset_t old_sigs; struct sigaction old_sigint, old_sigquit, old_sighup; clish_view_t *cur_view = clish_shell__get_view(this); unsigned int saved_wdog_timeout = this->wdog_timeout; assert(cmd); /* Pre-change view if the command is from another depth/view */ { clish_view_restore_t restore = clish_command__get_restore(cmd); if ((CLISH_RESTORE_VIEW == restore) && (clish_command__get_pview(cmd) != cur_view)) { clish_view_t *view = clish_command__get_pview(cmd); clish_shell__set_pwd(this, NULL, view, NULL, context); } else if ((CLISH_RESTORE_DEPTH == restore) && (clish_command__get_depth(cmd) < this->depth)) { this->depth = clish_command__get_depth(cmd); } } /* Lock the lockfile */ if (lock_path && clish_command__get_lock(cmd)) { lock_fd = clish_shell_lock(lock_path); if (-1 == lock_fd) { result = -1; goto error; /* Can't set lock */ } } /* Ignore and block SIGINT, SIGQUIT, SIGHUP */ if (!clish_command__get_interrupt(cmd)) { struct sigaction sa; sigset_t sigs; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); sa.sa_handler = SIG_IGN; sigaction(SIGINT, &sa, &old_sigint); sigaction(SIGQUIT, &sa, &old_sigquit); sigaction(SIGHUP, &sa, &old_sighup); sigemptyset(&sigs); sigaddset(&sigs, SIGINT); sigaddset(&sigs, SIGQUIT); sigaddset(&sigs, SIGHUP); sigprocmask(SIG_BLOCK, &sigs, &old_sigs); } /* Execute ACTION */ clish_context__set_action(context, clish_command__get_action(cmd)); result = clish_shell_exec_action(context, out); /* Restore SIGINT, SIGQUIT, SIGHUP */ if (!clish_command__get_interrupt(cmd)) { sigprocmask(SIG_SETMASK, &old_sigs, NULL); /* Is the signals delivery guaranteed here (before sigaction restore) for previously blocked and pending signals? The simple test is working well. I don't want to use sigtimedwait() function bacause it needs a realtime extensions. The sigpending() with the sleep() is not nice too. Report bug if clish will get the SIGINT after non-interruptable action. */ sigaction(SIGINT, &old_sigint, NULL); sigaction(SIGQUIT, &old_sigquit, NULL); sigaction(SIGHUP, &old_sighup, NULL); } /* Call config callback */ if (!result) clish_shell_exec_config(context); /* Call logging callback */ if (clish_shell__get_log(this) && clish_shell_check_hook(context, CLISH_SYM_TYPE_LOG)) { char *full_line = clish_shell__get_full_line(context); clish_shell_exec_log(context, full_line, result); lub_string_free(full_line); } /* Unlock the lockfile */ if (lock_fd != -1) clish_shell_unlock(lock_fd); /* Move into the new view */ if (!result) { char *viewname = clish_shell_expand(clish_command__get_viewname(cmd), SHELL_VAR_NONE, context); if (viewname) { /* Search for the view */ clish_view_t *view = clish_shell_find_view(this, viewname); if (!view) fprintf(stderr, "System error: Can't " "change view to %s\n", viewname); lub_string_free(viewname); /* Save the PWD */ if (view) { char *line = clish_shell__get_line(context); clish_shell__set_pwd(this, line, view, clish_command__get_viewid(cmd), context); lub_string_free(line); } } } /* Set appropriate timeout. Workaround: Don't turn on watchdog on the "set watchdog <timeout>" command itself. */ if (this->wdog_timeout && saved_wdog_timeout) { tinyrl__set_timeout(this->tinyrl, this->wdog_timeout); this->wdog_active = BOOL_TRUE; fprintf(stderr, "Warning: The watchdog is active. Timeout is %u " "seconds.\nWarning: Press any key to stop watchdog.\n", this->wdog_timeout); } else tinyrl__set_timeout(this->tinyrl, this->idle_timeout); error: return result; }