From f69ea1f550f84455c6c58673ed76d92794482de2 Mon Sep 17 00:00:00 2001 From: Werner Fink Date: Tue, 23 Mar 2010 14:37:01 +0000 Subject: [PATCH] * Add fix for Debian bug #536574 -- Can be enabled by -DACCTON_OFF * Add helper program fstab-decode to make it easier to handle /etc/mtab content. Patch by Miloslav Trmac and Fedora. * Add fix for Debian bug #335023 - Make sure TERM is set on FreeBSD. * Add fix for Debian bug #374038 - Make it clear that shutdown -c can only cancel a waiting shutdown, not an active one. * Add not to pidof manual page about the use of readlink(2). Patch by Bill Nottingham and Fedora. * Add changes for Debian bug #68621 - Add PAM support for programs spawned by init on the console like sulogin. Based on patch by Topi Miettinen. --- doc/Changelog | 10 ++++++ man/fstab-decode.8 | 45 ++++++++++++++++++++++++ man/pidof.8 | 6 +++- man/shutdown.8 | 7 ++-- src/Makefile | 42 ++++++++++++++-------- src/bootlogd.c | 3 ++ src/fstab-decode.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++ src/ifdown.c | 24 +++++++++++-- src/init.c | 42 ++++++++++++++++++++-- src/shutdown.c | 19 +++++++++- src/utmpdump.c | 4 +++ 11 files changed, 263 insertions(+), 25 deletions(-) create mode 100644 man/fstab-decode.8 create mode 100644 src/fstab-decode.c diff --git a/doc/Changelog b/doc/Changelog index 45e2d42..1c707b4 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -57,6 +57,16 @@ sysvinit (2.88dsf) UNRELEASED; urgency=low * sulogin - add the possibility to reset the terminal io * Fix some minor problems * init - enable is_selinux_enabled() to detect selinuxfs + * Add fix for Debian bug #536574 -- Can be enabled by -DACCTON_OFF + * Add helper program fstab-decode to make it easier to handle + /etc/mtab content. Patch by Miloslav Trmac and Fedora. + * Add fix for Debian bug #335023 - Make sure TERM is set on FreeBSD. + * Add fix for Debian bug #374038 - Make it clear that shutdown -c can + only cancel a waiting shutdown, not an active one. + * Add not to pidof manual page about the use of readlink(2). Patch by + Bill Nottingham and Fedora. + * Add changes for Debian bug #68621 - Add PAM support for programs spawned + by init on the console like sulogin. Based on patch by Topi Miettinen. -- Petter Reinholdtsen Sun, 12 Jul 2009 19:58:10 +0200 diff --git a/man/fstab-decode.8 b/man/fstab-decode.8 new file mode 100644 index 0000000..6e80021 --- /dev/null +++ b/man/fstab-decode.8 @@ -0,0 +1,45 @@ +.\" A man page for fstab-decode(8). +.\" +.\" Copyright (C) 2006 Red Hat, Inc. All rights reserved. +.\" +.\" This copyrighted material is made available to anyone wishing to use, +.\" modify, copy, or redistribute it subject to the terms and conditions of the +.\" GNU General Public License v.2. +.\" +.\" 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., +.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +.\" +.\" Author: Miloslav Trmac +.TH fstab-decode 8 "May 2006" + +.SH NAME +fstab-decode \- run a command with fstab-encoded arguments + +.SH SYNOPSIS +\fB fstab-decode\fR \fICOMMAND\fR [\fIARGUMENT\fR]... + +.SH DESCRIPTION +.B fstab-decode +decodes escapes in the specified \FIARGUMENT\fRs +and uses them to run \fICOMMAND\fR. +The argument escaping uses the same rules as path escaping in +\fB/etc/fstab\fR, +.B /etc/mtab +and \fB/proc/mtab\fR. + +.SH EXIT STATUS +.B fstab-decode +exits with status 127 if +.I COMMAND +can't be run. +Otherwise it exits with the status returned by \fICOMMAND\fR. + +.SH EXAMPLES + +.B fstab-decode umount $(awk '$3 == "vfat" { print $2 }' /etc/fstab) diff --git a/man/pidof.8 b/man/pidof.8 index 28db5c1..276a93c 100644 --- a/man/pidof.8 +++ b/man/pidof.8 @@ -77,7 +77,11 @@ the program behaves according to the name under which it is called. When \fIpidof\fP is invoked with a full pathname to the program it should find the pid of, it is reasonably safe. Otherwise it is possible that it returns pids of running programs that happen to have the same name -as the program you're after but are actually other programs. +as the program you're after but are actually other programs. Note that +that the executable name of running processes is calculated with +.BR readlink (2), +so symbolic links to executables will also match. + .SH SEE ALSO .BR shutdown (8), .BR init (8), diff --git a/man/shutdown.8 b/man/shutdown.8 index 8122e9a..919a77e 100644 --- a/man/shutdown.8 +++ b/man/shutdown.8 @@ -93,9 +93,10 @@ you'd expect. .\"}}} .\"{{{ -c .IP \fB\-c\fP -Cancel an already running shutdown. With this option it is of course -not possible to give the \fBtime\fP argument, but you can enter a -explanatory message on the command line that will be sent to all users. +Cancel a waiting shutdown. ("shutdown now" is no longer waiting.) With +this option it is of course not possible to give the time argument, but +you can enter explanatory message arguments on the command line that +will be sent to all users. .\"}}} .\"{{{ -t sec .IP "\fB\-t\fP \fIsec\fP" diff --git a/src/Makefile b/src/Makefile index a086198..35c9712 100644 --- a/src/Makefile +++ b/src/Makefile @@ -8,19 +8,20 @@ # Version: @(#)Makefile 2.85-13 23-Mar-2004 miquels@cistron.nl # +CPPFLAGS = -DUSE_PAM CFLAGS ?= -ansi -O2 -fomit-frame-pointer -CFLAGS += -W -Wall -D_GNU_SOURCE +override CFLAGS += -W -Wall -D_GNU_SOURCE STATIC = # For some known distributions we do not build all programs, otherwise we do. BIN = -SBIN = init halt shutdown runlevel killall5 +SBIN = init halt shutdown runlevel killall5 fstab-decode USRBIN = last mesg MAN1 = last.1 lastb.1 mesg.1 MAN5 = initscript.5 inittab.5 MAN8 = halt.8 init.8 killall5.8 pidof.8 poweroff.8 reboot.8 runlevel.8 -MAN8 += shutdown.8 telinit.8 +MAN8 += shutdown.8 telinit.8 fstab-decode.8 ifeq ($(DISTRO),) BIN += mountpoint @@ -31,6 +32,7 @@ MAN8 += sulogin.8 bootlogd.8 endif ifeq ($(DISTRO),Debian) +CPPFLAGS+= -DACCTON_OFF BIN += mountpoint SBIN += sulogin bootlogd MAN1 += mountpoint.1 @@ -43,6 +45,7 @@ MAN1 += wall.1 endif ifeq ($(DISTRO),SuSE) +CPPFLAGS+= -DUSE_SYSFS -DSANE_TIO -DSIGINT_ONLYONCE BIN += mountpoint SBIN += sulogin USRBIN += utmpdump @@ -50,28 +53,39 @@ MAN1 += utmpdump.1 mountpoint.1 MAN8 += sulogin.8 endif +ID = $(shell id -u) BIN_OWNER = root BIN_GROUP = root BIN_COMBO = $(BIN_OWNER):$(BIN_GROUP) STRIP = strip -s -R .comment -INSTALL_EXEC = install -o $(BIN_OWNER) -g $(BIN_GROUP) -m 755 -INSTALL_DATA = install -o $(BIN_OWNER) -g $(BIN_GROUP) -m 644 +ifeq ($(ID),0) + INSTALL_EXEC = install -o $(BIN_OWNER) -g $(BIN_GROUP) -m 755 + INSTALL_DATA = install -o $(BIN_OWNER) -g $(BIN_GROUP) -m 644 +else + INSTALL_EXEC = install -m 755 + INSTALL_DATA = install -m 644 +endif INSTALL_DIR = install -m 755 -d MANDIR = /usr/share/man ifeq ($(WITH_SELINUX),yes) - SELINUX_DEF=-DWITH_SELINUX - INIT_SELIBS=-lsepol -lselinux - SULOGIN_SELIBS=-lselinux + SELINUX_DEF = -DWITH_SELINUX + INITLIBS += -lsepol -lselinux + SULOGINLIBS = -lselinux else - SELINUX_DEF= - INIT_SELIBS= - SULOGIN_SELIBS= + SELINUX_DEF = + INITLIBS = + SULOGINLIBS = +endif + +# Additional libs for GNU libc. +ifneq ($(findstring -DUSE_PAM,$(CPPFLAGS)),) + INITLIBS += -lpam -lpam_misc endif # Additional libs for GNU libc. ifneq ($(wildcard /usr/lib*/libcrypt.a),) -LCRYPT = -lcrypt + SULOGINLIBS += -lcrypt endif all: $(BIN) $(SBIN) $(USRBIN) @@ -81,7 +95,7 @@ all: $(BIN) $(SBIN) $(USRBIN) #%.o: %.c # $(CC) $(CFLAGS) $(CPPFLAGS) -c $^ -o $@ -init: LDLIBS += $(INIT_SELIBS) $(STATIC) +init: LDLIBS += $(INITLIBS) $(STATIC) init: init.o init_utmp.o halt: halt.o ifdown.o hddown.o utmp.o reboot.h @@ -96,7 +110,7 @@ utmpdump: utmpdump.o runlevel: runlevel.o -sulogin: LDLIBS += $(LCRYPT) $(SULOGIN_SELIBS) $(STATIC) +sulogin: LDLIBS += $(SULOGINLIBS) $(STATIC) sulogin: sulogin.o wall: dowall.o wall.o diff --git a/src/bootlogd.c b/src/bootlogd.c index 6ee982a..570d382 100644 --- a/src/bootlogd.c +++ b/src/bootlogd.c @@ -263,6 +263,9 @@ int consolename(char *res, int rlen) } #ifdef TIOCGDEV +# ifndef ENOIOCTLCMD +# define ENOIOCTLCMD 515 +# endif if (ioctl(0, TIOCGDEV, &kdev) == 0) { int r = findtty(res, "/dev", rlen, (dev_t)kdev); if (0 != r) diff --git a/src/fstab-decode.c b/src/fstab-decode.c new file mode 100644 index 0000000..4a162df --- /dev/null +++ b/src/fstab-decode.c @@ -0,0 +1,86 @@ +/* fstab-decode(8). + +Copyright (c) 2006 Red Hat, Inc. All rights reserved. + +This copyrighted material is made available to anyone wishing to use, modify, +copy, or redistribute it subject to the terms and conditions of the GNU General +Public License v.2. + +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., 51 Franklin +Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Author: Miloslav Trmac */ + +#include +#include +#include +#include +#include + +/* Decode the fstab-encoded string in place. */ +static void +decode(char *s) +{ + const char *src; + char *dest; + + src = s; + dest = s; + while (*src != '\0') { + if (*src != '\\') + *dest = *src++; + else { + static const struct repl { + char orig[4]; + size_t len; + char new; + } repls[] = { +#define R(X, Y) { X, sizeof(X) - 1, Y } + R("\\", '\\'), + R("011", '\t'), + R("012", '\n'), + R("040", ' '), + R("134", '\\') +#undef R + }; + + size_t i; + + for (i = 0; i < sizeof (repls) / sizeof (repls[0]); + i++) { + if (memcmp(src + 1, repls[i].orig, + repls[i].len) == 0) { + *dest = repls[i].new; + src += 1 + repls[i].len; + goto found; + } + } + *dest = *src++; + found: + ; + } + dest++; + } + *dest = '\0'; +} + +int +main (int argc, char *argv[]) +{ + size_t i; + + if (argc < 2) { + fprintf(stderr, "Usage: fstab-decode command [arguments]\n"); + return EXIT_FAILURE; + } + for (i = 2; i < (size_t)argc; i++) + decode(argv[i]); + execvp(argv[1], argv + 1); + fprintf(stderr, "fstab-decode: %s: %s\n", argv[1], strerror(errno)); + return 127; +} diff --git a/src/ifdown.c b/src/ifdown.c index 42c0d6f..3048a35 100644 --- a/src/ifdown.c +++ b/src/ifdown.c @@ -77,15 +77,33 @@ int ifdown(void) continue; if (strchr(ifr[i].ifr_name, ':') != NULL) continue; - ifr[i].ifr_flags &= ~(IFF_UP); - if (ioctl(fd, SIOCSIFFLAGS, &ifr[i]) < 0) { + + /* Read interface flags */ + if (ioctl(fd, SIOCGIFFLAGS, &ifr[i]) < 0) { fprintf(stderr, "ifdown: shutdown "); perror(ifr[i].ifr_name); + continue; } + /* + * Expected in according to + * "UNIX Network Programming". + */ +#ifdef ifr_flags +# define IRFFLAGS ifr_flags +#else /* Present on kFreeBSD */ +# define IRFFLAGS ifr_flagshigh +#endif + if (ifr[i].IRFFLAGS & IFF_UP) { + ifr[i].IRFFLAGS &= ~(IFF_UP); + if (ioctl(fd, SIOCSIFFLAGS, &ifr[i]) < 0) { + fprintf(stderr, "ifdown: shutdown "); + perror(ifr[i].ifr_name); + } + } +#undef IRFFLAGS } } close(fd); return 0; } - diff --git a/src/init.c b/src/init.c index feeeeaa..271a64e 100644 --- a/src/init.c +++ b/src/init.c @@ -53,11 +53,10 @@ #include #ifdef WITH_SELINUX -#include -#include +# include +# include #endif - #ifdef __i386__ # ifdef __GLIBC__ /* GNU libc 2.x */ @@ -71,6 +70,11 @@ # endif #endif +#ifdef USE_PAM +# include +# include +#endif + #include "init.h" #include "initreq.h" #include "paths.h" @@ -746,6 +750,16 @@ void console_stty(void) return; } +#ifdef __FreeBSD_kernel__ + /* + * The kernel of FreeBSD expects userland to set TERM. Usually, we want + * "cons25". Later, gettys might disagree on this (i.e. we're not using + * syscons) but some boot scripts, like /etc/init.d/xserver-xorg, still + * need a non-dumb terminal. + */ + putenv ("TERM=cons25"); +#endif + (void) tcgetattr(fd, &tty); tty.c_cflag &= CBAUD|CBAUDEX|CSIZE|CSTOPB|PARENB|PARODD; @@ -902,6 +916,20 @@ void init_freeenv(char **e) } +#ifdef USE_PAM +static pam_handle_t *pamh = NULL; +static const struct pam_conv conv = { misc_conv, NULL }; +# define PAM_FAIL_CHECK(func, args...) \ + { \ + const int __ret = (func)(args); \ + if (__ret != PAM_SUCCESS) { \ + initlog(L_VB, "%s", pam_strerror(pamh, __ret)); \ + pam_end(pamh, __ret); \ + exit(1); \ + } \ + } +#endif /* USE_PAM */ + /* * Fork and execute. * @@ -1031,6 +1059,14 @@ int spawn(CHILD *ch, int *res) sigprocmask(SIG_SETMASK, &omask, NULL); +#ifdef USE_PAM + PAM_FAIL_CHECK(pam_start, "init", "root" , &conv, &pamh); + PAM_FAIL_CHECK(pam_set_item, pamh, PAM_TTY, console_dev); + PAM_FAIL_CHECK(pam_acct_mgmt, pamh, PAM_SILENT); + PAM_FAIL_CHECK(pam_open_session, pamh, PAM_SILENT); + PAM_FAIL_CHECK(pam_setcred, pamh, PAM_ESTABLISH_CRED|PAM_SILENT); +#endif + /* * Update utmp/wtmp file prior to starting * any child. This MUST be done right here in diff --git a/src/shutdown.c b/src/shutdown.c index 397dcf5..7e997da 100644 --- a/src/shutdown.c +++ b/src/shutdown.c @@ -32,11 +32,18 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE /* otherwise `extern char **environ' is missed */ +#endif +#ifndef ACCTON_OFF +# define ACCTON_OFF 0 +#endif #include #include #include #include #include +#include #include #include #include @@ -330,7 +337,7 @@ void fastdown() /* First idle init. */ if (kill(1, SIGTSTP) < 0) { - fprintf(stderr, "shutdown: can't idle init.\r\n"); + fprintf(stderr, "shutdown: can't idle init: %s.\r\n", strerror(errno)); exit(1); } @@ -357,7 +364,17 @@ void fastdown() write_wtmp("shutdown", "~~", 0, RUN_LVL, "~~"); /* This is for those who have quota installed. */ +#if defined(ACCTON_OFF) +# if (ACCTON_OFF > 1) && (_BSD_SOURCE || (_XOPEN_SOURCE && _XOPEN_SOURCE < 500)) + /* This is an alternative way to disable accounting, saving a fork() */ + if (acct(NULL)) + fprintf(stderr, "shutdown: can not stop process accounting: %s.\r\n", strerror(errno)); +# elif (ACCTON_OFF > 0) + spawn(1, "accton", "off", NULL); +# else spawn(1, "accton", NULL); +# endif +#endif spawn(1, "quotaoff", "-a", NULL); sync(); diff --git a/src/utmpdump.c b/src/utmpdump.c index d9174c6..97f9869 100644 --- a/src/utmpdump.c +++ b/src/utmpdump.c @@ -200,7 +200,11 @@ gettok(char *line, char *dest, int size, int eatspace) } void +# ifdef __GNUC__ +undump(FILE *fp, int forever __attribute__((unused)), int oldfmt) +#else undump(FILE *fp, int forever, int oldfmt) +#endif { struct utmp ut; struct oldutmp uto;