Example #1
0
static char *run(const char *cmd, int *exitstatus)
{
	pid_t pid;
	int p[2];
	char *ret;
	int status;

	if (pipe(p) != 0)
		err(1, "creating pipe");

	pid = fork();
	if (pid == -1)
		err(1, "forking");

	if (pid == 0) {
		if (dup2(p[1], STDOUT_FILENO) != STDOUT_FILENO
		    || dup2(p[1], STDERR_FILENO) != STDERR_FILENO
		    || close(p[0]) != 0
		    || close(STDIN_FILENO) != 0
		    || open("/dev/null", O_RDONLY) != STDIN_FILENO)
			exit(128);

		status = system(cmd);
		if (WIFEXITED(status))
			exit(WEXITSTATUS(status));
		/* Here's a hint... */
		exit(128 + WTERMSIG(status));
	}

	close(p[1]);
	ret = grab_fd(p[0]);
	/* This shouldn't fail... */
	if (waitpid(pid, &status, 0) != pid)
		err(1, "Failed to wait for child");
	close(p[0]);
	if (WIFEXITED(status))
		*exitstatus = WEXITSTATUS(status);
	else
		*exitstatus = -WTERMSIG(status);
	return ret;
}
/* arg* may be null */
static char *ask_process(const tal_t *ctx,
			 const char *name,
			 const char *arg1,
			 const char *arg2,
			 const char *arg3,
			 const char *arg4,
			 const char *arg5)
{
	char *output;
	int fds[2], status;

	if (pipe(fds) != 0)
		return NULL;

	switch (fork()) {
	case -1:
		return NULL;
	case 0:
		close(fds[0]);
		dup2(fds[1], STDOUT_FILENO);
		execlp(name, name, arg1, arg2, arg3, arg4, arg5, NULL);
		exit(errno);
	}

	close(fds[1]);
	output = grab_fd(ctx, fds[0]);
	close_noerr(fds[0]);

	wait(&status);
	if (!WIFEXITED(status)) {
		output = tal_free(output);
		errno = EINTR;
	} else if (WEXITSTATUS(status)) {
		output = tal_free(output);
		errno = WEXITSTATUS(status);
	}

	return output;
}
Example #3
0
char *run_with_timeout(const void *ctx, const char *cmd,
		       bool *ok, unsigned *timeout_ms)
{
	pid_t pid;
	int p[2];
	char *ret;
	int status, ms;
	struct timeval start, end;

	*ok = false;
	if (pipe(p) != 0)
		return talloc_asprintf(ctx, "Failed to create pipe: %s",
				       strerror(errno));

	if (tools_verbose)
		printf("Running: %s\n", cmd);

	gettimeofday(&start, NULL);
	pid = fork();
	if (pid == -1) {
		close_noerr(p[0]);
		close_noerr(p[1]);
		return talloc_asprintf(ctx, "Failed to fork: %s",
				       strerror(errno));
		return NULL;
	}

	if (pid == 0) {
		struct itimerval itim;

		if (dup2(p[1], STDOUT_FILENO) != STDOUT_FILENO
		    || dup2(p[1], STDERR_FILENO) != STDERR_FILENO
		    || close(p[0]) != 0
		    || close(STDIN_FILENO) != 0
		    || open("/dev/null", O_RDONLY) != STDIN_FILENO)
			exit(128);

		signal(SIGALRM, killme);
		itim.it_interval.tv_sec = itim.it_interval.tv_usec = 0;
		itim.it_value.tv_sec = *timeout_ms / 1000;
		itim.it_value.tv_usec = (*timeout_ms % 1000) * 1000;
		setitimer(ITIMER_REAL, &itim, NULL);

		status = system(cmd);
		if (WIFEXITED(status))
			exit(WEXITSTATUS(status));
		/* Here's a hint... */
		exit(128 + WTERMSIG(status));
	}

	close(p[1]);
	ret = grab_fd(ctx, p[0], NULL);
	/* This shouldn't fail... */
	if (waitpid(pid, &status, 0) != pid)
		err(1, "Failed to wait for child");

	gettimeofday(&end, NULL);
	if (end.tv_usec < start.tv_usec) {
		end.tv_usec += 1000000;
		end.tv_sec--;
	}
	ms = (end.tv_sec - start.tv_sec) * 1000
		+ (end.tv_usec - start.tv_usec) / 1000;
	if (ms > *timeout_ms)
		*timeout_ms = 0;
	else
		*timeout_ms -= ms;
	close(p[0]);
	if (tools_verbose) {
		printf("%s", ret);
		printf("Finished: %u ms, %s %u\n", ms,
		       WIFEXITED(status) ? "exit status" : "killed by signal",
		       WIFEXITED(status) ? WEXITSTATUS(status)
		       : WTERMSIG(status));
	}
	*ok = (WIFEXITED(status) && WEXITSTATUS(status) == 0);
	return ret;
}