/* sigaddset(&sigwait_set, SIGTERM); */
/* sigprocmask(SIG_BLOCK, &sigwait_set, NULL); */
+ // Terminal access control signals - we block these so that dinit can't be
+ // suspended if it writes to the terminal after some other process has claimed
+ // ownership of it.
+ signal(SIGTSTP, SIG_IGN);
+ signal(SIGTTIN, SIG_IGN);
+ signal(SIGTTOU, SIG_IGN);
+
/* list of services to start */
list<const char *> services_to_start;
#include <sstream>
#include <iterator>
#include <memory>
+
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
+#include <termios.h>
+
#include "service.h"
#include "dinit-log.h"
void ServiceRecord::stopped() noexcept
{
if (service_type != ServiceType::SCRIPTED && onstart_flags.runs_on_console) {
+ tcsetpgrp(0, getpgrp());
releaseConsole();
}
void ServiceRecord::started()
{
if (onstart_flags.runs_on_console && service_type == ServiceType::SCRIPTED) {
+ tcsetpgrp(0, getpgrp());
releaseConsole();
}
void ServiceRecord::failed_to_start()
{
if (onstart_flags.runs_on_console) {
+ tcsetpgrp(0, getpgrp());
releaseConsole();
}
return false;
}
+ // If the console already has a session leader, presumably it is us. On the other hand
+ // if it has no session leader, and we don't create one, then control inputs such as
+ // ^C will have no effect.
+ bool do_set_ctty = (tcgetsid(0) == -1);
+
if (forkpid == 0) {
// Child process. Must not allocate memory (or otherwise risk throwing any exception)
// from here until exit().
dup2(1, 2);
}
}
+ else {
+ // "run on console" - run as a foreground job on the terminal/console device
+ if (do_set_ctty) {
+ setsid();
+ ioctl(0, TIOCSCTTY, 0);
+ }
+ setpgid(0,0);
+ tcsetpgrp(0, getpgrp());
+
+ // TODO disable suspend (^Z)? (via tcsetattr)
+ // (should be done before TIOCSCTTY)
+ }
execvp(exec_arg_parts[0], const_cast<char **>(args));