283 const char *cfgdir, *plugindir, *prefix, *order;
286 struct dirent *entry;
287 List installed_plugins = {0}, ordered_plugins = {0}, leftout_plugins = {0};
289 size_t linelength = 0;
290 int check_patchlevel;
294 plugindir =
getenv_default (
"PLUGIN_DIR",
"/usr/lib/vdr/plugins");
296 order =
getenv_default (
"PLUGIN_ORDER_FILE",
"/etc/vdr/plugins/order.conf");
297 check_patchlevel = !strcmp (
getenv_default (
"PLUGIN_CHECK_PATCHLEVEL",
""),
301 dir = opendir (plugindir);
305 while ((entry = readdir (dir)) != NULL)
308 if (strncmp (entry->d_name, prefix, strlen (prefix)))
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))
315 list_append (&installed_plugins, entry->d_name + strlen (prefix));
317 if (errno || closedir (dir))
320 if (check_patchlevel)
328 switch (cpid = vfork ())
334 if (close (fp[0]) || close (STDOUT_FILENO)
335 || dup2 (fp[1], STDOUT_FILENO) == -1)
337 setenv (
"LANG",
"en", 1);
342 for (i = 0; i < installed_plugins.
length; ++i)
344 _errexit (asprintf (&line,
"vdr-plugin-%s", installed_plugins.
items[i]),
345 "finding module patchlevels");
349 execvp (
"dpkg", dpkg.
items);
355 char *patchlevels[installed_plugins.
length + 1];
358 fd = fdopen (fp[0],
"r");
359 for (i = 0; i <= installed_plugins.
length; ++i)
360 patchlevels[i] = NULL;
363 ssize_t l = getline (&line, &linelength, fd);
366 if (l && line[l - 1] ==
'\n')
368 if (!strncasecmp (line,
"Package: ", 9))
371 pkg = strdup (line + 9);
375 else if (pkg && !strncasecmp (line,
"Patchlevel: ", 12))
377 int p = !strcmp (pkg,
"vdr")
378 ? installed_plugins.
length
379 : (strlen (pkg) > 11)
380 ?
list_find (&installed_plugins, pkg + 11)
384 patchlevels[p] = strdup (line + 12);
397 if (patchlevels[installed_plugins.
length])
398 for (i = 0; i < installed_plugins.
length; ++i)
400 && !strcmp (patchlevels[i],
401 patchlevels[installed_plugins.
length]))
403 for (i = 0; i <= installed_plugins.
length; ++i)
404 free (patchlevels[i]);
405 for (i = 0; i < leftout_plugins.length; ++i)
408 leftout_plugins.
items[i]));
413 fd = fopen (order,
"r");
414 if (!fd && errno != ENOENT)
420 while (!feof (fd) && !ferror (fd))
422 ssize_t l = getline (&line, &linelength, fd);
425 if (l && line[l - 1] ==
'\n')
427 if (!line[0] || line[0] ==
'#')
432 list_find (&installed_plugins, line + 1));
435 l =
list_find (&installed_plugins, line);
442 if (ferror (fd) || fclose (fd))
447 for (i = 0; i < installed_plugins.
length; ++i)
452 for (i = 0; i < ordered_plugins.length; ++i)
455 errexit (asprintf (&file,
"%s/plugin.%s.conf", cfgdir,
456 ordered_plugins.items[i]),
458 fd = fopen (file,
"r");
459 if (!fd && errno != ENOENT)
464 errexit (asprintf (&file,
"-P%s", ordered_plugins.items[i]),
469 ssize_t l = getdelim (&line, &linelength, 256, fd);
470 if (ferror (fd) || fclose (fd))
473 if (l && line[l - 1] ==
'\n')
484 q = strchr (p,
'\n');
486 memmove (p, q + 1, strlen (q));
489 }
while ((p = strchr (p,
'\n')) != NULL);
491 errexit (asprintf (&file,
"-P%s %s", ordered_plugins.items[i], line),
498 if (leftout_plugins.length)
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);
554 bool daemonise =
true;
557 bool mod_reload =
false;
564 signal (SIGUSR2, SIG_IGN);
567 for (argp = 1; argp < argc; ++argp)
569 bool on = (argv[argp][0] ==
'-');
570 switch (((on || argv[argp][0] ==
'+') && argv[argp][1] && !argv[argp][2])
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;
579 if (argv[argp][0] ==
'-')
586 errmsg (
"usage: runvdr [-n|+n] [-k|+k] [-l|+l] [-r|+r] -- [OPTIONS]");
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)
598 if (strstr (pth,
"NPTL"))
600 setenv (
"LD_ASSUME_KERNEL",
"2.4.21", 1);
601 execve (
"/proc/self/exe", argv, environ);
609 openlog (
"vdr", LOG_PID | LOG_CONS, LOG_DAEMON);
615 errmsg (
"sorry, no vdr binary is not installed");
619 if (daemonise && daemon (0, 0))
625 char *modules = NULL;
630 size_t linelen = 0, linealloc = 0;
631 FILE *fd = fopen (
"/proc/modules",
"rb");
639 while ((c = fgetc (fd)) != -1 && c !=
'\n')
641 if (linelen + 2 >= linealloc)
643 line = realloc (line, linealloc += 64);
657 if (!strncmp (line,
"dvb-core", 8) && isspace (line[8]))
662 else if (!strncmp (line,
"dvb_core", 8) && isspace (line[8]))
667 else if (!strncmp (line,
"budget-core", 11) && isspace (line[11]))
672 else if (!strncmp (line,
"budget_core", 11) && isspace (line[11]))
678 errexit (fclose (fd),
"close /proc/modules");
692 switch (
vdr = vfork ())
704 const struct passwd *pwd = getpwnam (
"vdr");
705 gid_t groups[NGROUPS];
707 int numgroups = NGROUPS;
709 getgrouplist (
"vdr", pwd->pw_gid, groups, &numgroups);
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);
717 setenv (
"HOME", pwd->pw_dir, 1);
718 setenv (
"LOGNAME",
"vdr", 1);
719 if (setregid (pwd->pw_gid, pwd->pw_gid))
721 if (numgroups > 0 && setgroups (numgroups, groups))
723 if (setreuid (pwd->pw_uid, pwd->pw_uid))
731 syslog (LOG_INFO,
"vdr started, pid %d",
vdr);
745 if (status & 0x10000)
746 syslog (LOG_INFO,
"vdr exited, signal %d", status & 0xFFFF);
748 syslog (LOG_INFO,
"vdr exited, status %d", status);
749 if (status < 1 || status == 2)
753 if (status == 1 && modules)
756 syslog (LOG_INFO,
"reloading modules, restarting vdr");
758 const char *mod = modules;
761 switch (cpid = vfork ())
766 execl (
"/sbin/rmmod",
"rmmod", mod, NULL);
771 syslog (LOG_INFO,
"rmmod %s failed: status %d",
774 mod += strlen (mod) + 1;
776 switch (cpid = vfork ())
781 execl (
"/sbin/modprobe",
"modprobe",
"dvb", NULL);
786 syslog (LOG_INFO,
"modprobe dvb failed: status %d", status);
795 syslog (LOG_ERR,
"vdr is being respawned too often - sleeping");
797 struct timespec t = { 300, 0 };
798 while (nanosleep (&t, &t))