Ejemplo n.º 1
0
/**
 * service_enabled - Should the service run?
 * @svc:   Pointer to &svc_t object
 * @event: Dynamic event, opaque flag passed to callback
 * @arg:   Event argument, used only by external service plugins.
 *
 * This method calls an associated service callback, if registered by a
 * plugin, and returns the &svc_cmd_t status. If no plugin is registered
 * the service is statically enabled in /etc/finit.conf and the result
 * will always be %SVC_START.
 *
 * Returns:
 * Either one of %SVC_START, %SVC_STOP, %SVC_RELOAD.
 */
svc_cmd_t service_enabled(svc_t *svc, int event, void *arg)
{
	if (!svc) {
		errno = EINVAL;
		return SVC_STOP;
	}

	if (!svc_in_runlevel(svc, runlevel))
		return SVC_STOP;

	/*
	 * Event conditions for services are ignored during bootstrap.
	 */
	if (runlevel && !event_service_cond(svc->events))
		return SVC_STOP;

	/* Is there a service plugin registered? */
	if (svc->cb) {
		int   status;
		pid_t pid;

		/* Let callback run in separate process so it doesn't crash PID 1 */
		pid = fork();
		if (-1 == pid) {
			_pe("Failed in %s callback", svc->cmd);
			return SVC_STOP;
		}

		if (!pid) {
			status = svc->cb(svc, event, arg);
			exit(status);
		}

		if (waitpid(pid, &status, 0) == -1) {
			_pe("Failed reading status from %s callback", svc->cmd);
			return SVC_STOP;
		}

		/* Callback normally exits here. */
		if (WIFEXITED(status))
			return WEXITSTATUS(status);

		/* Check for SEGFAULT or other error ... */
		if (WIFSIGNALED(status) && WCOREDUMP(status))
			_e("Callback to %s crashed!\n", svc->cmd);
		else
			_e("Callback to %s did not exit normally!\n", svc->cmd);

		return SVC_STOP;
	}

	/* No service plugin, default to start, since listed in finit.conf */
	return SVC_START;
}
Ejemplo n.º 2
0
Archivo: service.c Proyecto: wkz/finit
/**
 * service_enabled - Should the service run?
 * @svc:   Pointer to &svc_t object
 * @event: Dynamic event, opaque flag passed to callback
 * @arg:   Event argument, used only by external service plugins.
 *
 * This method calls an associated service callback, if registered by a
 * plugin, and returns the &svc_cmd_t status. If no plugin is registered
 * the service is statically enabled in /etc/finit.conf and the result
 * will always be %SVC_START.
 *
 * Returns:
 * Either one of %SVC_START, %SVC_STOP, %SVC_RELOAD.
 */
svc_cmd_t service_enabled(svc_t *svc, int event, void *arg)
{
	svc_cmd_t cmd = SVC_START; /* Default to start, since listed in finit.conf */

	if (!svc) {
		errno = EINVAL;
		return SVC_STOP;
	}

	if (!svc_in_runlevel(svc, runlevel))
		return SVC_STOP;

	/*
	 * Event conditions for services are ignored during bootstrap.
	 */
	_d("Checking %s runlevel %d and events %s", svc->cmd, runlevel, svc->events);
	if (runlevel && !event_service_cond(svc->events))
		return SVC_STOP;

	if (svc->state == SVC_RELOAD_STATE)
		cmd = SVC_RELOAD;
	if (svc->state == SVC_PAUSED_STATE)
		cmd = SVC_STOP;

	/* Is there a service plugin registered? */
	if (svc->cb) {
		int   status;
		pid_t pid;

		/* Let callback run in separate process so it doesn't crash PID 1 */
		pid = fork();
		if (-1 == pid) {
			_pe("Failed in %s callback", svc->cmd);
			return SVC_STOP;
		}

		if (!pid)
			_exit(svc->cb(svc, event, arg));

		if (waitpid(pid, &status, 0) == -1) {
			_pe("Failed reading status from %s callback", svc->cmd);
			return SVC_STOP;
		}

		/* Callback normally exits here. */
		if (WIFEXITED(status)) {
			svc_cmd_t tmp = WEXITSTATUS(status);
			return tmp == SVC_START ? cmd : tmp;
		}

		/* Check for SEGFAULT or other error ... */
		if (WIFSIGNALED(status) && WCOREDUMP(status))
			_e("Callback to %s crashed!\n", svc->cmd);
		else
			_e("Callback to %s did not exit normally!\n", svc->cmd);

		return SVC_STOP;
	}

	_d("%s => %s", svc->cmd, (cmd == SVC_START
				  ? "SVC_START"
				  : (cmd == SVC_RELOAD
				     ? "SVC_RELOAD"
				     : "SVC_STOP")));

	return cmd;
}