diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2016-03-06 15:25:06 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2016-03-06 15:27:39 +0200 |
commit | 1a37a444eea3d238e45d01d47ac157b470f536ac (patch) | |
tree | 5a992298b9cdc93c31ffce6a7db302670e8eb0b9 /src | |
parent | ad5bd6e401657b9cb0fed04d15cdc6feeef91e15 (diff) | |
download | pies-1a37a444eea3d238e45d01d47ac157b470f536ac.tar.gz pies-1a37a444eea3d238e45d01d47ac157b470f536ac.tar.bz2 |
Reimplement the telinit legacy interface.
pies -T is now fully compatible with the legacy telinit command
* src/telinit.opt: New file.
* src/Makefile.am: Add telinit.opt
* src/cmdline.opt (-T): Remove explicit variable. Rest of
command line is processed specially.
* src/pies.h (telinit): Change prototype.
* src/sysvinit.c (telinit): Rewrite.
* src/.gitignore: Update.
* doc/pies.texi: Document telinit.
Diffstat (limited to 'src')
-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 | 28 | ||||
-rw-r--r-- | src/telinit.opt | 89 |
6 files changed, 111 insertions, 23 deletions
diff --git a/src/.gitignore b/src/.gitignore index a83b9ab..3bf90ef 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -5,6 +5,7 @@ meta1gram.h meta1gram.output meta1lex.c 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 @@ -38,26 +38,28 @@ pies_SOURCES = \ noinst_HEADERS = \ acl.h\ cmdline.h\ 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: $(AM_V_GEN)m4 -s $(top_srcdir)/@GRECS_SUBDIR@/build-aux/getopt.m4 $< > $@ cmdline.h: cmdline.opt piesctl-cl.h: piesctl-cl.opt +telinit.h: telinit.opt pies_LDADD = \ ../ident/libident.a\ ../lib/libpies.a\ @GRECS_LDADD@\ ../gnu/libgnu.a\ diff --git a/src/cmdline.opt b/src/cmdline.opt index 7d6f7d4..d8bd02f 100644 --- a/src/cmdline.opt +++ b/src/cmdline.opt @@ -109,17 +109,17 @@ OPTION(lint,t,, [<parse configuration file and exit>]) BEGIN log_to_stderr_only = 1; 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) OPTION(include-directory,I,DIR, [<add include directory>]) @@ -532,13 +532,13 @@ struct inetd_builtin *inetd_builtin_lookup (const char *service, int socktype); /* sysvinit.c */ 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); void sysvinit_sysdep_begin (void); void sysvinit_power (void); diff --git a/src/sysvinit.c b/src/sysvinit.c index a150058..9043619 100644 --- a/src/sysvinit.c +++ b/src/sysvinit.c @@ -526,12 +526,14 @@ sysvinit_fifo_handler (int fd, void *data) if (buf.req.magic != INIT_MAGIC) logmsg (LOG_ERR, _("got invalid initreq")); else { 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: buf.req.runlevel = toupper (buf.req.runlevel); switch (buf.req.runlevel) { @@ -904,49 +906,43 @@ is_comp_wait (struct component *comp) return 1; default: break; } 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); fd = open (init_fifo, O_WRONLY); 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 * getfld (char *str, char **endp) { char *p; 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; + } +} |