Ejemplo n.º 1
0
void conf_parse_cond(svc_t *svc, char *cond)
{
    size_t i = 0;
    char *ptr;

    if (!svc) {
        _e("Invalid service pointer");
        return;
    }

    /* By default we assume UNIX daemons support SIGHUP */
    if (svc_is_daemon(svc))
        svc->sighup = 1;

    if (!cond)
        return;

    /* First character must be '!' if SIGHUP is not supported. */
    ptr = cond;
    if (ptr[i] == '!') {
        svc->sighup = 0;
        ptr++;
    }

    while (ptr[i] != '>' && ptr[i] != 0)
        i++;
    ptr[i] = 0;

    if (i >= sizeof(svc->cond)) {
        logit(LOG_WARNING, "Too long event list in declaration of %s: %s", svc->cmd, ptr);
        return;
    }

    strlcpy(svc->cond, ptr, sizeof(svc->cond));
}
Ejemplo n.º 2
0
/* Remember: service_enabled() must be called before calling service_start() */
int service_start(svc_t *svc)
{
	int respawn, sd = 0;
	pid_t pid;
	sigset_t nmask, omask;

	if (!svc)
		return 1;
	respawn = svc->pid != 0;

	/* Don't try and start service if it doesn't exist. */
	if (!fexist(svc->cmd) && !svc->inetd.cmd) {
		if (verbose) {
			char msg[80];

			snprintf(msg, sizeof(msg), "Service %s does not exist!", svc->cmd);
			print_desc("", msg);
			print_result(1);
		}

		return 1;
	}

	/* Ignore if finit is SIGSTOP'ed */
	if (is_norespawn())
		return 0;

#ifndef INETD_DISABLED
	if (svc_is_inetd(svc)) {
		char ifname[IF_NAMESIZE] = "UNKNOWN";

		sd = svc->inetd.watcher.fd;

		if (svc->inetd.type == SOCK_STREAM) {
			/* Open new client socket from server socket */
			sd = accept(sd, NULL, NULL);
			if (sd < 0) {
				FLOG_PERROR("Failed accepting inetd service %d/tcp", svc->inetd.port);
				return 1;
			}

			_d("New client socket %d accepted for inetd service %d/tcp", sd, svc->inetd.port);

			/* Find ifname by means of getsockname() and getifaddrs() */
			inetd_stream_peek(sd, ifname);
		} else {           /* SOCK_DGRAM */
			/* Find ifname by means of IP_PKTINFO sockopt --> ifindex + if_indextoname() */
			inetd_dgram_peek(sd, ifname);
		}

		if (!inetd_is_allowed(&svc->inetd, ifname)) {
			FLOG_INFO("Service %s on port %d not allowed from interface %s.",
				  svc->inetd.name, svc->inetd.port, ifname);
			if (svc->inetd.type == SOCK_STREAM)
				close(sd);

			return 1;
		}

		FLOG_INFO("Starting inetd service %s for requst from iface %s ...", svc->inetd.name, ifname);
	} else
#endif
	if (verbose) {
		if (svc_is_daemon(svc))
			print_desc("", svc->desc);
		else if (!respawn)
			print_desc("Starting ", svc->desc);
	}

	/* Block sigchild while forking.  */
	sigemptyset(&nmask);
	sigaddset(&nmask, SIGCHLD);
	sigprocmask(SIG_BLOCK, &nmask, &omask);

	pid = fork();
	sigprocmask(SIG_SETMASK, &omask, NULL);
	if (pid == 0) {
		int i = 0;
		int status;
#ifdef ENABLE_STATIC
		int uid = 0; /* XXX: Fix better warning that dropprivs is disabled. */
#else
		int uid = getuser(svc->username);
#endif
		struct sigaction sa;
		char *args[MAX_NUM_SVC_ARGS];

		sigemptyset(&nmask);
		sigaddset(&nmask, SIGCHLD);
		sigprocmask(SIG_UNBLOCK, &nmask, NULL);

		/* Reset signal handlers that were set by the parent process */
		for (i = 1; i < NSIG; i++)
			DFLSIG(sa, i, 0);

		/* Set desired user */
		if (uid >= 0) {
			setuid(uid);

			/* Set default path for regular users */
			if (uid > 0)
				setenv("PATH", _PATH_DEFPATH, 1);
		}

		/* Serve copy of args to process in case it modifies them. */
		for (i = 0; i < (MAX_NUM_SVC_ARGS - 1) && svc->args[i][0] != 0; i++)
			args[i] = svc->args[i];
		args[i] = NULL;

		/* Redirect inetd socket to stdin for service */
		if (svc_is_inetd(svc)) {
			/* sd set previously */
			dup2(sd, STDIN_FILENO);
			close(sd);
			dup2(STDIN_FILENO, STDOUT_FILENO);
			dup2(STDIN_FILENO, STDERR_FILENO);
		} else if (debug) {
			int fd;
			char buf[CMD_SIZE] = "";

			fd = open(CONSOLE, O_WRONLY | O_APPEND);
			if (-1 != fd) {
				dup2(fd, STDOUT_FILENO);
				dup2(fd, STDERR_FILENO);
				close(fd);
			}

			for (i = 0; i < MAX_NUM_SVC_ARGS && args[i]; i++) {
				char arg[MAX_ARG_LEN];

				snprintf(arg, sizeof(arg), "%s ", args[i]);
				if (strlen(arg) < (sizeof(buf) - strlen(buf)))
					strcat(buf, arg);
			}
			_e("%starting %s: %s", respawn ? "Res" : "S", svc->cmd, buf);
		}

		if (svc->inetd.cmd)
			status = svc->inetd.cmd(svc->inetd.type);
		else
			status = execv(svc->cmd, args); /* XXX: Maybe use execve() to be able to launch scripts? */

		if (svc_is_inetd(svc)) {
			if (svc->inetd.type == SOCK_STREAM) {
				close(STDIN_FILENO);
				close(STDOUT_FILENO);
				close(STDERR_FILENO);
			}
		}

		exit(status);
	}
	svc->pid = pid;

	if (svc_is_inetd(svc)) {
		if (svc->inetd.type == SOCK_STREAM)
			close(sd);
	} else {
		int result;

		if (SVC_TYPE_RUN == svc->type)
			result = WEXITSTATUS(complete(svc->cmd, pid));
		else if (!respawn)
			result = svc->pid > 1 ? 0 : 1;
		else
			result = 0;

		if (verbose)
			print_result(result);
	}

	return 0;
}