From 9473830ad612dcb674f6048a9a17e372ff9d9ec3 Mon Sep 17 00:00:00 2001
From: Laurent Bercot
Date: Wed, 12 Aug 2015 20:00:17 +0000
Subject: Intermediary commit; working on source dir format change. Should
work, but untested as for now.
---
INSTALL | 6 +-
Makefile | 45 +-
configure | 26 +-
doc/index.html | 11 +-
doc/s6-rc-compile.html | 118 +++--
doc/s6-rc-db.html | 50 +-
doc/s6-rc.html | 12 +
examples/source/00/down | 1 -
examples/source/devd-log/producer | 1 -
examples/source/devd/logger | 1 -
examples/source/dns-cache-log/producer | 1 -
examples/source/dns-cache/logger | 1 -
examples/source/dns-server-tcp-4-log/producer | 1 -
examples/source/dns-server-tcp-4/logger | 1 -
examples/source/dns-server-udp-log/producer | 1 -
examples/source/dns-server-udp/logger | 1 -
examples/source/fdholder-log/producer | 1 -
examples/source/fdholder/logger | 1 -
examples/source/hostapd-log/producer | 1 -
examples/source/hostapd/logger | 1 -
examples/source/httpd-4-log/producer | 1 -
examples/source/httpd-4/logger | 1 -
examples/source/identd-4-log/producer | 1 -
examples/source/identd-4/logger | 1 -
examples/source/klogd-log/producer | 1 -
examples/source/klogd-srv/logger | 1 -
examples/source/ntpclient-log/producer | 1 -
examples/source/ntpclient/logger | 1 -
examples/source/qmail-log/producer | 1 -
examples/source/qmail/logger | 1 -
examples/source/qmtpd-4-log/producer | 1 -
examples/source/qmtpd-4/logger | 1 -
examples/source/smtpd-4-log/producer | 1 -
examples/source/smtpd-4/logger | 1 -
examples/source/sshd-4-log/producer | 1 -
examples/source/sshd-4/logger | 1 -
examples/source/syslogd-log/producer | 1 -
examples/source/syslogd-srv/logger | 1 -
examples/source/taiclockd-4-log/producer | 1 -
examples/source/taiclockd-4/logger | 1 -
examples/source/udhcpc-eth3-log/producer | 1 -
examples/source/udhcpc-eth3/logger | 1 -
examples/source/udhcpd-wlan0-log/producer | 1 -
examples/source/udhcpd-wlan0/logger | 1 -
package/deps.mak | 6 +-
package/targets.mak | 15 +-
src/include/s6-rc/s6rc-constants.h | 3 +
src/include/s6-rc/s6rc-db.h | 6 +-
src/libs6rc/deps-lib/s6rc | 4 +-
src/libs6rc/s6rc_db_check_depcycles.c | 26 +-
src/libs6rc/s6rc_db_check_revdeps.c | 5 +-
src/libs6rc/s6rc_db_read.c | 5 +-
src/s6-rc/s6-rc-compile.c | 660 ++++++++++++++++++--------
src/s6-rc/s6-rc-db.c | 58 ++-
src/s6-rc/s6-rc-update.c | 101 ++--
src/s6-rc/s6-rc.c | 8 +-
tools/gen-deps.sh | 14 +-
57 files changed, 809 insertions(+), 407 deletions(-)
delete mode 100644 examples/source/00/down
delete mode 100644 examples/source/devd-log/producer
delete mode 100644 examples/source/devd/logger
delete mode 100644 examples/source/dns-cache-log/producer
delete mode 100644 examples/source/dns-cache/logger
delete mode 100644 examples/source/dns-server-tcp-4-log/producer
delete mode 100644 examples/source/dns-server-tcp-4/logger
delete mode 100644 examples/source/dns-server-udp-log/producer
delete mode 100644 examples/source/dns-server-udp/logger
delete mode 100644 examples/source/fdholder-log/producer
delete mode 100644 examples/source/fdholder/logger
delete mode 100644 examples/source/hostapd-log/producer
delete mode 100644 examples/source/hostapd/logger
delete mode 100644 examples/source/httpd-4-log/producer
delete mode 100644 examples/source/httpd-4/logger
delete mode 100644 examples/source/identd-4-log/producer
delete mode 100644 examples/source/identd-4/logger
delete mode 100644 examples/source/klogd-log/producer
delete mode 100644 examples/source/klogd-srv/logger
delete mode 100644 examples/source/ntpclient-log/producer
delete mode 100644 examples/source/ntpclient/logger
delete mode 100644 examples/source/qmail-log/producer
delete mode 100644 examples/source/qmail/logger
delete mode 100644 examples/source/qmtpd-4-log/producer
delete mode 100644 examples/source/qmtpd-4/logger
delete mode 100644 examples/source/smtpd-4-log/producer
delete mode 100644 examples/source/smtpd-4/logger
delete mode 100644 examples/source/sshd-4-log/producer
delete mode 100644 examples/source/sshd-4/logger
delete mode 100644 examples/source/syslogd-log/producer
delete mode 100644 examples/source/syslogd-srv/logger
delete mode 100644 examples/source/taiclockd-4-log/producer
delete mode 100644 examples/source/taiclockd-4/logger
delete mode 100644 examples/source/udhcpc-eth3-log/producer
delete mode 100644 examples/source/udhcpc-eth3/logger
delete mode 100644 examples/source/udhcpd-wlan0-log/producer
delete mode 100644 examples/source/udhcpd-wlan0/logger
diff --git a/INSTALL b/INSTALL
index 3145866..b2c9d03 100644
--- a/INSTALL
+++ b/INSTALL
@@ -6,9 +6,9 @@ Build Instructions
- A POSIX-compliant C development environment
- GNU make version 4.0 or later
- - skalibs version 2.3.6.0 or later: http://skarnet.org/software/skalibs/
- - execline version 2.1.3.0 or later: http://skarnet.org/software/execline/
- - s6 version 2.2.0.0 or later: http://skarnet.org/software/s6/
+ - skalibs version 2.3.6.1 or later: http://skarnet.org/software/skalibs/
+ - execline version 2.1.3.1 or later: http://skarnet.org/software/execline/
+ - s6 version 2.2.0.1 or later: http://skarnet.org/software/s6/
This software will run on any operating system that implements
POSIX.1-2008, available at:
diff --git a/Makefile b/Makefile
index 7ff52e7..6eba87f 100644
--- a/Makefile
+++ b/Makefile
@@ -18,9 +18,23 @@ STATIC_LIBS :=
SHARED_LIBS :=
INTERNAL_LIBS :=
EXTRA_TARGETS :=
+LIB_DEFS :=
+
+define library_definition =
+LIB$(firstword $(subst =, ,$(1))) := lib$(lastword $(subst =, ,$(1))).$(if $(DO_ALLSTATIC),a,so).xyzzy
+ifdef DO_SHARED
+SHARED_LIBS += lib$(lastword $(subst =, ,$(1))).so.xyzzy
+endif
+ifdef DO_STATIC
+STATIC_LIBS += lib$(lastword $(subst =, ,$(1))).a.xyzzy
+endif
+endef
-include config.mak
include package/targets.mak
+
+$(foreach var,$(LIB_DEFS),$(eval $(call library_definition,$(var))))
+
include package/deps.mak
version_m := $(basename $(version))
@@ -30,8 +44,6 @@ CPPFLAGS_ALL := -iquote src/include-local -Isrc/include $(CPPFLAGS)
CFLAGS_ALL := $(CFLAGS) -pipe -Wall
CFLAGS_SHARED := -fPIC
LDFLAGS_ALL := $(LDFLAGS)
-LDFLAGS_SHARED := -shared
-LDLIBS_ALL := $(LDLIBS)
REALCC = $(CROSS_COMPILE)$(CC)
AR := $(CROSS_COMPILE)ar
RANLIB := $(CROSS_COMPILE)ranlib
@@ -67,11 +79,11 @@ ifneq ($(strip $(ALL_BINS)),)
endif
install: install-dynlib install-libexec install-bin install-sbin install-lib install-include
-install-dynlib: $(SHARED_LIBS:lib%.so=$(DESTDIR)$(dynlibdir)/lib%.so)
+install-dynlib: $(SHARED_LIBS:lib%.so.xyzzy=$(DESTDIR)$(dynlibdir)/lib%.so)
install-libexec: $(LIBEXEC_TARGETS:%=$(DESTDIR)$(libexecdir)/%)
install-bin: $(BIN_TARGETS:%=$(DESTDIR)$(bindir)/%)
install-sbin: $(SBIN_TARGETS:%=$(DESTDIR)$(sbindir)/%)
-install-lib: $(STATIC_LIBS:lib%.a=$(DESTDIR)$(libdir)/lib%.a)
+install-lib: $(STATIC_LIBS:lib%.a.xyzzy=$(DESTDIR)$(libdir)/lib%.a)
install-include: $(ALL_INCLUDES:src/include/$(package)/%.h=$(DESTDIR)$(includedir)/$(package)/%.h)
install-data: $(ALL_DATA:src/etc/%=$(DESTDIR)$(datadir)/%)
@@ -80,12 +92,12 @@ ifneq ($(exthome),)
update:
exec $(INSTALL) -l $(notdir $(home)) $(DESTDIR)$(exthome)
-global-links: $(DESTDIR)$(exthome) $(SHARED_LIBS:lib%.so=$(DESTDIR)$(sproot)/library.so/lib%.so) $(BIN_TARGETS:%=$(DESTDIR)$(sproot)/command/%) $(SBIN_TARGETS:%=$(DESTDIR)$(sproot)/command/%)
+global-links: $(DESTDIR)$(exthome) $(SHARED_LIBS:lib%.so.xyzzy=$(DESTDIR)$(sproot)/library.so/lib%.so.$(version_M)) $(BIN_TARGETS:%=$(DESTDIR)$(sproot)/command/%) $(SBIN_TARGETS:%=$(DESTDIR)$(sproot)/command/%)
$(DESTDIR)$(sproot)/command/%: $(DESTDIR)$(home)/command/%
exec $(INSTALL) -D -l ..$(subst $(sproot),,$(exthome))/command/$( A POSIX-compliant system with a standard C development environment
GNU make, version 4.0 or later
skalibs version
-2.3.6.0 or later
+2.3.6.1 or later
execline version
-2.1.3.0 or later
+2.1.3.1 or later
s6 version
-2.2.0.0 or later
+2.2.0.1 or later
Licensing
@@ -92,11 +92,6 @@ the previous versions of s6-rc and the current one.
Commands
-
- All these commands exit 111 if they encounter a temporary error, and
-100 if they encounter a permanent error - such as a misuse.
-
-
Offline tools: creating and managing a compiled service database
diff --git a/doc/s6-rc-compile.html b/doc/s6-rc-compile.html
index a11acfb..44327ba 100644
--- a/doc/s6-rc-compile.html
+++ b/doc/s6-rc-compile.html
@@ -36,7 +36,7 @@ the current service database via
Interface
- s6-rc-compile [ -v verbosity ] [ -u uids ] [ -g gids ] compiled source...
+ s6-rc-compile [ -v verbosity ] [ -u uids ] [ -g gids ] [ -h fdhuser ] compiled source...
@@ -46,7 +46,15 @@ it expects to find a valid service definition in service.
- s6-rc-compile outputs a compiled version of the service database
into compiled. This database contains information for all the
services declared in every source argument.
- - s6-rc-compile exits 0.
+
+
+ Exit codes
+
+
+ - 0: success
+ - 1: error in a source directory
+ - 100: wrong usage
+ - 111: system call failed
Options
@@ -64,6 +72,11 @@ numerical UIDs.
use this database with s6-rc to start and
stop services. gids must be a comma-separated list of
numerical GIDs.
+ -h fdhuser : arrange for the
+s6-fdholder-daemon
+program, which maintains the pipes for the longrun pipelines, to run
+as user fdhuser. By default, it runs as the user owning
+the supervision tree, i.e. most likely root.
@@ -85,7 +98,8 @@ duplicated and cannot contain a slash or a newline; they can
contain spaces and tabs, but using anything else than alphanumerical
characters, underscores and dashes is discouraged - the s6-rc programs
will handle weird names just fine, but other tools, especially
-shell scripts, may not.
+shell scripts, may not. Names are also forbidden to use the reserved
+s6rc- and s6-rc- prefixes.
@@ -221,15 +235,16 @@ directory, but there are a few differences:
s6-rc-compile crafts the servicedir itself, based on what it
finds in the service definition directory. It does not copy everything
directly from the definition directory to the servicedir; only two
-subdirectories will be copied as is, data and env.
+subdirectories will be copied verbatim, data and env.
So if you want to store service configuration data, to be used
by the run script, in the service directory, make sure it is in a
data/ or env/ subdirectory.
Definition directories cannot have a log subdirectory -
or if they do, it will be ignored. From s6-rc-compile's point of view,
logged s6 services must actually be defined as two separate
-s6-rc services, one for the producer and one for the logger; there is
-specific syntax to link those two services.
+s6-rc services, one defined as a producer and one defined as a consumer,
+making a pipeline of just two services; see below for more information
+about pipelines.
@@ -243,16 +258,23 @@ files will be copied, or recreated, in the generated
service directory.
Optional directories named data and env. These will
be copied verbatim into the generated service directory.
- An optional file named logger. If this file exists, then
-service will be flagged as a producer, and the file must
-contain the name of another longrun service servicelog, which will
-be declared as a logger for service. service must also
-be declared as a producer in servicelog's definition directory.
- An optional file named producer. If this file exists, then
-service will be flagged as a logger, and the file must
-contain the name of another longrun service serviceprod, which will
-be declared as a producer for service. service must also
-be declared as a logger in serviceprod's definition directory.
+ An optional file named producer-for. If this file exists, then
+it must contain the name of another longrun service servicelog;
+service is then declared as a producer for servicelog.
+servicelog must also, in its own definition directory,
+be declared as a consumer for service.
+ An optional file named consumer-for. If this file exists, then
+it must contain the name of another longrun service serviceprod;
+service is then declared as a consumer for serviceprod.
+serviceprod must also, in its own definition directory,
+be declared as a producer for service.
+ An optional file named pipeline-name. If this file exists
+along with a producer-for file, and there is no
+consumer-for file, then a bundle will automatically be
+created, named with the content of the pipeline-name file, and
+containing all the services in the pipeline that starts at service.
+See below for more about pipelining. The pipeline-name file
+is ignored if service is not a first producer.
@@ -271,26 +293,60 @@ services that are down.
- The logger and producer files are support for logged services:
-A service defined as a logger for producer p will have its s6 service
-directory set to p/log. Logged service definitions must be consistent:
+ The producer-for, consumer-for and pipeline-name
+files are used to set up automatic longrun pipelining.
+
+
+ Longrun pipelining
+
+
+ Users of supervision suites know about logged services: a service acts
+as a producer, and is coupled with another service, its logger; the
+supervision system automatically maintains an open pipe between the
+producer's stdout and the logger's stdin.
+
+
+
+ s6-rc comes with an extension of this mechanism. Rather than only
+allowing two longrun services to be pipelined, it can set up an
+indefinite number of longrun services this way.
- - It is impossible to have a both a logger and a producer file
-in the same definition directory: loggers cannot have loggers, producers cannot have
-producers.
- - The logger must be declared in the logger file in its producer's
-definition directory, and the producer must be declared in the producer file
-in its logger's definition directory. If it sees an inconsistency, s6-rc-compile
-will complain and exit 1.
- - The producer will automatically have a dependency to its logger (because,
-as much as systemd would have you believe the opposite, it is
-not safe to start a service while its logger is not up). This means that a
-s6-rc change command to start the service will
-automatically start the logger beforehand if it's not already up.
+ - The first producer declares its direct consumer in a producer-for file.
+ - Intermediate services declare both their direct producer in their
+consumer-for file, and their direct consumer in their
+producer-for file.
+ - The last consumer only declares its direct producer in a consumer-for file.
+ - The first producer may declare a name for the whole pipeline, in
+its pipeline-name file. If it does so, then a bundle is automatically
+created with
+the given name, and it contains all the services in the pipeline (plus the
+automatically generated supporting services that open and store the
+pipes).
+
+ s6-rc-compile will detect pipelines, and set up the service directories
+so that every producer's stdout is connected to its consumer's stdin, and
+that the pipes are not broken whenever one element in the chain dies.
+
+
+
+ s6-rc-compile checks for pipeline consistency. It must see a
+producer-for file in the producer's definition that is consistent
+with the consumer-for file in the consumer's definition. It will
+detect and reject cycles as well as collisions.
+
+
+
+ The pipe linking a producer and a consumer is created by an automatically
+generated oneshot service that both the producer and consumer depend on,
+and stored in a
+s6-fdholder-daemon
+instance created by an automatically generated longrun service.
+
+
A complete example
diff --git a/doc/s6-rc-db.html b/doc/s6-rc-db.html
index 280f98a..a60658e 100644
--- a/doc/s6-rc-db.html
+++ b/doc/s6-rc-db.html
@@ -43,7 +43,7 @@ operation.
s6-rc-db [ -l live ] [ -c compiled ] [ -u | -d ] timeout atomicname
s6-rc-db [ -l live ] [ -c compiled ] contents bundlename
s6-rc-db [ -l live ] [ -c compiled ] [ -u | -d ] dependencies servicename
- s6-rc-db [ -l live ] [ -c compiled ] servicedir longrunname
+ s6-rc-db [ -l live ] [ -c compiled ] pipeline longrunname
s6-rc-db [ -l live ] [ -c compiled ] [ -u | -d ] script oneshotname
s6-rc-db [ -l live ] [ -c compiled ] flags atomicname
s6-rc-db [ -l live ] [ -c compiled ] atomics servicename...
@@ -54,9 +54,8 @@ operation.
s6-rc-db expects to find a compiled service database
in compiled; by default it uses the service database
used by the live state in live.
-It reads and parses the compiled database it finds. If the
-database is invalid, it exits 4.
- Depending on the arguments given, it prints the requested
+It reads and parses the compiled database it finds; depending on
+its arguments, it prints the requested
information to stdout, then exits 0.
@@ -78,6 +77,17 @@ depending on whether it's about bringing the service up or down,
select the "down" data. This option is ignored when it is irrelevant.
+ Exit codes
+
+
+ - 0: success
+ - 3: identifier not found in service database
+ - 4: invalid or corrupted service database
+ - 5: wrong identifier type for the given command
+ - 100: wrong usage
+ - 111: system call failed
+
+
Subcommands
s6-rc-db help
@@ -134,8 +144,7 @@ dependency tables, or a dependency cycle.
Prints the type of servicename: oneshot, longrun
-or bundle. Exits 1 if
-servicename is not a valid identifier in the database.
+or bundle.
s6-rc-db timeout atomicname
@@ -143,8 +152,8 @@ or bundle. Exits 1 if
Prints the timeout value, in milliseconds, after which bringing
atomicname up or down is considered a failure if the
-called script still has not succeeded. Exits 1 if atomicname
-isn't a valid atomic service. By default, or if the -u
+called script still has not succeeded.
+By default, or if the -u
option has been given to s6-rc-db, the timeout for up is
printed; the timeout for down is printed instead if the
-d option has been given.
@@ -154,14 +163,12 @@ printed; the timeout for down is printed instead if the
Lists the atomic services represented by bundle bundlename.
-Exits 1 if bundlename is not a valid bundle.
s6-rc-db dependencies servicename
- Prints the list of direct dependencies for servicename.
-Exits 1 if servicename isn't a valid identifier. If
+ Prints the list of direct dependencies for servicename. If
servicename is a bundle, its set of direct dependencies
is the union of the direct dependencies of all the atomic services
contained in the bundle.
@@ -174,12 +181,13 @@ depend on servicename, or on one of its components if it
is a bundle.
- s6-rc-db servicedir longrunname
+ s6-rc-db pipeline longrunname
- Prints the service directory for longrun service longrunname;
-this value is relative to the scandir. Exits 1 if
-longrunname is not a valid longrun.
+ Prints the longrun service pipeline longrunname is a
+part of, one service per line, producers before consumers.
+If longrunname isn't
+part of a pipeline, only longrunname is printed.
s6-rc-db script oneshotname
@@ -190,8 +198,7 @@ an argv, i.e. a Unix command line. Each component of this
command line is
terminated by a null character, so to print it in
a human-readable format, pipe the output into something like
-xargs -0 echo. The command exits 1 if oneshotname
-is not a valid oneshot.
+xargs -0 echo.
@@ -203,8 +210,7 @@ is not a valid oneshot.
Prints a hexadecimal number that is the list of all binary flags
-for atomic service atomicname. Exits 1 if atomicname
-is not a valid atomic service.
+for atomic service atomicname.
@@ -219,8 +225,7 @@ future version of s6-rc.
servicename... arguments, i.e. the union of all
atomic services contained in servicename.... Each
argument in servicename... can be an atomic service or
-a bundle. If an argument isn't a valid identifier, the command
-exits 1.
+a bundle.
s6-rc-db all-dependencies servicename...
@@ -232,8 +237,7 @@ dependencies, recursively. In other words: for
servicename... to be up, every single service listed
in the output will need to be up. The output includes the
atomic services represented by the
-servicename... arguments themselves. If one of those
-arguments isn't a valid identifier, the command exits 1.
+servicename... arguments themselves.
diff --git a/doc/s6-rc.html b/doc/s6-rc.html
index ae3e469..75dba9a 100644
--- a/doc/s6-rc.html
+++ b/doc/s6-rc.html
@@ -59,6 +59,18 @@ information to stdout, then exits 0; or it performs a machine
state change.
+
Exit codes
+
+
+ - 0: success
+ - 1: some of the state transitions could not be performed
+ - 2: timed out during state change
+ - 3: unknown service name in the arguments
+ - 4: invalid service database
+ - 100: wrong usage
+ - 111: system call failed
+
+
Service selection
diff --git a/examples/source/00/down b/examples/source/00/down
deleted file mode 100644
index 8b13789..0000000
--- a/examples/source/00/down
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/examples/source/devd-log/producer b/examples/source/devd-log/producer
deleted file mode 100644
index 0b3e805..0000000
--- a/examples/source/devd-log/producer
+++ /dev/null
@@ -1 +0,0 @@
-devd
diff --git a/examples/source/devd/logger b/examples/source/devd/logger
deleted file mode 100644
index 09c60aa..0000000
--- a/examples/source/devd/logger
+++ /dev/null
@@ -1 +0,0 @@
-devd-log
diff --git a/examples/source/dns-cache-log/producer b/examples/source/dns-cache-log/producer
deleted file mode 100644
index d51d8a1..0000000
--- a/examples/source/dns-cache-log/producer
+++ /dev/null
@@ -1 +0,0 @@
-dns-cache
diff --git a/examples/source/dns-cache/logger b/examples/source/dns-cache/logger
deleted file mode 100644
index 54ef42e..0000000
--- a/examples/source/dns-cache/logger
+++ /dev/null
@@ -1 +0,0 @@
-dns-cache-log
diff --git a/examples/source/dns-server-tcp-4-log/producer b/examples/source/dns-server-tcp-4-log/producer
deleted file mode 100644
index eed0fe9..0000000
--- a/examples/source/dns-server-tcp-4-log/producer
+++ /dev/null
@@ -1 +0,0 @@
-dns-server-tcp-4
diff --git a/examples/source/dns-server-tcp-4/logger b/examples/source/dns-server-tcp-4/logger
deleted file mode 100644
index d437be5..0000000
--- a/examples/source/dns-server-tcp-4/logger
+++ /dev/null
@@ -1 +0,0 @@
-dns-server-tcp-4-log
diff --git a/examples/source/dns-server-udp-log/producer b/examples/source/dns-server-udp-log/producer
deleted file mode 100644
index 6517ecf..0000000
--- a/examples/source/dns-server-udp-log/producer
+++ /dev/null
@@ -1 +0,0 @@
-dns-server-udp
diff --git a/examples/source/dns-server-udp/logger b/examples/source/dns-server-udp/logger
deleted file mode 100644
index 81fc8f4..0000000
--- a/examples/source/dns-server-udp/logger
+++ /dev/null
@@ -1 +0,0 @@
-dns-server-udp-log
diff --git a/examples/source/fdholder-log/producer b/examples/source/fdholder-log/producer
deleted file mode 100644
index c9e44ab..0000000
--- a/examples/source/fdholder-log/producer
+++ /dev/null
@@ -1 +0,0 @@
-fdholder
diff --git a/examples/source/fdholder/logger b/examples/source/fdholder/logger
deleted file mode 100644
index 11f1ac2..0000000
--- a/examples/source/fdholder/logger
+++ /dev/null
@@ -1 +0,0 @@
-fdholder-log
diff --git a/examples/source/hostapd-log/producer b/examples/source/hostapd-log/producer
deleted file mode 100644
index f86cc31..0000000
--- a/examples/source/hostapd-log/producer
+++ /dev/null
@@ -1 +0,0 @@
-hostapd
diff --git a/examples/source/hostapd/logger b/examples/source/hostapd/logger
deleted file mode 100644
index b6e1e02..0000000
--- a/examples/source/hostapd/logger
+++ /dev/null
@@ -1 +0,0 @@
-hostapd-log
diff --git a/examples/source/httpd-4-log/producer b/examples/source/httpd-4-log/producer
deleted file mode 100644
index 3dfc041..0000000
--- a/examples/source/httpd-4-log/producer
+++ /dev/null
@@ -1 +0,0 @@
-httpd-4
diff --git a/examples/source/httpd-4/logger b/examples/source/httpd-4/logger
deleted file mode 100644
index 9835bc1..0000000
--- a/examples/source/httpd-4/logger
+++ /dev/null
@@ -1 +0,0 @@
-httpd-4-log
diff --git a/examples/source/identd-4-log/producer b/examples/source/identd-4-log/producer
deleted file mode 100644
index f3a2772..0000000
--- a/examples/source/identd-4-log/producer
+++ /dev/null
@@ -1 +0,0 @@
-identd-4
diff --git a/examples/source/identd-4/logger b/examples/source/identd-4/logger
deleted file mode 100644
index 7b1014d..0000000
--- a/examples/source/identd-4/logger
+++ /dev/null
@@ -1 +0,0 @@
-identd-4-log
diff --git a/examples/source/klogd-log/producer b/examples/source/klogd-log/producer
deleted file mode 100644
index 3a77aac..0000000
--- a/examples/source/klogd-log/producer
+++ /dev/null
@@ -1 +0,0 @@
-klogd-srv
diff --git a/examples/source/klogd-srv/logger b/examples/source/klogd-srv/logger
deleted file mode 100644
index 2f21a8f..0000000
--- a/examples/source/klogd-srv/logger
+++ /dev/null
@@ -1 +0,0 @@
-klogd-log
diff --git a/examples/source/ntpclient-log/producer b/examples/source/ntpclient-log/producer
deleted file mode 100644
index a0f3ade..0000000
--- a/examples/source/ntpclient-log/producer
+++ /dev/null
@@ -1 +0,0 @@
-ntpclient
diff --git a/examples/source/ntpclient/logger b/examples/source/ntpclient/logger
deleted file mode 100644
index c51cd0b..0000000
--- a/examples/source/ntpclient/logger
+++ /dev/null
@@ -1 +0,0 @@
-ntpclient-log
diff --git a/examples/source/qmail-log/producer b/examples/source/qmail-log/producer
deleted file mode 100644
index e9c4b1e..0000000
--- a/examples/source/qmail-log/producer
+++ /dev/null
@@ -1 +0,0 @@
-qmail
diff --git a/examples/source/qmail/logger b/examples/source/qmail/logger
deleted file mode 100644
index db09b5f..0000000
--- a/examples/source/qmail/logger
+++ /dev/null
@@ -1 +0,0 @@
-qmail-log
diff --git a/examples/source/qmtpd-4-log/producer b/examples/source/qmtpd-4-log/producer
deleted file mode 100644
index bf4ce61..0000000
--- a/examples/source/qmtpd-4-log/producer
+++ /dev/null
@@ -1 +0,0 @@
-qmtpd-4
diff --git a/examples/source/qmtpd-4/logger b/examples/source/qmtpd-4/logger
deleted file mode 100644
index fbc3153..0000000
--- a/examples/source/qmtpd-4/logger
+++ /dev/null
@@ -1 +0,0 @@
-qmtpd-4-log
diff --git a/examples/source/smtpd-4-log/producer b/examples/source/smtpd-4-log/producer
deleted file mode 100644
index bff8ca4..0000000
--- a/examples/source/smtpd-4-log/producer
+++ /dev/null
@@ -1 +0,0 @@
-smtpd-4
diff --git a/examples/source/smtpd-4/logger b/examples/source/smtpd-4/logger
deleted file mode 100644
index c6fa24d..0000000
--- a/examples/source/smtpd-4/logger
+++ /dev/null
@@ -1 +0,0 @@
-smtpd-4-log
diff --git a/examples/source/sshd-4-log/producer b/examples/source/sshd-4-log/producer
deleted file mode 100644
index 7d1730e..0000000
--- a/examples/source/sshd-4-log/producer
+++ /dev/null
@@ -1 +0,0 @@
-sshd-4
diff --git a/examples/source/sshd-4/logger b/examples/source/sshd-4/logger
deleted file mode 100644
index f103f82..0000000
--- a/examples/source/sshd-4/logger
+++ /dev/null
@@ -1 +0,0 @@
-sshd-4-log
diff --git a/examples/source/syslogd-log/producer b/examples/source/syslogd-log/producer
deleted file mode 100644
index 93c1661..0000000
--- a/examples/source/syslogd-log/producer
+++ /dev/null
@@ -1 +0,0 @@
-syslogd-srv
diff --git a/examples/source/syslogd-srv/logger b/examples/source/syslogd-srv/logger
deleted file mode 100644
index 75d14f5..0000000
--- a/examples/source/syslogd-srv/logger
+++ /dev/null
@@ -1 +0,0 @@
-syslogd-log
diff --git a/examples/source/taiclockd-4-log/producer b/examples/source/taiclockd-4-log/producer
deleted file mode 100644
index 7684875..0000000
--- a/examples/source/taiclockd-4-log/producer
+++ /dev/null
@@ -1 +0,0 @@
-taiclockd-4
diff --git a/examples/source/taiclockd-4/logger b/examples/source/taiclockd-4/logger
deleted file mode 100644
index 04d85c4..0000000
--- a/examples/source/taiclockd-4/logger
+++ /dev/null
@@ -1 +0,0 @@
-taiclockd-4-log
diff --git a/examples/source/udhcpc-eth3-log/producer b/examples/source/udhcpc-eth3-log/producer
deleted file mode 100644
index 6904444..0000000
--- a/examples/source/udhcpc-eth3-log/producer
+++ /dev/null
@@ -1 +0,0 @@
-udhcpc-eth3
diff --git a/examples/source/udhcpc-eth3/logger b/examples/source/udhcpc-eth3/logger
deleted file mode 100644
index 018297b..0000000
--- a/examples/source/udhcpc-eth3/logger
+++ /dev/null
@@ -1 +0,0 @@
-udhcpc-eth3-log
diff --git a/examples/source/udhcpd-wlan0-log/producer b/examples/source/udhcpd-wlan0-log/producer
deleted file mode 100644
index d336700..0000000
--- a/examples/source/udhcpd-wlan0-log/producer
+++ /dev/null
@@ -1 +0,0 @@
-udhcpd-wlan0
diff --git a/examples/source/udhcpd-wlan0/logger b/examples/source/udhcpd-wlan0/logger
deleted file mode 100644
index f5ac32a..0000000
--- a/examples/source/udhcpd-wlan0/logger
+++ /dev/null
@@ -1 +0,0 @@
-udhcpd-wlan0-log
diff --git a/package/deps.mak b/package/deps.mak
index a5d7b1d..a2a4dc4 100644
--- a/package/deps.mak
+++ b/package/deps.mak
@@ -5,6 +5,7 @@
src/include/s6-rc/s6rc-utils.h: src/include/s6-rc/s6rc-db.h
src/include/s6-rc/s6rc.h: src/include/s6-rc/s6rc-constants.h src/include/s6-rc/s6rc-db.h src/include/s6-rc/s6rc-utils.h
src/libs6rc/s6rc_db_check_depcycles.o src/libs6rc/s6rc_db_check_depcycles.lo: src/libs6rc/s6rc_db_check_depcycles.c src/include/s6-rc/s6rc-db.h
+src/libs6rc/s6rc_db_check_pipelines.o src/libs6rc/s6rc_db_check_pipelines.lo: src/libs6rc/s6rc_db_check_pipelines.c src/include/s6-rc/s6rc-db.h
src/libs6rc/s6rc_db_check_revdeps.o src/libs6rc/s6rc_db_check_revdeps.lo: src/libs6rc/s6rc_db_check_revdeps.c src/include/s6-rc/s6rc-db.h
src/libs6rc/s6rc_db_read.o src/libs6rc/s6rc_db_read.lo: src/libs6rc/s6rc_db_read.c src/include/s6-rc/s6rc-db.h
src/libs6rc/s6rc_db_read_sizes.o src/libs6rc/s6rc_db_read_sizes.lo: src/libs6rc/s6rc_db_read_sizes.c src/include/s6-rc/s6rc-db.h
@@ -17,8 +18,9 @@ src/s6-rc/s6-rc-init.o src/s6-rc/s6-rc-init.lo: src/s6-rc/s6-rc-init.c src/inclu
src/s6-rc/s6-rc-update.o src/s6-rc/s6-rc-update.lo: src/s6-rc/s6-rc-update.c src/include/s6-rc/config.h src/include/s6-rc/s6rc.h
src/s6-rc/s6-rc.o src/s6-rc/s6-rc.lo: src/s6-rc/s6-rc.c src/include/s6-rc/config.h src/include/s6-rc/s6rc.h
-libs6rc.a: src/libs6rc/s6rc_db_check_depcycles.o src/libs6rc/s6rc_db_read.o src/libs6rc/s6rc_db_read_sizes.o src/libs6rc/s6rc_db_read_uint32.o src/libs6rc/s6rc_db_check_revdeps.o src/libs6rc/s6rc_graph_closure.o
-libs6rc.so: src/libs6rc/s6rc_db_check_depcycles.lo src/libs6rc/s6rc_db_read.lo src/libs6rc/s6rc_db_read_sizes.lo src/libs6rc/s6rc_db_read_uint32.lo src/libs6rc/s6rc_db_check_revdeps.lo src/libs6rc/s6rc_graph_closure.lo
+libs6rc.a.xyzzy: src/libs6rc/s6rc_db_check_depcycles.o src/libs6rc/s6rc_db_check_pipelines.o src/libs6rc/s6rc_db_check_revdeps.o src/libs6rc/s6rc_db_read.o src/libs6rc/s6rc_db_read_sizes.o src/libs6rc/s6rc_db_read_uint32.o src/libs6rc/s6rc_graph_closure.o
+libs6rc.so.xyzzy: private EXTRA_LIBS := -lskarnet
+libs6rc.so.xyzzy: src/libs6rc/s6rc_db_check_depcycles.lo src/libs6rc/s6rc_db_check_pipelines.lo src/libs6rc/s6rc_db_check_revdeps.lo src/libs6rc/s6rc_db_read.lo src/libs6rc/s6rc_db_read_sizes.lo src/libs6rc/s6rc_db_read_uint32.lo src/libs6rc/s6rc_graph_closure.lo
s6-rc: private EXTRA_LIBS := ${TAINNOW_LIB}
s6-rc: src/s6-rc/s6-rc.o ${LIBS6RC} -lskarnet
s6-rc-compile: private EXTRA_LIBS :=
diff --git a/package/targets.mak b/package/targets.mak
index 9bcf975..5f50ad4 100644
--- a/package/targets.mak
+++ b/package/targets.mak
@@ -8,19 +8,6 @@ s6-rc-init \
s6-rc \
s6-rc-update
-
LIBEXEC_TARGETS :=
-ifdef DO_ALLSTATIC
-LIBS6RC := libs6rc.a
-else
-LIBS6RC := libs6rc.so
-endif
-
-ifdef DO_SHARED
-SHARED_LIBS := libs6rc.so
-endif
-
-ifdef DO_STATIC
-STATIC_LIBS := libs6rc.a
-endif
+LIB_DEFS := S6RC=s6rc
diff --git a/src/include/s6-rc/s6rc-constants.h b/src/include/s6-rc/s6rc-constants.h
index 92af2a9..87e7053 100644
--- a/src/include/s6-rc/s6rc-constants.h
+++ b/src/include/s6-rc/s6rc-constants.h
@@ -11,4 +11,7 @@
#define S6RC_ONESHOT_RUNNER "s6rc-oneshot-runner"
#define S6RC_ONESHOT_RUNNER_LEN (sizeof S6RC_ONESHOT_RUNNER - 1)
+#define S6RC_FDHOLDER "s6rc-fdholder"
+#define S6RC_FDHOLDER_LEN (sizeof S6RC_FDHOLDER - 1)
+
#endif
diff --git a/src/include/s6-rc/s6rc-db.h b/src/include/s6-rc/s6rc-db.h
index bc516b2..0053af9 100644
--- a/src/include/s6-rc/s6rc-db.h
+++ b/src/include/s6-rc/s6rc-db.h
@@ -4,6 +4,7 @@
#define S6RC_DB_H
#include
+#include
#include
#define S6RC_DB_BANNER_START "s6rc-db: start\n"
@@ -22,7 +23,7 @@ struct s6rc_oneshot_s
typedef struct s6rc_longrun_s s6rc_longrun_t, *s6rc_longrun_t_ref ;
struct s6rc_longrun_s
{
- uint32 servicedir ;
+ uint32 pipeline[2] ;
} ;
typedef union s6rc_longshot_u s6rc_longshot_t, *s6rc_longshot_t_ref ;
@@ -62,7 +63,8 @@ extern int s6rc_db_read_uint32 (buffer *, uint32 *) ;
extern int s6rc_db_read_sizes (int, s6rc_db_t *) ;
extern int s6rc_db_read (int, s6rc_db_t *) ;
-extern unsigned int s6rc_db_check_depcycles (s6rc_db_t const *, int, unsigned int *) ;
+extern int s6rc_db_check_pipelines (s6rc_db_t const *, diuint32 *) ;
+extern int s6rc_db_check_depcycles (s6rc_db_t const *, int, diuint32 *) ;
extern int s6rc_db_check_revdeps (s6rc_db_t const *) ;
#endif
diff --git a/src/libs6rc/deps-lib/s6rc b/src/libs6rc/deps-lib/s6rc
index 65b562e..194ea43 100644
--- a/src/libs6rc/deps-lib/s6rc
+++ b/src/libs6rc/deps-lib/s6rc
@@ -1,6 +1,8 @@
s6rc_db_check_depcycles.o
+s6rc_db_check_pipelines.o
+s6rc_db_check_revdeps.o
s6rc_db_read.o
s6rc_db_read_sizes.o
s6rc_db_read_uint32.o
-s6rc_db_check_revdeps.o
s6rc_graph_closure.o
+-lskarnet
diff --git a/src/libs6rc/s6rc_db_check_depcycles.c b/src/libs6rc/s6rc_db_check_depcycles.c
index 13dcf7b..db6ed6e 100644
--- a/src/libs6rc/s6rc_db_check_depcycles.c
+++ b/src/libs6rc/s6rc_db_check_depcycles.c
@@ -1,6 +1,7 @@
/* ISC license. */
#include
+#include
#include
#include
#include
@@ -9,22 +10,22 @@ typedef struct recinfo_s recinfo_t, *recinfo_t_ref ;
struct recinfo_s
{
s6rc_db_t const *db ;
- unsigned int n ;
+ uint32 n ;
unsigned char *gray ;
unsigned char *black ;
unsigned char h : 1 ;
} ;
-static unsigned int s6rc_db_checknocycle_rec (recinfo_t *recinfo, unsigned int i)
+static uint32 s6rc_db_checknocycle_rec (recinfo_t *recinfo, uint32 i)
{
if (!bitarray_peek(recinfo->black, i))
{
- unsigned int j = recinfo->db->services[i].ndeps[recinfo->h] ;
+ uint32 j = recinfo->db->services[i].ndeps[recinfo->h] ;
if (bitarray_peek(recinfo->gray, i)) return i ;
bitarray_set(recinfo->gray, i) ;
while (j--)
{
- register unsigned int r = s6rc_db_checknocycle_rec(recinfo, recinfo->db->deps[recinfo->h * recinfo->db->ndeps + recinfo->db->services[i].deps[recinfo->h] + j]) ;
+ register uint32 r = s6rc_db_checknocycle_rec(recinfo, recinfo->db->deps[recinfo->h * recinfo->db->ndeps + recinfo->db->services[i].deps[recinfo->h] + j]) ;
if (r < recinfo->n) return r ;
}
bitarray_set(recinfo->black, i) ;
@@ -32,19 +33,24 @@ static unsigned int s6rc_db_checknocycle_rec (recinfo_t *recinfo, unsigned int i
return recinfo->n ;
}
-unsigned int s6rc_db_check_depcycles (s6rc_db_t const *db, int h, unsigned int *problem)
+int s6rc_db_check_depcycles (s6rc_db_t const *db, int h, diuint32 *problem)
{
- unsigned int n = db->nshort + db->nlong ;
+ uint32 n = db->nshort + db->nlong ;
+ uint32 i = n ;
unsigned char gray[bitarray_div8(n)] ;
unsigned char black[bitarray_div8(n)] ;
recinfo_t info = { .db = db, .n = n, .gray = gray, .black = black, .h = !!h } ;
- unsigned int i = n ;
byte_zero(gray, bitarray_div8(n)) ;
byte_zero(black, bitarray_div8(n)) ;
while (i--)
{
- register unsigned int r = s6rc_db_checknocycle_rec(&info, i) ;
- if (r < n) return (*problem = r, i) ;
+ register uint32 r = s6rc_db_checknocycle_rec(&info, i) ;
+ if (r < n)
+ {
+ problem->left = i ;
+ problem->right = r ;
+ return 1 ;
+ }
}
- return n ;
+ return 0 ;
}
diff --git a/src/libs6rc/s6rc_db_check_revdeps.c b/src/libs6rc/s6rc_db_check_revdeps.c
index 0cb2845..a4342b1 100644
--- a/src/libs6rc/s6rc_db_check_revdeps.c
+++ b/src/libs6rc/s6rc_db_check_revdeps.c
@@ -1,6 +1,5 @@
/* ISC license. */
-#include
#include
#include
#include
@@ -25,6 +24,6 @@ int s6rc_db_check_revdeps (s6rc_db_t const *db)
while (j--) bitarray_not(matrix + m * db->deps[db->services[i].deps[0] + j], i, 1) ;
}
i = n * m ;
- while (i--) if (*p++) return 0 ;
- return 1 ;
+ while (i--) if (*p++) return 1 ;
+ return 0 ;
}
diff --git a/src/libs6rc/s6rc_db_read.c b/src/libs6rc/s6rc_db_read.c
index 7a38797..50e1f78 100644
--- a/src/libs6rc/s6rc_db_read.c
+++ b/src/libs6rc/s6rc_db_read.c
@@ -90,9 +90,8 @@ static inline int s6rc_db_read_services (buffer *b, s6rc_db_t *db)
#endif
if (i < db->nlong)
{
- if (!s6rc_db_read_uint32(b, &sv->x.longrun.servicedir)) return -1 ;
- DBG(" longrun - servicedir is %u: %s", sv->x.longrun.servicedir, db->string + sv->x.longrun.servicedir) ;
- if (!s6rc_db_check_valid_string(db->string, db->stringlen, sv->x.longrun.servicedir)) return 0 ;
+ if (!s6rc_db_read_uint32(b, &sv->x.longrun.pipeline[0])) return -1 ;
+ if (!s6rc_db_read_uint32(b, &sv->x.longrun.pipeline[1])) return -1 ;
}
else
{
diff --git a/src/s6-rc/s6-rc-compile.c b/src/s6-rc/s6-rc-compile.c
index 1126967..a1ffdee 100644
--- a/src/s6-rc/s6-rc-compile.c
+++ b/src/s6-rc/s6-rc-compile.c
@@ -27,10 +27,12 @@
#include
#include
-#define USAGE "s6-rc-compile [ -v verbosity ] [ -u okuid,okuid... ] [ -g okgid,okgid... ] destdir sources..."
+#define USAGE "s6-rc-compile [ -v verbosity ] [ -u okuid,okuid... ] [ -g okgid,okgid... ] [ -h fdholder_user ] destdir sources..."
#define dieusage() strerr_dieusage(100, USAGE)
#define dienomem() strerr_dief1x(111, "out of memory") ;
+#define S6RC_INTERNALS "s6-rc-compile internals"
+
#define S6RC_ONESHOT_RUNNER_RUNSCRIPT \
"#!" EXECLINE_SHEBANGPREFIX "execlineb -P\n" \
EXECLINE_EXTBINPREFIX "fdmove -c 2 1\n" \
@@ -40,8 +42,6 @@ S6_EXTBINPREFIX "s6-ipcserverd -1 --\n" \
S6_EXTBINPREFIX "s6-ipcserver-access -v0 -E -l0 -i data/rules --\n" \
S6_EXTBINPREFIX "s6-sudod -t 2000 --\n"
-#define BASE_RULES "servicedirs/" S6RC_ONESHOT_RUNNER "/data/rules/gid"
-
static unsigned int verbosity = 1 ;
static stralloc keep = STRALLOC_ZERO ;
static stralloc data = STRALLOC_ZERO ;
@@ -91,7 +91,6 @@ static avltree names_map = AVLTREE_INIT(8, 3, 8, &names_dtok, &names_cmp, &namei
typedef struct common_s common_t, *common_t_ref ;
struct common_s
{
- unsigned int name ; /* pos in data */
unsigned int kname ; /* pos in keep */
unsigned int ndeps ;
unsigned int depindex ; /* pos in indices */
@@ -103,7 +102,7 @@ typedef struct oneshot_s oneshot_t, *oneshot_t_ref ;
struct oneshot_s
{
common_t common ;
- unsigned int argvindex[2] ; /* pos in data */
+ unsigned int argvindex[2] ; /* pos in keep */
unsigned int argc[2] ;
} ;
@@ -112,9 +111,8 @@ struct longrun_s
{
common_t common ;
char const *srcdir ;
- unsigned int servicedirname ;
- unsigned int logrelated ;
- unsigned char logtype ;
+ unsigned int pipeline[2] ; /* pos in data */
+ unsigned int pipelinename ; /* pos in data */
} ;
typedef struct bundle_s bundle_t, *bundle_t_ref ;
@@ -128,19 +126,19 @@ struct bundle_s
typedef struct before_s before_t, *before_t_ref ;
struct before_s
{
- genalloc indices ; /* uint32 */
+ genalloc indices ; /* unsigned int */
genalloc oneshots ; /* oneshot_t */
genalloc longruns ; /* longrun_t */
genalloc bundles ; /* bundle_t */
unsigned int nargvs ;
- unsigned int maxnamelen ;
+ uint32 specialdeps[2] ;
} ;
-#define BEFORE_ZERO { .indices = GENALLOC_ZERO, .oneshots = GENALLOC_ZERO, .longruns = GENALLOC_ZERO, .bundles = GENALLOC_ZERO, .nargvs = 0 } ;
+#define BEFORE_ZERO { .indices = GENALLOC_ZERO, .oneshots = GENALLOC_ZERO, .longruns = GENALLOC_ZERO, .bundles = GENALLOC_ZERO, .nargvs = 0, .specialdeps = { 0, 0 } } ;
- /* Read all the sources, populate the map and string data */
+ /* Read all the sources, populate the name map */
static char const *typestr (servicetype_t type)
@@ -151,7 +149,7 @@ static char const *typestr (servicetype_t type)
"unknown" ;
}
-static int add_name (before_t *be, char const *srcdir, char const *name, servicetype_t type, unsigned int *pos, unsigned int *kpos)
+static int add_name_nocheck (before_t *be, char const *srcdir, char const *name, servicetype_t type, unsigned int *pos, unsigned int *kpos)
{
unsigned int id ;
@@ -214,20 +212,32 @@ static int add_name (before_t *be, char const *srcdir, char const *name, service
} ;
unsigned int namelen = str_len(name) ;
unsigned int i = genalloc_len(nameinfo_t, &nameinfo) ;
- if (!stralloc_catb(&data, name, namelen + 1)) dienomem() ;
if (type == SVTYPE_ONESHOT || type == SVTYPE_LONGRUN)
if (!stralloc_catb(&keep, name, namelen + 1)) dienomem() ;
+ if (!stralloc_catb(&data, name, namelen + 1)) dienomem() ;
if (!genalloc_append(nameinfo_t, &nameinfo, &info)) dienomem() ;
if (!avltree_insert(&names_map, i)) dienomem() ;
*pos = info.pos ;
*kpos = info.kpos ;
- if (namelen > be->maxnamelen) be->maxnamelen = namelen ;
return 0 ;
}
}
-static inline void add_specials (before_t *be)
+static void check_identifier (char const *srcdir, char const *s)
+{
+ if (!byte_diff(s, 5, "s6rc-") && !byte_diff(s, 6, "s6-rc-"))
+ strerr_dief5x(1, "in ", srcdir, ": identifier ", s, " starts with reserved prefix") ;
+}
+
+static int add_name (before_t *be, char const *srcdir, char const *name, servicetype_t type, unsigned int *pos, unsigned int *kpos)
+{
+ check_identifier(srcdir, name) ;
+ return add_name_nocheck(be, srcdir, name, type, pos, kpos) ;
+}
+
+static unsigned int add_internal_longrun (before_t *be, char const *name)
{
+ unsigned int pos ;
longrun_t service =
{
.common =
@@ -238,14 +248,86 @@ static inline void add_specials (before_t *be)
.timeout = { 0, 0 }
},
.srcdir = 0,
- .servicedirname = keep.len,
- .logrelated = 0,
- .logtype = 0
+ .pipeline = { 0, 0 }
} ;
- add_name(be, "(s6-rc-compile internals)", S6RC_ONESHOT_RUNNER, SVTYPE_LONGRUN, &service.common.name, &service.common.kname) ;
- if (!stralloc_cats(&keep, data.s + service.common.name)
- || !stralloc_0(&keep)) dienomem() ;
+ add_name_nocheck(be, S6RC_INTERNALS, name, SVTYPE_LONGRUN, &pos, &service.common.kname) ;
if (!genalloc_append(longrun_t, &be->longruns, &service)) dienomem() ;
+ return pos ;
+}
+
+static unsigned int add_internal_oneshot (before_t *be, char const *name, char const *ups, unsigned int upn, char const *downs, unsigned int downn)
+{
+ unsigned int pos ;
+ oneshot_t service =
+ {
+ .common =
+ {
+ .ndeps = 2,
+ .depindex = genalloc_len(unsigned int, &be->indices),
+ .annotation_flags = 0,
+ .timeout = { 0, 0 }
+ },
+ .argvindex = { keep.len, keep.len + downn }
+ } ;
+ service.argc[0] = byte_count(downs, downn, '\0') ;
+ service.argc[1] = byte_count(ups, upn, '\0') ;
+ if (!genalloc_catb(unsigned int, &be->indices, be->specialdeps, 2)
+ || !stralloc_catb(&keep, downs, downn)
+ || !stralloc_catb(&keep, ups, upn)) dienomem() ;
+ add_name_nocheck(be, S6RC_INTERNALS, name, SVTYPE_ONESHOT, &pos, &service.common.kname) ;
+ if (!genalloc_append(oneshot_t, &be->oneshots, &service)) dienomem() ;
+ return pos ;
+}
+
+static void add_word (char const *word)
+{
+ if (!stralloc_cats(&satmp, word) || !stralloc_0(&satmp)) dienomem() ;
+}
+
+static unsigned int add_storepipe (before_t *be, char const *name)
+{
+ unsigned int pos, sep, base = satmp.len ;
+ unsigned int namelen = str_len(name) ;
+ char svname[16 + namelen] ;
+ byte_copy(svname, 15, "s6rc-storepipe-") ;
+ byte_copy(svname + 15, namelen + 1, name) ;
+
+ add_word(EXECLINE_EXTBINPREFIX "piperw") ;
+ add_word("0") ;
+ add_word("1") ;
+ add_word(EXECLINE_EXTBINPREFIX "if") ;
+ add_word(" " S6_EXTBINPREFIX "s6-fdholder-store") ;
+ add_word(" ../s6rc-fdholder/s") ;
+ add_word(" pipe:s6rc-r-") ; satmp.len-- ; add_word(name) ;
+ add_word("") ;
+ add_word(EXECLINE_EXTBINPREFIX "if") ;
+ add_word("-nt") ;
+ add_word(" " S6_EXTBINPREFIX "s6-fdholder-store") ;
+ add_word(" -d1") ;
+ add_word(" ./s6rc-fdholder/s") ;
+ add_word(" pipe:s6rc-w-") ; satmp.len-- ; add_word(name) ;
+ add_word("") ;
+ add_word(EXECLINE_EXTBINPREFIX "exit") ;
+ add_word("1") ;
+
+ sep = satmp.len ;
+
+ add_word(EXECLINE_EXTBINPREFIX "foreground") ;
+ add_word(" " S6_EXTBINPREFIX "s6-fdholder-delete") ;
+ add_word(" ../s6rc-fdholder/s") ;
+ add_word(" pipe:s6rc-w-") ; satmp.len-- ; add_word(name) ;
+ add_word("") ;
+ add_word(EXECLINE_EXTBINPREFIX "foreground") ;
+ add_word(" " S6_EXTBINPREFIX "s6-fdholder-delete") ;
+ add_word(" ../s6rc-fdholder/s") ;
+ add_word(" pipe:s6rc-r-") ; satmp.len-- ; add_word(name) ;
+ add_word("") ;
+ add_word(EXECLINE_EXTBINPREFIX "exit") ;
+ add_word("0") ;
+
+ pos = add_internal_oneshot(be, svname, satmp.s + base, sep - base, satmp.s + sep, satmp.len - sep) ;
+ satmp.len = base ;
+ return pos ;
}
static int uint_uniq (unsigned int const *list, unsigned int n, unsigned int pos)
@@ -348,8 +430,9 @@ static uint32 read_timeout (int dirfd, char const *srcdir, char const *name, cha
static void add_common (before_t *be, int dirfd, char const *srcdir, char const *name, common_t *common, servicetype_t svtype)
{
+ unsigned int dummy ;
common->annotation_flags = 0 ;
- add_name(be, srcdir, name, svtype, &common->name, &common->kname) ;
+ add_name(be, srcdir, name, svtype, &dummy, &common->kname) ;
if (!add_namelist(be, dirfd, srcdir, name, "dependencies", &common->depindex, &common->ndeps))
{
if (errno != ENOENT)
@@ -363,19 +446,13 @@ static void add_common (before_t *be, int dirfd, char const *srcdir, char const
static inline void add_oneshot (before_t *be, int dirfd, char const *srcdir, char const *name)
{
- static unsigned int const special_dep = 0 ;
oneshot_t service ;
if (verbosity >= 3) strerr_warni3x(name, " has type ", "oneshot") ;
add_common(be, dirfd, srcdir, name, &service.common, SVTYPE_ONESHOT) ;
read_script(be, dirfd, srcdir, name, "up", &service.argvindex[1], &service.argc[1], 1) ;
read_script(be, dirfd, srcdir, name, "down", &service.argvindex[0], &service.argc[0], 0) ;
- if (uint_uniq(genalloc_s(unsigned int, &be->indices) + service.common.depindex, service.common.ndeps, 0))
- {
- if (!genalloc_append(unsigned int, &be->indices, &special_dep)) dienomem() ;
- service.common.ndeps++ ;
- }
- else if (verbosity)
- strerr_warnw6x(srcdir, "/", name, "/dependencies", " explicitly lists ", S6RC_ONESHOT_RUNNER) ;
+ if (!genalloc_append(unsigned int, &be->indices, &be->specialdeps[0])) dienomem() ;
+ service.common.ndeps++ ;
if (verbosity >= 4)
{
unsigned int i = service.common.ndeps ;
@@ -387,16 +464,15 @@ static inline void add_oneshot (before_t *be, int dirfd, char const *srcdir, cha
strerr_warnt7x("dependency from ", name, " to ", data.s + *p, " (", fmt, ")") ;
p++ ;
}
-
}
if (!genalloc_append(oneshot_t, &be->oneshots, &service)) dienomem() ;
}
static inline void add_longrun (before_t *be, int dirfd, char const *srcdir, char const *name)
{
- longrun_t service = { .srcdir = srcdir } ;
+ longrun_t service = { .srcdir = srcdir, .pipeline = { 0, 0 }, .pipelinename = 0 } ;
+ unsigned int relatedindex, n ;
int fd ;
- unsigned int logindex, n ;
if (verbosity >= 3) strerr_warni3x(name, " has type ", "longrun") ;
add_common(be, dirfd, srcdir, name, &service.common, SVTYPE_LONGRUN) ;
fd = open_readat(dirfd, "run") ;
@@ -415,40 +491,48 @@ static inline void add_longrun (before_t *be, int dirfd, char const *srcdir, cha
strerr_dief4x(1, srcdir, "/", name, "/run is not a regular file") ;
}
close(fd) ;
- if (add_namelist(be, dirfd, srcdir, name, "logger", &logindex, &n))
+ fd = 0 ;
+ if (add_namelist(be, dirfd, srcdir, name, "producer-for", &relatedindex, &n))
{
- register unsigned int const *deps = genalloc_s(unsigned int, &be->indices) + service.common.depindex ;
- register unsigned int i = 0 ;
if (n != 1)
- strerr_dief5x(1, srcdir, "/", name, "/logger", " should only contain one service name") ;
- service.logtype = 1 ;
- service.logrelated = genalloc_s(unsigned int, &be->indices)[logindex] ;
- service.servicedirname = service.common.kname ;
- for (; i < service.common.ndeps ; i++) if (service.logrelated == deps[i]) break ;
- if (i < service.common.ndeps)
- genalloc_setlen(unsigned int, &be->indices, logindex) ;
- else service.common.ndeps++ ;
+ strerr_dief5x(1, srcdir, "/", name, "/producer-for", " should only contain one service name") ;
+ service.pipeline[1] = genalloc_s(unsigned int, &be->indices)[relatedindex] ;
+ {
+ unsigned int dummy ;
+ unsigned int namelen = str_len(data.s + service.pipeline[1]) ;
+ char svname[16 + namelen] ;
+ byte_copy(svname, 15, "s6rc-storepipe-") ;
+ byte_copy(svname + 15, namelen + 1, data.s + service.pipeline[1]) ;
+ add_name_nocheck(be, srcdir, svname, SVTYPE_UNDEFINED, &n, &dummy) ;
+ if (!genalloc_append(unsigned int, &be->indices, &n)) dienomem() ;
+ service.common.ndeps += 2 ;
+ }
if (verbosity >= 3)
- strerr_warni3x(name, " is a producer for ", data.s + service.logrelated) ;
+ strerr_warni3x(name, " is a producer for ", data.s + service.pipeline[1]) ;
+ fd = 1 ;
}
- else if (add_namelist(be, dirfd, srcdir, name, "producer", &logindex, &n))
+ if (add_namelist(be, dirfd, srcdir, name, "consumer-for", &relatedindex, &n))
{
+ unsigned int namelen = str_len(name) ;
+ char svname[16 + namelen] ;
if (n != 1)
- strerr_dief5x(1, srcdir, "/", name, "/producer", " should only contain one service name") ;
- service.logtype = 2 ;
- service.logrelated = genalloc_s(unsigned int, &be->indices)[logindex] ;
- genalloc_setlen(unsigned int, &be->indices, logindex) ;
- service.servicedirname = keep.len ;
- if (!stralloc_cats(&keep, data.s + service.logrelated)
- || !stralloc_catb(&keep, "/log", 5)) dienomem() ;
+ strerr_dief5x(1, srcdir, "/", name, "/consumer-for", " should only contain one service name") ;
+ service.pipeline[0] = genalloc_s(unsigned int, &be->indices)[relatedindex] ;
+ byte_copy(svname, 15, "s6rc-storepipe-") ;
+ byte_copy(svname + 15, namelen + 1, name) ;
if (verbosity >= 3)
- strerr_warni3x(name, " is a logger for ", data.s + service.logrelated) ;
+ strerr_warni3x(name, " is a consumer for ", data.s + service.pipeline[0]) ;
+ n = add_storepipe(be, svname) ;
+ genalloc_s(unsigned int, &be->indices)[relatedindex] = n ;
+ service.common.ndeps++ ;
+ fd = 0 ;
}
- else
+ if (fd && add_namelist(be, dirfd, srcdir, name, "pipeline-name", &relatedindex, &n))
{
- service.logtype = 0 ;
- service.servicedirname = service.common.kname ;
- if (verbosity >= 3) strerr_warni2x(name, " has no logger or producer") ;
+ if (n != 1)
+ strerr_dief5x(1, srcdir, "/", name, "/pipeline-name", " should only contain one name") ;
+ service.pipelinename = genalloc_s(unsigned int, &be->indices)[relatedindex] ;
+ genalloc_setlen(unsigned int, &be->indices, relatedindex) ;
}
if (!genalloc_append(longrun_t, &be->longruns, &service)) dienomem() ;
}
@@ -501,7 +585,8 @@ static inline void add_sources (before_t *be, char const *srcdir)
if (!d) break ;
if (d->d_name[0] == '.') continue ;
if (d->d_name[str_chr(d->d_name, '\n')])
- strerr_dief3x(2, "subdirectory of ", srcdir, " contains a newline character") ;
+ strerr_dief3x(1, "subdirectory of ", srcdir, " contains a newline character") ;
+ check_identifier(srcdir, d->d_name) ;
satmp.len = cur ;
if (!stralloc_catb(&satmp, d->d_name, str_len(d->d_name) + 1)) dienomem() ;
if (stat(satmp.s + start, &st) < 0)
@@ -517,6 +602,48 @@ static inline void add_sources (before_t *be, char const *srcdir)
satmp.len = start ;
}
+static inline void add_pipeline_bundles (before_t *be)
+{
+ longrun_t const *longruns = genalloc_s(longrun_t, &be->longruns) ;
+ unsigned int n = genalloc_len(longrun_t, &be->longruns) ;
+ unsigned int i = n ;
+ while (i--) if (longruns[i].pipelinename)
+ {
+ bundle_t bundle = { .listindex = genalloc_len(unsigned int, &be->indices), .n = 1 } ;
+ unsigned int id ;
+ nameinfo_t const *info ;
+ unsigned int j = i ;
+ if (verbosity >= 3) strerr_warni2x("creating bundle for pipeline ", data.s + longruns[i].pipelinename) ;
+ add_name(be, S6RC_INTERNALS, data.s + longruns[i].pipelinename, SVTYPE_BUNDLE, &bundle.name, &id) ;
+ avltree_search(&names_map, keep.s + longruns[i].common.kname, &id) ;
+ info = genalloc_s(nameinfo_t, &nameinfo) + id ;
+ if (!genalloc_append(unsigned int, &be->indices, &info->pos)) dienomem() ;
+
+ while (longruns[j].pipeline[1])
+ {
+ if (bundle.n >= n)
+ strerr_dief4x(1, "pipeline ", data.s + longruns[i].pipelinename, " is too long: possible loop involving ", keep.s + longruns[j].common.kname) ;
+ avltree_search(&names_map, data.s + longruns[j].pipeline[1], &id) ;
+ info = genalloc_s(nameinfo_t, &nameinfo) + id ;
+ if (info->type != SVTYPE_LONGRUN)
+ strerr_dief5x(1, "longrun service ", keep.s + longruns[j].common.kname, " declares a consumer ", data.s + longruns[j].pipeline[1], " that is not a longrun service") ;
+ if (!genalloc_append(unsigned int, &be->indices, &info->pos)) dienomem() ;
+ j = info->i ;
+ {
+ unsigned int namelen = str_len(data.s + info->pos) ;
+ char svname[16 + namelen] ;
+ byte_copy(svname, 15, "s6rc-storepipe-") ;
+ byte_copy(svname + 15, namelen + 1, data.s + info->pos) ;
+ avltree_search(&names_map, svname, &id) ;
+ info = genalloc_s(nameinfo_t, &nameinfo) + id ;
+ if (!genalloc_append(unsigned int, &be->indices, &info->pos)) dienomem() ;
+ }
+ bundle.n += 2 ;
+ }
+ if (!genalloc_append(bundle_t, &be->bundles, &bundle)) dienomem() ;
+ }
+}
+
/* Resolve all names and dependencies */
@@ -530,7 +657,7 @@ struct bundle_recinfo_s
unsigned int n ;
unsigned int nlong ;
unsigned int nbits ;
- uint32 const *indices ;
+ unsigned int const *indices ;
unsigned char *barray ;
unsigned char *mark ;
unsigned int source ;
@@ -541,7 +668,7 @@ static void resolve_bundle_rec (bundle_recinfo_t *recinfo, unsigned int i)
if (!(recinfo->mark[i] & 2))
{
bundle_t const *me = recinfo->oldb + i ;
- uint32 const *listindex = recinfo->indices + me->listindex ;
+ unsigned int const *listindex = recinfo->indices + me->listindex ;
unsigned int j = 0 ;
if (recinfo->mark[i] & 1)
strerr_dief4x(1, "cyclic bundle definition: resolution of ", data.s + recinfo->oldb[recinfo->source].name, " encountered a cycle involving ", data.s + me->name) ;
@@ -572,7 +699,7 @@ static void resolve_bundle_rec (bundle_recinfo_t *recinfo, unsigned int i)
}
}
-static inline unsigned int resolve_bundles (bundle_t const *oldb, bundle_t *newb, unsigned int nshort, unsigned int nlong, unsigned int nbundles, uint32 const *indices, unsigned char *barray)
+static inline unsigned int resolve_bundles (bundle_t const *oldb, bundle_t *newb, unsigned int nshort, unsigned int nlong, unsigned int nbundles, unsigned int const *indices, unsigned char *barray)
{
unsigned int total = 0, i = 0 ;
unsigned char mark[nbundles] ;
@@ -609,7 +736,7 @@ static inline void flatlist_bundles (bundle_t *bundles, unsigned int nbundles, u
}
}
-static void resolve_deps (common_t const *me, unsigned int nlong, unsigned int n, unsigned int nbits, uint32 const *indices, unsigned char *sarray, unsigned char const *barray)
+static void resolve_deps (common_t const *me, unsigned int nlong, unsigned int n, unsigned int nbits, unsigned int const *indices, unsigned char *sarray, unsigned char const *barray)
{
unsigned int j = 0 ;
for (; j < me->ndeps ; j++)
@@ -626,7 +753,7 @@ static void resolve_deps (common_t const *me, unsigned int nlong, unsigned int n
{
char fmt[UINT_FMT] ;
fmt[uint_fmt(fmt, nlong + p->i)] = 0 ;
- strerr_warnt7x("atomic ", data.s + me->name, " depends on oneshot ", data.s + p->pos, " (", fmt, ")") ;
+ strerr_warnt7x("atomic ", keep.s + me->kname, " depends on oneshot ", data.s + p->pos, " (", fmt, ")") ;
}
break ;
case SVTYPE_LONGRUN :
@@ -635,7 +762,7 @@ static void resolve_deps (common_t const *me, unsigned int nlong, unsigned int n
{
char fmt[UINT_FMT] ;
fmt[uint_fmt(fmt, p->i)] = 0 ;
- strerr_warnt7x("atomic ", data.s + me->name, " depends on longrun ", data.s + p->pos, " (", fmt, ")") ;
+ strerr_warnt7x("atomic ", keep.s + me->kname, " depends on longrun ", data.s + p->pos, " (", fmt, ")") ;
}
break ;
case SVTYPE_BUNDLE :
@@ -644,21 +771,21 @@ static void resolve_deps (common_t const *me, unsigned int nlong, unsigned int n
{
char fmt[UINT_FMT] ;
fmt[uint_fmt(fmt, nlong + p->i)] = 0 ;
- strerr_warnt4x("atomic ", data.s + me->name, " depends on bundle ", data.s + p->pos) ;
+ strerr_warnt4x("atomic ", keep.s + me->kname, " depends on bundle ", data.s + p->pos) ;
}
break ;
default :
- strerr_dief4x(1, "during dependency resolution for service ", data.s + me->name, ": undefined service name ", data.s + p->pos) ;
+ strerr_dief4x(1, "during dependency resolution for service ", keep.s + me->kname, ": undefined service name ", data.s + p->pos) ;
}
}
}
-static inline void check_logger (longrun_t const *longruns, unsigned int i)
+static uint32 resolve_prodcons (longrun_t const *longruns, unsigned int i, int h, uint32 nlong)
{
unsigned int j ;
register nameinfo_t const *p ;
- if (!longruns[i].logtype) return ;
- avltree_search(&names_map, data.s + longruns[i].logrelated, &j) ;
+ if (!longruns[i].pipeline[h]) return nlong ;
+ avltree_search(&names_map, data.s + longruns[i].pipeline[h], &j) ;
p = genalloc_s(nameinfo_t, &nameinfo) + j ;
switch (p->type)
{
@@ -666,21 +793,21 @@ static inline void check_logger (longrun_t const *longruns, unsigned int i)
{
unsigned int k ;
register nameinfo_t const *q ;
- if (longruns[p->i].logtype != 3 - longruns[i].logtype) goto err ;
- avltree_search(&names_map, data.s + longruns[p->i].logrelated, &k) ;
+ avltree_search(&names_map, data.s + longruns[p->i].pipeline[!h], &k) ;
q = genalloc_s(nameinfo_t, &nameinfo) + k ;
if (q->type != SVTYPE_LONGRUN) goto err ;
if (q->i != i) goto err ;
break ;
- err:
- strerr_dief7x(1, "longrun service ", data.s + longruns[i].common.name, " declares a ", longruns[i].logtype == 2 ? "producer" : "logger", " named ", data.s + p->pos, " that does not declare it back ") ;
+ err:
+ strerr_dief7x(1, "longrun service ", keep.s + longruns[i].common.kname, " declares being a ", h ? "producer" : "consumer", " for a service named ", data.s + p->pos, " that does not declare it back ") ;
}
case SVTYPE_ONESHOT :
case SVTYPE_BUNDLE :
- strerr_dief8x(1, "longrun service ", data.s + longruns[i].common.name, " declares a ", longruns[i].logtype == 2 ? "producer" : "logger", " named ", data.s + p->pos, " of type ", p->type == SVTYPE_BUNDLE ? "bundle" : "oneshot") ;
+ strerr_dief8x(1, "longrun service ", keep.s + longruns[i].common.kname, " declares being a ", h ? "producer" : "consumer", " for a service named ", data.s + p->pos, " of type ", p->type == SVTYPE_BUNDLE ? "bundle" : "oneshot") ;
default :
- strerr_dief7x(1, "longrun service ", data.s + longruns[i].common.name, " declares a ", longruns[i].logtype == 2 ? "producer" : "logger", " named ", data.s + p->pos, " that is not defined") ;
+ strerr_dief6x(1, "longrun service ", keep.s + longruns[i].common.kname, " declares being a ", h ? "producer" : "consumer", " for an undefined service: ", data.s + p->pos) ;
}
+ return p->i ;
}
static inline unsigned int ugly_bitarray_vertical_countones (unsigned char const *sarray, unsigned int n, unsigned int i)
@@ -695,7 +822,7 @@ static inline unsigned int resolve_services (s6rc_db_t *db, before_t const *be,
{
oneshot_t const *oneshots = genalloc_s(oneshot_t const, &be->oneshots) ;
longrun_t const *longruns = genalloc_s(longrun_t const, &be->longruns) ;
- uint32 const *indices = genalloc_s(uint32 const, &be->indices) ;
+ unsigned int const *indices = genalloc_s(unsigned int const, &be->indices) ;
unsigned int n = db->nshort + db->nlong ;
unsigned int nbits = bitarray_div8(n) ;
unsigned int total[2] = { 0, 0 } ;
@@ -704,14 +831,14 @@ static inline unsigned int resolve_services (s6rc_db_t *db, before_t const *be,
byte_zero(sarray, nbits * n) ;
for (; i < db->nlong ; i++)
{
+ srcdirs[i] = longruns[i].srcdir ;
db->services[i].name = longruns[i].common.kname ;
db->services[i].flags = longruns[i].common.annotation_flags ;
db->services[i].timeout[0] = longruns[i].common.timeout[0] ;
db->services[i].timeout[1] = longruns[i].common.timeout[1] ;
- db->services[i].x.longrun.servicedir = longruns[i].servicedirname ;
- srcdirs[i] = longruns[i].srcdir ;
+ db->services[i].x.longrun.pipeline[0] = resolve_prodcons(longruns, i, 0, db->nlong) ;
+ db->services[i].x.longrun.pipeline[1] = resolve_prodcons(longruns, i, 1, db->nlong) ;
resolve_deps(&longruns[i].common, db->nlong, n, nbits, indices, sarray + i * nbits, barray) ;
- check_logger(longruns, i) ;
}
for (i = 0 ; i < db->nshort ; i++)
{
@@ -742,7 +869,9 @@ static inline void flatlist_services (s6rc_db_t *db, unsigned char const *sarray
{
unsigned int n = db->nshort + db->nlong ;
unsigned int nbits = bitarray_div8(n) ;
+ diuint32 problem ;
unsigned int i = 0 ;
+ register int r ;
if (verbosity >= 3) strerr_warni1x("converting service dependency array") ;
for (; i < n ; i++)
{
@@ -755,10 +884,18 @@ static inline void flatlist_services (s6rc_db_t *db, unsigned char const *sarray
for (; k < db->services[i].ndeps[1] ; j++)
if (bitarray_peek(sarray + i * nbits, j)) mydeps[k++] = j ;
}
- if (verbosity >= 3) strerr_warni1x("checking for dependency cycles") ;
- nbits = s6rc_db_check_depcycles(db, 1, &i) ;
- if (nbits < n)
- strerr_dief4x(1, "cyclic service definition: resolution of ", db->string + db->services[nbits].name, " encountered a cycle involving ", db->string + db->services[i].name) ;
+
+ if (verbosity >= 3) strerr_warni1x("checking database correctness") ;
+ if (s6rc_db_check_depcycles(db, 1, &problem))
+ strerr_dief4x(1, "cyclic service dependency involving", db->string + db->services[problem.left].name, " and ", db->string + db->services[problem.right].name) ;
+ r = s6rc_db_check_pipelines(db, &problem) ;
+ if (r)
+ {
+ if (r == 1)
+ strerr_dief4x(1, "cyclic longrun pipeline involving", db->string + db->services[problem.left].name, " and ", db->string + db->services[problem.right].name) ;
+ else
+ strerr_dief4x(1, "longrun pipeline collision involving", db->string + db->services[problem.left].name, " and ", db->string + db->services[problem.right].name) ;
+ }
}
@@ -803,6 +940,21 @@ static void auto_file (char const *compiled, char const *file, char const *s, un
}
}
+static void auto_symlink (char const *compiled, char const *name, char const *target)
+{
+ unsigned int clen = str_len(compiled) ;
+ unsigned int flen = str_len(name) ;
+ char fn[clen + flen + 2] ;
+ byte_copy(fn, clen, compiled) ;
+ fn[clen] = '/' ;
+ byte_copy(fn + clen + 1, flen + 1, name) ;
+ if (symlink(target, fn) < 0)
+ {
+ cleanup(compiled) ;
+ strerr_diefu4sys(111, "symlink ", target, " to ", fn) ;
+ }
+}
+
static void auto_rights (char const *compiled, char const *file, mode_t mode)
{
unsigned int clen = str_len(compiled) ;
@@ -837,40 +989,120 @@ static inline void write_sizes (char const *compiled, s6rc_db_t const *db)
auto_file(compiled, "n", pack, 20) ;
}
-static inline void write_specials (char const *compiled, uint64 const *uids, unsigned int uidn, gid_t const *gids, unsigned int gidn)
+static void make_skel (char const *compiled, char const *name, uint64 const *uids, unsigned int uidn, gid_t const *gids, unsigned int gidn)
{
+ unsigned int namelen = str_len(name) ;
unsigned int i = uidn ;
- char fn[sizeof(BASE_RULES) + UINT64_FMT + 6] = BASE_RULES ;
- auto_dir(compiled, "servicedirs/" S6RC_ONESHOT_RUNNER) ;
- auto_file(compiled, "servicedirs/" S6RC_ONESHOT_RUNNER "/notification-fd", "3\n", 2) ;
- auto_file(compiled, "servicedirs/" S6RC_ONESHOT_RUNNER "/run", S6RC_ONESHOT_RUNNER_RUNSCRIPT, sizeof(S6RC_ONESHOT_RUNNER_RUNSCRIPT) - 1) ;
- auto_rights(compiled, "servicedirs/" S6RC_ONESHOT_RUNNER "/run", 0755) ;
- auto_dir(compiled, "servicedirs/" S6RC_ONESHOT_RUNNER "/data") ;
- auto_dir(compiled, "servicedirs/" S6RC_ONESHOT_RUNNER "/data/rules") ;
- if (gidn) auto_dir(compiled, fn) ;
- fn[sizeof(BASE_RULES) - 4] = 'u' ;
+ char fn[UINT64_FMT + namelen + 35] ;
+ byte_copy(fn, 12, "servicedirs/") ;
+ byte_copy(fn + 12, namelen + 1, name) ;
+ auto_dir(compiled, fn) ;
+ byte_copy(fn + 12 + namelen, 17, "/notification-fd") ;
+ auto_file(compiled, fn, "3\n", 2) ;
+ byte_copy(fn + 13 + namelen, 5, "data") ;
+ auto_dir(compiled, fn) ;
+ byte_copy(fn + 17 + namelen, 7, "/rules") ;
+ auto_dir(compiled, fn) ;
+ if (gidn)
+ {
+ byte_copy(fn + 23 + namelen, 5, "/gid") ;
+ auto_dir(compiled, fn) ;
+ }
+ byte_copy(fn + 23 + namelen, 5, "/uid") ;
auto_dir(compiled, fn) ;
- fn[sizeof(BASE_RULES) - 1] = '/' ;
+ fn[27 + namelen] = '/' ;
while (i--)
{
- unsigned int len = uint64_fmt(fn + sizeof(BASE_RULES), uids[i]) ;
- fn[sizeof(BASE_RULES) + len] = 0 ;
+ unsigned int len = uint64_fmt(fn + 28 + namelen, uids[i]) ;
+ fn[28 + namelen + len] = 0 ;
auto_dir(compiled, fn) ;
- byte_copy(fn + sizeof(BASE_RULES) + len, 7, "/allow") ;
+ byte_copy(fn + 28 + namelen + len, 7, "/allow") ;
auto_file(compiled, fn, "", 0) ;
}
- fn[sizeof(BASE_RULES) - 4] = 'g' ;
i = gidn ;
while (i--)
{
- unsigned int len = gid_fmt(fn + sizeof(BASE_RULES), gids[i]) ;
- fn[sizeof(BASE_RULES) + len] = 0 ;
+ unsigned int len = gid_fmt(fn + 28 + namelen, gids[i]) ;
+ fn[28 + namelen + len] = 0 ;
auto_dir(compiled, fn) ;
- byte_copy(fn + sizeof(BASE_RULES) + len, 7, "/allow") ;
+ byte_copy(fn + 28 + namelen + len, 7, "/allow") ;
auto_file(compiled, fn, "", 0) ;
}
}
+static inline void write_oneshot_runner (char const *compiled, uint64 const *uids, unsigned int uidn, gid_t const *gids, unsigned int gidn)
+{
+ make_skel(compiled, S6RC_ONESHOT_RUNNER, uids, uidn, gids, gidn) ;
+ auto_file(compiled, "servicedirs/" S6RC_ONESHOT_RUNNER "/run", S6RC_ONESHOT_RUNNER_RUNSCRIPT, sizeof(S6RC_ONESHOT_RUNNER_RUNSCRIPT) - 1) ;
+ auto_rights(compiled, "servicedirs/" S6RC_ONESHOT_RUNNER "/run", 0755) ;
+}
+
+static inline void write_fdholder (char const *compiled, uint64 const *uids, unsigned int uidn, gid_t const *gids, unsigned int gidn, char const *fdhuser)
+{
+ unsigned int base = satmp.len ;
+ make_skel(compiled, S6RC_FDHOLDER, uids, uidn, gids, gidn) ;
+ {
+ char fn[62 + S6RC_FDHOLDER_LEN + UINT64_FMT] = "servicedirs/" S6RC_FDHOLDER "/data/rules/uid/" ;
+ char fmt[7 + UINT64_FMT] = "../uid/" ;
+ unsigned int i = uint64_fmt(fmt + 7, uids[0]) ;
+ fmt[7 + i] = 0 ;
+ byte_copy(fn + 28 + S6RC_FDHOLDER_LEN, i, fmt + 7) ;
+ byte_copy(fn + 28 + S6RC_FDHOLDER_LEN + i, 5, "/env") ;
+ auto_dir(compiled, fn) ;
+ byte_copy(fn + 32 + S6RC_FDHOLDER_LEN + i, 18, "/S6_FDHOLDER_LIST") ;
+ auto_file(compiled, fn, "\n", 1) ;
+ byte_copy(fn + 45 + S6RC_FDHOLDER_LEN + i, 12, "STORE_REGEX") ;
+ auto_file(compiled, fn, "^pipe:s6rc-\n", 12) ;
+ byte_copy(fn + 45 + S6RC_FDHOLDER_LEN + i, 15, "RETRIEVE_REGEX") ;
+ auto_symlink(compiled, fn, "S6_FDHOLDER_STORE_REGEX") ;
+ byte_copy(fn + 45 + S6RC_FDHOLDER_LEN + i, 8, "SETDUMP") ;
+ auto_file(compiled, fn, "\n", 1) ;
+ fn[45 + S6RC_FDHOLDER_LEN + i] = 'G' ;
+ auto_file(compiled, fn, "\n", 1) ;
+
+ for (i = 1 ; i < uidn ; i++)
+ {
+ unsigned int len = uint64_fmt(fn + 28 + S6RC_FDHOLDER_LEN, uids[i]) ;
+ fn[28 + S6RC_FDHOLDER_LEN + len] = 0 ;
+ auto_symlink(compiled, fn, fmt + 7) ;
+ }
+ fn[24 + S6RC_FDHOLDER_LEN] = 'g' ;
+ i = gidn ;
+ while (i--)
+ {
+ unsigned int len = gid_fmt(fn + 28 + S6RC_FDHOLDER_LEN, gids[i]) ;
+ fn[28 + S6RC_FDHOLDER_LEN + len] = 0 ;
+ auto_symlink(compiled, fn, fmt) ;
+ }
+ }
+
+ if (!stralloc_cats(&satmp,
+ "#!" EXECLINE_SHEBANGPREFIX "execlineb -P\n" \
+ EXECLINE_EXTBINPREFIX "fdmove -c 2 1\n" \
+ EXECLINE_EXTBINPREFIX "fdmove 1 3\n")) dienomem() ;
+ if (fdhuser)
+ {
+ if (!stralloc_cats(&satmp, S6_EXTBINPREFIX "s6-envuidgid -i -- ")
+ || !string_quote(&satmp, fdhuser, str_len(fdhuser))
+ || !stralloc_catb(&satmp, "\n", 1)) dienomem() ;
+ }
+ if (!stralloc_cats(&satmp, S6_EXTBINPREFIX "s6-fdholder-daemon -1 ")) dienomem() ;
+ if (fdhuser)
+ {
+ if (!stralloc_cats(&satmp, "-U ")) dienomem() ;
+ }
+ if (!stralloc_cats(&satmp, "-i data/rules -- s\n")) dienomem() ;
+ auto_file(compiled, "servicedirs/" S6RC_FDHOLDER "/run", satmp.s + base, satmp.len - base) ;
+ satmp.len = base ;
+ auto_rights(compiled, "servicedirs/" S6RC_FDHOLDER "/run", 0755) ;
+}
+
+static inline void write_specials (char const *compiled, uint64 const *uids, unsigned int uidn, gid_t const *gids, unsigned int gidn, char const *fdhuser)
+{
+ write_oneshot_runner(compiled, uids, uidn, gids, gidn) ;
+ write_fdholder(compiled, uids, uidn, gids, gidn, fdhuser) ;
+}
+
static inline void write_resolve (char const *compiled, s6rc_db_t const *db, bundle_t const *bundles, unsigned int nbundles, uint32 const *bdeps)
{
unsigned int clen = str_len(compiled) ;
@@ -975,95 +1207,138 @@ static void dircopy (char const *compiled, char const *srcfn, char const *dstfn)
}
}
-static void write_servicedir (char const *compiled, char const *srcdir, char const *src, char const *dst)
+static int read_uint (char const *file, unsigned int *fd)
{
- unsigned int clen = str_len(compiled) ;
- unsigned int srcdirlen = str_len(srcdir) ;
- unsigned int srclen = str_len(src) ;
- unsigned int dstlen = str_len(dst) ;
- struct stat st ;
- char dstfn[clen + 30 + dstlen] ;
- char srcfn[srcdirlen + srclen + 18] ;
- byte_copy(dstfn, clen, compiled) ;
- byte_copy(dstfn + clen, 13, "/servicedirs/") ;
- byte_copy(dstfn + clen + 13, dstlen + 1, dst) ;
- if (mkdir(dstfn, 0755) < 0)
+ char buf[UINT_FMT + 1] ;
+ register int r = openreadnclose(file, buf, UINT_FMT) ;
+ if (r < 0) return (errno == ENOENT) ? 0 : -1 ;
+ buf[byte_chr(buf, r, '\n')] = 0 ;
+ if (!uint0_scan(buf, fd)) return (errno = EINVAL, -1) ;
+ return 1 ;
+}
+
+static inline void write_run_wrapper (char const *compiled, char const *fn, s6rc_db_t const *db, unsigned int i, unsigned int fd)
+{
+ unsigned int base = satmp.len ;
+ if (!stralloc_cats(&satmp, "#!" EXECLINE_SHEBANGPREFIX "execlineb -P\n")) dienomem() ;
+ if (db->services[i].x.longrun.pipeline[0] < db->nlong)
{
- cleanup(compiled) ;
- strerr_diefu2sys(111, "mkdir ", dstfn) ;
+ if (!stralloc_cats(&satmp, EXECLINE_EXTBINPREFIX "s6-fdholder-retrieve ../s6rc-fdholder/s \"pipe:s6rc-r-")
+ || !string_quote_nodelim(&satmp, db->string + db->services[i].name, str_len(db->string + db->services[i].name))
+ || !stralloc_cats(&satmp, "\"\n")) dienomem() ;
}
- byte_copy(dstfn + clen + 13 + dstlen, 5, "/run") ;
- byte_copy(srcfn, srcdirlen, srcdir) ;
- srcfn[srcdirlen] = '/' ;
- byte_copy(srcfn + srcdirlen + 1, srclen, src) ;
- byte_copy(srcfn + srcdirlen + srclen + 1, 5, "/run") ;
- if (!filecopy(srcfn, dstfn, 0755))
+ if (db->services[i].x.longrun.pipeline[1] < db->nlong)
{
- cleanup(compiled) ;
- strerr_diefu4sys(111, "copy ", srcfn, " to ", dstfn) ;
+ char const *consumername = db->string + db->services[db->services[i].x.longrun.pipeline[1]].name ;
+ if (!stralloc_cats(&satmp, EXECLINE_EXTBINPREFIX "fdmove ")
+ || !stralloc_cats(&satmp, fd == 3 ? "4" : "3")
+ || !stralloc_cats(&satmp, " 0\n"
+ EXECLINE_EXTBINPREFIX "s6-fdholder-retrieve ../s6rc-fdholder/s \"pipe:s6rc-w-")
+ || !string_quote_nodelim(&satmp, consumername, str_len(consumername))
+ || !stralloc_cats(&satmp, "\"\n"
+ EXECLINE_EXTBINPREFIX "fdmove 1 0\n"
+ EXECLINE_EXTBINPREFIX "fdmove 0 ")
+ || !stralloc_cats(&satmp, fd == 3 ? "4" : "3")
+ || !stralloc_cats(&satmp, "\n")) dienomem() ;
}
- byte_copy(dstfn + clen + 14 + dstlen, 7, "finish") ;
- byte_copy(srcfn + srcdirlen + srclen + 2, 7, "finish") ;
- filecopy(srcfn, dstfn, 0755) ;
- byte_copy(dstfn + clen + 14 + dstlen, 15, "timeout-finish") ;
- byte_copy(srcfn + srcdirlen + srclen + 2, 15, "timeout-finish") ;
- filecopy(srcfn, dstfn, 0644) ;
- byte_copy(dstfn + clen + 14 + dstlen, 16, "notification-fd") ;
- byte_copy(srcfn + srcdirlen + srclen + 2, 16, "notification-fd") ;
- filecopy(srcfn, dstfn, 0644) ;
-
- byte_copy(srcfn + srcdirlen + srclen + 4, 7, "setsid") ;
- if (stat(srcfn, &st) < 0)
+ if (!stralloc_cats(&satmp, "./run.user\n")) dienomem() ;
+ auto_file(compiled, fn, satmp.s + base, satmp.len - base) ;
+ satmp.len = base ;
+ auto_rights(compiled, fn, 0755) ;
+}
+
+static inline void write_servicedirs (char const *compiled, s6rc_db_t const *db, char const *const *srcdirs)
+{
+ unsigned int clen = str_len(compiled) ;
+ unsigned int i = 2 ;
+ if (verbosity >= 3) strerr_warni3x("writing ", compiled, "/servicedirs") ;
+ for (; i < db->nlong ; i++)
{
- if (errno != ENOENT)
+ struct stat st ;
+ unsigned int srcdirlen = str_len(srcdirs[i]) ;
+ unsigned int len = str_len(db->string + db->services[i].name) ;
+ unsigned int fd = 0 ;
+ register int r ;
+ char srcfn[srcdirlen + len + 18] ;
+ char dstfn[clen + len + 30] ;
+ byte_copy(dstfn, clen, compiled) ;
+ byte_copy(dstfn + clen, 13, "/servicedirs/") ;
+ byte_copy(dstfn + clen + 13, len + 1, db->string + db->services[i].name) ;
+ if (mkdir(dstfn, 0755) < 0)
{
cleanup(compiled) ;
- strerr_diefu2sys(111, "stat ", srcfn) ;
+ strerr_diefu2sys(111, "mkdir ", dstfn) ;
}
- }
- else
- {
- int fd ;
- byte_copy(dstfn + clen + 16 + dstlen, 7, "setsid") ;
- fd = open_trunc(dstfn) ;
- if (fd < 0)
+ byte_copy(srcfn, srcdirlen, srcdirs[i]) ;
+ srcfn[srcdirlen] = '/' ;
+ byte_copy(srcfn + srcdirlen + 1, len, db->string + db->services[i].name) ;
+ byte_copy(srcfn + srcdirlen + 1 + len, 17, "/notification-fd") ;
+ r = read_uint(srcfn, &fd) ;
+ if (r < 0)
{
cleanup(compiled) ;
- strerr_diefu2sys(111, "touch ", dstfn) ;
+ strerr_diefu2sys(111, "read ", srcfn) ;
+ }
+ if (r)
+ {
+ char fmt[UINT_FMT] ;
+ unsigned int fmtlen = uint_fmt(fmt, fd) ;
+ fmt[fmtlen++] = '\n' ;
+ byte_copy(dstfn + clen + 13 + len, 17, "/notification-fd") ;
+ if (!openwritenclose_unsafe(dstfn, fmt, fmtlen))
+ {
+ cleanup(compiled) ;
+ strerr_diefu2sys(111, "write to ", dstfn) ;
+ }
}
- close(fd) ;
- }
-
- byte_copy(dstfn + clen + 14 + dstlen, 5, "data") ;
- byte_copy(srcfn + srcdirlen + srclen + 2, 5, "data") ;
- dircopy(compiled, srcfn, dstfn) ;
- byte_copy(dstfn + clen + 14 + dstlen, 4, "env") ;
- byte_copy(srcfn + srcdirlen + srclen + 2, 4, "env") ;
- dircopy(compiled, srcfn, dstfn) ;
-}
-static inline void write_servicedirs (char const *compiled, s6rc_db_t const *db, char const *const *srcdirs, unsigned int maxnamelen)
-{
- unsigned int clen = str_len(compiled) ;
- unsigned int i = 1 ;
- char fn[clen + 23 + maxnamelen] ;
- char islogger[db->nlong] ;
- if (verbosity >= 3) strerr_warni3x("writing ", compiled, "/servicedirs") ;
- byte_copy(fn, clen, compiled) ;
- byte_copy(fn + clen, 12, "/servicedirs") ;
- fn[clen+12] = '/' ;
- byte_zero(islogger, db->nlong) ;
- for (; i < db->nlong ; i++)
- {
- char const *servicedirname = db->string + db->services[i].x.longrun.servicedir ;
- islogger[i] = servicedirname[str_chr(servicedirname, '/')] ;
- if (!islogger[i])
- write_servicedir(compiled, srcdirs[i], db->string + db->services[i].name, servicedirname) ;
- }
- for (i = 1 ; i < db->nlong ; i++)
- {
- if (islogger[i])
- write_servicedir(compiled, srcdirs[i], db->string + db->services[i].name, db->string + db->services[i].x.longrun.servicedir) ;
+ byte_copy(dstfn + clen + 13 + len, 5, "/run") ;
+ if (db->services[i].x.longrun.pipeline[0] < db->nlong || db->services[i].x.longrun.pipeline[1] < db->nlong)
+ {
+ write_run_wrapper(compiled, dstfn + clen + 1, db, i, fd) ;
+ byte_copy(dstfn + clen + 17 + len, 6, ".user") ;
+ }
+ byte_copy(srcfn + srcdirlen + 1 + len, 5, "/run") ;
+ if (!filecopy(srcfn, dstfn, 0755))
+ {
+ cleanup(compiled) ;
+ strerr_diefu4sys(111, "copy ", srcfn, " to ", dstfn) ;
+ }
+ byte_copy(dstfn + clen + 14 + len, 7, "finish") ;
+ byte_copy(srcfn + srcdirlen + len + 2, 7, "finish") ;
+ filecopy(srcfn, dstfn, 0755) ;
+ byte_copy(dstfn + clen + 14 + len, 15, "timeout-finish") ;
+ byte_copy(srcfn + srcdirlen + len + 2, 15, "timeout-finish") ;
+ filecopy(srcfn, dstfn, 0644) ;
+
+ byte_copy(srcfn + srcdirlen + len + 4, 7, "setsid") ;
+ if (stat(srcfn, &st) < 0)
+ {
+ if (errno != ENOENT)
+ {
+ cleanup(compiled) ;
+ strerr_diefu2sys(111, "stat ", srcfn) ;
+ }
+ }
+ else
+ {
+ int fd ;
+ byte_copy(dstfn + clen + 16 + len, 7, "setsid") ;
+ fd = open_trunc(dstfn) ;
+ if (fd < 0)
+ {
+ cleanup(compiled) ;
+ strerr_diefu2sys(111, "touch ", dstfn) ;
+ }
+ close(fd) ;
+ }
+
+ byte_copy(dstfn + clen + 14 + len, 5, "data") ;
+ byte_copy(srcfn + srcdirlen + len + 2, 5, "data") ;
+ dircopy(compiled, srcfn, dstfn) ;
+ byte_copy(dstfn + clen + 14 + len, 4, "env") ;
+ byte_copy(srcfn + srcdirlen + len + 2, 4, "env") ;
+ dircopy(compiled, srcfn, dstfn) ;
}
}
@@ -1081,8 +1356,9 @@ static inline int write_service (buffer *b, s6rc_service_t const *sv, int type)
uint32_pack_big(pack + 28, sv->deps[1]) ;
if (type)
{
- uint32_pack_big(pack + 32, sv->x.longrun.servicedir) ;
- m = 36 ;
+ uint32_pack_big(pack + 32, sv->x.longrun.pipeline[0]) ;
+ uint32_pack_big(pack + 36, sv->x.longrun.pipeline[1]) ;
+ m = 40 ;
}
else
{
@@ -1154,21 +1430,23 @@ static inline void write_db (char const *compiled, s6rc_db_t const *db)
strerr_diefu2sys(111, "write to ", dbfn) ;
}
-static inline void write_compiled (char const *compiled, s6rc_db_t const *db, char const *const *srcdirs, bundle_t const *bundles, unsigned int nbundles, uint32 const *bdeps, unsigned int maxnamelen, uint64 const *uids, unsigned int uidn, gid_t const *gids, unsigned int gidn)
+static inline void write_compiled (char const *compiled, s6rc_db_t const *db, char const *const *srcdirs, bundle_t const *bundles, unsigned int nbundles, uint32 const *bdeps, uint64 const *uids, unsigned int uidn, gid_t const *gids, unsigned int gidn, char const *fdhuser)
{
if (verbosity >= 2) strerr_warni2x("writing compiled information to ", compiled) ;
init_compiled(compiled) ;
write_sizes(compiled, db) ;
write_resolve(compiled, db, bundles, nbundles, bdeps) ;
+ stralloc_free(&data) ;
write_db(compiled, db) ;
- write_specials(compiled, uids, uidn, gids, gidn) ;
- write_servicedirs(compiled, db, srcdirs, maxnamelen) ;
+ write_specials(compiled, uids, uidn, gids, gidn, fdhuser) ;
+ write_servicedirs(compiled, db, srcdirs) ;
}
int main (int argc, char const *const *argv)
{
before_t before = BEFORE_ZERO ;
char const *compiled ;
+ char const *fdhuser = 0 ;
unsigned int uidn = 0, gidn = 0 ;
uint64 uids[256] ;
gid_t gids[256] ;
@@ -1177,13 +1455,14 @@ int main (int argc, char const *const *argv)
subgetopt_t l = SUBGETOPT_ZERO ;
for (;;)
{
- register int opt = subgetopt_r(argc, argv, "v:u:g:", &l) ;
+ register int opt = subgetopt_r(argc, argv, "v:u:g:h:", &l) ;
if (opt == -1) break ;
switch (opt)
{
case 'v' : if (!uint0_scan(l.arg, &verbosity)) dieusage() ; break ;
case 'u' : if (!uint64_scanlist(uids, 255, l.arg, &uidn)) dieusage() ; break ;
case 'g' : if (!gid_scanlist(gids, 255, l.arg, &gidn)) dieusage() ; break ;
+ case 'h' : fdhuser = l.arg ; break ;
default : dieusage() ;
}
}
@@ -1192,14 +1471,15 @@ int main (int argc, char const *const *argv)
if (argc < 2) dieusage() ;
if (!uidn && !gidn) uids[uidn++] = 0 ;
compiled = *argv++ ;
- add_specials(&before) ;
+ before.specialdeps[0] = add_internal_longrun(&before, S6RC_ONESHOT_RUNNER) ;
+ before.specialdeps[1] = add_internal_longrun(&before, S6RC_FDHOLDER) ;
for (; *argv ; argv++) add_sources(&before, *argv) ;
+ add_pipeline_bundles(&before) ;
{
unsigned int n = genalloc_len(oneshot_t, &before.oneshots) + genalloc_len(longrun_t, &before.longruns) ;
unsigned int nbits = bitarray_div8(n) ;
unsigned int nbundles = genalloc_len(bundle_t, &before.bundles) ;
- unsigned int maxnamelen = before.maxnamelen ;
s6rc_service_t servicesblob[n] ;
s6rc_db_t db =
{
@@ -1214,13 +1494,13 @@ int main (int argc, char const *const *argv)
unsigned char sarray[nbits * n] ;
bundle_t bundles[nbundles] ;
unsigned char barray[nbits * nbundles] ;
- unsigned int nbdeps = resolve_bundles(genalloc_s(bundle_t, &before.bundles), bundles, db.nshort, db.nlong, nbundles, genalloc_s(uint32, &before.indices), barray) ;
+ unsigned int nbdeps = resolve_bundles(genalloc_s(bundle_t, &before.bundles), bundles, db.nshort, db.nlong, nbundles, genalloc_s(unsigned int, &before.indices), barray) ;
uint32 bdeps[nbdeps] ;
genalloc_free(bundle_t, &before.bundles) ;
flatlist_bundles(bundles, nbundles, nbits, barray, bdeps) ;
db.ndeps = resolve_services(&db, &before, srcdirs, sarray, barray) ;
- genalloc_free(uint32, &before.indices) ;
+ genalloc_free(unsigned int, &before.indices) ;
genalloc_free(oneshot_t, &before.oneshots) ;
genalloc_free(longrun_t, &before.longruns) ;
genalloc_free(nameinfo_t, &nameinfo) ;
@@ -1229,7 +1509,7 @@ int main (int argc, char const *const *argv)
uint32 deps[db.ndeps << 1] ;
db.deps = deps ;
flatlist_services(&db, sarray) ;
- write_compiled(compiled, &db, srcdirs, bundles, nbundles, bdeps, maxnamelen, uids, uidn, gids, gidn) ;
+ write_compiled(compiled, &db, srcdirs, bundles, nbundles, bdeps, uids, uidn, gids, gidn, fdhuser) ;
}
}
diff --git a/src/s6-rc/s6-rc-db.c b/src/s6-rc/s6-rc-db.c
index aeaff76..8621b6c 100644
--- a/src/s6-rc/s6-rc-db.c
+++ b/src/s6-rc/s6-rc-db.c
@@ -180,16 +180,6 @@ static void print_timeout (char const *name, int h)
strerr_diefu1sys(111, "write to stdout") ;
}
-static void print_servicedir (char const *name)
-{
- unsigned int n = resolve_service(name) ;
- if (n >= db->nlong)
- strerr_dief5x(5, "in database ", compiled, ": identifier ", name, " does not represent a longrun service") ;
- if (buffer_puts(buffer_1, db->string + db->services[n].x.longrun.servicedir) < 0
- || buffer_putflush(buffer_1, "\n", 1) < 0)
- strerr_diefu1sys(111, "write to stdout") ;
-}
-
static void print_script (char const *name, int h)
{
unsigned int argc ;
@@ -209,6 +199,30 @@ static void print_script (char const *name, int h)
strerr_diefu1sys(111, "write to stdout") ;
}
+static inline void print_pipeline (char const *name)
+{
+ unsigned int n = resolve_service(name) ;
+ if (n >= db->nlong)
+ strerr_dief5x(5, "in database ", compiled, ": identifier ", name, " does not represent a longrun") ;
+ for (;;)
+ {
+ register unsigned int j = db->services[n].x.longrun.pipeline[0] ;
+ if (j >= db->nlong) break ;
+ n = j ;
+ }
+ for (;;)
+ {
+ register unsigned int j = db->services[n].x.longrun.pipeline[1] ;
+ if (buffer_puts(buffer_1, db->string + db->services[n].name) < 0
+ || buffer_put(buffer_1, "\n", 1) < 0)
+ strerr_diefu1sys(111, "write to stdout") ;
+ if (j >= db->nlong) break ;
+ n = j ;
+ }
+ if (buffer_flush(buffer_1))
+ strerr_diefu1sys(111, "write to stdout") ;
+}
+
static inline void print_flags (char const *name)
{
unsigned int n = resolve_service(name) ;
@@ -278,7 +292,7 @@ static inline void print_help (void)
"s6-rc-db [ -u | -d ] timeout atomicname\n"
"s6-rc-db contents bundlename\n"
"s6-rc-db [ -u | -d ] dependencies servicename...\n"
-"s6-rc-db servicedir longrunname\n"
+"s6-rc-db pipeline longrunname\n"
"s6-rc-db [ -u | -d ] script oneshotname\n"
"s6-rc-db flags atomicname\n"
"s6-rc-db atomics servicename...\n"
@@ -305,7 +319,7 @@ static inline unsigned int parse_command (char const *command)
"timeout",
"contents",
"dependencies",
- "servicedir",
+ "pipeline",
"script",
"flags",
"atomics",
@@ -421,11 +435,19 @@ int main (int argc, char const *const *argv)
{
case 1 : /* check */
{
- unsigned int problem, w ;
- if (!s6rc_db_check_revdeps(&dbblob))
+ diuint32 problem ;
+ if (s6rc_db_check_revdeps(&dbblob))
strerr_dief3x(4, "invalid service database in ", compiled, ": direct and reverse dependencies are mismatched") ;
- w = s6rc_db_check_depcycles(&dbblob, 1, &problem) ;
- if (w < n) strerr_dief6x(4, "invalid service database in ", compiled, ": service ", stringblob + serviceblob[w].name, " has a dependency cycle involving ", stringblob + serviceblob[problem].name) ;
+ if (s6rc_db_check_depcycles(&dbblob, 1, &problem))
+ strerr_dief8x(4, "invalid service database in ", compiled, ": dependency ", "cycle", " involving ", stringblob + serviceblob[problem.left].name, " and ", stringblob + serviceblob[problem.right].name) ;
+ r = s6rc_db_check_pipelines(&dbblob, &problem) ;
+ if (r)
+ {
+ if (r == 1)
+ strerr_dief8x(4, "invalid service database in ", compiled, ": pipeline ", "cycle", " involving ", stringblob + serviceblob[problem.left].name, " and ", stringblob + serviceblob[problem.right].name) ;
+ else
+ strerr_dief8x(4, "invalid service database in ", compiled, ": pipeline ", "collision", " involving ", stringblob + serviceblob[problem.left].name, " and ", stringblob + serviceblob[problem.right].name) ;
+ }
break ;
}
case 2 : /* list */
@@ -450,8 +472,8 @@ int main (int argc, char const *const *argv)
case 6 : /* dependencies */
print_union(argv + 1, up, 1, 0) ;
break ;
- case 7 : /* servicedir */
- print_servicedir(argv[1]) ;
+ case 7 : /* pipeline */
+ print_pipeline(argv[1]) ;
break ;
case 8 : /* script */
print_script(argv[1], up) ;
diff --git a/src/s6-rc/s6-rc-update.c b/src/s6-rc/s6-rc-update.c
index 42a84e8..08f719f 100644
--- a/src/s6-rc/s6-rc-update.c
+++ b/src/s6-rc/s6-rc-update.c
@@ -8,8 +8,10 @@
#include
#include
#include
-#include
+#include
+#include
#include
+#include
#include
#include
#include
@@ -21,7 +23,7 @@
#include
#include
-#define USAGE "s6-rc-update [ -n ] [ -v verbosity ] [ -t timeout ] [ -l live ] newdb"
+#define USAGE "s6-rc-update [ -n ] [ -v verbosity ] [ -t timeout ] [ -l live ] [ -f conversion_file ] newdb"
#define dieusage() strerr_dieusage(100, USAGE)
#define dienomem() strerr_diefu1sys(111, "build string") ;
@@ -29,6 +31,11 @@ static char const *live = S6RC_LIVE_BASE ;
static unsigned int livelen = sizeof(S6RC_LIVE_BASE) - 1 ;
static unsigned int verbosity = 1 ;
+
+
+ /* Conversions and transitions */
+
+
static inline void parse_line (stralloc *sa, char const *s, unsigned int slen, unsigned int *newnames, unsigned char *oldstate, cdb_t *oldc, s6rc_db_t const *olddb)
{
unsigned int base = sa->len ;
@@ -60,6 +67,9 @@ static inline void parse_line (stralloc *sa, char const *s, unsigned int slen, u
strerr_diefu3sys(111, "read ", live, "/compiled/resolve.cdb") ;
uint32_unpack_big(pack, &x) ;
if (x >= oldn) strerr_dief3x(4, "invalid database in ", live, "/compiled") ;
+ if (oldstate[x] & 64)
+ strerr_dief3x(6, "service ", olddb->string + olddb->services[x].name, " appears more than once in conversion file") ;
+ oldstate[x] |= 64 ;
cur = base + slen + str_len(sa->s + base + slen) + 1 ;
if (n >= 2 && !str_diff(sa->s + cur, "->"))
{
@@ -80,18 +90,17 @@ static inline void parse_line (stralloc *sa, char const *s, unsigned int slen, u
}
}
-static inline void parse_conversion_file (stralloc *sa, unsigned int *newnames, unsigned char *oldstate, int fdoldc, s6rc_db_t const *olddb)
+static inline void parse_conversion_file (char const *convfile, stralloc *sa, unsigned int *newnames, unsigned char *oldstate, cdb_t *oldc, s6rc_db_t const *olddb)
{
+ int fd = open_readb(convfile) ;
+ char buf[4096] ;
+ buffer b = BUFFER_INIT(&fd_readsv, fd, buf, 4096) ;
unsigned int base = satmp.len ;
- cdb_t oldc = CDB_ZERO ;
- int oldfdres = open_readatb(fdoldc, "resolve.cdb") ;
- if (oldfdres < 0) strerr_diefu3sys(111, "open ", live, "/compiled/resolve.cdb") ;
- if (!cdb_init_map(&oldc, oldfdres, 1))
- strerr_diefu3sys(111, "cdb_init ", live, "/compiled/resolve.cdb") ;
+ if (fd < 0) strerr_diefu2sys(111, "open ", convfile) ;
for (;;)
{
- register int r = skagetln(buffer_0, &satmp, '\n') ;
+ register int r = skagetln(&b, &satmp, '\n') ;
if (!r) break ;
if (r < 0)
{
@@ -99,45 +108,53 @@ static inline void parse_conversion_file (stralloc *sa, unsigned int *newnames,
if (!stralloc_0(&satmp)) dienomem() ;
}
else satmp.s[satmp.len - 1] = 0 ;
- parse_line(sa, satmp.s + base, satmp.len - base, newnames, oldstate, &oldc, olddb) ;
+ parse_line(sa, satmp.s + base, satmp.len - base, newnames, oldstate, oldc, olddb) ;
satmp.len = base ;
}
satmp.len = base ;
+ close(fd) ;
+}
+
+static inline void stuff_with_oldc (unsigned char *oldstate, int fdoldc, s6rc_db_t const *olddb, char const *convfile, unsigned int *nameindex, stralloc *namedata)
+{
+ cdb_t oldc = CDB_ZERO ;
+ int oldfdres = open_readatb(fdoldc, "resolve.cdb") ;
+ if (oldfdres < 0) strerr_diefu3sys(111, "open ", live, "/compiled/resolve.cdb") ;
+ if (!cdb_init_map(&oldc, oldfdres, 1))
+ strerr_diefu3sys(111, "cdb_init ", live, "/compiled/resolve.cdb") ;
+
+ parse_conversion_file(convfile, namedata, nameindex, oldstate, &oldc, olddb) ;
+
cdb_free(&oldc) ;
close(oldfdres) ;
}
-static inline void fill_convtable_and_flags (unsigned char *conversion_table, unsigned char *oldstate, unsigned char *newstate, char const *namedata, unsigned int const *nameindex, int fdnewc, char const *newfn, s6rc_db_t const *olddb, s6rc_db_t const *newdb)
+static inline void fill_convtable_and_flags (unsigned char *conversion_table, unsigned char *oldstate, unsigned char *newstate, char const *namedata, unsigned int const *nameindex, cdb_t *newc, char const *newfn, s6rc_db_t const *olddb, s6rc_db_t const *newdb)
{
unsigned int newn = newdb->nshort + newdb->nlong ;
- cdb_t newc = CDB_ZERO ;
- int newfdres = open_readatb(fdnewc, "resolve.cdb") ;
unsigned int i = olddb->nshort + olddb->nlong ;
- if (newfdres < 0) strerr_diefu3sys(111, "open ", newfn, "/resolve.cdb") ;
- if (!cdb_init_map(&newc, newfdres, 1))
- strerr_diefu3sys(111, "cdb_init ", newfn, "/resolve.cdb") ;
while (i--)
{
char const *newname = oldstate[i] & 16 ? namedata + nameindex[i] : olddb->string + olddb->services[i].name ;
unsigned int len ;
- int r = cdb_find(&newc, newname, str_len(newname)) ;
+ int r = cdb_find(newc, newname, str_len(newname)) ;
if (r < 0) strerr_diefu3sys(111, "read ", newfn, "/resolve.cdb") ;
if (!r)
{
oldstate[i] |= 2 ; /* disappeared -> want down */
continue ;
}
- if (cdb_datalen(&newc) & 3)
+ if (cdb_datalen(newc) & 3)
strerr_dief3x(4, "invalid resolve database in ", newfn, "/resolve.cdb") ;
- len = cdb_datalen(&newc) >> 2 ;
+ len = cdb_datalen(newc) >> 2 ;
if (len > newn)
strerr_dief3x(4, "invalid resolve database in ", newfn, "/resolve.cdb") ;
{
- char pack[cdb_datalen(&newc) + 1] ;
+ char pack[cdb_datalen(newc) + 1] ;
char const *p = pack ;
- if (cdb_read(&newc, pack, cdb_datalen(&newc), cdb_datapos(&newc)) < 0)
+ if (cdb_read(newc, pack, cdb_datalen(newc), cdb_datapos(newc)) < 0)
strerr_diefu3sys(111, "read ", newfn, "/resolve.cdb") ;
if (len == 1) oldstate[i] |= 8 ; /* atomic or singleton bundle */
while (len--)
@@ -154,6 +171,18 @@ static inline void fill_convtable_and_flags (unsigned char *conversion_table, un
}
}
+}
+
+static inline void stuff_with_newc (int fdnewc, char const *newfn, unsigned char *conversion_table, unsigned char *oldstate, unsigned char *newstate, char const *namedata, unsigned int const *nameindex, s6rc_db_t const *olddb, s6rc_db_t const *newdb)
+{
+ cdb_t newc = CDB_ZERO ;
+ int newfdres = open_readatb(fdnewc, "resolve.cdb") ;
+ if (newfdres < 0) strerr_diefu3sys(111, "open ", newfn, "/compiled/resolve.cdb") ;
+ if (!cdb_init_map(&newc, newfdres, 1))
+ strerr_diefu3sys(111, "cdb_init ", newfn, "/compiled/resolve.cdb") ;
+
+ fill_convtable_and_flags(conversion_table, oldstate, newstate, namedata, nameindex, &newc, newfn, olddb, newdb) ;
+
cdb_free(&newc) ;
close(newfdres) ;
}
@@ -183,17 +212,20 @@ static inline void adjust_newalreadyup (unsigned char const *oldstate, unsigned
}
}
-static void compute_transitions (unsigned char *oldstate, int fdoldc, s6rc_db_t const *olddb, unsigned char *newstate, int fdnewc, char const *newfn, s6rc_db_t const *newdb)
+static void compute_transitions (char const *convfile, unsigned char *oldstate, int fdoldc, s6rc_db_t const *olddb, unsigned char *newstate, int fdnewc, char const *newfn, s6rc_db_t const *newdb)
{
unsigned int oldn = olddb->nshort + olddb->nlong ;
unsigned int newn = newdb->nshort + newdb->nlong ;
unsigned char conversion_table[oldn * bitarray_div8(newn)] ;
+ unsigned int oldpairings[olddb->nlong] ;
+ unsigned int newpairings[newdb->nlong] ;
byte_zero(conversion_table, oldn * bitarray_div8(newn)) ;
{
stralloc namedata = STRALLOC_ZERO ;
unsigned int nameindex[oldn] ;
- parse_conversion_file(&namedata, nameindex, oldstate, fdoldc, olddb) ;
- fill_convtable_and_flags(conversion_table, oldstate, newstate, namedata.s, nameindex, fdnewc, newfn, olddb, newdb) ;
+
+ stuff_with_oldc(oldstate, fdoldc, olddb, convfile, nameindex, &namedata) ;
+ stuff_with_newc(fdnewc, newfn, conversion_table, oldstate, newstate, namedata.s, nameindex, olddb, newdb) ;
stralloc_free(&namedata) ;
}
adjust_newwantup(oldstate, oldn, newstate, newn, conversion_table) ;
@@ -201,6 +233,11 @@ static void compute_transitions (unsigned char *oldstate, int fdoldc, s6rc_db_t
adjust_newalreadyup(oldstate, oldn, newstate, newn, conversion_table) ;
}
+
+
+ /* Service directory replacement */
+
+
static int safe_servicedir_update (char const *dst, char const *src, int h)
{
unsigned int dstlen = str_len(dst) ;
@@ -252,8 +289,9 @@ static int safe_servicedir_update (char const *dst, char const *src, int h)
byte_copy(dstfn + dstlen + 1, 4, "run") ;
if (!hiercopy(srcfn, dstfn)) goto err ;
byte_copy(srcfn + srclen + 1, 4, "run") ;
- byte_copy(dstfn + dstlen + 1, 4, "finish") ;
- hiercopy(srcfn, dstfn) ;
+ byte_copy(dstfn + dstlen + 1, 7, "finish") ;
+ byte_copy(tmpfn + dstlen + 1, 11, "finish.new") ;
+ if (hiercopy(srcfn, tmpfn) && rename(tmpfn, dstfn) < 0) goto err ;
if (h)
{
byte_copy(dstfn + dstlen + 1, 5, "down") ;
@@ -302,6 +340,11 @@ static inline void update_servicedirs (unsigned char const *oldstate, unsigned i
{
}
+
+
+ /* The update itself. */
+
+
static inline void update_state_and_compiled (unsigned char const *newstate, unsigned int newn, char const *newcompiled)
{
char fn[livelen + 14] ;
@@ -346,6 +389,7 @@ static void fill_tfmt (char *tfmt, tain_t const *deadline)
int main (int argc, char const *const *argv, char const *const *envp)
{
+ char const *convfile = "/dev/null" ;
tain_t deadline ;
int dryrun = 0 ;
PROG = "s6-rc-update" ;
@@ -355,7 +399,7 @@ int main (int argc, char const *const *argv, char const *const *envp)
subgetopt_t l = SUBGETOPT_ZERO ;
for (;;)
{
- register int opt = subgetopt_r(argc, argv, "v:t:nl:", &l) ;
+ register int opt = subgetopt_r(argc, argv, "v:t:nl:f:", &l) ;
if (opt == -1) break ;
switch (opt)
{
@@ -363,6 +407,7 @@ int main (int argc, char const *const *argv, char const *const *envp)
case 't' : if (!uint0_scan(l.arg, &t)) dieusage() ; break ;
case 'n' : dryrun = 1 ; break ;
case 'l' : live = l.arg ; livelen = str_len(live) ; break ;
+ case 'f' : convfile = l.arg ; break ;
default : dieusage() ;
}
}
@@ -464,7 +509,7 @@ int main (int argc, char const *const *argv, char const *const *envp)
/* Read the conversion file and compute what to do */
if (verbosity >= 2) strerr_warni1x("computing state adjustments") ;
- compute_transitions(oldstate, fdoldc, &olddb, newstate, fdnewc, argv[0], &newdb) ;
+ compute_transitions(convfile, oldstate, fdoldc, &olddb, newstate, fdnewc, argv[0], &newdb) ;
tain_now_g() ;
if (!tain_future(&deadline)) strerr_dief1x(1, "timed out") ;
diff --git a/src/s6-rc/s6-rc.c b/src/s6-rc/s6-rc.c
index 2cb4caa..db30690 100644
--- a/src/s6-rc/s6-rc.c
+++ b/src/s6-rc/s6-rc.c
@@ -121,7 +121,7 @@ static pid_t start_oneshot (unsigned int i, int h)
static pid_t start_longrun (unsigned int i, int h)
{
- unsigned int svdlen = str_len(db->string + db->services[i].x.longrun.servicedir) ;
+ unsigned int svdlen = str_len(db->string + db->services[i].name) ;
unsigned int m = 0 ;
char fmt[UINT32_FMT] ;
char vfmt[UINT_FMT] ;
@@ -129,7 +129,7 @@ static pid_t start_longrun (unsigned int i, int h)
char const *newargv[7 + !!dryrun[0] * 6] ;
byte_copy(servicefn, livelen, live) ;
byte_copy(servicefn + livelen, 9, "/scandir/") ;
- byte_copy(servicefn + livelen + 9, svdlen, db->string + db->services[i].x.longrun.servicedir) ;
+ byte_copy(servicefn + livelen + 9, svdlen, db->string + db->services[i].name) ;
if (h)
{
byte_copy(servicefn + livelen + 9 + svdlen, 17, "/notification-fd") ;
@@ -166,11 +166,11 @@ static void success_longrun (unsigned int i, int h)
{
if (!dryrun[0])
{
- unsigned int svdlen = str_len(db->string + db->services[i].x.longrun.servicedir) ;
+ unsigned int svdlen = str_len(db->string + db->services[i].name) ;
char fn[livelen + svdlen + 15] ;
byte_copy(fn, livelen, live) ;
byte_copy(fn + livelen, 9, "/scandir/") ;
- byte_copy(fn + livelen + 9, svdlen, db->string + db->services[i].x.longrun.servicedir) ;
+ byte_copy(fn + livelen + 9, svdlen, db->string + db->services[i].name) ;
byte_copy(fn + livelen + 9 + svdlen, 6, "/down") ;
if (h)
{
diff --git a/tools/gen-deps.sh b/tools/gen-deps.sh
index 4615f28..f8cf5ee 100755
--- a/tools/gen-deps.sh
+++ b/tools/gen-deps.sh
@@ -57,11 +57,17 @@ echo
for dir in $(ls -1 src | grep -v ^include) ; do
for file in $(ls -1 src/$dir/deps-lib) ; do
deps=
+ libs=
while read dep ; do
- deps="$deps src/$dir/$dep"
+ if echo $dep | grep -q -e ^-l -e '^\${.*_LIB}' ; then
+ libs="$libs $dep"
+ else
+ deps="$deps src/$dir/$dep"
+ fi
done < src/$dir/deps-lib/$file
- echo "lib$file.a:$deps"
- echo "lib${file}.so:$(echo "$deps" | sed 's/\.o/.lo/g')"
+ echo "lib${file}.a.xyzzy:$deps"
+ echo "lib${file}.so.xyzzy: private EXTRA_LIBS :=$libs"
+ echo "lib${file}.so.xyzzy:$(echo "$deps" | sed 's/\.o/.lo/g')"
done
for file in $(ls -1 src/$dir/deps-exe) ; do
@@ -71,7 +77,7 @@ for dir in $(ls -1 src | grep -v ^include) ; do
if echo $dep | grep -q -- \\.o$ ; then
dep="src/$dir/$dep"
fi
- if echo $dep | grep -q '^\${.*_LIB}' ; then
+ if echo $dep | grep -q -- '^\${.*_LIB}' ; then
libs="$libs $dep"
else
deps="$deps $dep"
--
cgit v1.2.3