[checkers] checkers are now dlopen'ed plugins
[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 #include "checkers.h"
17 #include "vector.h"
18 #include "structs.h"
19 #include "debug.h"
20
21 #define PROGRAM_SIZE    100
22 #define FIELD_PROGRAM
23
24 #define strfieldcpy(to, from) \
25 do { \
26         to[sizeof(to)-1] = '\0'; \
27         strncpy(to, from, sizeof(to)-1); \
28 } while (0)
29
30 int execute_program(char *path, char *value, int len)
31 {
32         int retval;
33         int count;
34         int status;
35         int fds[2];
36         pid_t pid;
37         char *pos;
38         char arg[PROGRAM_SIZE];
39         char *argv[sizeof(arg) / 2];
40         int i;
41
42         i = 0;
43
44         if (strchr(path, ' ')) {
45                 strfieldcpy(arg, path);
46                 pos = arg;
47                 while (pos != NULL) {
48                         if (pos[0] == '\'') {
49                                 /* don't separate if in apostrophes */
50                                 pos++;
51                                 argv[i] = strsep(&pos, "\'");
52                                 while (pos[0] == ' ')
53                                         pos++;
54                         } else {
55                                 argv[i] = strsep(&pos, " ");
56                         }
57                         i++;
58                 }
59         } else {
60                 argv[i++] = path;
61         }
62         argv[i] =  NULL;
63
64         retval = pipe(fds);
65
66         if (retval != 0)
67                 return -1;
68
69
70         pid = fork();
71
72         switch(pid) {
73         case 0:
74                 /* child */
75                 close(STDOUT_FILENO);
76
77                 /* dup write side of pipe to STDOUT */
78                 dup(fds[1]);
79
80                 retval = execv(argv[0], argv);
81
82                 exit(-1);
83         case -1:
84                 return -1;
85         default:
86                 /* parent reads from fds[0] */
87                 close(fds[1]);
88                 retval = 0;
89                 i = 0;
90                 while (1) {
91                         count = read(fds[0], value + i, len - i-1);
92                         if (count <= 0)
93                                 break;
94
95                         i += count;
96                         if (i >= len-1) {
97                                 retval = -1;
98                                 break;
99                         }
100                 }
101
102                 if (count < 0)
103                         retval = -1;
104
105                 if (i > 0 && value[i-1] == '\n')
106                         i--;
107                 value[i] = '\0';
108
109                 wait(&status);
110                 close(fds[0]);
111
112                 if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0))
113                         retval = -1;
114         }
115         return retval;
116 }
117
118 extern int
119 apply_format (char * string, char * cmd, struct path * pp)
120 {
121         char * pos;
122         char * dst;
123         char * p;
124         int len;
125         int myfree;
126
127         if (!string)
128                 return 1;
129
130         if (!cmd)
131                 return 1;
132
133         dst = cmd;
134         p = dst;
135         pos = strchr(string, '%');
136         myfree = CALLOUT_MAX_SIZE;
137
138         if (!pos) {
139                 strcpy(dst, string);
140                 return 0;
141         }
142
143         len = (int) (pos - string) + 1;
144         myfree -= len;
145
146         if (myfree < 2)
147                 return 1;
148
149         snprintf(p, len, "%s", string);
150         p += len - 1;
151         pos++;
152
153         switch (*pos) {
154         case 'n':
155                 len = strlen(pp->dev) + 1;
156                 myfree -= len;
157
158                 if (myfree < 2)
159                         return 1;
160
161                 snprintf(p, len, "%s", pp->dev);
162                 p += len - 1;
163                 break;
164         case 'd':
165                 len = strlen(pp->dev_t) + 1;
166                 myfree -= len;
167
168                 if (myfree < 2)
169                         return 1;
170
171                 snprintf(p, len, "%s", pp->dev_t);
172                 p += len - 1;
173                 break;
174         default:
175                 break;
176         }
177         pos++;
178
179         if (!*pos)
180                 return 0;
181
182         len = strlen(pos) + 1;
183         myfree -= len;
184
185         if (myfree < 2)
186                 return 1;
187
188         snprintf(p, len, "%s", pos);
189         condlog(3, "reformated callout = %s", dst);
190         return 0;
191 }
192