File: | libglusterfs/src/run.c |
Location: | line 311, column 17 |
Description: | Value stored to 'ret' is never read |
1 | /* |
2 | Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> |
3 | This file is part of GlusterFS. |
4 | |
5 | This file is licensed to you under your choice of the GNU Lesser |
6 | General Public License, version 3 or any later version (LGPLv3 or |
7 | later), or the GNU General Public License, version 2 (GPLv2), in all |
8 | cases as published by the Free Software Foundation. |
9 | */ |
10 | |
11 | #ifndef _GNU_SOURCE1 |
12 | #define _GNU_SOURCE1 |
13 | #endif |
14 | |
15 | #include <stdio.h> |
16 | #include <unistd.h> |
17 | #include <stdlib.h> |
18 | #include <stdarg.h> |
19 | #include <string.h> |
20 | #include <errno(*__errno_location ()).h> |
21 | #include <fcntl.h> |
22 | #include <dirent.h> |
23 | #include <assert.h> |
24 | #include <signal.h> |
25 | #include <sys/wait.h> |
26 | #include <sys/resource.h> |
27 | |
28 | #ifdef RUN_STANDALONE |
29 | #define GF_CALLOC(n, s, t)__gf_calloc (n, s, t) calloc(n, s) |
30 | #define GF_ASSERT(cond)do { if (!(cond)) { do { do { if (0) printf ("Assertion failed: " "cond"); } while (0); _gf_log_callingfn ("", "run.c", __FUNCTION__ , 30, GF_LOG_ERROR, "Assertion failed: " "cond"); } while (0) ; } } while (0) assert(cond)((cond) ? (void) (0) : __assert_fail ("cond", "run.c", 30, __PRETTY_FUNCTION__ )) |
31 | #define GF_REALLOC(p, s)__gf_realloc (p, s) realloc(p, s) |
32 | #define GF_FREE(p)__gf_free (p) free(p) |
33 | #define gf_strdup(s) strdup(s) |
34 | #define gf_vasprintf(p, f, va) vasprintf(p, f, va) |
35 | #define gf_loglevel_t int |
36 | #define gf_log(dom, levl, fmt, args...)do { do { if (0) printf (fmt, args...); } while (0); _gf_log ( dom, "run.c", __FUNCTION__, 36, levl, fmt, args...); } while ( 0) printf("LOG: " fmt "\n", ##args) |
37 | #define LOG_DEBUG 0 |
38 | #ifdef __linux__1 |
39 | #define GF_LINUX_HOST_OS1 |
40 | #endif |
41 | #else /* ! RUN_STANDALONE */ |
42 | #include "glusterfs.h" |
43 | #include "common-utils.h" |
44 | #endif |
45 | |
46 | #include "run.h" |
47 | |
48 | void |
49 | runinit (runner_t *runner) |
50 | { |
51 | int i = 0; |
52 | |
53 | runner->argvlen = 64; |
54 | runner->argv = GF_CALLOC (runner->argvlen,__gf_calloc (runner->argvlen, sizeof (*runner->argv), gf_common_mt_run_argv ) |
55 | sizeof (*runner->argv),__gf_calloc (runner->argvlen, sizeof (*runner->argv), gf_common_mt_run_argv ) |
56 | gf_common_mt_run_argv)__gf_calloc (runner->argvlen, sizeof (*runner->argv), gf_common_mt_run_argv ); |
57 | runner->runerr = runner->argv ? 0 : errno(*__errno_location ()); |
58 | runner->chpid = -1; |
59 | for (i = 0; i < 3; i++) { |
60 | runner->chfd[i] = -1; |
61 | runner->chio[i] = NULL((void*)0); |
62 | } |
63 | } |
64 | |
65 | FILE * |
66 | runner_chio (runner_t *runner, int fd) |
67 | { |
68 | GF_ASSERT (fd > 0 && fd < 3)do { if (!(fd > 0 && fd < 3)) { do { do { if (0 ) printf ("Assertion failed: " "fd > 0 && fd < 3" ); } while (0); _gf_log_callingfn ("", "run.c", __FUNCTION__, 68, GF_LOG_ERROR, "Assertion failed: " "fd > 0 && fd < 3" ); } while (0); } } while (0); |
69 | |
70 | if ((fd > 0) && (fd < 3)) |
71 | return runner->chio[fd]; |
72 | |
73 | return NULL((void*)0); |
74 | } |
75 | |
76 | static void |
77 | runner_insert_arg (runner_t *runner, char *arg) |
78 | { |
79 | int i = 0; |
80 | |
81 | GF_ASSERT (arg)do { if (!(arg)) { do { do { if (0) printf ("Assertion failed: " "arg"); } while (0); _gf_log_callingfn ("", "run.c", __FUNCTION__ , 81, GF_LOG_ERROR, "Assertion failed: " "arg"); } while (0); } } while (0); |
82 | |
83 | if (runner->runerr) |
84 | return; |
85 | |
86 | for (i = 0; i < runner->argvlen; i++) { |
87 | if (runner->argv[i] == NULL((void*)0)) |
88 | break; |
89 | } |
90 | GF_ASSERT (i < runner->argvlen)do { if (!(i < runner->argvlen)) { do { do { if (0) printf ("Assertion failed: " "i < runner->argvlen"); } while ( 0); _gf_log_callingfn ("", "run.c", __FUNCTION__, 90, GF_LOG_ERROR , "Assertion failed: " "i < runner->argvlen"); } while ( 0); } } while (0); |
91 | |
92 | if (i == runner->argvlen - 1) { |
93 | runner->argv = GF_REALLOC (runner->argv,__gf_realloc (runner->argv, runner->argvlen * 2 * sizeof (*runner->argv)) |
94 | runner->argvlen * 2 * sizeof (*runner->argv))__gf_realloc (runner->argv, runner->argvlen * 2 * sizeof (*runner->argv)); |
95 | if (!runner->argv) { |
96 | runner->runerr = errno(*__errno_location ()); |
97 | return; |
98 | } |
99 | memset (/* "+" is aware of the type of its left side, |
100 | * no need to multiply with type-size */ |
101 | runner->argv + runner->argvlen, |
102 | 0, runner->argvlen * sizeof (*runner->argv)); |
103 | runner->argvlen *= 2; |
104 | } |
105 | |
106 | runner->argv[i] = arg; |
107 | } |
108 | |
109 | void |
110 | runner_add_arg (runner_t *runner, const char *arg) |
111 | { |
112 | arg = gf_strdup (arg); |
113 | if (!arg) { |
114 | runner->runerr = errno(*__errno_location ()); |
115 | return; |
116 | } |
117 | |
118 | runner_insert_arg (runner, (char *)arg); |
119 | } |
120 | |
121 | static void |
122 | runner_va_add_args (runner_t *runner, va_list argp) |
123 | { |
124 | const char *arg; |
125 | |
126 | while ((arg = va_arg (argp, const char *)__builtin_va_arg(argp, const char *))) |
127 | runner_add_arg (runner, arg); |
128 | } |
129 | |
130 | void |
131 | runner_add_args (runner_t *runner, ...) |
132 | { |
133 | va_list argp; |
134 | |
135 | va_start (argp, runner)__builtin_va_start(argp, runner); |
136 | runner_va_add_args (runner, argp); |
137 | va_end (argp)__builtin_va_end(argp); |
138 | } |
139 | |
140 | void |
141 | runner_argprintf (runner_t *runner, const char *format, ...) |
142 | { |
143 | va_list argva; |
144 | char *arg = NULL((void*)0); |
145 | int ret = 0; |
146 | |
147 | va_start (argva, format)__builtin_va_start(argva, format); |
148 | ret = gf_vasprintf (&arg, format, argva); |
149 | va_end (argva)__builtin_va_end(argva); |
150 | |
151 | if (ret < 0) { |
152 | runner->runerr = errno(*__errno_location ()); |
153 | return; |
154 | } |
155 | |
156 | runner_insert_arg (runner, arg); |
157 | } |
158 | |
159 | void |
160 | runner_log (runner_t *runner, const char *dom, gf_loglevel_t lvl, |
161 | const char *msg) |
162 | { |
163 | char *buf = NULL((void*)0); |
164 | size_t len = 0; |
165 | int i = 0; |
166 | |
167 | if (runner->runerr) |
168 | return; |
169 | |
170 | for (i = 0;; i++) { |
171 | if (runner->argv[i] == NULL((void*)0)) |
172 | break; |
173 | len += (strlen (runner->argv[i]) + 1); |
174 | } |
175 | |
176 | buf = GF_CALLOC (1, len + 1, gf_common_mt_run_logbuf)__gf_calloc (1, len + 1, gf_common_mt_run_logbuf); |
177 | if (!buf) { |
178 | runner->runerr = errno(*__errno_location ()); |
179 | return; |
180 | } |
181 | for (i = 0;; i++) { |
182 | if (runner->argv[i] == NULL((void*)0)) |
183 | break; |
184 | strcat (buf, runner->argv[i]); |
185 | strcat (buf, " "); |
186 | } |
187 | if (len > 0) |
188 | buf[len - 1] = '\0'; |
189 | |
190 | gf_log (dom, lvl, "%s: %s", msg, buf)do { do { if (0) printf ("%s: %s", msg, buf); } while (0); _gf_log (dom, "run.c", __FUNCTION__, 190, lvl, "%s: %s", msg, buf); } while (0); |
191 | |
192 | GF_FREE (buf)__gf_free (buf); |
193 | } |
194 | |
195 | void |
196 | runner_redir (runner_t *runner, int fd, int tgt_fd) |
197 | { |
198 | GF_ASSERT (fd > 0 && fd < 3)do { if (!(fd > 0 && fd < 3)) { do { do { if (0 ) printf ("Assertion failed: " "fd > 0 && fd < 3" ); } while (0); _gf_log_callingfn ("", "run.c", __FUNCTION__, 198, GF_LOG_ERROR, "Assertion failed: " "fd > 0 && fd < 3" ); } while (0); } } while (0); |
199 | |
200 | if ((fd > 0) && (fd < 3)) |
201 | runner->chfd[fd] = (tgt_fd >= 0) ? tgt_fd : -2; |
202 | } |
203 | |
204 | int |
205 | runner_start (runner_t *runner) |
206 | { |
207 | int pi[3][2] = {{-1, -1}, {-1, -1}, {-1, -1}}; |
208 | int xpi[2]; |
209 | int ret = 0; |
210 | int errno_priv = 0; |
211 | int i = 0; |
212 | sigset_t set; |
213 | |
214 | if (runner->runerr) { |
215 | errno(*__errno_location ()) = runner->runerr; |
216 | return -1; |
217 | } |
218 | |
219 | GF_ASSERT (runner->argv[0])do { if (!(runner->argv[0])) { do { do { if (0) printf ("Assertion failed: " "runner->argv[0]"); } while (0); _gf_log_callingfn ("", "run.c" , __FUNCTION__, 219, GF_LOG_ERROR, "Assertion failed: " "runner->argv[0]" ); } while (0); } } while (0); |
220 | |
221 | /* set up a channel to child to communicate back |
222 | * possible execve(2) failures |
223 | */ |
224 | ret = pipe(xpi); |
225 | if (ret != -1) |
226 | ret = fcntl (xpi[1], F_SETFD2, FD_CLOEXEC1); |
227 | |
228 | for (i = 0; i < 3; i++) { |
229 | if (runner->chfd[i] != -2) |
230 | continue; |
231 | ret = pipe (pi[i]); |
232 | if (ret != -1) { |
233 | runner->chio[i] = fdopen (pi[i][i ? 0 : 1], i ? "r" : "w"); |
234 | if (!runner->chio[i]) |
235 | ret = -1; |
236 | } |
237 | } |
238 | |
239 | if (ret != -1) |
240 | runner->chpid = fork (); |
241 | switch (runner->chpid) { |
242 | case -1: |
243 | errno_priv = errno(*__errno_location ()); |
244 | close (xpi[0]); |
245 | close (xpi[1]); |
246 | for (i = 0; i < 3; i++) { |
247 | close (pi[i][0]); |
248 | close (pi[i][1]); |
249 | } |
250 | errno(*__errno_location ()) = errno_priv; |
251 | return -1; |
252 | case 0: |
253 | for (i = 0; i < 3; i++) |
254 | close (pi[i][i ? 0 : 1]); |
255 | close (xpi[0]); |
256 | ret = 0; |
257 | |
258 | for (i = 0; i < 3; i++) { |
259 | if (ret == -1) |
260 | break; |
261 | switch (runner->chfd[i]) { |
262 | case -1: |
263 | /* no redir */ |
264 | break; |
265 | case -2: |
266 | /* redir to pipe */ |
267 | ret = dup2 (pi[i][i ? 1 : 0], i); |
268 | break; |
269 | default: |
270 | /* redir to file */ |
271 | ret = dup2 (runner->chfd[i], i); |
272 | } |
273 | } |
274 | |
275 | if (ret != -1 ) { |
276 | #ifdef GF_LINUX_HOST_OS1 |
277 | DIR *d = NULL((void*)0); |
278 | struct dirent *de = NULL((void*)0); |
279 | char *e = NULL((void*)0); |
280 | |
281 | d = opendir ("/proc/self/fd"); |
282 | if (d) { |
283 | while ((de = readdir (d))) { |
284 | i = strtoul (de->d_name, &e, 10); |
285 | if (*e == '\0' && i > 2 && |
286 | i != dirfd (d) && i != xpi[1]) |
287 | close (i); |
288 | } |
289 | closedir (d); |
290 | } else |
291 | ret = -1; |
292 | #else |
293 | struct rlimit rl; |
294 | ret = getrlimit (RLIMIT_NOFILERLIMIT_NOFILE, &rl); |
295 | GF_ASSERT (ret == 0)do { if (!(ret == 0)) { do { do { if (0) printf ("Assertion failed: " "ret == 0"); } while (0); _gf_log_callingfn ("", "run.c", __FUNCTION__ , 295, GF_LOG_ERROR, "Assertion failed: " "ret == 0"); } while (0); } } while (0); |
296 | |
297 | for (i = 3; i < rl.rlim_cur; i++) { |
298 | if (i != xpi[1]) |
299 | close (i); |
300 | } |
301 | #endif |
302 | } |
303 | |
304 | if (ret != -1) { |
305 | /* save child from inheriting our singal handling */ |
306 | sigemptyset (&set); |
307 | sigprocmask (SIG_SETMASK2, &set, NULL((void*)0)); |
308 | |
309 | execvp (runner->argv[0], runner->argv); |
310 | } |
311 | ret = write (xpi[1], &errno(*__errno_location ()), sizeof (errno(*__errno_location ()))); |
Value stored to 'ret' is never read | |
312 | _exit (1); |
313 | } |
314 | |
315 | errno_priv = errno(*__errno_location ()); |
316 | for (i = 0; i < 3; i++) |
317 | close (pi[i][i ? 1 : 0]); |
318 | close (xpi[1]); |
319 | if (ret == -1) { |
320 | for (i = 0; i < 3; i++) { |
321 | if (runner->chio[i]) { |
322 | fclose (runner->chio[i]); |
323 | runner->chio[i] = NULL((void*)0); |
324 | } |
325 | } |
326 | } else { |
327 | ret = read (xpi[0], (char *)&errno_priv, sizeof (errno_priv)); |
328 | close (xpi[0]); |
329 | if (ret <= 0) |
330 | return 0; |
331 | GF_ASSERT (ret == sizeof (errno_priv))do { if (!(ret == sizeof (errno_priv))) { do { do { if (0) printf ("Assertion failed: " "ret == sizeof (errno_priv)"); } while (0); _gf_log_callingfn ("", "run.c", __FUNCTION__, 331, GF_LOG_ERROR , "Assertion failed: " "ret == sizeof (errno_priv)"); } while (0); } } while (0); |
332 | } |
333 | errno(*__errno_location ()) = errno_priv; |
334 | return -1; |
335 | } |
336 | |
337 | int |
338 | runner_end_reuse (runner_t *runner) |
339 | { |
340 | int i = 0; |
341 | int ret = -1; |
342 | int chstat = 0; |
343 | |
344 | if (runner->chpid > 0) { |
345 | if (waitpid (runner->chpid, &chstat, 0) == runner->chpid) |
346 | ret = chstat; |
347 | } |
348 | |
349 | for (i = 0; i < 3; i++) { |
350 | if (runner->chio[i]) { |
351 | fclose (runner->chio[i]); |
352 | runner->chio[i] = NULL((void*)0); |
353 | } |
354 | } |
355 | |
356 | return ret; |
357 | } |
358 | |
359 | int |
360 | runner_end (runner_t *runner) |
361 | { |
362 | int i = 0; |
363 | int ret = -1; |
364 | char **p = NULL((void*)0); |
365 | |
366 | ret = runner_end_reuse (runner); |
367 | |
368 | if (runner->argv) { |
369 | for (p = runner->argv; *p; p++) |
370 | GF_FREE (*p)__gf_free (*p); |
371 | GF_FREE (runner->argv)__gf_free (runner->argv); |
372 | } |
373 | for (i = 0; i < 3; i++) |
374 | close (runner->chfd[i]); |
375 | |
376 | return ret; |
377 | } |
378 | |
379 | static int |
380 | runner_run_generic (runner_t *runner, int (*rfin)(runner_t *runner)) |
381 | { |
382 | int ret = 0; |
383 | |
384 | ret = runner_start (runner); |
385 | |
386 | return -(rfin (runner) || ret); |
387 | } |
388 | |
389 | int |
390 | runner_run (runner_t *runner) |
391 | { |
392 | return runner_run_generic (runner, runner_end); |
393 | } |
394 | |
395 | |
396 | int |
397 | runner_run_nowait (runner_t *runner) |
398 | { |
399 | int pid; |
400 | |
401 | pid = fork (); |
402 | |
403 | if (!pid) { |
404 | setsid (); |
405 | _exit (runner_start (runner)); |
406 | } |
407 | |
408 | if (pid > 0) |
409 | runner->chpid = pid; |
410 | return runner_end (runner); |
411 | } |
412 | |
413 | |
414 | int |
415 | runner_run_reuse (runner_t *runner) |
416 | { |
417 | return runner_run_generic (runner, runner_end_reuse); |
418 | } |
419 | |
420 | int |
421 | runcmd (const char *arg, ...) |
422 | { |
423 | runner_t runner; |
424 | va_list argp; |
425 | |
426 | runinit (&runner); |
427 | /* ISO C requires a named argument before '...' */ |
428 | runner_add_arg (&runner, arg); |
429 | |
430 | va_start (argp, arg)__builtin_va_start(argp, arg); |
431 | runner_va_add_args (&runner, argp); |
432 | va_end (argp)__builtin_va_end(argp); |
433 | |
434 | return runner_run (&runner); |
435 | } |
436 | |
437 | #ifdef RUN_DO_TESTS |
438 | static void |
439 | TBANNER (const char *txt) |
440 | { |
441 | printf("######\n### testing %s\n", txt); |
442 | } |
443 | |
444 | int |
445 | main (int argc, char **argv) |
446 | { |
447 | runner_t runner; |
448 | char buf[80]; |
449 | char *wdbuf;; |
450 | int ret; |
451 | int fd; |
452 | long pathmax = pathconf ("/", _PC_PATH_MAX_PC_PATH_MAX); |
453 | struct timeval tv = {0,}; |
454 | struct timeval *tvp = NULL((void*)0); |
455 | |
456 | wdbuf = malloc (pathmax); |
457 | assert (wdbuf)((wdbuf) ? (void) (0) : __assert_fail ("wdbuf", "run.c", 457, __PRETTY_FUNCTION__)); |
458 | getcwd (wdbuf, pathmax); |
459 | |
460 | TBANNER ("basic functionality"); |
461 | runcmd ("echo", "a", "b", NULL((void*)0)); |
462 | |
463 | TBANNER ("argv extension"); |
464 | runcmd ("echo", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", |
465 | "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", |
466 | "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", |
467 | "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", |
468 | "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", |
469 | "51", "52", "53", "54", "55", "56", "57", "58", "59", "60", |
470 | "61", "62", "63", "64", "65", "66", "67", "68", "69", "70", |
471 | "71", "72", "73", "74", "75", "76", "77", "78", "79", "80", |
472 | "81", "82", "83", "84", "85", "86", "87", "88", "89", "90", |
473 | "91", "92", "93", "94", "95", "96", "97", "98", "99", "100", NULL((void*)0)); |
474 | |
475 | TBANNER ("add_args, argprintf, log, and popen-style functionality"); |
476 | runinit (&runner); |
477 | runner_add_args (&runner, "echo", "pid:", NULL((void*)0)); |
478 | runner_argprintf (&runner, "%d\n", getpid()); |
479 | runner_add_arg (&runner, "wd:"); |
480 | runner_add_arg (&runner, wdbuf); |
481 | runner_redir (&runner, 1, RUN_PIPE-1); |
482 | runner_start (&runner); |
483 | runner_log (&runner, "(x)", LOG_DEBUG, "starting program"); |
484 | while (fgets (buf, sizeof(buf), runner_chio (&runner, 1))) |
485 | printf ("got: %s", buf); |
486 | runner_end (&runner); |
487 | |
488 | TBANNER ("execve error reporting"); |
489 | ret = runcmd ("bafflavvitty", NULL((void*)0)); |
490 | printf ("%d %d [%s]\n", ret, errno(*__errno_location ()), strerror (errno(*__errno_location ()))); |
491 | |
492 | TBANNER ("output redirection"); |
493 | fd = mkstemp ("/tmp/foof"); |
494 | assert (fd != -1)((fd != -1) ? (void) (0) : __assert_fail ("fd != -1", "run.c" , 494, __PRETTY_FUNCTION__)); |
495 | runinit (&runner); |
496 | runner_add_args (&runner, "echo", "foo", NULL((void*)0)); |
497 | runner_redir (&runner, 1, fd); |
498 | ret = runner_run (&runner); |
499 | printf ("%d", ret); |
500 | if (ret != 0) |
501 | printf (" %d [%s]", errno(*__errno_location ()), strerror (errno(*__errno_location ()))); |
502 | putchar ('\n'); |
503 | |
504 | if (argc > 1) { |
505 | tv.tv_sec = strtoul (argv[1], NULL((void*)0), 10); |
506 | if (tv.tv_sec > 0) |
507 | tvp = &tv; |
508 | select (0, 0, 0, 0, tvp); |
509 | } |
510 | |
511 | return 0; |
512 | } |
513 | #endif |