Exemplo n.º 1
0
/* the echo service. stupid, but useful for testing */
static int qh_echo(int sd, char *buf, unsigned int len)
{
	if (!strcmp(buf, "help")) {
		nsock_printf_nul(sd,
		                 "Query handler that simply echoes back what you send it.");
		return 0;
	}
	return nsock_write_all(sd, buf, len);
}
Exemplo n.º 2
0
int daemon_init(void)
{
	int pid = 0;
	int lockfile = 0;
	int val = 0;
	char buf[256];
	struct flock lock;

	if (set_working_directory() == (ERROR)) {
		return (ERROR);
	}

	umask(S_IWGRP | S_IWOTH);

	lockfile = open(lock_file, O_RDWR | O_CREAT, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);

	if (lockfile < 0) {
		nm_log(NSLOG_RUNTIME_ERROR, "Failed to obtain lock on file %s: %s\n", lock_file, strerror(errno));
		nm_log(NSLOG_PROCESS_INFO | NSLOG_RUNTIME_ERROR, "Bailing out due to errors encountered while attempting to daemonize... (PID=%d)", (int)getpid());
		return (ERROR);
	}

	/* see if we can read the contents of the lockfile */
	if ((val = read(lockfile, buf, (size_t)10)) < 0) {
		nm_log(NSLOG_RUNTIME_ERROR, "Lockfile exists but cannot be read");
		return (ERROR);
	}

	/* we read something - check the PID */
	if (val > 0) {
		if ((val = sscanf(buf, "%d", &pid)) < 1) {
			nm_log(NSLOG_RUNTIME_ERROR, "Lockfile '%s' does not contain a valid PID (%s)", lock_file, buf);
			return (ERROR);
		}
	}

	/* check for SIGHUP */
	if (val == 1 && pid == (int)getpid()) {
		return OK;
	}
	else {

		lock.l_type = F_WRLCK;
		lock.l_start = 0;
		lock.l_whence = SEEK_SET;
		lock.l_len = 0;
		if (fcntl(lockfile, F_GETLK, &lock) == -1) {
			nm_log(NSLOG_RUNTIME_ERROR, "Failed to access lockfile '%s'. %s. Bailing out...", lock_file, strerror(errno));
			return (ERROR);
		}

		if (lock.l_type != F_UNLCK) {
			nm_log(NSLOG_RUNTIME_ERROR, "Lockfile '%s' looks like its already held by another instance of Naemon (PID %d).  Bailing out, pre-fork...", lock_file, (int)lock.l_pid);
			return (ERROR);
		}
	}

	/*
	 * set up a pipe used for sending a message from the child to the parent
	 * when initialization is complete.
	 */
	if (pipe(upipe_fd) < 0) {
		nm_log(NSLOG_RUNTIME_ERROR, "Failed to set up unnamned pipe: %s",
			strerror(errno));
		return (ERROR);
	}

	if ((pid = (int)fork()) < 0) {
		nm_log(NSLOG_RUNTIME_ERROR, "Unable to fork out the daemon process: %s",
			strerror(errno));
		return (ERROR);
	} else if (pid != 0) {
		/* parent stops - when child is done, we exit here */
		int return_code = EXIT_FAILURE;
		if (close(upipe_fd[PIPE_WRITE]) < 0) {
			nm_log(NSLOG_RUNTIME_ERROR, "Unable to close parent write end: %s",
				strerror(errno));
			return_code = EXIT_FAILURE;
		}
		/*
		 * wait for child to send the OK return code, if the child dies
		 * we stop blocking and the return code remains EXIT_FAILURE.
		 */
		if (read(upipe_fd[PIPE_READ], &return_code, sizeof(int)) < 0) {
			nm_log(NSLOG_RUNTIME_ERROR, "Unable to read from pipe: %s",
				strerror(errno));
			return_code = EXIT_FAILURE;
		}
		if (close(upipe_fd[PIPE_READ]) < 0) {
			nm_log(NSLOG_RUNTIME_ERROR, "Unable to close parent read end: %s",
				strerror(errno));
			return_code = EXIT_FAILURE;
		}
		if (return_code != OK) {
			/* signal the child to die in case an error occurs in parent */
			kill(pid, SIGTERM);
		}
		exit(return_code);
	} else {
		/* close read end of the pipe in the child */
		if (close(upipe_fd[PIPE_READ]) < 0) {
			nm_log(NSLOG_RUNTIME_ERROR, "Unable to close child read end: %s",
				strerror(errno));
			return ERROR;
		}
	}

	/* child becomes session leader... */
	setsid();
	/* place a file lock on the lock file */
	lock.l_type = F_WRLCK;
	lock.l_start = 0;
	lock.l_whence = SEEK_SET;
	lock.l_len = 0;
	lock.l_pid = getpid();
	if (fcntl(lockfile, F_SETLK, &lock) == -1) {
		if (errno == EACCES || errno == EAGAIN) {
			fcntl(lockfile, F_GETLK, &lock);
			nm_log(NSLOG_RUNTIME_ERROR, "Lockfile '%s' looks like its already held by another instance of Naemon (PID %d).  Bailing out, post-fork...", lock_file, (int)lock.l_pid);
		} else
			nm_log(NSLOG_RUNTIME_ERROR, "Cannot lock lockfile '%s': %s. Bailing out...", lock_file, strerror(errno));

		return (ERROR);
	}

	/* write PID to lockfile... */
	lseek(lockfile, 0, SEEK_SET);
	if (ftruncate(lockfile, 0) != 0) {
		nm_log(NSLOG_RUNTIME_ERROR, "Cannot truncate lockfile '%s': %s. Bailing out...", lock_file, strerror(errno));
		return (ERROR);
	}
	sprintf(buf, "%d\n", (int)getpid());

	if (nsock_write_all(lockfile, buf, strlen(buf)) != 0) {
		nm_log(NSLOG_RUNTIME_ERROR, "Cannot write PID to lockfile '%s': %s. Bailing out...", lock_file, strerror(errno));
		return (ERROR);
	}

	/* make sure lock file stays open while program is executing... */
	val = fcntl(lockfile, F_GETFD, 0);
	val |= FD_CLOEXEC;
	fcntl(lockfile, F_SETFD, val);

	/* close existing stdin, stdout, stderr */
	close(0);
	close(1);
	close(2);

	/* THIS HAS TO BE DONE TO AVOID PROBLEMS WITH STDERR BEING REDIRECTED TO SERVICE MESSAGE PIPE! */
	/* re-open stdin, stdout, stderr with known values */
	open("/dev/null", O_RDONLY);
	open("/dev/null", O_WRONLY);
	open("/dev/null", O_WRONLY);

	broker_program_state(NEBTYPE_PROCESS_DAEMONIZE, NEBFLAG_NONE, NEBATTR_NONE);

	return OK;
}