summaryrefslogtreecommitdiff
path: root/simpleinit/initctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'simpleinit/initctl.c')
-rw-r--r--simpleinit/initctl.c217
1 files changed, 217 insertions, 0 deletions
diff --git a/simpleinit/initctl.c b/simpleinit/initctl.c
new file mode 100644
index 00000000..3b38b496
--- /dev/null
+++ b/simpleinit/initctl.c
@@ -0,0 +1,217 @@
+/* initctl.c
+
+ Source file for initctl (init(8) control tool).
+
+ Copyright (C) 2000 Richard Gooch
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Richard Gooch may be reached by email at rgooch@atnf.csiro.au
+ The postal address is:
+ Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia.
+*/
+
+/*
+ This tool will send control messages to init(8). For example, it may
+ request init(8) to start a service and will wait for that service to be
+ available. If the service is already available, init(8) will not start it
+ again.
+ This tool may also be used to inspect the list of currently available
+ services.
+
+
+ Written by Richard Gooch 28-FEB-2000
+
+ Updated by Richard Gooch 11-OCT-2000: Added provide support.
+
+ Last updated by Richard Gooch 6-NOV-2000: Renamed to initctl.c
+
+
+*/
+#include <unistd.h>
+#include <stdio.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include "simpleinit.h"
+
+
+static void signal_handler (int sig);
+
+
+static int caught_signal = 0;
+
+
+int main (int argc, char **argv)
+{
+ int fd, nbytes;
+ struct sigaction sa;
+ sigset_t ss;
+ char *ptr;
+ long *buffer;
+ struct command_struct *command;
+
+ buffer = calloc(COMMAND_SIZE / sizeof (long) + 1, sizeof(long));
+ if (!buffer) {
+ fprintf (stderr, "Unable allocate buffer for command\n");
+ exit(1);
+ }
+ command = (struct command_struct *) buffer;
+
+ sigemptyset (&ss);
+ sigaddset (&ss, SIG_PRESENT);
+ sigaddset (&ss, SIG_NOT_PRESENT);
+ sigaddset (&ss, SIG_FAILED);
+ sigprocmask (SIG_BLOCK, &ss, NULL);
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = 0;
+ sa.sa_handler = signal_handler;
+ sigaction (SIG_PRESENT, &sa, NULL);
+ sigaction (SIG_NOT_PRESENT, &sa, NULL);
+ sigaction (SIG_FAILED, &sa, NULL);
+ command->pid = getpid ();
+ command->ppid = getppid ();
+ if ( ( ptr = strrchr (argv[0], '/') ) == NULL ) ptr = argv[0];
+ else ++ptr;
+ /* First generate command number by looking at invocation name */
+ if (strcmp (ptr, "display-services") == 0)
+ command->command = COMMAND_DUMP_LIST;
+ else if (strcmp (ptr, "need") == 0) command->command = COMMAND_NEED;
+ else if (strcmp (ptr, "provide") == 0) command->command = COMMAND_PROVIDE;
+ else command->command = COMMAND_TEST;
+ /* Now check for switches */
+ if ( (argc > 1) && (argv[1][0] == '-') )
+ {
+ switch (argv[1][1])
+ {
+ case 'n':
+ command->command = COMMAND_NEED;
+ break;
+ case 'r':
+ command->command = COMMAND_ROLLBACK;
+ break;
+ case 'd':
+ command->command = COMMAND_DUMP_LIST;
+ break;
+ case 'p':
+ command->command = COMMAND_PROVIDE;
+ break;
+ default:
+ fprintf (stderr, "Illegal switch: \"%s\"\n", argv[1]);
+ exit (1);
+ /*break;*/
+ }
+ --argc;
+ ++argv;
+ }
+ switch (command->command)
+ {
+ case COMMAND_NEED:
+ case COMMAND_PROVIDE:
+ if (argc < 2)
+ {
+ fprintf (stderr, "Usage:\tneed|provide programme\n");
+ exit (1);
+ }
+ /* Fall through */
+ case COMMAND_ROLLBACK:
+ if (argc > 1) strcpy (command->name, argv[1]);
+ else command->name[0] = '\0';
+ break;
+ case COMMAND_DUMP_LIST:
+ if (tmpnam (command->name) == NULL)
+ {
+ fprintf (stderr, "Unable to create a unique filename\t%s\n",
+ ERRSTRING);
+ exit (1);
+ }
+ if (mkfifo (command->name, S_IRUSR) != 0)
+ {
+ fprintf (stderr, "Unable to create FIFO: \"%s\"\t%s\n",
+ command->name, ERRSTRING);
+ exit (1);
+ }
+ break;
+ }
+ if ( ( fd = open ("/dev/initctl", O_WRONLY, 0) ) < 0 )
+ {
+ fprintf (stderr, "Error opening\t%s\n", ERRSTRING);
+ exit (1);
+ }
+ if (write (fd, buffer, COMMAND_SIZE) < COMMAND_SIZE)
+ {
+ fprintf (stderr, "Error writing\t%s\n", ERRSTRING);
+ exit (1);
+ }
+ close (fd);
+ if (command->command != COMMAND_DUMP_LIST)
+ {
+ sigemptyset (&ss);
+ while (caught_signal == 0) sigsuspend (&ss);
+ switch (command->command)
+ {
+ case COMMAND_PROVIDE:
+ switch (caught_signal)
+ {
+ case SIG_PRESENT:
+ return 1;
+ case SIG_NOT_PRESENT:
+ return 0;
+ case SIG_NOT_CHILD:
+ fprintf (stderr, "Error\n");
+ return 2;
+ default:
+ return 3;
+ }
+ break;
+ default:
+ switch (caught_signal)
+ {
+ case SIG_PRESENT:
+ return 0;
+ case SIG_NOT_PRESENT:
+ return 2;
+ case SIG_FAILED:
+ return 1;
+ default:
+ return 3;
+ }
+ break;
+ }
+ return 3;
+ }
+ /* Read back the data and display it */
+ if ( ( fd = open (command->name, O_RDONLY, 0) ) < 0 )
+ {
+ fprintf (stderr, "Error opening:\"%s\"\t%s\n",
+ command->name, ERRSTRING);
+ exit (1);
+ }
+ unlink (command->name);
+ fflush (stdout);
+ while ( ( nbytes = read (fd, buffer, COMMAND_SIZE) ) > 0 )
+ write (1, buffer, nbytes);
+ close (fd);
+ return (0);
+} /* End Function main */
+
+static void signal_handler (int sig)
+{
+ caught_signal = sig;
+} /* End Function signal_handler */