diff options
-rw-r--r-- | doc/pies.texi | 189 | ||||
-rw-r--r-- | src/.gitignore | 1 | ||||
-rw-r--r-- | src/Makefile.am | 8 | ||||
-rw-r--r-- | src/cmdline.opt | 6 | ||||
-rw-r--r-- | src/pies.h | 2 | ||||
-rw-r--r-- | src/sysvinit.c | 24 | ||||
-rw-r--r-- | src/telinit.opt | 89 |
7 files changed, 264 insertions, 55 deletions
diff --git a/doc/pies.texi b/doc/pies.texi index ae4a56a..1f162a2 100644 --- a/doc/pies.texi +++ b/doc/pies.texi @@ -1651,6 +1651,11 @@ component @var{tag} @{ # @xref{flags}. flags (@var{flags}); + # @r{For @i{init} components: runlevels in which to start this} + # @r{component.} + # @xref{Runlevels}. + runlevels @var{string}; + # @r{Listen on the given url.} # @xref{Inetd-Style Components}. socket @var{url}; @@ -1704,14 +1709,14 @@ component @var{tag} @{ # @xref{Inetd-Style Components, access-denied-message}. access-denied-message @var{text}; - # @r{ACL for administrative access to this component.} - # @FIXME-xref{Access to Components}. + # @r{ACL for administrative (read-write) access to this component.} + # @xref{Visibility}. admin-acl @var{name}; # @r{or:} admin-acl @{ @dots{} @} # @r{ACL for read-only access to this component.} - # @FIXME-xref{Access to Components}. + # @xref{Visibility}. list-acl @var{name}; # @r{or:} list-acl @{ @dots{} @} @@ -2149,29 +2154,40 @@ seconds. This statement is reserved for use in the future. Currently The control interface is protected by three access control lists (@xref{ACL}, for a discussion of their syntax). -@deffn {Config: control} acl - Controls who can connect to the control interface. +@deffn {Config: control} acl @var{name} +@deffnx {Config: control} acl @{ @dots{} @} + Controls who can connect to the interface. The first form refers to +a named ACL that must have been defined earlier by @code{defacl} +statement (@pxref{defacl}). Use the second form to define a new ACL +in place. @end deffn -@deffn {Config: control} user-acl +@deffn {Config: control} user-acl @var{name} +@deffnx {Config: control} user-acl @{ @dots{} @} Control interface provides two kinds of operations: @dfn{read-only} (such as getting information about running components) and @dfn{write} operations (such as stopping or restarting components). - The @code{user-acl} controls read access to components that don't -have per-component @code{user-acl} (@FIXME-pxref{per-component user-acl}). + The @code{user-acl} controls read access. Access to particular +components can also be controlled individually, using the +per-component @code{list-acl} statement (@pxref{Visibility, list-acl}). @end deffn -@deffn {Config: control} admin-acl - Defines access control list for write access to the @command{pies} -instance itself and to the components for which no specific -@code{admin-acl} statements are supplied (@FIXME-pxref{per-component -admin-acl}). +@deffn {Config: control} admin-acl @var{name} +@deffnx {Config: control} admin-acl @{ @dots{} @} + Controls write access to the @command{pies} instance itself and to +the components for which no specific @code{admin-acl} statements are +supplied (@pxref{Visibility, admin-acl}). In particular, whoever passes @code{admin-acl} can issue commands for stopping the instance and reloading its configuration. @end deffn + When checking whether the user has a particular kind of access to a +component, first the corresponding ACL from the @code{control} section +is checked. If it allows access, then the per-component ACL is tried. +If it allows access too, then the operation is permitted. + @deffn {Config: control} realm @var{name} Defines the realm for basic authentication. Default value is @samp{pies}. @end deffn @@ -2454,6 +2470,15 @@ Sets the PID file name. Sets the name of the @samp{quotation-of-the-day} file. @end deffn +The following statements are retained for compatibility with earlier +@command{pies} versions. They are silently ignored: + +@deffn {Config} control-file @var{arg} +@end deffn + +@deffn {Config} stat-file @var{arg} +@end deffn + @node Pies Debugging @chapter Pies Debugging @xopindex{debug, described} @@ -2573,8 +2598,9 @@ UNIX socket for communication using @command{piesctl}. * Runlevels:: * Init Process Configuration:: * Init Command Line:: -* piesctl telinit:: * Init Environment:: +* piesctl telinit:: +* telinit command:: @end menu @node Runlevels @@ -2756,9 +2782,18 @@ Stop parsing after this line. The remaining material is ignored. Both the traditional @file{/etc/inittab} and pies-native @file{/etc/pies.init} files are entirely equivalent, excepting that, naturally, the latter is more flexible and gives much more -possibilities in defining the system behavior. The inittab entry -discussed above is equivalent to the following statement in -@file{pies.init} file: +possibilities in defining the system behavior. The declaration of a +component in @file{/etc/pies.init} can contain all the statements +discussed in @ref{Component Statement}. The only difference is that +runlevels to start the component is must be specified: + +@deffn {Config: component} runlevels @var{string} +Specifies the runlevel to start the component in. The @var{string} +argument is a string of runlevel characters. +@end deffn + +For example, the inittab entry discussed above is equivalent to the +following statement in @file{pies.init} file: @example component @var{id} @{ @@ -2768,6 +2803,18 @@ component @var{id} @{ @} @end example +The default runlevel is specified in @file{/etc/pies.init} using +the following construct: + +@deffn {Config} initdefault @var{rl} +Declare the default runlevel. The argument is the runlevel name. +E.g. + +@example +initdefault 3; +@end example +@end deffn + If both @file{/etc/inittab} and @file{/etc/pies.init} are present, the latter can declare components with the same @var{id} as the ones declared in the former. In that case, the two entries will be merged, @@ -2822,6 +2869,32 @@ Initialize default runlevel @samp{S}. Run emergency shell @command{/sbin/sulogin}, prior to initialization. @end table +@node Init Environment +@section Init Environment + +Programs run from @command{pies} init process inherit a basic +environment consisting of the following variables: + +@table @option +@item PREVLEVEL=@var{L} +Previous runlevel, or letter @samp{N} if the runlevel hasn't been +changed since startup. + +@item RUNLEVEL=@var{L} +Current runlevel. + +@item CONSOLE=@var{device} +Pathname of the console device file. + +@item INIT_VERSION="GNU Pies @value{VERSION}" +Version of @command{pies}. + +@item PATH=/bin:/usr/bin:/sbin:/usr/sbin +@end table + +Once the system is booted up, the environment can be controlled using +the @command{piesctl telinit environ} (or @command{pies -T -e}) command. + @node piesctl telinit @section piesctl telinit @@ -2847,32 +2920,73 @@ hold at most 32 variables. Unset variable @var{NAME}. @end deffn -@node Init Environment -@section Init Environment +@node telinit command +@section The Telinit Command -Programs run from @command{pies} init process inherit a basic -environment consisting of the following variables: +@xopindex{telinit option, introduced} + When given the @option{-T} (@option{--telinit}) option, +@command{pies} emulates the behavior of the traditional +@command{telinit} command. This is a legacy way of communicating with +the init process. The commands are sent via named pipe +@file{/dev/initctl}. When the @option{-T} option is given, the rest +of command line after it is handled as @command{telinit} options. The +following command: -@table @option -@item PREVLEVEL=@var{L} -Previous runlevel, or letter @samp{N} if the runlevel hasn't been -changed since startup. +@example +pies -T [-t @var{n}] @var{r} +@end example -@item RUNLEVEL=@var{L} -Current runlevel. +@noindent +tells init process to switch to runlevel @var{r}. Possible values for +@var{r} are: -@item CONSOLE=@var{device} -Pathname of the console device file. +@table @asis +@item 0 to 9 +Instructs init to switch to the specified runlevel. +@item S or s +Tells init to switch to the single user mode. +@item a, b, or c +Tells init to enable on-demand components with the specified +runlevel. The actual runlevel is not changed. +@item Q or q +Tells init to rescan configuration files. +@end table -@item INIT_VERSION="GNU Pies @value{VERSION}" -Version of @command{pies}. +The @option{-t} (@option{--timeout}) option sets the time to wait +for processes to terminate after sending them the SIGTERM signal. Any +processes that remain running after @var{n} seconds will be sent the +SIGKILL signal. The default value is 5 seconds. -@item PATH=/bin:/usr/bin:/sbin:/usr/sbin -@end table +This usage is equivalent to the @command{piesctl telinit runlevel} +command (@pxref{piesctl telinit}). -Once the system is booted up, the environment can be controlled using +The @option{-e} (@option{--environment}) option modifies the init +process environment. Its argument is either a variable assignment +@samp{@var{name}=@var{value}} to set a variable, or the name of a +variable to unset it. Several @option{-e} options can be given to +process multiple variables in a single command. Note, however, that +given @var{n} @option{-e} options, the total length of their arguments +is limited to 367 - @var{n} bytes. + +This option provides a limited subset of the functionality offered by the @command{piesctl telinit environ} command. +The table below summarizes all options available in @option{telinit} +mode: + +@table @option +@item -t @var{n} +Wait @var{n} seconds for processes to terminate after sending them the +SIGTERM signal. Any processes that remain running after that time +will be sent the SIGKILL signal. The default value is 5 seconds. + +@item -e @var{var}=@var{value} +Define environment variable @var{var} as having value @var{value}. + +@item -e @var{var} +Unset environment variable @var{var}. +@end table + @node Configuration Examples @chapter Configuration Examples In this section we provide several examples of working @command{pies} @@ -3243,6 +3357,13 @@ arguments, dependencies for each component are listed. @xref{trace-depend}. List prerequisites for components named in the command line. Without arguments, prerequisites for each component are listed. @xref{trace-prereq}. +@opsummary{telinit} +@item --telinit +@item -T +Emulate the @command{telinit} legacy interface. The rest of command +line following this option is processed as @command{telinit} options. +@xref{telinit command}, for a detailed description of these. + @item -E Preprocess configuration file and exit. @xref{Preprocessor}. diff --git a/src/.gitignore b/src/.gitignore index a83b9ab..3bf90ef 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -8,3 +8,4 @@ pies pies.rc piesctl piesctl-cl.h +telinit.h diff --git a/src/Makefile.am b/src/Makefile.am index 6515804..b0e9b6f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -41,13 +41,14 @@ noinst_HEADERS = \ meta1parse.h\ pies.h\ prog.h\ - piesctl-cl.h + piesctl-cl.h\ + telinit.h -BUILT_SOURCES=cmdline.h piesctl-cl.h +BUILT_SOURCES=cmdline.h piesctl-cl.h telinit.h incdir=$(pkgdatadir)/$(VERSION)/include inc_DATA = pp-setup -EXTRA_DIST = cmdline.opt piesctl-cl.opt pp-setup inetd.in +EXTRA_DIST = cmdline.opt piesctl-cl.opt telinit.opt pp-setup inetd.in SUFFIXES=.opt .c .h .opt.h: @@ -55,6 +56,7 @@ SUFFIXES=.opt .c .h cmdline.h: cmdline.opt piesctl-cl.h: piesctl-cl.opt +telinit.h: telinit.opt pies_LDADD = \ ../ident/libident.a\ diff --git a/src/cmdline.opt b/src/cmdline.opt index 7d6f7d4..d8bd02f 100644 --- a/src/cmdline.opt +++ b/src/cmdline.opt @@ -112,11 +112,11 @@ BEGIN lint_mode = 1; END -OPTION(telinit,T,RUNLEVEL, - [<emulate telinit command>]) +OPTION(telinit,T,, + [<telinit command: run "pies -T --help" for help>]) BEGIN log_to_stderr_only = 1; - exit (telinit (optarg)); + exit (telinit (argc - (optind - 1), argv + (optind - 1))); END GROUP(Preprocessor) @@ -535,7 +535,7 @@ void sysvinit_begin (void); int is_comp_wait (struct component *comp); int is_valid_runlevel (int c); int console_open (int mode); -int telinit (const char *arg); +int telinit (int argc, char **argv); int inittab_parse (const char *file); int sysvinit_sigtrans (int sig, int *pact); void sysvinit_runlevel_setup (int mask); diff --git a/src/sysvinit.c b/src/sysvinit.c index a150058..9043619 100644 --- a/src/sysvinit.c +++ b/src/sysvinit.c @@ -529,6 +529,8 @@ sysvinit_fifo_handler (int fd, void *data) { debug (1, ("INITREQ: cmd=%d, runlevel=%d, sleeptime=%d", buf.req.cmd, buf.req.runlevel, buf.req.sleeptime)); + if (buf.req.sleeptime > 0) + shutdown_timeout = buf.req.sleeptime; switch (buf.req.cmd) { case INIT_CMD_RUNLVL: @@ -908,24 +910,18 @@ is_comp_wait (struct component *comp) return 0; } +#include "telinit.h" + int -telinit (const char *arg) +telinit (int argc, char **argv) { int fd; struct sysvinit_request req; - if (arg[1] || !is_valid_runlevel (*arg)) - { - logmsg (LOG_CRIT, "invalid argument"); - exit (EX_USAGE); - } memset (&req, 0, sizeof (req)); req.magic = INIT_MAGIC; - req.cmd = INIT_CMD_RUNLVL; - req.runlevel = *arg; -#if 0 - req.sleeptime = sltime; -#endif + + telinit_parser (&req, argc, argv); signal (SIGALRM, SIG_DFL); alarm (5); @@ -933,17 +929,17 @@ telinit (const char *arg) if (fd < 0) { logmsg (LOG_ERR, _("cannot open %s: %s"), init_fifo, strerror (errno)); - exit (EX_UNAVAILABLE); + return EX_UNAVAILABLE; } if (write (fd, &req, sizeof (req)) != sizeof (req)) { logmsg (LOG_ERR, _("error writing to %s: %s"), init_fifo, strerror (errno)); - exit (EX_UNAVAILABLE); + return EX_UNAVAILABLE; } alarm (0); close (fd); - exit (0); + return 0; } static char * diff --git a/src/telinit.opt b/src/telinit.opt new file mode 100644 index 0000000..f052a53 --- /dev/null +++ b/src/telinit.opt @@ -0,0 +1,89 @@ +/* This file is part of GNU Pies. -*- c -*- + Copyright (C) 2016 Sergey Poznyakoff + + GNU Pies 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 3, or (at your option) + any later version. + + GNU Pies 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 GNU Pies. If not, see <http://www.gnu.org/licenses/>. */ + +OPTIONS_COMMAND_BEGIN("pies", + [<>], + [<send command to init process via the legacy interface>], + [<[RUNLEVEL]>], + [<gnu>], + [<noversion>]) + +OPTION(timeout,t,[<SECONDS>], + [<set interval between sending TERM and KILL signals>]) +BEGIN + char *p; + errno = 0; + shutdown_timeout = strtoul (optarg, &p, 0); + if (*p || errno) + { + logmsg (LOG_ERR, _("invalid number: %s"), optarg); + exit (EX_USAGE); + } +END + +OPTION(environment,e,[<VAR=[VAL]>],[<change environment>]) +BEGIN + size_t len = strlen (optarg); + if (envsize + len + 2 > sizeof(req->data)) + { + logmsg (LOG_ERR, _("-e argument too long")); + exit (EX_USAGE); + } + memcpy (req->data + envsize, optarg, len); + envsize += len; + req->data[envsize++] = 0; +END + +OPTIONS_END + +static void +telinit_parser (struct sysvinit_request *req, int argc, char *argv[]) +{ + int i; + char *cmds[] = { "-T", NULL }; + size_t envsize = 0; + + proginfo.subcmd = cmds; + GETOPT(argc, argv, i); + argc -= i; + argv += i; + if (envsize) + { + req->data[envsize++] = 0; + req->cmd = INIT_CMD_SETENV; + if (argc) + { + logmsg (LOG_ERR, _("too many arguments")); + exit (EX_USAGE); + } + } + else + { + if (argc != 1) + { + logmsg (LOG_ERR, _("bad number of arguments")); + exit (EX_USAGE); + } + if (argv[0][1] || !is_valid_runlevel (argv[0][0])) + { + logmsg (LOG_ERR, _("invalid runlevel: %s"), argv[0]); + exit (EX_USAGE); + } + req->cmd = INIT_CMD_RUNLVL; + req->runlevel = argv[0][0]; + req->sleeptime = shutdown_timeout; + } +} |