+# Single-user mode. This just starts a shell on the console; other services
+# can be started by issuing dinitctl commands. On exit, "boot" resumes.
+
type = process
command = /bin/sh
restart = false
-options = runs-on-console
+options = shares-console
chain-to = boot
used for \fBscripted\fR and \fBbgprocess\fR services. It allows for
interrupting startup via the \fIinterrupt\fR key (normally control-C). This is
useful to allow filesystem checks to be interrupted/skipped.
+
+This option is implied by \fBruns\-on\-console\fR, and is mutually exclusive
+with \fBshares\-console\fR; setting this option, or setting \fBruns\-on\-console\fR,
+unsets \fBshares\-console\fR.
+.TP
+\fBshares\-console\fR
+Specifies that this service should be given access to the console (input and output
+will be connected to the console), but that it should not exclusively hold the
+console and not delay the start of services with \fBstarts\-on\-console\fR.
+
+This is mutually exclusive with both \fBstarts\-on\-console\fR and \fBruns\-on\-console\fR;
+setting this option unsets both those options.
.TP
\fBstarts-rwfs\fR
This service mounts the root filesystem read/write (or at least mounts the
event_loop.get_time(restart_interval_time, clock_type::MONOTONIC);
restart_interval_count = 0;
- if (start_ps_process(exec_arg_parts, onstart_flags.starts_on_console)) {
+ if (start_ps_process(exec_arg_parts,
+ onstart_flags.starts_on_console || onstart_flags.shares_console)) {
// Note: we don't set a start timeout for PROCESS services.
if (start_timeout != time_val(0,0) && get_type() != service_type_t::PROCESS) {
restart_timer.arm_timer_rel(event_loop, start_timeout);
}
}
- if (! start_ps_process(exec_arg_parts, have_console)) {
+ if (! start_ps_process(exec_arg_parts, have_console || onstart_flags.shares_console)) {
restarting = false;
if (service_state == service_state_t::STARTING) {
failed_to_start();
* transition stage, at the latest.
*/
-struct service_flags_t {
+struct service_flags_t
+{
// on-start flags:
bool rw_ready : 1; // file system should be writable once this service starts
bool log_ready : 1; // syslog should be available once this service starts
bool no_sigterm : 1; // do not send SIGTERM
bool runs_on_console : 1; // run "in the foreground"
bool starts_on_console : 1; // starts in the foreground
+ bool shares_console : 1; // run on console, but not exclusively
bool pass_cs_fd : 1; // pass this service a control socket connection via fd
bool start_interruptible : 1; // the startup of this service process is ok to interrupt with SIGINT
bool skippable : 1; // if interrupted the service is skipped (scripted services)
bool signal_process_only : 1; // signal the session process, not the whole group
service_flags_t() noexcept : rw_ready(false), log_ready(false), no_sigterm(false),
- runs_on_console(false), starts_on_console(false), pass_cs_fd(false),
- start_interruptible(false), skippable(false), signal_process_only(false)
+ runs_on_console(false), starts_on_console(false), shares_console(false),
+ pass_cs_fd(false), start_interruptible(false), skippable(false), signal_process_only(false)
{
}
};
return -1;
}
-static const char * uid_err_msg = "Specified user id contains invalid numeric characters or is outside allowed range.";
+static const char * uid_err_msg = "Specified user id contains invalid numeric characters "
+ "or is outside allowed range.";
// Parse a userid parameter which may be a numeric user ID or a username. If a name, the
// userid is looked up via the system user database (getpwnam() function). In this case,
static_assert((uintmax_t)std::numeric_limits<uid_t>::max()
<= (uintmax_t)std::numeric_limits<unsigned long long>::max(), "uid_t is too large");
unsigned long long v = std::stoull(param, &ind, 0);
- if (v > static_cast<unsigned long long>(std::numeric_limits<uid_t>::max()) || ind != param.length()) {
+ if (v > static_cast<unsigned long long>(std::numeric_limits<uid_t>::max())
+ || ind != param.length()) {
throw service_description_exc(service_name, uid_err_msg);
}
return v;
onstart_flags.runs_on_console = true;
// A service that runs on the console necessarily starts on console:
onstart_flags.starts_on_console = true;
+ onstart_flags.shares_console = false;
}
else if (option_txt == "starts-on-console") {
onstart_flags.starts_on_console = true;
+ onstart_flags.shares_console = false;
+ }
+ else if (option_txt == "shares-console") {
+ onstart_flags.shares_console = true;
+ onstart_flags.runs_on_console = false;
+ onstart_flags.starts_on_console = false;
}
else if (option_txt == "pass-cs-fd") {
onstart_flags.pass_cs_fd = true;