vdr  2.2.0
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 
92 static const char *progname;
93 
94 static const char mod_dvb[] = "dvb-core\0\0";
95 static const char mod_budget[] = "budget-core\0\0";
96 #define BASEMOD (budget ? mod_budget : mod_dvb)
97 
98 #define NUM_STOPTIMES 5
99 static time_t stoptimes[NUM_STOPTIMES];
100 static size_t stoptimecount = 0;
101 
102 static volatile int usr1 = 0;
103 
104 static pid_t vdr = 0;
105 
106 
107 typedef struct {
108  size_t length;
109  char **items;
110 } List;
111 
112 
113 static int
114 dowait (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 
138 static void
139 sig_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 
151 static void
152 sig_propagate (int sig)
153 {
154  signal (sig, sig_propagate);
155  if (sig == SIGUSR1)
156  usr1 = 1;
157  if (vdr > 0)
158  kill (vdr, sig);
159 }
160 
161 
162 static void
163 sig_default (int sig)
164 {
165  signal (sig, sig_default);
166 }
167 
168 
169 static char *
170 parse_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 
190 static char *
191 parse_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 
216 static const char *
217 getenv_default (const char *var, const char *dflt)
218 {
219  const char *v = getenv (var);
220  return (v && *v) ? v : dflt;
221 }
222 
223 
224 static void
225 list_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 
237 static 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 
255 static size_t
256 list_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 
267 static void
268 list_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 
280 static 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 
512 static 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 
530 static 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 
549 int
550 main (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? */
792  if (stoptimecount == NUM_STOPTIMES &&
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 }
#define PIDFILE
Definition: runvdr.c:48
static size_t stoptimecount
Definition: runvdr.c:100
#define errmsg(reason,...)
Definition: runvdr.c:51
static void sig_propagate(int sig)
Definition: runvdr.c:152
size_t length
Definition: runvdr.c:108
#define errno_log(reason,...)
Definition: runvdr.c:69
static void pidfile_remove(void)
Definition: runvdr.c:531
#define _errexit(fn, reason,...)
Definition: runvdr.c:88
char ** items
Definition: runvdr.c:109
static void pidfile_write(void)
Definition: runvdr.c:513
static const char mod_dvb[]
Definition: runvdr.c:94
static void list_append(List *list, const char *item)
Definition: runvdr.c:225
static pid_t vdr
Definition: runvdr.c:104
static void scan_plugins(List *args)
Definition: runvdr.c:281
static const char * progname
Definition: runvdr.c:92
#define NUM_STOPTIMES
Definition: runvdr.c:98
static time_t stoptimes[NUM_STOPTIMES]
Definition: runvdr.c:99
#define _errno_log(reason,...)
Definition: runvdr.c:77
static void sig_quit(int sig)
Definition: runvdr.c:139
static size_t list_find(List *list, const char *cmp)
Definition: runvdr.c:256
static const char * getenv_default(const char *var, const char *dflt)
Definition: runvdr.c:217
static void list_remove(List *list, size_t index)
Definition: runvdr.c:268
static char * parse_modules_24(char *line, int budget)
Definition: runvdr.c:170
static volatile int usr1
Definition: runvdr.c:102
static const char * VERSION
Definition: dvbhddevice.c:13
static void list_free(List *list)
Definition: runvdr.c:238
#define BASEMOD
Definition: runvdr.c:96
#define _errno_msg(reason,...)
Definition: runvdr.c:63
int main(int argc, char *argv[])
Definition: runvdr.c:550
static void sig_default(int sig)
Definition: runvdr.c:163
static const char mod_budget[]
Definition: runvdr.c:95
static char * parse_modules_26(char *line, int budget)
Definition: runvdr.c:191
#define errno_msg(reason,...)
Definition: runvdr.c:57
static int dowait(int which)
Definition: runvdr.c:114
#define errexit(fn, reason,...)
Definition: runvdr.c:85
Definition: runvdr.c:107
#define VDRBIN
Definition: runvdr.c:49