From 5ba6f0a62817f6031936b8880a15c404840924bb Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Tue, 29 Apr 2008 10:25:45 +0000 Subject: [PATCH] We need to ensure that the init script started is correct, translating symlinks. This has a new rule - multiplexed services must exist in the same dir as the master sript. So we need to ensuret that net.lo(0) is the real script and not a symlink itself. This fixes Gentoo #219526. --- init.d/.gitignore | 4 ++ init.d/Makefile | 7 +++ init.d/Makefile.FreeBSD | 2 + init.d/Makefile.Linux | 2 + init.d/Makefile.NetBSD | 2 + sh/net.sh.in => init.d/net.lo.in | 0 mk/scripts.mk | 4 +- sh/.gitignore | 2 + sh/Makefile | 6 +-- sh/Makefile.FreeBSD | 2 - sh/Makefile.Linux | 1 - sh/Makefile.NetBSD | 1 - src/rc/runscript.c | 77 +++++++++++++++++++++++--------- 13 files changed, 80 insertions(+), 30 deletions(-) rename sh/net.sh.in => init.d/net.lo.in (100%) diff --git a/init.d/.gitignore b/init.d/.gitignore index e04a53f7..10872127 100644 --- a/init.d/.gitignore +++ b/init.d/.gitignore @@ -26,3 +26,7 @@ mixer nscd powerd syscons +net.lo +ttys +swap-blk +wscons diff --git a/init.d/Makefile b/init.d/Makefile index a9f62e25..b670eacb 100644 --- a/init.d/Makefile +++ b/init.d/Makefile @@ -3,7 +3,14 @@ SRCS= bootmisc.in fsck.in halt.sh.in hostname.in local.in localmount.in \ netmount.in root.in swap.in sysctl.in urandom.in BIN= ${OBJS} +INSTALLAFTER= _installafter +CLEANFILES+= net.lo +TARGETS+= net.lo + MK= ../mk include ${MK}/os.mk include Makefile.${OS} include ${MK}/scripts.mk + +_installafter: net.lo + ${INSTALL} -m ${BINMODE} net.lo ${DESTDIR}/${INITDIR}/${NET_LO} diff --git a/init.d/Makefile.FreeBSD b/init.d/Makefile.FreeBSD index 8bcb9694..3cd6feb6 100644 --- a/init.d/Makefile.FreeBSD +++ b/init.d/Makefile.FreeBSD @@ -1,3 +1,5 @@ +NET_LO= net.lo0 + # Generic BSD scripts SRCS+= hostid.in moused.in newsyslog.in pf.in rarpd.in rc-enabled.in \ rpcbind.in savecore.in syslogd.in diff --git a/init.d/Makefile.Linux b/init.d/Makefile.Linux index 0e476b57..ae9e6ba4 100644 --- a/init.d/Makefile.Linux +++ b/init.d/Makefile.Linux @@ -1,3 +1,5 @@ +NET_LO= net.lo + SRCS+= hwclock.in consolefont.in keymaps.in modules.in mtab.in numlock.in \ procfs.in termencoding.in diff --git a/init.d/Makefile.NetBSD b/init.d/Makefile.NetBSD index 0bf2f657..2d1141bd 100644 --- a/init.d/Makefile.NetBSD +++ b/init.d/Makefile.NetBSD @@ -1,3 +1,5 @@ +NET_LO= net.lo0 + # Generic BSD scripts SRCS+= hostid.in moused.in newsyslog.in pf.in rarpd.in rc-enabled.in \ rpcbind.in savecore.in syslogd.in diff --git a/sh/net.sh.in b/init.d/net.lo.in similarity index 100% rename from sh/net.sh.in rename to init.d/net.lo.in diff --git a/mk/scripts.mk b/mk/scripts.mk index ced18441..f65c1422 100644 --- a/mk/scripts.mk +++ b/mk/scripts.mk @@ -22,9 +22,9 @@ SED_REPLACE= -e 's:@SHELL@:${SH}:g' -e 's:@LIB@:${LIBNAME}:g' -e 's:@SYSCONFDIR .in: ${SED} ${SED_REPLACE} ${SED_EXTRA} $< > $@ -all: ${OBJS} +all: ${OBJS} ${TARGETS} -realinstall: ${BIN} ${CONF} ${CONF_APPEND} +realinstall: ${BIN} ${CONF} ${INC} @if test -n "${DIR}"; then \ ${ECHO} ${INSTALL} -d ${DESTDIR}/${DIR}; \ ${INSTALL} -d ${DESTDIR}/${DIR} || exit $$?; \ diff --git a/sh/.gitignore b/sh/.gitignore index 91d8a146..028281d4 100644 --- a/sh/.gitignore +++ b/sh/.gitignore @@ -4,3 +4,5 @@ net.sh rc-functions.sh runscript.sh init.sh +ifwatchd-carrier.sh +ifwatchd-nocarrier.sh diff --git a/sh/Makefile b/sh/Makefile index cc4aa35f..efca9800 100644 --- a/sh/Makefile +++ b/sh/Makefile @@ -1,8 +1,8 @@ DIR= ${PREFIX}/${RC_LIB}/sh -SRCS= functions.sh.in gendepends.sh.in net.sh.in \ +SRCS= functions.sh.in gendepends.sh.in \ rc-functions.sh.in runscript.sh.in INC= init-common-post.sh rc-mount.sh functions.sh rc-functions.sh -BIN= gendepends.sh init.sh net.sh runscript.sh +BIN= gendepends.sh init.sh runscript.sh INSTALLAFTER= _installafter @@ -13,8 +13,6 @@ include ${MK}/scripts.mk _installafter: ${INSTALL} -d ${DESTDIR}/${INITDIR} - @# Provide an init script for the loopback interface - ln -snf ${PREFIX}/${RC_LIB}/sh/net.sh ${DESTDIR}/${INITDIR}/${NET_LO} || exit $$? @# Put functions.sh into the init.d dir so 3rd party apps don't have to @# be multilib aware ln -snf ${PREFIX}/${RC_LIB}/sh/functions.sh ${DESTDIR}/${INITDIR} || exit $$? diff --git a/sh/Makefile.FreeBSD b/sh/Makefile.FreeBSD index 93a00a01..d4e6b866 100644 --- a/sh/Makefile.FreeBSD +++ b/sh/Makefile.FreeBSD @@ -1,7 +1,5 @@ SRCS+= init.sh.in -NET_LO= net.lo0 - .SUFFIXES: .sh.BSD.in .sh.BSD.in.sh: ${SED} ${SED_REPLACE} ${SED_EXTRA} $< > $@ diff --git a/sh/Makefile.Linux b/sh/Makefile.Linux index b73b4665..bb48f42e 100644 --- a/sh/Makefile.Linux +++ b/sh/Makefile.Linux @@ -1,4 +1,3 @@ -NET_LO= net.lo SRCS+= init.sh.in init-early.sh.in BIN+= init-early.sh diff --git a/sh/Makefile.NetBSD b/sh/Makefile.NetBSD index 0e4200aa..bd443934 100644 --- a/sh/Makefile.NetBSD +++ b/sh/Makefile.NetBSD @@ -1,6 +1,5 @@ SRCS+= init.sh.in -NET_LO= net.lo0 SRCS+= ifwatchd-carrier.sh.in ifwatchd-nocarrier.sh.in BIN+= ifwatchd-carrier.sh ifwatchd-nocarrier.sh diff --git a/src/rc/runscript.c b/src/rc/runscript.c index 4ecf305d..af140d62 100644 --- a/src/rc/runscript.c +++ b/src/rc/runscript.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -707,7 +708,8 @@ static void svc_start(bool deps) hook_out = RC_HOOK_SERVICE_START_OUT; rc_plugin_run(RC_HOOK_SERVICE_START_IN, applet); - if (rc_conf_yesno("rc_depend_strict")) + errno = 0; + if (rc_conf_yesno("rc_depend_strict") || errno == ENOENT) depoptions |= RC_DEP_STRICT; if (deps) { @@ -933,8 +935,8 @@ static void svc_stop(bool deps) ewarn ("WARNING: you are stopping a boot service"); if (deps && ! (state & RC_SERVICE_WASINACTIVE)) { - - if (rc_conf_yesno("rc_depend_strict")) + errno = 0; + if (rc_conf_yesno("rc_depend_strict") || errno == ENOENT) depoptions |= RC_DEP_STRICT; if (! deptree && ((deptree = _rc_deptree_load(NULL)) == NULL)) @@ -1102,39 +1104,73 @@ int runscript(int argc, char **argv) int retval; int opt; RC_STRING *svc; - char dir[PATH_MAX]; + char path[PATH_MAX]; + char lnk[PATH_MAX]; size_t l = 0; size_t ll; - char *save; + char *dir, *save; + const char *file; int depoptions = RC_DEP_TRACE; + struct stat stbuf; /* Show help if insufficient args */ if (argc < 2 || ! exists(argv[1])) { - fprintf(stderr, "runscript is not meant to be to run directly\n"); + fprintf(stderr, "runscript should not be run directly\n"); exit(EXIT_FAILURE); } - applet = basename_c(argv[1]); - if (argc < 3) - usage(EXIT_FAILURE); - - if (*argv[1] == '/') - service = xstrdup(argv[1]); - else { - getcwd(dir, sizeof(dir)); - l = strlen(dir) + strlen(argv[1]) + 2; - service = xmalloc(sizeof (char) * l); - snprintf(service, l, "%s/%s", dir, argv[1]); + if (stat(argv[1], &stbuf) != 0) { + fprintf(stderr, "runscript `%s': %s\n", + argv[1], strerror(errno)); + exit(EXIT_FAILURE); } atexit(cleanup); + /* We need to work out the real full path to our service. + * This works fine, provided that we ONLY allow mulitplexed services + * to exist in the same directory as the master link. + * Also, the master link as to be a real file in the init dir. */ + if (!realpath(argv[1], path)) { + fprintf(stderr, "realpath: %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + memset(lnk, 0, sizeof(lnk)); + if (readlink(argv[1], lnk, sizeof(lnk)-1)) { + dir = dirname(path); + if (strchr(lnk, '/')) { + save = xstrdup(dir); + dir = dirname(lnk); + if (strcmp(dir, save) == 0) + file = basename_c(argv[1]); + else + file = basename_c(lnk); + free(save); + dir = dirname(path); + } else + file = basename_c(argv[1]); + ll = strlen(dir) + strlen(file) + 2; + service = xmalloc(ll); + snprintf(service, ll, "%s/%s", dir, file); + if (stat(service, &stbuf) != 0) { + free(service); + service = xstrdup(lnk); + } + } + if (!service) + service = xstrdup(path); + applet = basename_c(service); + + if (argc < 3) + usage(EXIT_FAILURE); + /* Change dir to / to ensure all init scripts don't use stuff in pwd */ chdir("/"); #ifdef __linux__ - /* coldplug events can trigger init scripts, but we don't want to run them - until after rc sysinit has completed so we punt them to the boot runlevel */ + /* coldplug events can trigger init scripts, but we don't want to run + * them until after rc sysinit has completed so we punt them to the + * boot runlevel */ if (exists("/dev/.rcsysinit")) { eerror("%s: cannot run until sysvinit completes", applet); if (mkdir("/dev/.rcboot", 0755) != 0 && errno != EEXIST) @@ -1264,7 +1300,8 @@ int runscript(int argc, char **argv) strcmp(optarg, "ibefore") == 0 || strcmp(optarg, "iprovide") == 0) { - if (rc_conf_yesno("rc_depend_strict")) + errno = 0; + if (rc_conf_yesno("rc_depend_strict") || errno == ENOENT) depoptions |= RC_DEP_STRICT; if (! deptree && ((deptree = _rc_deptree_load(NULL)) == NULL))