|
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 |
}
|