Example #1
0
/*----------------------------------------------------------- */
int clish_shell_exec_action(clish_context_t *context, char **out)
{
	int result = -1;
	clish_sym_t *sym;
	char *script;
	clish_hook_action_fn_t *func = NULL;
	const clish_action_t *action = clish_context__get_action(context);
	clish_shell_t *shell = clish_context__get_shell(context);

	if (!(sym = clish_action__get_builtin(action)))
		return 0;
	if (shell->dryrun && !clish_sym__get_permanent(sym))
		return 0;
	if (!(func = clish_sym__get_func(sym))) {
		fprintf(stderr, "Error: Default ACTION symbol is not specified.\n");
		return -1;
	}
	script = clish_shell_expand(clish_action__get_script(action), SHELL_VAR_ACTION, context);
	result = func(context, script, out);
	lub_string_free(script);

	return result;
}
Example #2
0
/*----------------------------------------------------------- */
int clish_shell_exec_action(clish_context_t *context, char **out)
{
	int result = -1;
	const clish_sym_t *sym;
	char *script;
	const void *func = NULL; /* We don't know the func API at this time */
	const clish_action_t *action = clish_context__get_action(context);
	clish_shell_t *shell = clish_context__get_shell(context);
	bool_t intr = clish_action__get_interrupt(action);
	/* Signal vars */
	struct sigaction old_sigint, old_sigquit, old_sighup;
	struct sigaction sa;
	sigset_t old_sigs;

	if (!(sym = clish_action__get_builtin(action)))
		return 0;
	if (shell->dryrun && !clish_sym__get_permanent(sym))
		return 0;
	if (!(func = clish_sym__get_func(sym))) {
		fprintf(stderr, "Error: Default ACTION symbol is not specified.\n");
		return -1;
	}
	script = clish_shell_expand(clish_action__get_script(action), SHELL_VAR_ACTION, context);

	/* Ignore and block SIGINT, SIGQUIT, SIGHUP.
	 * The SIG_IGN is not a case because it will be inherited
	 * while a fork(). It's necessary to ignore signals because
	 * the klish itself and ACTION script share the same terminal.
	 */
	sa.sa_flags = 0;
	sigemptyset(&sa.sa_mask);
	sa.sa_handler = sigignore; /* Empty signal handler */
	sigaction(SIGINT, &sa, &old_sigint);
	sigaction(SIGQUIT, &sa, &old_sigquit);
	sigaction(SIGHUP, &sa, &old_sighup);
	/* Block signals for children processes. The block state is inherited. */
	if (!intr) {
		sigset_t sigs;
		sigemptyset(&sigs);
		sigaddset(&sigs, SIGINT);
		sigaddset(&sigs, SIGQUIT);
		sigaddset(&sigs, SIGHUP);
		sigprocmask(SIG_BLOCK, &sigs, &old_sigs);
	}

	/* Find out the function API */
	/* CLISH_SYM_API_SIMPLE */
	if (clish_sym__get_api(sym) == CLISH_SYM_API_SIMPLE) {
		result = ((clish_hook_action_fn_t *)func)(context, script, out);

	/* CLISH_SYM_API_STDOUT and output is not needed */
	} else if ((clish_sym__get_api(sym) == CLISH_SYM_API_STDOUT) && (!out)) {
		result = ((clish_hook_oaction_fn_t *)func)(context, script);

	/* CLISH_SYM_API_STDOUT and outpus is needed */
	} else if (clish_sym__get_api(sym) == CLISH_SYM_API_STDOUT) {
		result = clish_shell_exec_oaction((clish_hook_oaction_fn_t *)func,
			context, script, out);
	}

	/* Restore SIGINT, SIGQUIT, SIGHUP */
	if (!intr) {
		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 because
		   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);

	lub_string_free(script);

	return result;
}