Blame libmultipath/callout.c

Packit Service 0af388
/*
Packit Service 0af388
 * Source: copy of the udev package source file
Packit Service 0af388
 *
Packit Service 0af388
 * Copyrights of the source file apply
Packit Service 0af388
 * Copyright (c) 2004 Christophe Varoqui
Packit Service 0af388
 */
Packit Service 0af388
#include <stdio.h>
Packit Service 0af388
#include <sys/stat.h>
Packit Service 0af388
#include <string.h>
Packit Service 0af388
#include <unistd.h>
Packit Service 0af388
#include <sys/types.h>
Packit Service 0af388
#include <stdlib.h>
Packit Service 0af388
#include <fcntl.h>
Packit Service 0af388
#include <sys/wait.h>
Packit Service 0af388
#include <errno.h>
Packit Service 0af388
Packit Service 0af388
#include "checkers.h"
Packit Service 0af388
#include "vector.h"
Packit Service 0af388
#include "structs.h"
Packit Service 0af388
#include "util.h"
Packit Service 0af388
#include "callout.h"
Packit Service 0af388
#include "debug.h"
Packit Service 0af388
Packit Service 0af388
int execute_program(char *path, char *value, int len)
Packit Service 0af388
{
Packit Service 0af388
	int retval;
Packit Service 0af388
	int count;
Packit Service 0af388
	int status;
Packit Service 0af388
	int fds[2], null_fd;
Packit Service 0af388
	pid_t pid;
Packit Service 0af388
	char *pos;
Packit Service 0af388
	char arg[CALLOUT_MAX_SIZE];
Packit Service 0af388
	int argc = sizeof(arg) / 2;
Packit Service 0af388
	char *argv[argc + 1];
Packit Service 0af388
	int i;
Packit Service 0af388
Packit Service 0af388
	i = 0;
Packit Service 0af388
Packit Service 0af388
	if (strchr(path, ' ')) {
Packit Service 0af388
		strlcpy(arg, path, sizeof(arg));
Packit Service 0af388
		pos = arg;
Packit Service 0af388
		while (pos != NULL && i < argc) {
Packit Service 0af388
			if (pos[0] == '\'') {
Packit Service 0af388
				/* don't separate if in apostrophes */
Packit Service 0af388
				pos++;
Packit Service 0af388
				argv[i] = strsep(&pos, "\'");
Packit Service 0af388
				while (pos[0] == ' ')
Packit Service 0af388
					pos++;
Packit Service 0af388
			} else {
Packit Service 0af388
				argv[i] = strsep(&pos, " ");
Packit Service 0af388
			}
Packit Service 0af388
			i++;
Packit Service 0af388
		}
Packit Service 0af388
	} else {
Packit Service 0af388
		argv[i++] = path;
Packit Service 0af388
	}
Packit Service 0af388
	argv[i] =  NULL;
Packit Service 0af388
Packit Service 0af388
	retval = pipe(fds);
Packit Service 0af388
Packit Service 0af388
	if (retval != 0) {
Packit Service 0af388
		condlog(0, "error creating pipe for callout: %s", strerror(errno));
Packit Service 0af388
		return -1;
Packit Service 0af388
	}
Packit Service 0af388
Packit Service 0af388
	pid = fork();
Packit Service 0af388
Packit Service 0af388
	switch(pid) {
Packit Service 0af388
	case 0:
Packit Service 0af388
		/* child */
Packit Service 0af388
Packit Service 0af388
		/* dup write side of pipe to STDOUT */
Packit Service 0af388
		if (dup2(fds[1], STDOUT_FILENO) < 0) {
Packit Service 0af388
			condlog(1, "failed to dup2 stdout: %m");
Packit Service 0af388
			return -1;
Packit Service 0af388
		}
Packit Service 0af388
		close(fds[0]);
Packit Service 0af388
		close(fds[1]);
Packit Service 0af388
Packit Service 0af388
		/* Ignore writes to stderr */
Packit Service 0af388
		null_fd = open("/dev/null", O_WRONLY);
Packit Service 0af388
		if (null_fd > 0) {
Packit Service 0af388
			if (dup2(null_fd, STDERR_FILENO) < 0)
Packit Service 0af388
				condlog(1, "failed to dup2 stderr: %m");
Packit Service 0af388
			close(null_fd);
Packit Service 0af388
		}
Packit Service 0af388
Packit Service 0af388
		retval = execv(argv[0], argv);
Packit Service 0af388
		condlog(0, "error execing %s : %s", argv[0], strerror(errno));
Packit Service 0af388
		exit(-1);
Packit Service 0af388
	case -1:
Packit Service 0af388
		condlog(0, "fork failed: %s", strerror(errno));
Packit Service 0af388
		close(fds[0]);
Packit Service 0af388
		close(fds[1]);
Packit Service 0af388
		return -1;
Packit Service 0af388
	default:
Packit Service 0af388
		/* parent reads from fds[0] */
Packit Service 0af388
		close(fds[1]);
Packit Service 0af388
		retval = 0;
Packit Service 0af388
		i = 0;
Packit Service 0af388
		while (1) {
Packit Service 0af388
			count = read(fds[0], value + i, len - i-1);
Packit Service 0af388
			if (count <= 0)
Packit Service 0af388
				break;
Packit Service 0af388
Packit Service 0af388
			i += count;
Packit Service 0af388
			if (i >= len-1) {
Packit Service 0af388
				condlog(0, "not enough space for response from %s", argv[0]);
Packit Service 0af388
				retval = -1;
Packit Service 0af388
				break;
Packit Service 0af388
			}
Packit Service 0af388
		}
Packit Service 0af388
Packit Service 0af388
		if (count < 0) {
Packit Service 0af388
			condlog(0, "no response from %s", argv[0]);
Packit Service 0af388
			retval = -1;
Packit Service 0af388
		}
Packit Service 0af388
Packit Service 0af388
		if (i > 0 && value[i-1] == '\n')
Packit Service 0af388
			i--;
Packit Service 0af388
		value[i] = '\0';
Packit Service 0af388
Packit Service 0af388
		wait(&status);
Packit Service 0af388
		close(fds[0]);
Packit Service 0af388
Packit Service 0af388
		retval = -1;
Packit Service 0af388
		if (WIFEXITED(status)) {
Packit Service 0af388
			status = WEXITSTATUS(status);
Packit Service 0af388
			if (status == 0)
Packit Service 0af388
				retval = 0;
Packit Service 0af388
			else
Packit Service 0af388
				condlog(0, "%s exited with %d", argv[0], status);
Packit Service 0af388
		}
Packit Service 0af388
		else if (WIFSIGNALED(status))
Packit Service 0af388
			condlog(0, "%s was terminated by signal %d", argv[0], WTERMSIG(status));
Packit Service 0af388
		else
Packit Service 0af388
			condlog(0, "%s terminated abnormally", argv[0]);
Packit Service 0af388
	}
Packit Service 0af388
	return retval;
Packit Service 0af388
}
Packit Service 0af388
Packit Service 0af388
int apply_format(char * string, char * cmd, struct path * pp)
Packit Service 0af388
{
Packit Service 0af388
	char * pos;
Packit Service 0af388
	char * dst;
Packit Service 0af388
	char * p;
Packit Service 0af388
	char * q;
Packit Service 0af388
	int len;
Packit Service 0af388
	int myfree;
Packit Service 0af388
Packit Service 0af388
	if (!string)
Packit Service 0af388
		return 1;
Packit Service 0af388
Packit Service 0af388
	if (!cmd)
Packit Service 0af388
		return 1;
Packit Service 0af388
Packit Service 0af388
	dst = cmd;
Packit Service 0af388
	p = dst;
Packit Service 0af388
	pos = strchr(string, '%');
Packit Service 0af388
	myfree = CALLOUT_MAX_SIZE;
Packit Service 0af388
Packit Service 0af388
	if (!pos) {
Packit Service 0af388
		strcpy(dst, string);
Packit Service 0af388
		return 0;
Packit Service 0af388
	}
Packit Service 0af388
Packit Service 0af388
	len = (int) (pos - string) + 1;
Packit Service 0af388
	myfree -= len;
Packit Service 0af388
Packit Service 0af388
	if (myfree < 2)
Packit Service 0af388
		return 1;
Packit Service 0af388
Packit Service 0af388
	snprintf(p, len, "%s", string);
Packit Service 0af388
	p += len - 1;
Packit Service 0af388
	pos++;
Packit Service 0af388
Packit Service 0af388
	switch (*pos) {
Packit Service 0af388
	case 'n':
Packit Service 0af388
		len = strlen(pp->dev) + 1;
Packit Service 0af388
		myfree -= len;
Packit Service 0af388
Packit Service 0af388
		if (myfree < 2)
Packit Service 0af388
			return 1;
Packit Service 0af388
Packit Service 0af388
		snprintf(p, len, "%s", pp->dev);
Packit Service 0af388
		for (q = p; q < p + len; q++) {
Packit Service 0af388
			if (q && *q == '!')
Packit Service 0af388
				*q = '/';
Packit Service 0af388
		}
Packit Service 0af388
		p += len - 1;
Packit Service 0af388
		break;
Packit Service 0af388
	case 'd':
Packit Service 0af388
		len = strlen(pp->dev_t) + 1;
Packit Service 0af388
		myfree -= len;
Packit Service 0af388
Packit Service 0af388
		if (myfree < 2)
Packit Service 0af388
			return 1;
Packit Service 0af388
Packit Service 0af388
		snprintf(p, len, "%s", pp->dev_t);
Packit Service 0af388
		p += len - 1;
Packit Service 0af388
		break;
Packit Service 0af388
	default:
Packit Service 0af388
		break;
Packit Service 0af388
	}
Packit Service 0af388
	pos++;
Packit Service 0af388
Packit Service 0af388
	if (!*pos) {
Packit Service 0af388
		condlog(3, "formatted callout = %s", dst);
Packit Service 0af388
		return 0;
Packit Service 0af388
	}
Packit Service 0af388
Packit Service 0af388
	len = strlen(pos) + 1;
Packit Service 0af388
	myfree -= len;
Packit Service 0af388
Packit Service 0af388
	if (myfree < 2)
Packit Service 0af388
		return 1;
Packit Service 0af388
Packit Service 0af388
	snprintf(p, len, "%s", pos);
Packit Service 0af388
	condlog(3, "reformatted callout = %s", dst);
Packit Service 0af388
	return 0;
Packit Service 0af388
}