1 /*
2 * Process spawn functions
3 * Copyright (C) 2008 Andreas Öman
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <sys/types.h>
20 #include <sys/wait.h>
21 #include <sys/stat.h>
22 #include <stdio.h>
23 #include <unistd.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <assert.h>
28 #include <syslog.h>
29 #include <fcntl.h>
30 #include <dirent.h>
31 #include <signal.h>
32
33 #include "tvheadend.h"
34 #include "tvhpoll.h"
35 #include "file.h"
36 #include "spawn.h"
37
38 #if ENABLE_ANDROID
39 #define WIFCONTINUED(s) ((s) == 0xffff)
40 #endif
41
42 extern char **environ;
43
44 pthread_mutex_t spawn_mutex = PTHREAD_MUTEX_INITIALIZER;
45
46 static LIST_HEAD(, spawn) spawns;
47
48 static char *spawn_info_buf = NULL;
49 static char *spawn_error_buf = NULL;
50
51 static th_pipe_t spawn_pipe_info;
52 static th_pipe_t spawn_pipe_error;
53
54 static pthread_t spawn_pipe_tid;
55
56 static int spawn_pipe_running;
57
58 typedef struct spawn {
59 LIST_ENTRY(spawn) link;
60 pid_t pid;
61 const char *name;
62 int64_t killed;
63 } spawn_t;
64
65 static void spawn_reaper(void);
66
67 /*
68 *
69 */
70 #define SPAWN_PIPE_READ_SIZE 4096
71
72 static void
spawn_pipe_read(th_pipe_t * p,char ** _buf,int level)73 spawn_pipe_read( th_pipe_t *p, char **_buf, int level )
74 {
75 char *buf = *_buf, *s;
76 size_t len;
77 int r;
78
79 if (buf == NULL) {
80 buf = malloc(SPAWN_PIPE_READ_SIZE);
81 buf[0] = '\0';
82 buf[SPAWN_PIPE_READ_SIZE - 1] = 0;
83 *_buf = buf;
84 }
85 while (1) {
86 len = strlen(buf);
87 r = read(p->rd, buf + len, SPAWN_PIPE_READ_SIZE - 1 - len);
88 if (r < 1) {
89 if (errno == EAGAIN)
90 break;
91 if (ERRNO_AGAIN(errno))
92 continue;
93 break;
94 }
95 buf[len + r] = '\0';
96 tvhlog_hexdump(LS_SPAWN, buf + len, r);
97 while (1) {
98 s = buf;
99 while (*s && *s != '\n' && *s != '\r')
100 s++;
101 if (*s == '\0')
102 break;
103 *s++ = '\0';
104 if (buf[0])
105 tvhlog(level, LS_SPAWN, "%s", buf);
106 memmove(buf, s, strlen(s) + 1);
107 }
108 if (strlen(buf) == SPAWN_PIPE_READ_SIZE - 1) {
109 tvherror(LS_SPAWN, "pipe buffer full");
110 buf[0] = '\0';
111 }
112 }
113 }
114
115 static void *
spawn_pipe_thread(void * aux)116 spawn_pipe_thread(void *aux)
117 {
118 tvhpoll_event_t ev[2];
119 tvhpoll_t *efd = tvhpoll_create(2);
120 int nfds;
121
122 memset(ev, 0, sizeof(ev));
123 ev[0].events = TVHPOLL_IN;
124 ev[0].fd = spawn_pipe_info.rd;
125 ev[0].data.ptr = &spawn_pipe_info;
126 ev[1].events = TVHPOLL_IN;
127 ev[1].fd = spawn_pipe_error.rd;
128 ev[1].data.ptr = &spawn_pipe_error;
129 tvhpoll_add(efd, ev, 2);
130
131 while (atomic_get(&spawn_pipe_running)) {
132
133 nfds = tvhpoll_wait(efd, ev, 2, 500);
134
135 if (nfds > 0) {
136 spawn_pipe_read(&spawn_pipe_info, &spawn_info_buf, LOG_INFO);
137 spawn_pipe_read(&spawn_pipe_error, &spawn_error_buf, LOG_ERR);
138 }
139 spawn_reaper();
140
141 }
142
143 tvhpoll_destroy(efd);
144 return NULL;
145 }
146
147 static void
spawn_pipe_write(th_pipe_t * p,const char * fmt,va_list ap)148 spawn_pipe_write( th_pipe_t *p, const char *fmt, va_list ap )
149 {
150 char buf[512], *s = buf;
151 int r;
152
153 vsnprintf(buf, sizeof(buf), fmt, ap);
154 while (*s) {
155 r = write(p->wr, s, strlen(s));
156 if (r < 0) {
157 if (errno == EAGAIN)
158 break;
159 if (ERRNO_AGAIN(errno))
160 continue;
161 break;
162 }
163 if (!r)
164 break;
165 s += r;
166 }
167 }
168
169 void
spawn_info(const char * fmt,...)170 spawn_info( const char *fmt, ... )
171 {
172 va_list ap;
173
174 va_start(ap, fmt);
175 spawn_pipe_write(&spawn_pipe_info, fmt, ap);
176 va_end(ap);
177 }
178
179 void
spawn_error(const char * fmt,...)180 spawn_error( const char *fmt, ... )
181 {
182 va_list ap;
183
184 va_start(ap, fmt);
185 spawn_pipe_write(&spawn_pipe_error, fmt, ap);
186 va_end(ap);
187 }
188
189 /*
190 * Search PATH for executable
191 */
192 int
find_exec(const char * name,char * out,size_t len)193 find_exec ( const char *name, char *out, size_t len )
194 {
195 int ret = 0;
196 char bin[512];
197 char *path, *tmp, *tmp2 = NULL;
198 DIR *dir;
199 struct dirent *de;
200 struct stat st;
201 if (name[0] == '/') {
202 if (lstat(name, &st)) return 0;
203 if (!S_ISREG(st.st_mode) || !(st.st_mode & S_IEXEC)) return 0;
204 strlcpy(out, name, len);
205 return 1;
206 }
207 if (!(path = getenv("PATH"))) return 0;
208 path = strdup(path);
209 tmp = strtok_r(path, ":", &tmp2);
210 while (tmp && !ret) {
211 if ((dir = opendir(tmp))) {
212 while ((de = readdir(dir))) {
213 if (strstr(de->d_name, name) != de->d_name) continue;
214 snprintf(bin, sizeof(bin), "%s/%s", tmp, de->d_name);
215 if (lstat(bin, &st)) continue;
216 if (!S_ISREG(st.st_mode) || !(st.st_mode & S_IEXEC)) continue;
217 strlcpy(out, bin, len);
218 ret = 1;
219 break;
220 }
221 closedir(dir);
222 }
223 tmp = strtok_r(NULL, ":", &tmp2);
224 }
225 free(path);
226 return ret;
227 }
228
229 /**
230 * Reap one child
231 */
232 int
spawn_reap(pid_t wpid,char * stxt,size_t stxtlen)233 spawn_reap(pid_t wpid, char *stxt, size_t stxtlen)
234 {
235 pid_t pid;
236 int status, res;
237 spawn_t *s;
238
239 pid = waitpid(wpid, &status, WNOHANG);
240 if(pid < 0 && ERRNO_AGAIN(errno))
241 return -EAGAIN;
242 if(pid < 0)
243 return -errno;
244 if(pid < 1) {
245 if (wpid > 0 && pid != wpid)
246 return -EAGAIN;
247 return 0;
248 }
249
250 pthread_mutex_lock(&spawn_mutex);
251 LIST_FOREACH(s, &spawns, link)
252 if(s->pid == pid)
253 break;
254
255 res = -EIO;
256 if (WIFEXITED(status)) {
257 res = WEXITSTATUS(status);
258 if (stxt)
259 snprintf(stxt, stxtlen, "exited, status=%d", WEXITSTATUS(status));
260 } else if (WIFSIGNALED(status)) {
261 if (stxt)
262 snprintf(stxt, stxtlen, "killed by signal %d, "
263 "stopped by signal %d",
264 WTERMSIG(status),
265 WSTOPSIG(status));
266 } else if (WIFCONTINUED(status)) {
267 if (stxt)
268 snprintf(stxt, stxtlen, "continued");
269 } else {
270 if (stxt)
271 snprintf(stxt, stxtlen, "unknown status");
272 }
273
274 if(s != NULL) {
275 LIST_REMOVE(s, link);
276 free((void *)s->name);
277 free(s);
278 }
279 pthread_mutex_unlock(&spawn_mutex);
280 return res;
281 }
282
283 /**
284 * The reaper is called once a second to finish of any pending spawns
285 */
286 static void
spawn_reaper(void)287 spawn_reaper(void)
288 {
289 int r;
290 spawn_t *s;
291
292 do {
293 r = spawn_reap(-1, NULL, 0);
294 if (r == -EAGAIN)
295 continue;
296 if (r <= 0)
297 break;
298 } while (1);
299
300 /* forced kill for expired PIDs */
301 pthread_mutex_lock(&spawn_mutex);
302 LIST_FOREACH(s, &spawns, link)
303 if (s->killed && s->killed < mclk()) {
304 /* kill the whole process group */
305 r = kill(-(s->pid), SIGKILL);
306 if (r && errno == EPERM)
307 tvherror(LS_SPAWN, "Unable to kill task pid %d (not enough permissions)", s->pid);
308 }
309 pthread_mutex_unlock(&spawn_mutex);
310 }
311
312 /**
313 * Kill the pid (only if waiting)
314 */
315 int
spawn_kill(pid_t pid,int sig,int timeout)316 spawn_kill(pid_t pid, int sig, int timeout)
317 {
318 int r = -ESRCH;
319 spawn_t *s;
320
321 if (pid > 0) {
322 spawn_reaper();
323
324 pthread_mutex_lock(&spawn_mutex);
325 LIST_FOREACH(s, &spawns, link)
326 if(s->pid == pid)
327 break;
328 if (s) {
329 if (!s->killed)
330 s->killed = mclk() + sec2mono(MINMAX(timeout, 5, 3600));
331 /* kill the whole process group */
332 r = kill(-pid, sig);
333 if (r < 0) {
334 if (errno == EPERM)
335 tvherror(LS_SPAWN, "Unable to kill task pid %d (not enough permissions)", s->pid);
336 r = -errno;
337 }
338 }
339 pthread_mutex_unlock(&spawn_mutex);
340 }
341 return r;
342 }
343
344 /**
345 * Enqueue a spawn on the pending spawn list
346 */
347 static spawn_t *
spawn_enq(const char * name,int pid)348 spawn_enq(const char *name, int pid)
349 {
350 spawn_t *s = calloc(1, sizeof(spawn_t));
351 s->name = strdup(name);
352 s->pid = pid;
353 pthread_mutex_lock(&spawn_mutex);
354 LIST_INSERT_HEAD(&spawns, s, link);
355 pthread_mutex_unlock(&spawn_mutex);
356 return s;
357 }
358
359
360 /**
361 *
362 */
363 int
spawn_parse_args(char *** argv,int argc,const char * cmd,const char ** replace)364 spawn_parse_args(char ***argv, int argc, const char *cmd, const char **replace)
365 {
366 char *s, *f, *p, *a;
367 const char **r;
368 int i = 0, l, eow;
369
370 if (!argv || !cmd)
371 return -1;
372
373 s = tvh_strdupa(cmd);
374 *argv = calloc(argc, sizeof(char *));
375
376 while (*s && i < argc - 1) {
377 while (*s == ' ')
378 s++;
379 f = s;
380 eow = 0;
381 while (*s) {
382 if (*s == '\\') {
383 l = *(s + 1);
384 if (l == 'b')
385 l = '\b';
386 else if (l == 'f')
387 l = '\f';
388 else if (l == 'n')
389 l = '\n';
390 else if (l == 'r')
391 l = '\r';
392 else if (l == 't')
393 l = '\t';
394 else
395 l = 0;
396 if (l) {
397 *s++ = l;
398 memmove(s, s + 1, strlen(s));
399 } else {
400 memmove(s, s + 1, strlen(s));
401 if (*s)
402 s++;
403 }
404 } else if (eow) {
405 if (*s == eow) {
406 memmove(s, s + 1, strlen(s));
407 eow = 0;
408 } else {
409 s++;
410 }
411 } else if (*s == '\'' || *s == '"') {
412 eow = *s;
413 memmove(s, s + 1, strlen(s));
414 } else if (*s == ' ') {
415 break;
416 } else {
417 s++;
418 }
419 }
420 if (f != s) {
421 if (*s) {
422 *(char *)s = '\0';
423 s++;
424 }
425 for (r = replace; r && *r; r += 2) {
426 p = strstr(f, *r);
427 if (p) {
428 l = strlen(*r);
429 a = malloc(strlen(f) + strlen(r[1]) + 1);
430 *p = '\0';
431 strcpy(a, f);
432 strcat(a, r[1]);
433 strcat(a, p + l);
434 (*argv)[i++] = a;
435 break;
436 }
437 }
438 if (r && *r)
439 continue;
440 (*argv)[i++] = strdup(f);
441 }
442 }
443 (*argv)[i] = NULL;
444 return 0;
445 }
446
447 /**
448 *
449 */
450 void
spawn_free_args(char ** argv)451 spawn_free_args(char **argv)
452 {
453 char **a = argv;
454 for (; *a; a++)
455 free(*a);
456 free(argv);
457 }
458
459 /**
460 * Execute the given program and return its standard output as file-descriptor (pipe).
461 */
462 int
spawn_and_give_stdout(const char * prog,char * argv[],char * envp[],int * rd,pid_t * pid,int redir_stderr)463 spawn_and_give_stdout(const char *prog, char *argv[], char *envp[],
464 int *rd, pid_t *pid, int redir_stderr)
465 {
466 pid_t p;
467 int fd[2], f, i, maxfd;
468 char bin[256];
469 const char *local_argv[2] = { NULL, NULL };
470 char **e, **e0, **e2, **e3, *p1, *p2;
471
472 if (*prog != '/' && *prog != '.') {
473 if (!find_exec(prog, bin, sizeof(bin))) return -1;
474 prog = bin;
475 }
476
477 if (!argv) argv = (void *)local_argv;
478 if (!argv[0]) {
479 if (argv != (void *)local_argv) {
480 for (i = 1, e = argv + 1; *e; i++, e++);
481 i = (i + 1) * sizeof(char *);
482 e = alloca(i);
483 memcpy(e, argv, i);
484 argv = e;
485 }
486 argv[0] = (char *)prog;
487 }
488
489 if (!envp || !envp[0]) {
490 e = environ;
491 } else {
492 for (i = 0, e2 = environ; *e2; i++, e2++);
493 for (f = 0, e2 = envp; *e2; f++, e2++);
494 e = alloca((i + f + 1) * sizeof(char *));
495 memcpy(e, environ, i * sizeof(char *));
496 e0 = e + i;
497 *e0 = NULL;
498 for (e2 = envp; *e2; e2++) {
499 for (e3 = e; *e3; e3++) {
500 p1 = strchr(*e2, '=');
501 p2 = strchr(*e3, '=');
502 if (p1 - *e2 == p2 - *e3 && !strncmp(*e2, *e3, p1 - *e2)) {
503 *e3 = *e2;
504 break;
505 }
506 }
507 if (!*e3) {
508 *e0++ = *e2;
509 *e0 = NULL;
510 }
511 }
512 *e0 = NULL;
513 }
514
515 maxfd = sysconf(_SC_OPEN_MAX);
516
517 pthread_mutex_lock(&fork_lock);
518
519 if(pipe(fd) == -1) {
520 pthread_mutex_unlock(&fork_lock);
521 return -1;
522 }
523
524 p = fork();
525
526 if(p == -1) {
527 pthread_mutex_unlock(&fork_lock);
528 tvherror(LS_SPAWN, "Unable to fork() for \"%s\" -- %s",
529 prog, strerror(errno));
530 return -1;
531 }
532
533 if(p == 0) {
534 f = open("/dev/null", O_RDWR);
535 if(f == -1) {
536 spawn_error("pid %d cannot open /dev/null for redirect %s -- %s",
537 getpid(), prog, strerror(errno));
538 exit(1);
539 }
540
541 close(0);
542 close(1);
543 close(2);
544
545 dup2(f, 0);
546 dup2(fd[1], 1);
547 dup2(redir_stderr ? spawn_pipe_error.wr : f, 2);
548
549 close(fd[0]);
550 close(fd[1]);
551 close(f);
552
553 spawn_info("Executing \"%s\"\n", prog);
554
555 for (f = 3; f < maxfd; f++)
556 close(f);
557
558 execve(prog, argv, e);
559 spawn_error("pid %d cannot execute %s -- %s\n",
560 getpid(), prog, strerror(errno));
561 exit(1);
562 }
563
564 pthread_mutex_unlock(&fork_lock);
565
566 spawn_enq(prog, p);
567
568 close(fd[1]);
569
570 *rd = fd[0];
571 if (pid) {
572 *pid = p;
573
574 // make the spawned process a session leader so killing the
575 // process group recursively kills any child process that
576 // might have been spawned
577 setpgid(p, p);
578 }
579 return 0;
580 }
581
582 /**
583 * Execute the given program with arguments
584 *
585 * *outp will point to the allocated buffer
586 * The function will return the size of the buffer
587 */
588 int
spawnv(const char * prog,char * argv[],pid_t * pid,int redir_stdout,int redir_stderr)589 spawnv(const char *prog, char *argv[], pid_t *pid, int redir_stdout, int redir_stderr)
590 {
591 pid_t p, f, maxfd;
592 char bin[256];
593 const char *local_argv[2] = { NULL, NULL };
594
595 if (*prog != '/' && *prog != '.') {
596 if (!find_exec(prog, bin, sizeof(bin))) return -1;
597 prog = bin;
598 }
599
600 if(!argv) argv = (void *)local_argv;
601 if (!argv[0]) argv[0] = (char*)prog;
602
603 maxfd = sysconf(_SC_OPEN_MAX);
604
605 pthread_mutex_lock(&fork_lock);
606
607 p = fork();
608
609 if(p == -1) {
610 pthread_mutex_unlock(&fork_lock);
611 tvherror(LS_SPAWN, "Unable to fork() for \"%s\" -- %s",
612 prog, strerror(errno));
613 return -1;
614 }
615
616 if(p == 0) {
617 f = open("/dev/null", O_RDWR);
618 if(f == -1) {
619 spawn_error("pid %d cannot open /dev/null for redirect %s -- %s",
620 getpid(), prog, strerror(errno));
621 exit(1);
622 }
623
624 close(0);
625 close(1);
626 close(2);
627
628 dup2(f, 0);
629 dup2(redir_stdout ? spawn_pipe_info.wr : f, 1);
630 dup2(redir_stderr ? spawn_pipe_error.wr : f, 2);
631
632 close(f);
633
634 spawn_info("Executing \"%s\"\n", prog);
635
636 for (f = 3; f < maxfd; f++)
637 close(f);
638
639 execve(prog, argv, environ);
640 spawn_error("pid %d cannot execute %s -- %s\n",
641 getpid(), prog, strerror(errno));
642 close(1);
643 exit(1);
644 }
645
646 pthread_mutex_unlock(&fork_lock);
647
648 spawn_enq(prog, p);
649
650 if (pid)
651 *pid = p;
652
653 return 0;
654 }
655
656 /*
657 *
658 */
spawn_init(void)659 void spawn_init(void)
660 {
661 tvh_pipe(O_NONBLOCK, &spawn_pipe_info);
662 tvh_pipe(O_NONBLOCK, &spawn_pipe_error);
663 atomic_set(&spawn_pipe_running, 1);
664 pthread_create(&spawn_pipe_tid, NULL, spawn_pipe_thread, NULL);
665 }
666
spawn_done(void)667 void spawn_done(void)
668 {
669 spawn_t *s;
670
671 atomic_set(&spawn_pipe_running, 0);
672 pthread_kill(spawn_pipe_tid, SIGTERM);
673 pthread_join(spawn_pipe_tid, NULL);
674 tvh_pipe_close(&spawn_pipe_error);
675 tvh_pipe_close(&spawn_pipe_info);
676 free(spawn_error_buf);
677 free(spawn_info_buf);
678 while ((s = LIST_FIRST(&spawns)) != NULL) {
679 LIST_REMOVE(s, link);
680 free((char *)s->name);
681 free(s);
682 }
683 }
684