simpleinit: remove this deprecated set of utils
Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
parent
ea7e29132e
commit
0ff9e65ea3
|
@ -45,10 +45,6 @@ if BUILD_PARTX
|
||||||
SUBDIRS += partx
|
SUBDIRS += partx
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if BUILD_INIT
|
|
||||||
SUBDIRS += simpleinit
|
|
||||||
endif
|
|
||||||
|
|
||||||
if BUILD_MOUNT
|
if BUILD_MOUNT
|
||||||
SUBDIRS += mount
|
SUBDIRS += mount
|
||||||
endif
|
endif
|
||||||
|
@ -96,7 +92,7 @@ checkconfig:
|
||||||
|
|
||||||
|
|
||||||
ENABLE_ALL = --enable-static-programs \
|
ENABLE_ALL = --enable-static-programs \
|
||||||
--enable-elvtune --enable-init --enable-kill --enable-last \
|
--enable-elvtune --enable-kill --enable-last \
|
||||||
--enable-mesg --enable-partx --enable-raw --enable-rdev --enable-reset \
|
--enable-mesg --enable-partx --enable-raw --enable-rdev --enable-reset \
|
||||||
--enable-login-utils --enable-write --enable-arch --enable-mount
|
--enable-login-utils --enable-write --enable-arch --enable-mount
|
||||||
|
|
||||||
|
|
|
@ -968,14 +968,6 @@ AC_ARG_ENABLE([elvtune],
|
||||||
)
|
)
|
||||||
AM_CONDITIONAL(BUILD_ELVTUNE, test "x$enable_elvtune" = xyes)
|
AM_CONDITIONAL(BUILD_ELVTUNE, test "x$enable_elvtune" = xyes)
|
||||||
|
|
||||||
|
|
||||||
AC_ARG_ENABLE([init],
|
|
||||||
AS_HELP_STRING([--enable-init], [build simpleinit, shutdown, initctl]),
|
|
||||||
[], enable_init=no
|
|
||||||
)
|
|
||||||
AM_CONDITIONAL(BUILD_INIT, test "x$enable_init" = xyes)
|
|
||||||
|
|
||||||
|
|
||||||
AC_ARG_ENABLE([kill],
|
AC_ARG_ENABLE([kill],
|
||||||
AS_HELP_STRING([--enable-kill], [build kill]),
|
AS_HELP_STRING([--enable-kill], [build kill]),
|
||||||
[], enable_kill=no
|
[], enable_kill=no
|
||||||
|
@ -1223,7 +1215,6 @@ fsck/Makefile
|
||||||
getopt/Makefile
|
getopt/Makefile
|
||||||
hwclock/Makefile
|
hwclock/Makefile
|
||||||
include/Makefile
|
include/Makefile
|
||||||
simpleinit/Makefile
|
|
||||||
lib/Makefile
|
lib/Makefile
|
||||||
login-utils/Makefile
|
login-utils/Makefile
|
||||||
Makefile
|
Makefile
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
initctl
|
|
||||||
shutdown
|
|
||||||
simpleinit
|
|
|
@ -1,27 +0,0 @@
|
||||||
include $(top_srcdir)/config/include-Makefile.am
|
|
||||||
|
|
||||||
sbin_PROGRAMS = simpleinit shutdown initctl
|
|
||||||
dist_man_MANS = fastboot.8 fasthalt.8 halt.8 reboot.8 simpleinit.8 shutdown.8 \
|
|
||||||
initctl.8
|
|
||||||
|
|
||||||
simpleinit_SOURCES = simpleinit.c simpleinit.h
|
|
||||||
initctl_SOURCES = initctl.c simpleinit.h
|
|
||||||
|
|
||||||
if NEED_LIBCRYPT
|
|
||||||
simpleinit_LDADD = -lcrypt
|
|
||||||
endif
|
|
||||||
|
|
||||||
install-exec-hook::
|
|
||||||
cd $(DESTDIR)$(sbindir) && ln -sf shutdown reboot
|
|
||||||
cd $(DESTDIR)$(sbindir) && ln -sf shutdown fastboot
|
|
||||||
cd $(DESTDIR)$(sbindir) && ln -sf shutdown halt
|
|
||||||
cd $(DESTDIR)$(sbindir) && ln -sf shutdown fasthalt
|
|
||||||
cd $(DESTDIR)$(sbindir) && ln -sf initctl need
|
|
||||||
cd $(DESTDIR)$(sbindir) && ln -sf initctl display-services
|
|
||||||
cd $(DESTDIR)$(sbindir) && ln -sf initctl provide
|
|
||||||
|
|
||||||
install-data-hook:
|
|
||||||
cd $(DESTDIR)$(mandir)/man8 && ln -sf initctl.8 need.8
|
|
||||||
cd $(DESTDIR)$(mandir)/man8 && ln -sf initctl.8 display-services.8
|
|
||||||
cd $(DESTDIR)$(mandir)/man8 && ln -sf initctl.8 provide.8
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
.so man8/shutdown.8
|
|
|
@ -1 +0,0 @@
|
||||||
.so man8/shutdown.8
|
|
|
@ -1 +0,0 @@
|
||||||
.so man8/shutdown.8
|
|
|
@ -1,110 +0,0 @@
|
||||||
.\" Copyright (C) 2000-2001 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.
|
|
||||||
.\"
|
|
||||||
.\" initctl.8 Richard Gooch 21-FEB-2001
|
|
||||||
.\"
|
|
||||||
.TH INITCTL 8 "21 Feb 2001" "Util-Linux Package"
|
|
||||||
.SH NAME
|
|
||||||
initctl \- utility to control simpleinit(8)
|
|
||||||
.SH SYNOPSIS
|
|
||||||
.B need
|
|
||||||
.RB [ \-r ]
|
|
||||||
.I service
|
|
||||||
.br
|
|
||||||
.B display-services
|
|
||||||
.br
|
|
||||||
.B provide
|
|
||||||
.I service
|
|
||||||
.SH OVERVIEW
|
|
||||||
The \fBinitctl\fP programme is designed to help improve the
|
|
||||||
robustness, scalability and readability of system boot scripts. It is
|
|
||||||
now possible to write a modularised set of boot scripts without the
|
|
||||||
complex and fragile numbered symlink scheme used in SysV-style boot
|
|
||||||
scripts. Each script can simply declare, using \fBneed\fP(8), what
|
|
||||||
must run before them.
|
|
||||||
.SH DESCRIPTION for need
|
|
||||||
The \fBneed\fP programme is a utility that tells \fBsimpleinit\fP(8)
|
|
||||||
to start a \fIservice\fP (usually a script in \fI/sbin/init.d\fP) and
|
|
||||||
will wait for the service to become available. If the service is
|
|
||||||
already available, it will not be started again.
|
|
||||||
|
|
||||||
The \fB-r\fP option is used to tell \fBsimpleinit\fP(8) to "roll back"
|
|
||||||
(stop) services up to (but not including) \fIservice\fP. If
|
|
||||||
\fIservice\fP is not specified, all services are stopped. The \fB-r\fP
|
|
||||||
option thus allows the system to be partially or wholly shut down in
|
|
||||||
an orderly fashion. The \fBshutdown\fP(8) programme still needs to be
|
|
||||||
run.
|
|
||||||
|
|
||||||
.SH DESCRIPTION for display-services
|
|
||||||
When invoked as \fBdisplay-services\fP it will write the list of
|
|
||||||
currently available services and the list of failed services to the
|
|
||||||
standard output.
|
|
||||||
|
|
||||||
.SH DESCRIPTION for provide
|
|
||||||
When invoked as \fBprovide\fP it tells \fBsimpleinit\fP(8) that the
|
|
||||||
parent (calling) process will be providing a service with name
|
|
||||||
\fIservice\fP. If the calling process exits successfully (status 0)
|
|
||||||
the service is deemed to be available. Only one instance of
|
|
||||||
\fIservice\fP may be started, so alternate providers will block and
|
|
||||||
may fail.
|
|
||||||
|
|
||||||
Using \fBprovide\fP it is possible to have multiple potential
|
|
||||||
providers for the same (generic) service (e.g. \fBsendmail\fP and
|
|
||||||
\fBqmail\fP both provide a \fBmta\fP service), where only one actually
|
|
||||||
provides the service. This may be used by service startup scripts
|
|
||||||
which check for configuration files.
|
|
||||||
.SH EXIT CODE
|
|
||||||
The exit code from \fBneed\fP is 0 if the service was successfully
|
|
||||||
started, 1 if the service failed badly, and 2 if the service is
|
|
||||||
unavailable (i.e. disabled in configuration files). These exit codes
|
|
||||||
reflect the exit codes from the service startup scripts.
|
|
||||||
|
|
||||||
The exit code from \fBneed -r\fP is 0 if the service was successfully
|
|
||||||
stopped, 1 if the service could not be stopped, and 2 if the service
|
|
||||||
was not available to start with. The service shutdown scripts may only
|
|
||||||
return 0 (for success) or 1 (for failure).
|
|
||||||
|
|
||||||
The exit code from \fBprovide\fP is 0 if the service may be provided,
|
|
||||||
1 if it may not, and 2 if the parent process is not a child of
|
|
||||||
init. It may block waiting for another provider which is initialising
|
|
||||||
the service.
|
|
||||||
.SH SIGNALS
|
|
||||||
\fBinitctl\fP(8) uses \fBSIGUSR1\fP, \fBSIGUSR2\fP and \fBSIGPOLL\fP
|
|
||||||
for communication with \fBsimpleinit\fP(8). Don't send these signals
|
|
||||||
to it.
|
|
||||||
.SH FILES
|
|
||||||
.PD 0
|
|
||||||
.TP 20
|
|
||||||
.BI /dev/initctl
|
|
||||||
This is the control FIFO, created by \fBsimpleinit\fP(8), which
|
|
||||||
\fBinitctl\fP(8) writes commands to.
|
|
||||||
.SH SEE ALSO
|
|
||||||
.BR simpleinit (8),
|
|
||||||
.BR init (8)
|
|
||||||
.PP
|
|
||||||
A more complete discussion of the new boot script system, based on
|
|
||||||
\fBneed\fP(8), is available from:
|
|
||||||
http://www.atnf.csiro.au/~rgooch/linux/boot-scripts/
|
|
||||||
.SH AUTHOR
|
|
||||||
Richard Gooch (rgooch@atnf.csiro.au)
|
|
||||||
|
|
||||||
.SH AVAILABILITY
|
|
||||||
The initctl command is part of the util-linux package and is available from
|
|
||||||
ftp://ftp.kernel.org/pub/linux/utils/util-linux/.
|
|
|
@ -1,217 +0,0 @@
|
||||||
/* 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 */
|
|
|
@ -1 +0,0 @@
|
||||||
.so man8/shutdown.8
|
|
|
@ -1,169 +0,0 @@
|
||||||
.\" Copyright 1992 Rickard E. Faith (faith@cs.unc.edu)
|
|
||||||
.\" May be distributed under the GNU General Public License
|
|
||||||
.\"
|
|
||||||
.\"
|
|
||||||
.TH SHUTDOWN 8 "2 March 2000" "Linux 2.0" "Linux Programmer's Manual"
|
|
||||||
.SH NAME
|
|
||||||
shutdown \- close down the system
|
|
||||||
.SH SYNOPSIS
|
|
||||||
.B shutdown
|
|
||||||
.RB [ \-h | \-r ]
|
|
||||||
.RB [ \-fqs ]
|
|
||||||
.RB [ now | \fIhh\fP:\fIss\fP | +\fImins\fP ]
|
|
||||||
.RI [ message ]
|
|
||||||
.br
|
|
||||||
.B reboot
|
|
||||||
.RB [ \-h | \-r ]
|
|
||||||
.RB [ \-fqs ]
|
|
||||||
.RB [ now | \fIhh\fP:\fIss\fP | +\fImins\fP ]
|
|
||||||
.RI [ message ]
|
|
||||||
.br
|
|
||||||
.B fastboot
|
|
||||||
.RB [ \-h | \-r ]
|
|
||||||
.RB [ \-fqs ]
|
|
||||||
.RB [ now | \fIhh\fP:\fIss\fP | +\fImins\fP ]
|
|
||||||
.RI [ message ]
|
|
||||||
.br
|
|
||||||
.B halt
|
|
||||||
.RB [ \-h | \-r ]
|
|
||||||
.RB [ \-fqs ]
|
|
||||||
.RB [ now | \fIhh\fP:\fIss\fP | +\fImins\fP ]
|
|
||||||
.RI [ message ]
|
|
||||||
.br
|
|
||||||
.B fasthalt
|
|
||||||
.RB [ \-h | \-r ]
|
|
||||||
.RB [ \-fqs ]
|
|
||||||
.RB [ now | \fIhh\fP:\fIss\fP | +\fImins\fP ]
|
|
||||||
.RI [ message ]
|
|
||||||
.SH DESCRIPTION
|
|
||||||
.\" " for emacs hilit19
|
|
||||||
In general,
|
|
||||||
.B shutdown
|
|
||||||
prepares the system for a power down or reboot. A absolute or delta time
|
|
||||||
can be given, and periodic messages will be sent to all users warning of
|
|
||||||
the shutdown. If no message is specified on the command line,
|
|
||||||
.B shutdown
|
|
||||||
will ask for a message to be sent, unless the
|
|
||||||
.B \-q
|
|
||||||
option is set.
|
|
||||||
|
|
||||||
.B halt
|
|
||||||
is the same as
|
|
||||||
.B "shutdown -h -q now"
|
|
||||||
|
|
||||||
.B fasthalt
|
|
||||||
is the same as
|
|
||||||
.B "shutdown -h -q -f now"
|
|
||||||
|
|
||||||
.B reboot
|
|
||||||
is the same as
|
|
||||||
.B "shutdown -r -q now"
|
|
||||||
|
|
||||||
.B fastboot
|
|
||||||
is the same as
|
|
||||||
.B "shutdown -r -q -f now"
|
|
||||||
|
|
||||||
The default delta time, if none is specified, is 2 minutes.
|
|
||||||
|
|
||||||
Five minutes before shutdown (or immediately, if shutdown is less than five
|
|
||||||
minutes away), the
|
|
||||||
.I /etc/nologin
|
|
||||||
file is created with a message stating that the system is going down and
|
|
||||||
that logins are no longer permitted. The
|
|
||||||
.BR login (1)
|
|
||||||
program will not allow non-superusers to login during this period. A
|
|
||||||
message will be sent to all users at this time.
|
|
||||||
|
|
||||||
When the shutdown time arrives,
|
|
||||||
.B shutdown
|
|
||||||
notifies all users, tells
|
|
||||||
.BR init (8)
|
|
||||||
not to spawn more
|
|
||||||
.BR getty (8)'s,
|
|
||||||
writes the shutdown time into the
|
|
||||||
.I /var/log/wtmp
|
|
||||||
file, kills all other processes on the system,
|
|
||||||
.BR sync (2)'s,
|
|
||||||
unmounts all the disks,
|
|
||||||
.BR sync (2)'s
|
|
||||||
again, waits for a second, and then either terminates or reboots the
|
|
||||||
system.
|
|
||||||
|
|
||||||
Prior to unmounting all discs, the \fBSIGQUIT\fP signal is sent to the
|
|
||||||
\fBinit\fP process, which will in turn exec \fBshutdown\fP(8). This
|
|
||||||
allows for clean unmounting, even if the old inode for the \fBinit\fP
|
|
||||||
process was unlinked. If the current process ID (PID) equals 1, then
|
|
||||||
\fBshutdown\fP(8) will pause forever.
|
|
||||||
.SH OPTIONS
|
|
||||||
.TP
|
|
||||||
.B \-h
|
|
||||||
Halt the system. Do not reboot. This option is used when powering down
|
|
||||||
the system.
|
|
||||||
.TP
|
|
||||||
.B \-r
|
|
||||||
Reboot the system.
|
|
||||||
.TP
|
|
||||||
.B \-f
|
|
||||||
Fast. When the system is rebooted, the file systems will not be checked.
|
|
||||||
This is arranged by creating
|
|
||||||
.IR /fastboot ,
|
|
||||||
which
|
|
||||||
.I /etc/rc
|
|
||||||
must detect (and delete).
|
|
||||||
.TP
|
|
||||||
.B \-q
|
|
||||||
Quiet. This uses a default broadcast message, and does not prompt the user
|
|
||||||
for one.
|
|
||||||
.TP
|
|
||||||
.B \-s
|
|
||||||
Reboot in single user mode. This is arranged by creating
|
|
||||||
.IR /etc/singleboot ,
|
|
||||||
which
|
|
||||||
.BR simpleinit (8)
|
|
||||||
detects (and deletes).
|
|
||||||
.SH FILES
|
|
||||||
.nf
|
|
||||||
.I /etc/rc
|
|
||||||
.I /fastboot
|
|
||||||
.I /etc/singleboot
|
|
||||||
.I /etc/nologin
|
|
||||||
.I /var/log/wtmp
|
|
||||||
.I /etc/shutdown.conf
|
|
||||||
.fi
|
|
||||||
.SH CONFIG
|
|
||||||
The configuration file \fI/etc/shutdown.conf\fP is used to determine
|
|
||||||
the action to take when halting the machine. The currently supported
|
|
||||||
file format is extremely primitive. The first line must contain two
|
|
||||||
strings separated by whitespace. The first string must be
|
|
||||||
\fBHALT_ACTION\fP and the second specifies the action you wish to take
|
|
||||||
on halt. The options allowed are:
|
|
||||||
.TP
|
|
||||||
.B halt
|
|
||||||
This will simply halt the system. This is the default behaviour.
|
|
||||||
Note also that this is the fallback if another option fails.
|
|
||||||
.TP
|
|
||||||
.B power_off
|
|
||||||
This will use the kernel power shutdown facility. This is usually only
|
|
||||||
available on machines with Advanced Power Management (APM).
|
|
||||||
.TP
|
|
||||||
.I programname
|
|
||||||
This specifies a command to run to shut down the power. The first
|
|
||||||
character must be a "/". Bear in mind that this command will be run
|
|
||||||
with only the root filesystem mounted (and it will be read-only), and
|
|
||||||
no daemons running.
|
|
||||||
.SH "SEE ALSO"
|
|
||||||
.BR umount (8),
|
|
||||||
.BR login (1),
|
|
||||||
.BR reboot (2),
|
|
||||||
.BR simpleinit (8),
|
|
||||||
.BR init (8)
|
|
||||||
.SH BUGS
|
|
||||||
Unlike the BSD
|
|
||||||
.BR shutdown ,
|
|
||||||
users are notified of shutdown only once or twice, instead of many times,
|
|
||||||
and at shorter and shorter intervals as "apocalypse approaches."
|
|
||||||
Some would construe this as a feature.
|
|
||||||
.SH AUTHOR
|
|
||||||
This page documents the version of
|
|
||||||
.B shutdown
|
|
||||||
originally written by Peter Orbaek (poe@daimi.aau.dk).
|
|
|
@ -1,747 +0,0 @@
|
||||||
/* shutdown.c - shutdown a Linux system
|
|
||||||
* Initially written by poe@daimi.aau.dk
|
|
||||||
* Currently maintained at ftp://ftp.daimi.aau.dk/pub/Software/Linux/
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Modified by jrs@world.std.com to try to exec "umount -a" and if
|
|
||||||
* that doesn't work, then umount filesystems ourselves in reverse
|
|
||||||
* order. The old-way was in forward order. Also if the device
|
|
||||||
* field of the mtab does not start with a "/" then give umount
|
|
||||||
* the mount point instead. This is needed for the nfs and proc
|
|
||||||
* filesystems and yet is compatible with older systems.
|
|
||||||
*
|
|
||||||
* We also use the mntent library interface to read the mtab file
|
|
||||||
* instead of trying to parse it directly and no longer give a
|
|
||||||
* warning about not being able to umount the root.
|
|
||||||
*
|
|
||||||
* The reason "umount -a" should be tried first is because it may do
|
|
||||||
* special processing for some filesystems (such as informing an
|
|
||||||
* nfs server about nfs umounts) that we don't want to cope with here.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Various changes and additions to resemble SunOS 4 shutdown/reboot/halt(8)
|
|
||||||
* more closely by Scott Telford (s.telford@ed.ac.uk) 93/05/18.
|
|
||||||
* (I butchered Scotts patches somewhat. - poe)
|
|
||||||
*
|
|
||||||
* Changes by Richard Gooch <rgooch@atnf.csiro.au> (butchered by aeb)
|
|
||||||
* introducing shutdown.conf.
|
|
||||||
*
|
|
||||||
* 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
|
|
||||||
* - added Native Language Support
|
|
||||||
*
|
|
||||||
* 2000-03-02 Richard Gooch <rgooch@atnf.csiro.au>
|
|
||||||
* - pause forever if (pid == 1) and send SIGQUIT to pid = 1
|
|
||||||
*
|
|
||||||
* 2000-11-04 Richard Gooch <rgooch@atnf.csiro.au>
|
|
||||||
* - continue reaping if (pid == 1)
|
|
||||||
*
|
|
||||||
* 2000-11-06 Richard Gooch <rgooch@atnf.csiro.au>
|
|
||||||
* - shut down "finalprog" from /etc/inittab
|
|
||||||
* - kill normal user (non-root and non-daemon) processes first with SIGTERM
|
|
||||||
*
|
|
||||||
* 2000-11-08 Richard Gooch <rgooch@atnf.csiro.au>
|
|
||||||
* - rollback services
|
|
||||||
* - do not unmount devfs (otherwise get harmless but annoying messages)
|
|
||||||
* - created syncwait() for faster shutting down
|
|
||||||
* - kill getty processes
|
|
||||||
* 2001-05-12 Richard Gooch <rgooch@atnf.csiro.au>
|
|
||||||
* - unblock all signals (sigmask from simpleinit(8) stopped sleep(3))
|
|
||||||
* - close all files
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <utmp.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <termios.h>
|
|
||||||
#include <mntent.h>
|
|
||||||
#include <sys/mount.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <syslog.h>
|
|
||||||
#include <sys/resource.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/utsname.h>
|
|
||||||
#include "linux_reboot.h"
|
|
||||||
#include "pathnames.h"
|
|
||||||
#include "strutils.h"
|
|
||||||
#include "nls.h"
|
|
||||||
#include "usleep.h"
|
|
||||||
|
|
||||||
static void usage(void), int_handler(int), write_user(struct utmp *);
|
|
||||||
static void wall(void), write_wtmp(void), unmount_disks(void);
|
|
||||||
static void unmount_disks_ourselves(void);
|
|
||||||
static void swap_off(void), do_halt(char *);
|
|
||||||
static void kill_mortals (int sig);
|
|
||||||
static void stop_finalprog (void);
|
|
||||||
static void syncwait (int timeval);
|
|
||||||
|
|
||||||
|
|
||||||
char *prog; /* name of the program */
|
|
||||||
int opt_reboot; /* true if -r option or reboot command */
|
|
||||||
int timeout; /* number of seconds to shutdown */
|
|
||||||
int opt_quiet; /* true if no message is wanted */
|
|
||||||
int opt_fast; /* true if fast boot */
|
|
||||||
char message[90]; /* reason for shutdown if any... */
|
|
||||||
int opt_single = 0; /* true is we want to boot singleuser */
|
|
||||||
char *whom; /* who is shutting the system down */
|
|
||||||
int opt_msgset = 0; /* message set on command line */
|
|
||||||
/* change 1 to 0 if no file is to be used by default */
|
|
||||||
int opt_use_config_file = 1; /* read _PATH_SHUTDOWN_CONF */
|
|
||||||
char halt_action[256]; /* to find out what to do upon halt */
|
|
||||||
|
|
||||||
/* #define DEBUGGING */
|
|
||||||
|
|
||||||
#define WR(s) write(fd, s, strlen(s))
|
|
||||||
#define WRCRLF write(fd, "\r\n", 2)
|
|
||||||
#define ERRSTRING strerror(errno)
|
|
||||||
|
|
||||||
#define UMOUNT_ARGS "umount", "-a", "-t", "nodevfs,devtmpfs"
|
|
||||||
#define SWAPOFF_ARGS "swapoff", "-a"
|
|
||||||
|
|
||||||
void
|
|
||||||
usage(void)
|
|
||||||
{
|
|
||||||
fprintf(stderr,
|
|
||||||
_("Usage: shutdown [-h|-r] [-fqs] [now|hh:ss|+mins]\n"));
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
my_puts(char *s)
|
|
||||||
{
|
|
||||||
/* Use a fresh stdout after forking */
|
|
||||||
freopen(_PATH_CONSOLE, "w", stdout);
|
|
||||||
puts(s);
|
|
||||||
fflush(stdout);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
int_handler(int sig)
|
|
||||||
{
|
|
||||||
unlink(_PATH_NOLOGIN);
|
|
||||||
signal(SIGINT, SIG_DFL);
|
|
||||||
my_puts(_("Shutdown process aborted"));
|
|
||||||
_exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
iswhitespace(int a) {
|
|
||||||
return (a == ' ' || a == '\t');
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
int c, i, fd;
|
|
||||||
char *ptr;
|
|
||||||
|
|
||||||
i = getdtablesize ();
|
|
||||||
for (fd = 3; fd < i; fd++) close (fd);
|
|
||||||
if (getpid () == 1)
|
|
||||||
{
|
|
||||||
for (fd = 0; fd < 3; fd++) close (fd);
|
|
||||||
while (1) wait (NULL); /* Grim reaper never stops */
|
|
||||||
}
|
|
||||||
sigsetmask (0); /* simpleinit(8) blocks all signals: undo for ALRM */
|
|
||||||
for (i = 1; i < NSIG; i++) signal (i, SIG_DFL);
|
|
||||||
|
|
||||||
setlocale(LC_ALL, "");
|
|
||||||
bindtextdomain(PACKAGE, LOCALEDIR);
|
|
||||||
textdomain(PACKAGE);
|
|
||||||
|
|
||||||
#ifndef DEBUGGING
|
|
||||||
if(setreuid (0, 0))
|
|
||||||
errx(EXIT_FAILURE, _("only root can shut a system down."));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(*argv[0] == '-') argv[0]++; /* allow shutdown as login shell */
|
|
||||||
prog = argv[0];
|
|
||||||
if((ptr = strrchr(argv[0], '/'))) prog = ++ptr;
|
|
||||||
|
|
||||||
/* All names (halt, reboot, fasthalt, fastboot, shutdown)
|
|
||||||
refer to the same program with the same options,
|
|
||||||
only the defaults differ. */
|
|
||||||
if(!strcmp("halt", prog)) {
|
|
||||||
opt_reboot = 0;
|
|
||||||
opt_quiet = 1;
|
|
||||||
opt_fast = 0;
|
|
||||||
timeout = 0;
|
|
||||||
} else if(!strcmp("fasthalt", prog)) {
|
|
||||||
opt_reboot = 0;
|
|
||||||
opt_quiet = 1;
|
|
||||||
opt_fast = 1;
|
|
||||||
timeout = 0;
|
|
||||||
} else if(!strcmp("reboot", prog)) {
|
|
||||||
opt_reboot = 1;
|
|
||||||
opt_quiet = 1;
|
|
||||||
opt_fast = 0;
|
|
||||||
timeout = 0;
|
|
||||||
} else if(!strcmp("fastboot", prog)) {
|
|
||||||
opt_reboot = 1;
|
|
||||||
opt_quiet = 1;
|
|
||||||
opt_fast = 1;
|
|
||||||
timeout = 0;
|
|
||||||
} else {
|
|
||||||
/* defaults */
|
|
||||||
opt_reboot = 0;
|
|
||||||
opt_quiet = 0;
|
|
||||||
opt_fast = 0;
|
|
||||||
timeout = 2*60;
|
|
||||||
}
|
|
||||||
|
|
||||||
c = 0;
|
|
||||||
while(++c < argc) {
|
|
||||||
if(argv[c][0] == '-') {
|
|
||||||
for(i = 1; argv[c][i]; i++) {
|
|
||||||
switch(argv[c][i]) {
|
|
||||||
case 'C':
|
|
||||||
opt_use_config_file = 1;
|
|
||||||
break;
|
|
||||||
case 'h':
|
|
||||||
opt_reboot = 0;
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
opt_reboot = 1;
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
opt_fast = 1;
|
|
||||||
break;
|
|
||||||
case 'q':
|
|
||||||
opt_quiet = 1;
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
opt_single = 1;
|
|
||||||
|
|
||||||
default:
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if(!strcmp("now", argv[c])) {
|
|
||||||
timeout = 0;
|
|
||||||
} else if(argv[c][0] == '+') {
|
|
||||||
timeout = 60 * atoi(&argv[c][1]);
|
|
||||||
} else if (isdigit(argv[c][0])) {
|
|
||||||
char *colon;
|
|
||||||
int hour = 0;
|
|
||||||
int minute = 0;
|
|
||||||
time_t tics;
|
|
||||||
struct tm *tt;
|
|
||||||
int now, then;
|
|
||||||
|
|
||||||
if((colon = strchr(argv[c], ':'))) {
|
|
||||||
*colon = '\0';
|
|
||||||
hour = atoi(argv[c]);
|
|
||||||
minute = atoi(++colon);
|
|
||||||
} else usage();
|
|
||||||
|
|
||||||
(void) time(&tics);
|
|
||||||
tt = localtime(&tics);
|
|
||||||
|
|
||||||
now = 3600 * tt->tm_hour + 60 * tt->tm_min;
|
|
||||||
then = 3600 * hour + 60 * minute;
|
|
||||||
timeout = then - now;
|
|
||||||
if(timeout < 0)
|
|
||||||
errx(EXIT_FAILURE, _("that must be tomorrow, "
|
|
||||||
"can't you wait till then?"));
|
|
||||||
} else {
|
|
||||||
xstrncpy(message, argv[c], sizeof(message));
|
|
||||||
opt_msgset = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
halt_action[0] = 0;
|
|
||||||
|
|
||||||
/* No doubt we shall want to extend this some day
|
|
||||||
and register a series of commands to be executed
|
|
||||||
at various points during the shutdown sequence,
|
|
||||||
and to define the number of milliseconds to sleep, etc. */
|
|
||||||
if (opt_use_config_file) {
|
|
||||||
char line[256], *p;
|
|
||||||
FILE *fp;
|
|
||||||
|
|
||||||
/* Read and parse the config file */
|
|
||||||
halt_action[0] = '\0';
|
|
||||||
if ((fp = fopen (_PATH_SHUTDOWN_CONF, "r")) != NULL) {
|
|
||||||
if (fgets (line, sizeof(line), fp) != NULL &&
|
|
||||||
strncasecmp (line, "HALT_ACTION", 11) == 0 &&
|
|
||||||
iswhitespace(line[11])) {
|
|
||||||
p = strchr(line, '\n');
|
|
||||||
if (p)
|
|
||||||
*p = 0; /* strip final '\n' */
|
|
||||||
p = line+11;
|
|
||||||
while(iswhitespace(*p))
|
|
||||||
p++;
|
|
||||||
strcpy(halt_action, p);
|
|
||||||
}
|
|
||||||
fclose (fp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!opt_quiet && !opt_msgset) {
|
|
||||||
/* now ask for message, gets() is insecure */
|
|
||||||
int cnt = sizeof(message)-1;
|
|
||||||
char *ptr;
|
|
||||||
|
|
||||||
printf("Why? "); fflush(stdout);
|
|
||||||
|
|
||||||
ptr = message;
|
|
||||||
while(--cnt >= 0 && (*ptr = getchar()) && *ptr != '\n') {
|
|
||||||
ptr++;
|
|
||||||
}
|
|
||||||
*ptr = '\0';
|
|
||||||
} else if (!opt_msgset) {
|
|
||||||
strcpy(message, _("for maintenance; bounce, bounce"));
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUGGING
|
|
||||||
printf("timeout = %d, quiet = %d, reboot = %d\n",
|
|
||||||
timeout, opt_quiet, opt_reboot);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* so much for option-processing, now begin termination... */
|
|
||||||
if(!(whom = getlogin()) || !*whom) whom = "ghost";
|
|
||||||
if(strlen(whom) > 40) whom[40] = 0; /* see write_user() */
|
|
||||||
|
|
||||||
setpriority(PRIO_PROCESS, 0, PRIO_MIN);
|
|
||||||
signal(SIGINT, int_handler);
|
|
||||||
signal(SIGHUP, int_handler);
|
|
||||||
signal(SIGQUIT, int_handler);
|
|
||||||
signal(SIGTERM, int_handler);
|
|
||||||
|
|
||||||
chdir("/");
|
|
||||||
|
|
||||||
if(timeout > 5*60) {
|
|
||||||
sleep(timeout - 5*60);
|
|
||||||
timeout = 5*60;
|
|
||||||
}
|
|
||||||
|
|
||||||
if((fd = open(_PATH_NOLOGIN, O_WRONLY|O_CREAT, 0644)) >= 0) {
|
|
||||||
/* keep xgettext happy and leave \r\n outside strings */
|
|
||||||
WRCRLF;
|
|
||||||
WR(_("The system is being shut down within 5 minutes"));
|
|
||||||
WRCRLF;
|
|
||||||
write(fd, message, strlen(message));
|
|
||||||
WRCRLF;
|
|
||||||
WR(_("Login is therefore prohibited."));
|
|
||||||
WRCRLF;
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
signal(SIGPIPE, SIG_IGN);
|
|
||||||
|
|
||||||
if(timeout > 0) {
|
|
||||||
wall();
|
|
||||||
sleep(timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
timeout = 0;
|
|
||||||
wall();
|
|
||||||
sleep(3);
|
|
||||||
|
|
||||||
/* now there's no turning back... */
|
|
||||||
signal(SIGINT, SIG_IGN);
|
|
||||||
|
|
||||||
/* do syslog message... */
|
|
||||||
openlog(prog, LOG_CONS, LOG_AUTH);
|
|
||||||
if (opt_reboot)
|
|
||||||
syslog(LOG_NOTICE, _("rebooted by %s: %s"),
|
|
||||||
whom, message);
|
|
||||||
else
|
|
||||||
syslog(LOG_NOTICE, _("halted by %s: %s"),
|
|
||||||
whom, message);
|
|
||||||
closelog();
|
|
||||||
|
|
||||||
if(opt_fast)
|
|
||||||
if((fd = open("/fastboot", O_WRONLY|O_CREAT, 0644)) >= 0)
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
kill(1, SIGTSTP); /* tell init not to spawn more getty's */
|
|
||||||
write_wtmp();
|
|
||||||
if(opt_single)
|
|
||||||
if((fd = open(_PATH_SINGLE, O_CREAT|O_WRONLY, 0644)) >= 0)
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
sync();
|
|
||||||
|
|
||||||
signal(SIGTERM, SIG_IGN);
|
|
||||||
if(fork() > 0) sleep(1000); /* the parent will die soon... */
|
|
||||||
setpgrp(); /* so the shell wont kill us in the fall */
|
|
||||||
|
|
||||||
#ifndef DEBUGGING
|
|
||||||
/* a gentle kill of all other processes except init */
|
|
||||||
kill_mortals (SIGTERM);
|
|
||||||
for (fd = 0; fd < 3; fd++) close (fd);
|
|
||||||
stop_finalprog ();
|
|
||||||
sleep (1); /* Time for saves to start */
|
|
||||||
kill (1, SIGTERM); /* Tell init to kill spawned gettys */
|
|
||||||
usleep (100000); /* Wait for gettys to die */
|
|
||||||
my_puts (""); /* Get past the login prompt */
|
|
||||||
system ("/sbin/initctl -r"); /* Roll back services */
|
|
||||||
syncwait (1);
|
|
||||||
my_puts ("Sending SIGTERM to all remaining processes...");
|
|
||||||
kill (-1, SIGTERM);
|
|
||||||
sleep (2); /* Default 2, some people need 5 */
|
|
||||||
|
|
||||||
kill (-1, SIGKILL); /* Now use brute force... */
|
|
||||||
|
|
||||||
/* turn off accounting */
|
|
||||||
acct(NULL);
|
|
||||||
#endif
|
|
||||||
/* RedHat and SuSE like to remove /etc/nologin.
|
|
||||||
Perhaps the usual sequence is
|
|
||||||
touch nologin; shutdown -h; fiddle with hardware;
|
|
||||||
boot; fiddle with software; rm nologin
|
|
||||||
and removing it here will be counterproductive.
|
|
||||||
Let us see whether people complain. */
|
|
||||||
unlink(_PATH_NOLOGIN);
|
|
||||||
|
|
||||||
/* Tell init(8) to exec so that the old inode may be freed cleanly if
|
|
||||||
required. Need to sleep before remounting root read-only */
|
|
||||||
kill (1, SIGQUIT);
|
|
||||||
|
|
||||||
sleep (1); /* Time for processes to die and close files */
|
|
||||||
syncwait (2);
|
|
||||||
|
|
||||||
/* remove swap files and partitions using swapoff */
|
|
||||||
swap_off();
|
|
||||||
|
|
||||||
/* unmount disks... */
|
|
||||||
unmount_disks();
|
|
||||||
syncwait (1);
|
|
||||||
|
|
||||||
if(opt_reboot) {
|
|
||||||
my_reboot(LINUX_REBOOT_CMD_RESTART); /* RB_AUTOBOOT */
|
|
||||||
my_puts(_("\nWhy am I still alive after reboot?"));
|
|
||||||
} else {
|
|
||||||
my_puts(_("\nNow you can turn off the power..."));
|
|
||||||
|
|
||||||
/* allow C-A-D now, faith@cs.unc.edu, re-fixed 8-Jul-96 */
|
|
||||||
my_reboot(LINUX_REBOOT_CMD_CAD_ON); /* RB_ENABLE_CAD */
|
|
||||||
sleep (1); /* Wait for devices to finish writing to media */
|
|
||||||
do_halt(halt_action);
|
|
||||||
}
|
|
||||||
/* NOTREACHED */
|
|
||||||
exit(EXIT_SUCCESS); /* to quiet gcc */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*** end of main() ***/
|
|
||||||
|
|
||||||
void
|
|
||||||
do_halt(char *action) {
|
|
||||||
if (strcasecmp (action, "power_off") == 0) {
|
|
||||||
printf(_("Calling kernel power-off facility...\n"));
|
|
||||||
fflush(stdout);
|
|
||||||
my_reboot(LINUX_REBOOT_CMD_POWER_OFF);
|
|
||||||
printf(_("Error powering off\t%s\n"), ERRSTRING);
|
|
||||||
fflush(stdout);
|
|
||||||
sleep (2);
|
|
||||||
} else
|
|
||||||
|
|
||||||
/* This should be improved; e.g. Mike Jagdis wants "/sbin/mdstop -a" */
|
|
||||||
/* Maybe we should also fork and wait */
|
|
||||||
if (action[0] == '/') {
|
|
||||||
printf(_("Executing the program \"%s\" ...\n"), action);
|
|
||||||
fflush(stdout);
|
|
||||||
execl(action, action, NULL);
|
|
||||||
printf(_("Error executing\t%s\n"), ERRSTRING);
|
|
||||||
fflush(stdout);
|
|
||||||
sleep (2);
|
|
||||||
}
|
|
||||||
|
|
||||||
my_reboot(LINUX_REBOOT_CMD_HALT); /* RB_HALT_SYSTEM */
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
write_user(struct utmp *ut)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
int minutes, hours;
|
|
||||||
char term[40] = {'/','d','e','v','/',0};
|
|
||||||
char msg[100];
|
|
||||||
|
|
||||||
minutes = timeout / 60;
|
|
||||||
hours = minutes / 60;
|
|
||||||
minutes %= 60;
|
|
||||||
|
|
||||||
(void) strncat(term, ut->ut_line, sizeof(ut->ut_line));
|
|
||||||
|
|
||||||
/* try not to get stuck on a mangled ut_line entry... */
|
|
||||||
if((fd = open(term, O_WRONLY|O_NONBLOCK)) < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
msg[0] = '\007'; /* gettext crashes on \a */
|
|
||||||
sprintf(msg+1, _("URGENT: broadcast message from %s:"), whom);
|
|
||||||
WRCRLF;
|
|
||||||
WR(msg);
|
|
||||||
WRCRLF;
|
|
||||||
|
|
||||||
if (hours > 1)
|
|
||||||
sprintf(msg, _("System going down in %d hours %d minutes"),
|
|
||||||
hours, minutes);
|
|
||||||
else if (hours == 1)
|
|
||||||
sprintf(msg, _("System going down in 1 hour %d minutes"),
|
|
||||||
minutes);
|
|
||||||
else if (minutes > 1)
|
|
||||||
sprintf(msg, _("System going down in %d minutes\n"),
|
|
||||||
minutes);
|
|
||||||
else if (minutes == 1)
|
|
||||||
sprintf(msg, _("System going down in 1 minute\n"));
|
|
||||||
else
|
|
||||||
sprintf(msg, _("System going down IMMEDIATELY!\n"));
|
|
||||||
|
|
||||||
WR(msg);
|
|
||||||
WRCRLF;
|
|
||||||
|
|
||||||
sprintf(msg, _("\t... %s ...\n"), message);
|
|
||||||
WR(msg);
|
|
||||||
WRCRLF;
|
|
||||||
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
wall(void)
|
|
||||||
{
|
|
||||||
/* write to all users, that the system is going down. */
|
|
||||||
struct utmp *ut;
|
|
||||||
|
|
||||||
utmpname(_PATH_UTMP);
|
|
||||||
setutent();
|
|
||||||
|
|
||||||
while((ut = getutent())) {
|
|
||||||
if(ut->ut_type == USER_PROCESS)
|
|
||||||
write_user(ut);
|
|
||||||
}
|
|
||||||
endutent();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
write_wtmp(void)
|
|
||||||
{
|
|
||||||
/* write in wtmp that we are dying */
|
|
||||||
int fd;
|
|
||||||
struct utmp ut;
|
|
||||||
|
|
||||||
memset((char *)&ut, 0, sizeof(ut));
|
|
||||||
strcpy(ut.ut_line, "~");
|
|
||||||
memcpy(ut.ut_name, "shutdown", sizeof(ut.ut_name));
|
|
||||||
|
|
||||||
time(&ut.ut_time);
|
|
||||||
ut.ut_type = BOOT_TIME;
|
|
||||||
|
|
||||||
if((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0644)) >= 0) {
|
|
||||||
write(fd, (char *)&ut, sizeof(ut));
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
swap_off(void)
|
|
||||||
{
|
|
||||||
/* swapoff esp. swap FILES so the underlying partition can be
|
|
||||||
unmounted. It you don't have swapoff(1) or use mount to
|
|
||||||
add swapspace, this may not be necessary, but I guess it
|
|
||||||
won't hurt */
|
|
||||||
|
|
||||||
int pid;
|
|
||||||
int result;
|
|
||||||
int status;
|
|
||||||
|
|
||||||
sync();
|
|
||||||
if ((pid = fork()) < 0) {
|
|
||||||
my_puts(_("Cannot fork for swapoff. Shrug!"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!pid) {
|
|
||||||
execl("/sbin/swapoff", SWAPOFF_ARGS, NULL);
|
|
||||||
execl("/etc/swapoff", SWAPOFF_ARGS, NULL);
|
|
||||||
execl("/bin/swapoff", SWAPOFF_ARGS, NULL);
|
|
||||||
execlp("swapoff", SWAPOFF_ARGS, NULL);
|
|
||||||
my_puts(_("Cannot exec swapoff, "
|
|
||||||
"hoping umount will do the trick."));
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
while ((result = wait(&status)) != -1 && result != pid)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
unmount_disks(void)
|
|
||||||
{
|
|
||||||
/* better to use umount directly because it may be smarter than us */
|
|
||||||
|
|
||||||
int pid;
|
|
||||||
int result;
|
|
||||||
int status;
|
|
||||||
|
|
||||||
sync();
|
|
||||||
if ((pid = fork()) < 0) {
|
|
||||||
my_puts(_("Cannot fork for umount, trying manually."));
|
|
||||||
unmount_disks_ourselves();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!pid) {
|
|
||||||
execl(_PATH_UMOUNT, UMOUNT_ARGS, NULL);
|
|
||||||
|
|
||||||
/* need my_printf instead of my_puts here */
|
|
||||||
freopen(_PATH_CONSOLE, "w", stdout);
|
|
||||||
printf(_("Cannot exec %s, trying umount.\n"), _PATH_UMOUNT);
|
|
||||||
fflush(stdout);
|
|
||||||
|
|
||||||
execlp("umount", UMOUNT_ARGS, NULL);
|
|
||||||
my_puts(_("Cannot exec umount, giving up on umount."));
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
while ((result = wait(&status)) != -1 && result != pid)
|
|
||||||
;
|
|
||||||
my_puts(_("Unmounting any remaining filesystems..."));
|
|
||||||
unmount_disks_ourselves();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
unmount_disks_ourselves(void)
|
|
||||||
{
|
|
||||||
/* unmount all disks */
|
|
||||||
|
|
||||||
FILE *mtab;
|
|
||||||
struct mntent *mnt;
|
|
||||||
char *mntlist[128];
|
|
||||||
int i;
|
|
||||||
int n;
|
|
||||||
char *filesys;
|
|
||||||
|
|
||||||
sync();
|
|
||||||
if (!(mtab = setmntent(_PATH_MOUNTED, "r"))) {
|
|
||||||
my_puts("shutdown: Cannot open " _PATH_MOUNTED ".");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
n = 0;
|
|
||||||
while (n < 100 && (mnt = getmntent(mtab))) {
|
|
||||||
/*
|
|
||||||
* Neil Phillips: trying to unmount temporary / kernel
|
|
||||||
* filesystems is pointless and may cause error messages;
|
|
||||||
* /dev can be a ramfs managed by udev.
|
|
||||||
*/
|
|
||||||
if (strcmp(mnt->mnt_type, "devfs") == 0 ||
|
|
||||||
strcmp(mnt->mnt_type, "proc") == 0 ||
|
|
||||||
strcmp(mnt->mnt_type, "sysfs") == 0 ||
|
|
||||||
strcmp(mnt->mnt_type, "ramfs") == 0 ||
|
|
||||||
strcmp(mnt->mnt_type, "tmpfs") == 0 ||
|
|
||||||
strcmp(mnt->mnt_type, "devpts") == 0)
|
|
||||||
continue;
|
|
||||||
mntlist[n++] = strdup(mnt->mnt_dir);
|
|
||||||
}
|
|
||||||
endmntent(mtab);
|
|
||||||
|
|
||||||
/* we are careful to do this in reverse order of the mtab file */
|
|
||||||
|
|
||||||
for (i = n - 1; i >= 0; i--) {
|
|
||||||
filesys = mntlist[i];
|
|
||||||
#ifdef DEBUGGING
|
|
||||||
printf("umount %s\n", filesys);
|
|
||||||
#else
|
|
||||||
if (umount(mntlist[i]) < 0)
|
|
||||||
printf(_("shutdown: Couldn't umount %s: %s\n"),
|
|
||||||
filesys, ERRSTRING);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void kill_mortals (int sig)
|
|
||||||
{
|
|
||||||
int npids = 0;
|
|
||||||
int index = 0;
|
|
||||||
int pid;
|
|
||||||
struct stat statbuf;
|
|
||||||
DIR *dp;
|
|
||||||
struct dirent *de;
|
|
||||||
pid_t *pids = NULL;
|
|
||||||
char path[256];
|
|
||||||
|
|
||||||
if ( ( dp = opendir ("/proc") ) == NULL ) return;
|
|
||||||
while ( ( de = readdir (dp) ) != NULL )
|
|
||||||
{
|
|
||||||
if ( !isdigit (de->d_name[0]) ) continue;
|
|
||||||
pid = atoi (de->d_name);
|
|
||||||
sprintf (path, "/proc/%d", pid);
|
|
||||||
if (stat (path, &statbuf) != 0) continue;
|
|
||||||
if (statbuf.st_uid < 100) continue;
|
|
||||||
if (index <= npids)
|
|
||||||
{
|
|
||||||
pids = realloc (pids, npids + 16384);
|
|
||||||
if (pids == NULL) return;
|
|
||||||
npids += 16384;
|
|
||||||
}
|
|
||||||
pids[index++] = pid;
|
|
||||||
}
|
|
||||||
fputs ("Sending SIGTERM to mortals...", stderr);
|
|
||||||
for (--index; index >= 0; --index) kill (pids[index], sig);
|
|
||||||
free (pids);
|
|
||||||
closedir (dp);
|
|
||||||
} /* End Function kill_mortals */
|
|
||||||
|
|
||||||
static void stop_finalprog (void)
|
|
||||||
{
|
|
||||||
char *p1, *p2;
|
|
||||||
FILE *fp;
|
|
||||||
char line[256];
|
|
||||||
|
|
||||||
if ( ( fp = fopen (_PATH_INITTAB, "r") ) == NULL ) return;
|
|
||||||
while (fgets (line, 256, fp) != NULL)
|
|
||||||
{
|
|
||||||
pid_t pid;
|
|
||||||
|
|
||||||
line[strlen (line) - 1] = '\0';
|
|
||||||
p1 = line;
|
|
||||||
while ( isspace (*p1) ) ++p1;
|
|
||||||
if (strncmp (p1, "finalprog", 9) != 0) continue;
|
|
||||||
if ( ( p1 = strchr (p1 + 9, '=') ) == NULL ) continue;
|
|
||||||
for (++p1; isspace (*p1); ++p1);
|
|
||||||
if (*p1 == '\0') continue;
|
|
||||||
for (p2 = p1; !isspace (*p2); ++p2);
|
|
||||||
*p2 = '\0';
|
|
||||||
switch ( pid = fork () )
|
|
||||||
{
|
|
||||||
case 0: /* Child */
|
|
||||||
execl (p1, p1, "stop", NULL);
|
|
||||||
break;
|
|
||||||
case -1: /* Error */
|
|
||||||
break;
|
|
||||||
default: /* Parent */
|
|
||||||
waitpid (pid, NULL, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
fclose (fp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
fclose (fp);
|
|
||||||
} /* End Function stop_finalprog */
|
|
||||||
|
|
||||||
static void syncwait (int timeval)
|
|
||||||
{
|
|
||||||
static int do_wait = 0;
|
|
||||||
static int first_time = 1;
|
|
||||||
|
|
||||||
sync ();
|
|
||||||
/* Kernel version 1.3.20 and after are supposed to wait automatically */
|
|
||||||
if (first_time)
|
|
||||||
{
|
|
||||||
struct utsname uts;
|
|
||||||
|
|
||||||
first_time = 0;
|
|
||||||
uname (&uts);
|
|
||||||
if (uts.release[0] < '2') do_wait = 1;
|
|
||||||
}
|
|
||||||
if (do_wait) sleep (timeval);
|
|
||||||
} /* End Function syncwait */
|
|
|
@ -1,180 +0,0 @@
|
||||||
.\" Copyright 1992, 1993 Rickard E. Faith (faith@cs.unc.edu)
|
|
||||||
.\" May be distributed under the GNU General Public License
|
|
||||||
.\" " for emacs's hilit19 mode :-)
|
|
||||||
.TH SIMPLEINIT 8 "25 February 2001" "Linux 0.99" "Linux Programmer's Manual"
|
|
||||||
.SH NAME
|
|
||||||
simpleinit \- process control initialization
|
|
||||||
.SH SYNOPSIS
|
|
||||||
.B init
|
|
||||||
.RB [ single ]
|
|
||||||
.RI [ script ]
|
|
||||||
.SH DESCRIPTION
|
|
||||||
.B init
|
|
||||||
is invoked as the last step in the Linux boot sequence. If the
|
|
||||||
.B single
|
|
||||||
option is used, or if the file
|
|
||||||
.I /etc/singleboot
|
|
||||||
exists, then single user mode will be entered, by starting
|
|
||||||
.IR /bin/sh .
|
|
||||||
If the file
|
|
||||||
.I /etc/securesingle
|
|
||||||
exists, then the root password will be required to start single user mode.
|
|
||||||
If the root password does not exist, or if
|
|
||||||
.I /etc/passwd
|
|
||||||
does not exist, the checking of the password will be skipped.
|
|
||||||
|
|
||||||
If the file
|
|
||||||
.I /etc/TZ
|
|
||||||
exists, then the contents of that file will be read, and used to set the TZ
|
|
||||||
environment variable for each process started by
|
|
||||||
.BR simpleinit .
|
|
||||||
This "feature" is only available if it's configured at compile-time. It's
|
|
||||||
not normally needed.
|
|
||||||
|
|
||||||
After single user mode is terminated, the
|
|
||||||
.I /etc/rc
|
|
||||||
file is executed, and the information in
|
|
||||||
.I /etc/inittab
|
|
||||||
will be used to start processes. Alternatively, the \fI/etc/inittab\fP
|
|
||||||
file may be configured to run a different boot script. See below for
|
|
||||||
details.
|
|
||||||
|
|
||||||
.SH "THE INITTAB FILE"
|
|
||||||
Because of the number of init programs which are appearing in the Linux
|
|
||||||
community, the documentation for the
|
|
||||||
.I /etc/inittab
|
|
||||||
file, which is usually found with the
|
|
||||||
.BR inittab (5)
|
|
||||||
man page, is presented here:
|
|
||||||
|
|
||||||
The format is
|
|
||||||
|
|
||||||
.RS
|
|
||||||
.B bootprog=file
|
|
||||||
|
|
||||||
.B fileprefix=string
|
|
||||||
|
|
||||||
.B PATH=search path
|
|
||||||
|
|
||||||
.B INIT_PATH=search path
|
|
||||||
|
|
||||||
.B "ttyline:termcap-entry:getty-command"
|
|
||||||
|
|
||||||
.B finalprog=path
|
|
||||||
.RE
|
|
||||||
|
|
||||||
An example is as follows:
|
|
||||||
|
|
||||||
.nf
|
|
||||||
.RS
|
|
||||||
bootprog =
|
|
||||||
fileprefix = /sbin/init.d/
|
|
||||||
PATH = /usr/sbin:/usr/bin:/sbin:/bin
|
|
||||||
INIT_PATH = /sbin/init.d
|
|
||||||
|
|
||||||
tty1:linux:/sbin/getty 9600 tty1
|
|
||||||
tty2:linux:/sbin/getty 9600 tty2
|
|
||||||
tty3:linux:/sbin/getty 9600 tty3
|
|
||||||
tty4:linux:/sbin/getty 9600 tty4
|
|
||||||
# tty5:linux:/sbin/getty 9600 tty5
|
|
||||||
# ttyS1:dumb:/sbin/getty 9600 ttyS1
|
|
||||||
# ttyS2:dumb:/sbin/getty -m -t60 2400 ttyS2
|
|
||||||
|
|
||||||
finalprog = /sbin/rc.xdm
|
|
||||||
.RE
|
|
||||||
.fi
|
|
||||||
|
|
||||||
Lines beginning with the
|
|
||||||
.B #
|
|
||||||
character are treated as comments. Please see documentation for the
|
|
||||||
.BR getty (8)
|
|
||||||
command that you are using, since there are several of these in the Linux
|
|
||||||
community at this time.
|
|
||||||
|
|
||||||
The \fBbootprog\fP value is appended to the \fBfileprefix\fP value,
|
|
||||||
and the result specifies the boot programme (script) to run. If
|
|
||||||
unspecified, the default is \fI/etc/rc\fP. If the boot programme is a
|
|
||||||
directory, then all scripts in that directory tree are executed, in
|
|
||||||
parallel. See the \fBneed\fP(8) programme for details on how to
|
|
||||||
elegantly control order of execution and manage dependencies.
|
|
||||||
|
|
||||||
The \fBPATH\fP value is assigned to the PATH environment variable of
|
|
||||||
child processes (boot scripts).
|
|
||||||
|
|
||||||
The \fBINIT_PATH\fP value is used by simpleinit(8) itself to find the
|
|
||||||
location of scripts to run (if an absolute path is not given). If
|
|
||||||
unset and the boot programme is a directory, that directory is used.
|
|
||||||
Finally, if the script cannot be found in this path, the standard
|
|
||||||
\fBPATH\fP is used. This separation allows boot scripts to invoke
|
|
||||||
programmes of the same name without conflict and without needing to
|
|
||||||
specify absolute paths.
|
|
||||||
|
|
||||||
The \fBfinalprog\fP value specifies the path of the programme to run
|
|
||||||
after all \fBgetty\fP(8) instances are spawned. At bootup, it is
|
|
||||||
passed a single argument: "start". At shutdown, it is called again,
|
|
||||||
this time with the argument: "stop".
|
|
||||||
.SH SIGNALS
|
|
||||||
\fBsimpleinit\fP(8) responds to signals in a variety of ways:
|
|
||||||
.TP
|
|
||||||
.B SIGHUP
|
|
||||||
The \fI/etc/inittab\fP configuration file will be read again.
|
|
||||||
.TP
|
|
||||||
.B SIGTSTP
|
|
||||||
This flips a toggle, which controls whether more processes will be
|
|
||||||
spawned.
|
|
||||||
.TP
|
|
||||||
.B SIGINT
|
|
||||||
\fBsimpleinit\fP(8) will sync a few times, and try to start
|
|
||||||
\fBreboot\fP(8). Failing this, it will execute the system
|
|
||||||
\fBreboot\fP(2) call. Under Linux, it is possible to configure the
|
|
||||||
Ctrl-Alt-Del sequence to send a signal to the \fBinit\fP process
|
|
||||||
instead of rebooting the system (\fBsimpleinit\fP(8) does this by
|
|
||||||
default).
|
|
||||||
.TP
|
|
||||||
.B SIGQUIT
|
|
||||||
The \fBreboot\fP(8) programme is executed in place of the
|
|
||||||
\fBsimpleinit\fP(8) programme. This allows \fBreboot\fP(8) to cleanly
|
|
||||||
remount (read-only) the root filesystem, even if the old inode for the
|
|
||||||
\fBinit\fP process was unlinked.
|
|
||||||
.SH FILES
|
|
||||||
.I /etc/inittab
|
|
||||||
.br
|
|
||||||
.I /etc/singleboot
|
|
||||||
.br
|
|
||||||
.I /etc/securesingle
|
|
||||||
.br
|
|
||||||
.I /etc/TZ
|
|
||||||
.br
|
|
||||||
.I /etc/passwd
|
|
||||||
.br
|
|
||||||
.I /etc/rc
|
|
||||||
.SH "SEE ALSO"
|
|
||||||
.BR inittab (5),
|
|
||||||
.BR ctrlaltdel (8)
|
|
||||||
.BR reboot (8),
|
|
||||||
.BR termcap (5),
|
|
||||||
.BR getty (8),
|
|
||||||
.BR agetty (8),
|
|
||||||
.BR shutdown (8),
|
|
||||||
.BR initctl (8)
|
|
||||||
.SH BUGS
|
|
||||||
This program is called
|
|
||||||
.B simpleinit
|
|
||||||
to distinguish it from the System V compatible versions of init which are
|
|
||||||
starting to appear in the Linux community.
|
|
||||||
.B simpleinit
|
|
||||||
should be linked to, or made identical with,
|
|
||||||
.I init
|
|
||||||
for correct functionality.
|
|
||||||
.SH AUTHOR
|
|
||||||
Peter Orbaek (poe@daimi.aau.dk)
|
|
||||||
.br
|
|
||||||
Version 1.20, with patches for singleuser mode by Werner Almesberger
|
|
||||||
.br
|
|
||||||
Richard Gooch <rgooch@atnf.csiro.au>
|
|
||||||
.br
|
|
||||||
Dependency support
|
|
||||||
|
|
||||||
.SH AVAILABILITY
|
|
||||||
The simpleinit command is part of the util-linux package and is available from
|
|
||||||
ftp://ftp.kernel.org/pub/linux/utils/util-linux/.
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,28 +0,0 @@
|
||||||
#include <limits.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
|
|
||||||
#define ERRSTRING strerror (errno)
|
|
||||||
#define COMMAND_SIZE (PIPE_BUF - 4)
|
|
||||||
|
|
||||||
|
|
||||||
#define COMMAND_TEST 0 /* No wait, signal */
|
|
||||||
#define COMMAND_NEED 1 /* Wait, signal */
|
|
||||||
#define COMMAND_ROLLBACK 2 /* Wait, signal */
|
|
||||||
#define COMMAND_DUMP_LIST 3 /* No wait, no signal */
|
|
||||||
#define COMMAND_PROVIDE 4 /* Wait, signal */
|
|
||||||
|
|
||||||
#define SIG_PRESENT SIGUSR1 /* Service is available */
|
|
||||||
#define SIG_STOPPED SIGUSR1 /* Service was stopped OK */
|
|
||||||
#define SIG_NOT_PRESENT SIGUSR2 /* Not present, but that's OK */
|
|
||||||
#define SIG_FAILED SIGPOLL /* Startup failed */
|
|
||||||
#define SIG_NOT_STOPPED SIGPOLL /* Failed to stop */
|
|
||||||
#define SIG_NOT_CHILD SIGPOLL /* Not a child of init */
|
|
||||||
|
|
||||||
struct command_struct /* Must always be COMMAND_SIZE */
|
|
||||||
{
|
|
||||||
signed int command;
|
|
||||||
pid_t pid;
|
|
||||||
pid_t ppid;
|
|
||||||
char name[1];
|
|
||||||
};
|
|
Loading…
Reference in New Issue