vdr 2.7.5
runvdr.c
Go to the documentation of this file.
1/* runvdr.c: launch vdr, handle restarts
2 *
3 * Copyright (C) 2004 Darren Salt & contributors
4 * Contributors: Henning Glawe
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc., 59
18 * Temple Place - Suite 330, Boston, MA 02111-1307, USA. Or point your
19 * browser to http://www.gnu.org/copyleft/gpl.html
20 *
21 * Email:
22 * Author/maintainer:
23 * - Darren Salt: linux@youmustbejoking.demon.co.uk
24 * Contributors:
25 * - Henning Glawe: glaweh@physik.fu-berlin.de
26 */
27
28#define _GNU_SOURCE
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <stdbool.h>
33#include <ctype.h>
34#include <signal.h>
35#include <errno.h>
36#include <time.h>
37#include <syslog.h>
38#include <grp.h>
39#include <sys/types.h>
40#include <sys/stat.h>
41#include <fcntl.h>
42#include <dirent.h>
43#include <sys/param.h>
44#include <sys/wait.h>
45#include <unistd.h>
46#include <pwd.h>
47
48#define PIDFILE "/var/run/vdr.pid"
49#define VDRBIN "/usr/bin/vdr"
50
51#define errmsg(reason,...) \
52 do { \
53 fprintf (stderr, "%s: " reason "\n", progname, ## __VA_ARGS__); \
54 exit (1); \
55 } while (0)
56
57#define errno_msg(reason,...) \
58 do { \
59 fprintf (stderr, "%s: " reason ": %s\n", progname, ## __VA_ARGS__, strerror (errno)); \
60 exit (2); \
61 } while (0)
62
63#define _errno_msg(reason,...) \
64 do { \
65 fprintf (stderr, "%s: " reason ": %s\n", progname, ## __VA_ARGS__, strerror (errno)); \
66 _exit (2); \
67 } while (0)
68
69#define errno_log(reason,...) \
70 do { \
71 int err = errno; \
72 fprintf (stderr, "%s: " reason ": %s\n", progname, ## __VA_ARGS__, strerror (err)); \
73 syslog (LOG_ERR, reason ": %s", ## __VA_ARGS__, strerror (err)); \
74 exit (2); \
75 } while (0)
76
77#define _errno_log(reason,...) \
78 do { \
79 int err = errno; \
80 fprintf (stderr, "%s: " reason ": %s\n", progname, ## __VA_ARGS__, strerror (err)); \
81 syslog (LOG_ERR, reason ": %s", ## __VA_ARGS__, strerror (err)); \
82 _exit (2); \
83 } while (0)
84
85#define errexit(fn, reason,...) \
86 do { if ((fn) == -1) { errno_msg (reason, ## __VA_ARGS__); } } while (0)
87
88#define _errexit(fn, reason,...) \
89 do { if ((fn) == -1) { _errno_msg (reason, ## __VA_ARGS__); } } while (0)
90
91
92static const char *progname;
93
94static const char mod_dvb[] = "dvb-core\0\0";
95static const char mod_budget[] = "budget-core\0\0";
96#define BASEMOD (budget ? mod_budget : mod_dvb)
97
98#define NUM_STOPTIMES 5
99static time_t stoptimes[NUM_STOPTIMES];
100static size_t stoptimecount = 0;
101
102static volatile int usr1 = 0;
103
104static pid_t vdr = 0;
105
106
107typedef struct {
108 size_t length;
109 char **items;
110} List;
111
112
113static int
114dowait (int which)
115{
116 int status;
117 while (1)
118 {
119 switch (waitpid (which, &status, 0))
120 {
121 case -1:
122 if (errno != ECHILD)
123 errno_msg ("problem in wait()");
124 return -1;
125 case 0:
126 break;
127 default:
128 if (WIFEXITED (status))
129 return WEXITSTATUS (status);
130 if (WIFSIGNALED (status))
131 return WTERMSIG (status) | 0x10000;
132 return -1;
133 }
134 }
135}
136
137
138static void
139sig_quit (int sig)
140{
141 if (vdr > 0)
142 {
143 kill (vdr, sig);
144 vdr = 0;
145 dowait (-1);
146 }
147 exit (0);
148}
149
150
151static void
153{
154 signal (sig, sig_propagate);
155 if (sig == SIGUSR1)
156 usr1 = 1;
157 if (vdr > 0)
158 kill (vdr, sig);
159}
160
161
162static void
163sig_default (int sig)
164{
165 signal (sig, sig_default);
166}
167
168
169static char *
170parse_modules_24 (char *line, int budget)
171{
172 line = strchr (line, '[');
173 if (!line)
174 return strdup (BASEMOD); /* unknown format */
175 char *mod = strchr (++line, ']');
176 if (!mod)
177 return strdup (BASEMOD); /* unknown format */
178 *mod = 0;
179 /* |line| now points to "foo bar baz" (from "[foo bar baz]") */
180 mod = NULL;
181 errexit (asprintf (&mod, "%s %s ", line, BASEMOD), "finding module names");
182 /* replace spaces with NULs */
183 char *space = mod;
184 while ((space = strchr (space + 1, ' ')) != NULL)
185 *space = 0;
186 return mod;
187}
188
189
190static char *
191parse_modules_26 (char *line, int budget)
192{
193 /* line == "module size usage dependencies state address" */
194 if ((line = strchr (line, ' ')) == NULL ||
195 (line = strchr (line + 1, ' ')) == NULL ||
196 (line = strchr (line + 1, ' ')) == NULL)
197 return strdup (BASEMOD); /* unknown format */
198 /* line == "dependencies state address" */
199 char *mod = strchr (++line, ' ');
200 if (!mod)
201 return strdup (BASEMOD); /* unknown format */
202 *mod = 0;
203 /* line == "dependencies" (comma-separated list) */
204 if (line[0] == '-' && line[1] == 0)
205 return strdup (BASEMOD); /* no dependent modules */
206 mod = NULL;
207 errexit (asprintf (&mod, "%s%s,", line, BASEMOD), "finding module names");
208 /* replace commas with NULs */
209 char *comma = mod;
210 while ((comma = strchr (comma + 1, ',')) != NULL)
211 *comma = 0;
212 return mod;
213}
214
215
216static const char *
217getenv_default (const char *var, const char *dflt)
218{
219 const char *v = getenv (var);
220 return (v && *v) ? v : dflt;
221}
222
223
224static void
225list_append (List *list, const char *item)
226{
227 int l = list->length;
228 list->items = realloc (list->items, ++list->length * sizeof (const char *));
229 if (!list->items)
230 errmsg ("out of memory");
231 list->items[l] = item ? strdup (item) : NULL;
232 if (item && !list->items[l])
233 errmsg ("out of memory");
234}
235
236
237static void
239{
240 unsigned int i;
241 if (list)
242 {
243 if (list->items)
244 {
245 for (i = 0; i < list->length; ++i)
246 free (list->items[i]);
247 free (list->items);
248 list->items = NULL;
249 }
250 list->length = 0;
251 }
252}
253
254
255static size_t
256list_find (List *list, const char *cmp)
257{
258 unsigned int i;
259 if (list && list->length)
260 for (i = 0; i < list->length; ++i)
261 if (!strcmp (list->items[i], cmp))
262 return i;
263 return -1;
264}
265
266
267static void
268list_remove (List *list, size_t index)
269{
270 if (!list || index >= list->length)
271 return;
272
273 --list->length;
274 if (index < list->length)
275 memmove (&list->items[index], &list->items[index + 1],
276 (list->length - index) * sizeof (char **));
277}
278
279
280static void
282{
283 const char *cfgdir, *plugindir, *prefix, *order;
284 FILE *fd;
285 DIR *dir;
286 struct dirent *entry;
287 List installed_plugins = {0}, ordered_plugins = {0}, leftout_plugins = {0};
288 char *line = NULL;
289 size_t linelength = 0;
290 int check_patchlevel;
291 unsigned int i;
292
293 cfgdir = getenv_default ("PLUGIN_CFG_DIR", "/etc/vdr/plugins");
294 plugindir = getenv_default ("PLUGIN_DIR", "/usr/lib/vdr/plugins");
295 prefix = getenv_default ("PLUGIN_PREFIX", "libvdr-");
296 order = getenv_default ("PLUGIN_ORDER_FILE", "/etc/vdr/plugins/order.conf");
297 check_patchlevel = !strcmp (getenv_default ("PLUGIN_CHECK_PATCHLEVEL", ""),
298 "yes");
299
300 /* Find installed plugins */
301 dir = opendir (plugindir);
302 if (!dir)
303 errno_msg ("can't scan %s", plugindir);
304 errno = 0;
305 while ((entry = readdir (dir)) != NULL)
306 {
307 char *p;
308 if (strncmp (entry->d_name, prefix, strlen (prefix)))
309 continue;
310 p = strstr (entry->d_name, VERSION);
311 if (!p || p != entry->d_name + strlen (entry->d_name) - strlen (VERSION) ||
312 strncmp (p - 4, ".so.", 4))
313 continue;
314 p[-4] = 0; /* hmm... */
315 list_append (&installed_plugins, entry->d_name + strlen (prefix));
316 }
317 if (errno || closedir (dir))
318 errno_msg ("can't scan %s", plugindir);
319
320 if (check_patchlevel)
321 {
322 /* extract patchlevel info */
323 List dpkg = {0};
324 int cpid;
325 int fp[2];
326 if (pipe (fp))
327 errno_msg ("can't open pipe for dpkg");
328 switch (cpid = vfork ())
329 {
330 case -1:
331 errno_msg ("couldn't run dpkg");
332
333 case 0:
334 if (close (fp[0]) || close (STDOUT_FILENO)
335 || dup2 (fp[1], STDOUT_FILENO) == -1)
336 _errno_msg ("couldn't run dpkg");
337 setenv ("LANG", "en", 1);
338 list_append (&dpkg, "dpkg");
339 list_append (&dpkg, "-s");
340 list_append (&dpkg, "--");
341 list_append (&dpkg, "vdr");
342 for (i = 0; i < installed_plugins.length; ++i)
343 {
344 _errexit (asprintf (&line, "vdr-plugin-%s", installed_plugins.items[i]),
345 "finding module patchlevels");
346 list_append (&dpkg, line);
347 free (line);
348 }
349 execvp ("dpkg", dpkg.items);
350 _errno_msg ("couldn't run dpkg");
351
352 default:
353 {
354 char *pkg = NULL;
355 char *patchlevels[installed_plugins.length + 1];
356
357 close (fp[1]);
358 fd = fdopen (fp[0], "r");
359 for (i = 0; i <= installed_plugins.length; ++i)
360 patchlevels[i] = NULL;
361 for (;;)
362 {
363 ssize_t l = getline (&line, &linelength, fd);
364 if (l < 0)
365 break;
366 if (l && line[l - 1] == '\n')
367 line[--l] = 0;
368 if (!strncasecmp (line, "Package: ", 9))
369 {
370 free (pkg);
371 pkg = strdup (line + 9);
372 if (!pkg)
373 errmsg ("out of memory");
374 }
375 else if (pkg && !strncasecmp (line, "Patchlevel: ", 12))
376 {
377 int p = !strcmp (pkg, "vdr")
378 ? installed_plugins.length
379 : (strlen (pkg) > 11)
380 ? list_find (&installed_plugins, pkg + 11)
381 : (size_t) -1;
382 if (p != -1)
383 {
384 patchlevels[p] = strdup (line + 12);
385 if (!patchlevels[p])
386 errmsg ("out of memory");
387 }
388 free (pkg);
389 pkg = NULL;
390 }
391 }
392 free (pkg);
393 if (dowait (cpid) != 0)
394 exit (2);
395 close (fp[0]);
396 fclose (fd);
397 if (patchlevels[installed_plugins.length])
398 for (i = 0; i < installed_plugins.length; ++i)
399 if (patchlevels[i]
400 && !strcmp (patchlevels[i],
401 patchlevels[installed_plugins.length]))
402 list_append (&leftout_plugins, installed_plugins.items[i]);
403 for (i = 0; i <= installed_plugins.length; ++i)
404 free (patchlevels[i]);
405 for (i = 0; i < leftout_plugins.length; ++i)
406 list_remove (&installed_plugins,
407 list_find (&installed_plugins,
408 leftout_plugins.items[i]));
409 }
410 }
411 }
412
413 fd = fopen (order, "r");
414 if (!fd && errno != ENOENT)
415 errno_msg ("can't read %s", order);
416
417 /* Load plugin order */
418 if (fd)
419 {
420 while (!feof (fd) && !ferror (fd))
421 {
422 ssize_t l = getline (&line, &linelength, fd);
423 if (l < 0)
424 break;
425 if (l && line[l - 1] == '\n')
426 line[--l] = 0;
427 if (!line[0] || line[0] == '#')
428 continue;
429 if (line[0] == '-')
430 {
431 list_remove (&installed_plugins,
432 list_find (&installed_plugins, line + 1));
433 continue;
434 }
435 l = list_find (&installed_plugins, line);
436 if (l != -1)
437 {
438 list_remove (&installed_plugins, l);
439 list_append (&ordered_plugins, line);
440 }
441 }
442 if (ferror (fd) || fclose (fd))
443 errno_msg ("can't read %s", order);
444 }
445
446 /* Append unordered plugins to ordered plugins */
447 for (i = 0; i < installed_plugins.length; ++i)
448 list_append (&ordered_plugins, installed_plugins.items[i]);
449 list_free (&installed_plugins);
450
451 /* Add the command-line arguments for each plugin */
452 for (i = 0; i < ordered_plugins.length; ++i)
453 {
454 char *file = NULL;
455 errexit (asprintf (&file, "%s/plugin.%s.conf", cfgdir,
456 ordered_plugins.items[i]),
457 "plugin scan");
458 fd = fopen (file, "r");
459 if (!fd && errno != ENOENT)
460 errno_msg ("can't read %s", order);
461 free (file);
462
463 if (!fd)
464 errexit (asprintf (&file, "-P%s", ordered_plugins.items[i]),
465 "plugin scan");
466 else
467 {
468 char *p, *q;
469 ssize_t l = getdelim (&line, &linelength, 256, fd); /* slurp */
470 if (ferror (fd) || fclose (fd))
471 errno_msg ("can't read %s", order);
472
473 if (l && line[l - 1] == '\n')
474 line[--l] = 0;
475
476 /* Lose comment lines */
477 p = line;
478 do
479 {
480 if (*p == '\n')
481 *p++ = ' ';
482 if (*p != '#')
483 continue;
484 q = strchr (p, '\n');
485 if (q)
486 memmove (p, q + 1, strlen (q));
487 else
488 *p = 0;
489 } while ((p = strchr (p, '\n')) != NULL);
490
491 errexit (asprintf (&file, "-P%s %s", ordered_plugins.items[i], line),
492 "plugin scan");
493 }
494 list_append (args, file);
495 free (file);
496 }
497
498 if (leftout_plugins.length)
499 {
500 fputs ("WARNING: The following plugins have been left out due to"
501 "possible binary incompatibility:", stderr);
502 for (i = 0; i < leftout_plugins.length; ++i)
503 fprintf (stderr, " %s", leftout_plugins.items[i]);
504 fputs ("\n", stderr);
505 }
506
507 list_free (&ordered_plugins);
508 free (line);
509}
510
511
512static void
514{
515 char pidbuf[12];
516 int fd = open (PIDFILE, O_CREAT | O_EXCL | O_WRONLY, 0600);
517 if (fd < 0)
518 {
519 if (errno == EEXIST)
520 errmsg ("pidfile exists - is vdr already running?");
521 errno_msg ("couldn't create pidfile");
522 }
523 snprintf (pidbuf, sizeof (pidbuf), "%d\n", getpid ());
524 write (fd, pidbuf, strlen (pidbuf));
525 if (close (fd))
526 errno_msg ("couldn't create pidfile");
527}
528
529
530static void
532{
533 char pidbuf[12];
534 int fd = open (PIDFILE, O_RDONLY);
535 if (fd < 0)
536 return;
537 memset (pidbuf, 0, sizeof (pidbuf));
538 read (fd, pidbuf, sizeof (pidbuf) - 1);
539 pid_t pid = atoi (pidbuf);
540 if (pid != getpid () && !kill (pid, 0))
541 syslog (LOG_INFO, "erk, pidfile doesn't contain my PID");
542 else if (unlink (PIDFILE))
543 fprintf (stderr, "%s: unlink pidfile: %s\n", progname, strerror (errno));
544 if (close (fd))
545 fprintf (stderr, "%s: close pidfile: %s\n", progname, strerror (errno));
546}
547
548
549int
550main (int argc, char *argv[])
551{
552 progname = argv[0];
553 List vdr_opts = {0};
554 bool daemonise = true;
555 bool nptl = true;
556 bool logio = false;
557 bool mod_reload = false;
558 int argp;
559
560 signal (SIGHUP, sig_quit);
561 signal (SIGINT, sig_quit);
562 signal (SIGTERM, sig_quit);
563 signal (SIGUSR1, sig_propagate);
564 signal (SIGUSR2, SIG_IGN);
565 signal (SIGCHLD, sig_default);
566
567 for (argp = 1; argp < argc; ++argp)
568 {
569 bool on = (argv[argp][0] == '-');
570 switch (((on || argv[argp][0] == '+') && argv[argp][1] && !argv[argp][2])
571 ? argv[argp][1] : 0) /* '*' in "-*" or "+*", else NUL */
572 {
573 case 'n': daemonise = !on; continue;
574 case 'k': nptl = !on; continue;
575 case 'l': logio = on; continue;
576 case 'r': mod_reload = on; continue;
577
578 case '-':
579 if (argv[argp][0] == '-')
580 {
581 ++argp;
582 goto found_last_arg;
583 }
584 /* else fall through */
585 default:
586 errmsg ("usage: runvdr [-n|+n] [-k|+k] [-l|+l] [-r|+r] -- [OPTIONS]");
587 }
588 }
589 found_last_arg:
590
591 if (!nptl)
592 {
593 /* Check for NPTL and re-exec if present - VDR /may/ not run well with NPTL */
594 size_t pth_l = confstr (_CS_GNU_LIBPTHREAD_VERSION, 0, 0);
595 char *pth = (char *)malloc (pth_l);
596 if (confstr (_CS_GNU_LIBPTHREAD_VERSION, pth, pth_l) > 0)
597 {
598 if (strstr (pth, "NPTL"))
599 {
600 setenv ("LD_ASSUME_KERNEL", "2.4.21", 1);
601 execve ("/proc/self/exe", argv, environ);
602 errno_msg ("couldn't reload myself");
603 return 2;
604 }
605 }
606 free (pth);
607 }
608
609 openlog ("vdr", LOG_PID | LOG_CONS, LOG_DAEMON);
610
611 struct stat st;
612 if (stat (VDRBIN, &st))
613 {
614 if (errno == ENOENT)
615 errmsg ("sorry, no vdr binary is not installed");
616 errno_msg ("error when checking %s", VDRBIN);
617 }
618
619 if (daemonise && daemon (0, 0))
620 errno_msg ("daemonise");
621
622 atexit (pidfile_remove);
623 pidfile_write ();
624
625 char *modules = NULL;
626
627 if (mod_reload)
628 {
629 char *line = NULL;
630 size_t linelen = 0, linealloc = 0;
631 FILE *fd = fopen ("/proc/modules", "rb");
632 if (!fd)
633 errno_msg ("open /proc/modules");
634
635 for (;;)
636 {
637 int c;
638 linelen = 0;
639 while ((c = fgetc (fd)) != -1 && c != '\n')
640 {
641 if (linelen + 2 >= linealloc)
642 {
643 line = realloc (line, linealloc += 64);
644 if (!line)
645 errno_msg ("read /proc/modules");
646 }
647 line[linelen] = c;
648 ++linelen;
649 }
650 if (ferror (fd))
651 errno_msg ("read /proc/modules");
652 if (feof (fd))
653 break;
654 if (!linelen)
655 continue;
656 line[linelen] = 0;
657 if (!strncmp (line, "dvb-core", 8) && isspace (line[8]))
658 {
659 free (modules);
660 modules = parse_modules_24 (line, 0);
661 }
662 else if (!strncmp (line, "dvb_core", 8) && isspace (line[8]))
663 {
664 free (modules);
665 modules = parse_modules_26 (line, 0);
666 }
667 else if (!strncmp (line, "budget-core", 11) && isspace (line[11]))
668 {
669 free (modules);
670 modules = parse_modules_24 (line, 1);
671 }
672 else if (!strncmp (line, "budget_core", 11) && isspace (line[11]))
673 {
674 free (modules);
675 modules = parse_modules_26 (line, 1);
676 }
677 }
678 errexit (fclose (fd), "close /proc/modules");
679 free (line);
680 }
681
682 while (1)
683 {
684 int i = argp - 1;
685
686 list_free (&vdr_opts);
687 list_append (&vdr_opts, "vdr");
688 while (argv[++i])
689 list_append (&vdr_opts, argv[i]);
690 scan_plugins (&vdr_opts);
691 list_append (&vdr_opts, NULL);
692 switch (vdr = vfork ())
693 {
694 int status;
695
696 case -1:
697 errno_log ("couldn't start vdr");
698 exit (2);
699
700 case 0: /* child process - run vdr */
701 setsid ();
702 if (getuid () == 0)
703 {
704 const struct passwd *pwd = getpwnam ("vdr");
705 gid_t groups[NGROUPS];
706 char *cwd;
707 int numgroups = NGROUPS;
708
709 getgrouplist ("vdr", pwd->pw_gid, groups, &numgroups);
710 chdir (pwd->pw_dir);
711 setenv ("SHELL", pwd->pw_shell, 1);
712 setenv ("USER", "vdr", 1);
713 setenv ("MAIL", "/var/mail/vdr", 1);
714 setenv ("PATH", "/bin:/usr/bin", 1);
715 setenv ("PWD", cwd = get_current_dir_name (), 1);
716 free (cwd);
717 setenv ("HOME", pwd->pw_dir, 1);
718 setenv ("LOGNAME", "vdr", 1);
719 if (setregid (pwd->pw_gid, pwd->pw_gid))
720 _errno_log ("couldn't set gid for vdr");
721 if (numgroups > 0 && setgroups (numgroups, groups))
722 _errno_log ("couldn't set groups for vdr");
723 if (setreuid (pwd->pw_uid, pwd->pw_uid))
724 _errno_log ("couldn't set uid for vdr");
725 }
726 execv (VDRBIN, vdr_opts.items);
727 /* Eek, failed - log and exit*/
728 _errno_log ("couldn't start %s [%d]", VDRBIN, errno);
729
730 default: /* parent process - wait for child to exit */
731 syslog (LOG_INFO, "vdr started, pid %d", vdr);
732 status = dowait (-1);
733
734 /* get stop time */
736 {
737 memmove (stoptimes, stoptimes + 1,
738 sizeof (stoptimes) - sizeof (stoptimes[0]));
739 time (&stoptimes[NUM_STOPTIMES - 1]);
740 }
741 else
742 time (&stoptimes[stoptimecount++]);
743
744 /* do some logging; exit if requested */
745 if (status & 0x10000)
746 syslog (LOG_INFO, "vdr exited, signal %d", status & 0xFFFF);
747 else
748 syslog (LOG_INFO, "vdr exited, status %d", status);
749 if (status < 1 || status == 2)
750 exit (0);
751
752 /* reload modules if requested */
753 if (status == 1 && modules)
754 {
755 int status, cpid;
756 syslog (LOG_INFO, "reloading modules, restarting vdr");
757 sleep (10);
758 const char *mod = modules;
759 while (mod && *mod)
760 {
761 switch (cpid = vfork ())
762 {
763 case -1:
764 break;
765 case 0:
766 execl ("/sbin/rmmod", "rmmod", mod, NULL);
767 _exit (errno);
768 default:
769 status = dowait (cpid);
770 if (status)
771 syslog (LOG_INFO, "rmmod %s failed: status %d",
772 mod, status);
773 }
774 mod += strlen (mod) + 1;
775 }
776 switch (cpid = vfork ())
777 {
778 case -1:
779 break;
780 case 0:
781 execl ("/sbin/modprobe", "modprobe", "dvb", NULL);
782 exit (0);
783 default:
784 status = dowait (cpid);
785 if (status)
786 syslog (LOG_INFO, "modprobe dvb failed: status %d", status);
787 }
788 }
789 sleep (1);
790
791 /* stop time too recent? too many exits recently? */
793 (stoptimes[NUM_STOPTIMES] - stoptimes[0]) < 60)
794 {
795 syslog (LOG_ERR, "vdr is being respawned too often - sleeping");
796 usr1 = 0;
797 struct timespec t = { 300, 0 };
798 while (nanosleep (&t, &t))
799 if (usr1)
800 break;
801 }
802 }
803 }
804}
static const char * VERSION
Definition dvbhddevice.c:14
static void list_remove(List *list, size_t index)
Definition runvdr.c:268
#define _errexit(fn, reason,...)
Definition runvdr.c:88
static const char * getenv_default(const char *var, const char *dflt)
Definition runvdr.c:217
int main(int argc, char *argv[])
Definition runvdr.c:550
static int dowait(int which)
Definition runvdr.c:114
#define NUM_STOPTIMES
Definition runvdr.c:98
static const char mod_dvb[]
Definition runvdr.c:94
static void sig_default(int sig)
Definition runvdr.c:163
static void list_free(List *list)
Definition runvdr.c:238
static const char mod_budget[]
Definition runvdr.c:95
static void sig_propagate(int sig)
Definition runvdr.c:152
static void sig_quit(int sig)
Definition runvdr.c:139
static void pidfile_write(void)
Definition runvdr.c:513
#define VDRBIN
Definition runvdr.c:49
static volatile int usr1
Definition runvdr.c:102
static void scan_plugins(List *args)
Definition runvdr.c:281
#define BASEMOD
Definition runvdr.c:96
#define _errno_msg(reason,...)
Definition runvdr.c:63
#define _errno_log(reason,...)
Definition runvdr.c:77
static time_t stoptimes[NUM_STOPTIMES]
Definition runvdr.c:99
static pid_t vdr
Definition runvdr.c:104
#define errno_msg(reason,...)
Definition runvdr.c:57
#define errexit(fn, reason,...)
Definition runvdr.c:85
static size_t list_find(List *list, const char *cmp)
Definition runvdr.c:256
static size_t stoptimecount
Definition runvdr.c:100
static char * parse_modules_26(char *line, int budget)
Definition runvdr.c:191
static void list_append(List *list, const char *item)
Definition runvdr.c:225
#define errmsg(reason,...)
Definition runvdr.c:51
static const char * progname
Definition runvdr.c:92
#define errno_log(reason,...)
Definition runvdr.c:69
static char * parse_modules_24(char *line, int budget)
Definition runvdr.c:170
#define PIDFILE
Definition runvdr.c:48
static void pidfile_remove(void)
Definition runvdr.c:531
Definition runvdr.c:107
char ** items
Definition runvdr.c:109
size_t length
Definition runvdr.c:108