// (C) 2017 Underground Software
//
-#define _DEFAULT_SOURCE // Without this, functions in unistd.h go missing
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <sys/reboot.h>
#include <sys/syscall.h>
-#include <sys/socket.h>
+#include <sys/stat.h>
#include <sys/types.h>
#include <sys/un.h>
#include <sys/wait.h>
-static const char socketPath[] = "/run/initctl";
+static const char fifoPath[] = "/dev/initctl";
static int shuttingDown = 0;
static int verbose = 0; // N.B.: There is no mechanism to set this ATM
static struct sigaction action;
//
// Remove the given process from the MPL by index
//
-void RemoveEntry(int entry)
+static void RemoveEntry(int entry)
{
free(processCmd[entry]);
free(processName[entry]);
//
// Add a process to the MPL
//
-void AddEntry(pid_t pid, char * name, char * command)
+static void AddEntry(pid_t pid, char * name, char * command)
{
int i;
// Take a given space delimited string and turn it into an array of strings
// suitable for execv().
//
-void MakeArgumentList(char * s)
+static void MakeArgumentList(char * s)
{
char buf[4096];
char * tokSave;
// monitor: Tells Launch whether or not this process should be monitored
// and respawned if it goes away (0 = no, 1 = yes)
//
-pid_t Launch(char * name, char * command, int monitor)
+static pid_t Launch(char * name, char * command, int monitor)
{
if (verbose)
printf("Starting %s (%smonitored)...\n", name, (monitor ? "" : "un"));
// At some point, we'll read inittab instead of recording just our own internal
// processes...
//
-void HandleSIGCHLD(int signum, siginfo_t * info, void * ptr)
+static void HandleSIGCHLD(int signum)
{
while (1)
{
//
// Start up the system, using the awesome power of OpenRC
//
-void Init(void)
+static void Init(void)
{
- printf("*** init-ng v1.0.0 starting...\n");
+ printf("*** init-ng v1.0.1 starting...\n");
pid_t pid = Launch("openrc", "/sbin/rc sysinit", 0);
waitpid(pid, NULL, 0);
}
-void ShutDown(int cmd)
+static void ShutDown(int cmd)
{
shuttingDown = 1;
pid_t pid = Launch("openrc", "/sbin/rc reboot", 0);
//
-// Connect to PID 1's socket to send a command
+// Connect to PID 1's FIFO to send a command
//
-void DoCmd(char * cmd)
+static void DoCmd(char * cmd)
{
- struct sockaddr_un remote;
- int s = socket(AF_UNIX, SOCK_STREAM, 0);
+ FILE * file = fopen(fifoPath, "w");
- if (s == -1)
+ if (file == NULL)
{
- // Handle error
- printf("Could not get socket in DoCmd()...\n");
+ perror("DoCmd: fopen");
return;
}
- remote.sun_family = AF_UNIX;
- strcpy(remote.sun_path, socketPath);
- int len = strlen(remote.sun_path) + sizeof(remote.sun_family);
- int s2 = connect(s, (struct sockaddr *)&remote, len);
-
- if (s2 == -1)
- {
- // Handle error
- printf("Could not connect in DoCmd()...\n");
- return;
- }
-
- send(s, cmd, strlen(cmd), 0);
- close(s);
+ size_t ignored = fwrite(cmd, 1, strlen(cmd), file);
+ fclose(file);
}
// Install SIGCHLD signal handler to do process monitoring
memset(&action, 0, sizeof(action));
- action.sa_sigaction = HandleSIGCHLD;
+ action.sa_handler = HandleSIGCHLD;
action.sa_flags = SA_SIGINFO;
sigaction(SIGCHLD, &action, NULL);
- // Create socket to listen on for commands...
- struct sockaddr_un local, remote;
- unsigned int s = socket(AF_UNIX, SOCK_STREAM, 0);
-
- if (s == -1)
+ // Create a named pipe to listen on for commands
+ if (mkfifo(fifoPath, 0600) == -1)
{
- perror("socket");
- printf("init-ng: socket() failed!\n");
- }
-
- local.sun_family = AF_UNIX;
- strcpy(local.sun_path, socketPath);
- unlink(local.sun_path);
- int len = strlen(local.sun_path) + sizeof(local.sun_family);
-
- if (bind(s, (struct sockaddr *)&local, len) == -1)
- {
- perror("bind");
- printf("init-ng: bind() failed!\n");
- }
-
- // Queue size of 20 ought to be enough for anybody ;-)
- if (listen(s, 20) == -1)
- {
- perror("listen");
- printf("init-ng: listen() failed!\n");
+ // This is bad... If this happens, we have no comms
+ perror("mkfifo");
}
// Main loop for PID 1. All commands are received and acted upon from here.
while (1)
{
- int t = sizeof(remote);
- unsigned int s2 = accept(s, (struct sockaddr *)&remote, &t);
+ // This will block until a command is sent down the pipe...
+ FILE * file = fopen(fifoPath, "r");
- if (s2 == -1)
+ if (file == NULL)
{
// Check to see if the signal handler blew things up on us
if (errno == EINTR)
continue;
- // An unanticipated error occurred, handle it
- perror("accept");
- printf("init-ng: accept() failed!\n");
+ perror("fopen");
+ continue;
}
- // Get the message from the socket
- int n = recv(s2, buf, 2048, 0);
- buf[n] = 0;
+ // Grab whatever was shoved into the FIFO
+ size_t read = fread(buf, 1, 2047, file);
+ buf[read] = 0;
+ fclose(file);
if (verbose)
- printf("PID1: Received \"%s\" from socket...\n", buf);
+ printf("PID1: Received \"%s\" from FIFO...\n", buf);
// Now do something with it...
if (strcmp(buf, "poweroff") == 0)
{
printf("[Status placeholder]\n");
}
-
- close(s2);
}
// We should never get here...