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