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