[legal] seed the copyright headers
[platform/upstream/multipath-tools.git] / libmultipath / callout.c
1 /*
2  * Source: copy of the udev package source file
3  *
4  * Copyrights of the source file apply
5  * Copyright (c) 2004 Christophe Varoqui
6  */
7 #include <stdio.h>
8 #include <sys/stat.h>
9 #include <string.h>
10 #include <unistd.h>
11 #include <sys/types.h>
12 #include <stdlib.h>
13 #include <sys/wait.h>
14 #include <errno.h>
15
16 #define PROGRAM_SIZE    100
17 #define FIELD_PROGRAM
18
19 #define strfieldcpy(to, from) \
20 do { \
21         to[sizeof(to)-1] = '\0'; \
22         strncpy(to, from, sizeof(to)-1); \
23 } while (0)
24
25 int execute_program(char *path, char *value, int len)
26 {
27         int retval;
28         int count;
29         int status;
30         int fds[2];
31         pid_t pid;
32         char *pos;
33         char arg[PROGRAM_SIZE];
34         char *argv[sizeof(arg) / 2];
35         int i;
36
37         i = 0;
38
39         if (strchr(path, ' ')) {
40                 strfieldcpy(arg, path);
41                 pos = arg;
42                 while (pos != NULL) {
43                         if (pos[0] == '\'') {
44                                 /* don't separate if in apostrophes */
45                                 pos++;
46                                 argv[i] = strsep(&pos, "\'");
47                                 while (pos[0] == ' ')
48                                         pos++;
49                         } else {
50                                 argv[i] = strsep(&pos, " ");
51                         }
52                         i++;
53                 }
54         } else {
55                 argv[i++] = path;
56         }
57         argv[i] =  NULL;
58
59         retval = pipe(fds);
60
61         if (retval != 0)
62                 return -1;
63
64
65         pid = fork();
66
67         switch(pid) {
68         case 0:
69                 /* child */
70                 close(STDOUT_FILENO);
71
72                 /* dup write side of pipe to STDOUT */
73                 dup(fds[1]);
74
75                 retval = execv(argv[0], argv);
76
77                 exit(-1);
78         case -1:
79                 return -1;
80         default:
81                 /* parent reads from fds[0] */
82                 close(fds[1]);
83                 retval = 0;
84                 i = 0;
85                 while (1) {
86                         count = read(fds[0], value + i, len - i-1);
87                         if (count <= 0)
88                                 break;
89
90                         i += count;
91                         if (i >= len-1) {
92                                 retval = -1;
93                                 break;
94                         }
95                 }
96
97                 if (count < 0)
98                         retval = -1;
99
100                 if (i > 0 && value[i-1] == '\n')
101                         i--;
102                 value[i] = '\0';
103
104                 wait(&status);
105                 close(fds[0]);
106
107                 if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0))
108                         retval = -1;
109         }
110         return retval;
111 }