sysvinit/sysvinit-2.86.dif

968 lines
24 KiB
Plaintext

--- .pkgextract
+++ .pkgextract 2006-08-18 14:45:28.000000000 +0200
@@ -0,0 +1,14 @@
+patch -p0 -b -s --suffix=.nfs4pidof < ../sysvinit-2.86-nfs4pidof.patch
+patch -p0 -b -s --suffix=.sulogin < ../sysvinit-2.86-sulogin.patch
+patch -p0 -b -s --suffix=.ststdmn < ../sysvinit-2.82-startstop.patch
+patch -p0 -b -s --suffix=.suse < ../sysvinit-2.85-suse.patch
+patch -p0 -b -s --suffix=.paths < ../sysvinit-2.85-paths.patch
+patch -p0 -b -s --suffix=.utmp < ../sysvinit-2.86-utmp.patch
+patch -p0 -b -s --suffix=.race < ../sysvinit-2.86-race.patch
+patch -p0 -b -s --suffix=.lib64 < ../sysvinit-2.86-lib64.patch
+patch -p0 -b -s --suffix=.mltline < ../sysvinit-2.82-multiline.patch
+patch -p0 -b -s --suffix=.usage < ../sysvinit-2.86-usage-message.patch
+patch -p0 -b -s --suffix=.fulltime < ../sysvinit-2.86-full-time.patch
+patch -p0 -b -s --suffix=.hddown < ../sysvinit-2.86-hddown.patch
+patch -p0 -b -s --suffix=.selinux < ../sysvinit-2.86-selinux.patch
+patch -p0 -b -s --suffix=.fuse < ../sysvinit-2.86-fuse-no-kill.patch
--- src/Makefile
+++ src/Makefile 2009-05-11 10:05:28.482401539 +0200
@@ -8,17 +8,20 @@
# Version: @(#)Makefile 2.85-13 23-Mar-2004 miquels@cistron.nl
#
+DISTRO = SuSE
+
CC = gcc
-CFLAGS = -Wall -O2 -fomit-frame-pointer -D_GNU_SOURCE
-LDFLAGS = -s
-STATIC =
+CFLAGS = -Wall $(RPM_OPT_FLAGS) -D_GNU_SOURCE -pipe
+LDFLAGS = -Wl,-warn-common,--as-needed,-O2
+STATIC = -Wl,--reduce-memory-overheads,--hash-size=8599
+IFLAGS = -D__NO_STRING_INLINES -D__OPTIMIZE_SIZE__ -Os
# For some known distributions we do not build all programs, otherwise we do.
BIN =
SBIN = init halt shutdown runlevel killall5
-USRBIN = last mesg
+USRBIN = last
-MAN1 = last.1 lastb.1 mesg.1
+MAN1 = last.1 lastb.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
@@ -26,27 +29,36 @@ MAN8 += shutdown.8 telinit.8
ifeq ($(DISTRO),)
BIN += mountpoint
SBIN += sulogin bootlogd
-USRBIN += utmpdump wall
-MAN1 += mountpoint.1 wall.1
+USRBIN += utmpdump wall mesg
+MAN1 += utmpdump.1 mountpoint.1 wall.1 mesg.1
MAN8 += sulogin.8 bootlogd.8
endif
ifeq ($(DISTRO),Debian)
BIN += mountpoint
SBIN += sulogin bootlogd
-MAN1 += mountpoint.1
+USRBIN += mesg
+MAN1 += mountpoint.1 mesg.1
MAN8 += sulogin.8 bootlogd.8
endif
ifeq ($(DISTRO),Owl)
-USRBIN += wall
-MAN1 += wall.1
+USRBIN += wall mesg
+MAN1 += wall.1 mesg.1
+endif
+
+ifeq ($(DISTRO),SuSE)
+BIN += mountpoint
+SBIN += sulogin
+USRBIN += utmpdump
+MAN1 += utmpdump.1 mountpoint.1
+MAN8 += sulogin.8
endif
BIN_OWNER = root
BIN_GROUP = root
BIN_COMBO = $(BIN_OWNER):$(BIN_GROUP)
-INSTALL = install -o $(BIN_OWNER) -g $(BIN_GROUP)
+INSTALL = install
MANDIR = /usr/share/man
# Additional libs for GNU libc.
@@ -90,13 +102,13 @@ bootlogd: bootlogd.o
$(CC) $(LDFLAGS) -o $@ bootlogd.o -lutil
init.o: init.c init.h set.h reboot.h initreq.h
- $(CC) -c $(CFLAGS) init.c
+ $(CC) -c $(CFLAGS) $(IFLAGS) init.c
utmp.o: utmp.c init.h
$(CC) -c $(CFLAGS) utmp.c
init_utmp.o: utmp.c init.h
- $(CC) -c $(CFLAGS) -DINIT_MAIN utmp.c -o init_utmp.o
+ $(CC) -c $(CFLAGS) -DINIT_MAIN $(IFLAGS) utmp.c -o init_utmp.o
cleanobjs:
rm -f *.o *.bak
@@ -119,10 +131,10 @@ install:
for i in $(USRBIN); do \
$(INSTALL) -m 755 $$i $(ROOT)/usr/bin/; \
done
- # $(INSTALL) -m 755 etc/initscript.sample $(ROOT)/etc/
- ln -sf halt $(ROOT)/sbin/reboot
- ln -sf halt $(ROOT)/sbin/poweroff
- ln -sf init $(ROOT)/sbin/telinit
+ ln -sf halt $(ROOT)/sbin/reboot
+ ln -sf halt $(ROOT)/sbin/poweroff
+ ln -sf init $(ROOT)/sbin/telinit
+ ln -sf killall5 $(ROOT)/sbin/pidof
ln -sf ../sbin/killall5 $(ROOT)/bin/pidof
if [ ! -f $(ROOT)/usr/bin/lastb ]; then \
ln -sf last $(ROOT)/usr/bin/lastb; \
--- src/bootlogd.c
+++ src/bootlogd.c 2006-08-18 14:45:28.000000000 +0200
@@ -210,7 +210,7 @@ int isconsole(char *s, char *res, int rl
int consolename(char *res, int rlen)
{
#ifdef TIOCGDEV
- unsigned int kdev;
+ kdev_t kdev;
#endif
struct stat st, st2;
char buf[256];
@@ -506,7 +506,7 @@ int main(int argc, char **argv)
}
(void)ioctl(0, TIOCCONS, NULL);
-#if 1
+#if 0
/* Work around bug in 2.1/2.2 kernels. Fixed in 2.2.13 and 2.3.18 */
if ((n = open("/dev/tty0", O_RDWR)) >= 0) {
(void)ioctl(n, TIOCCONS, NULL);
--- src/dowall.c
+++ src/dowall.c 2006-08-18 14:45:28.000000000 +0200
@@ -65,7 +65,7 @@ static void getuidtty(char **userp, char
uid_t uid;
char *tty;
static char uidbuf[32];
- static char ttynm[32];
+ static char ttynm[UT_LINESIZE + 4];
static int init = 0;
if (!init) {
@@ -79,9 +79,13 @@ static void getuidtty(char **userp, char
}
if ((tty = ttyname(0)) != NULL) {
- if (strncmp(tty, "/dev/", 5) == 0)
- tty += 5;
- sprintf(ttynm, "(%.28s) ", tty);
+ if (strncmp(tty, _PATH_DEV, strlen(_PATH_DEV)) == 0) {
+ tty += strlen(_PATH_DEV);
+ if (tty[0] == '/')
+ tty ++;
+ }
+ snprintf(ttynm, sizeof(ttynm), "(%.*s) ",
+ UT_LINESIZE, tty);
} else
ttynm[0] = 0;
init++;
@@ -129,7 +133,7 @@ void wall(char *text, int fromshutdown,
struct sigaction sa;
struct utmp *utmp;
time_t t;
- char term[UT_LINESIZE+6];
+ char term[UT_LINESIZE + strlen(_PATH_DEV) + 1];
char line[81];
char *date, *p;
char *user, *tty;
@@ -178,11 +182,11 @@ void wall(char *text, int fromshutdown,
while ((utmp = getutent()) != NULL) {
if(utmp->ut_type != USER_PROCESS ||
utmp->ut_user[0] == 0) continue;
- if (strncmp(utmp->ut_line, "/dev/", 5) == 0) {
+ if (strncmp(utmp->ut_line, _PATH_DEV, strlen(_PATH_DEV)) == 0) {
term[0] = 0;
- strncat(term, utmp->ut_line, UT_LINESIZE);
+ strncat(term, utmp->ut_line, sizeof(term)-1);
} else
- snprintf(term, sizeof(term), "/dev/%.*s",
+ snprintf(term, sizeof(term), _PATH_DEV "%.*s",
UT_LINESIZE, utmp->ut_line);
if (strstr(term, "/../")) continue;
--- src/init.c
+++ src/init.c 2009-05-11 00:00:00.000000000 +0200
@@ -54,12 +54,12 @@
#include <sepol/sepol.h>
#ifdef __i386__
-# if (__GLIBC__ >= 2)
- /* GNU libc 2.x */
+# if defined (__GLIBC__)
# define STACK_DEBUG 1
# if (__GLIBC__ == 2 && __GLIBC_MINOR__ == 0)
- /* Only glibc 2.0 needs this */
# include <sigcontext.h>
+# elif ( __GLIBC__ > 2) && ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 1))
+# include <bits/sigcontext.h>
# endif
# endif
#endif
@@ -70,6 +70,12 @@
#include "reboot.h"
#include "set.h"
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 2, 3)))
+#endif
+static void initlog(int loglevel, char *fmt, ...);
+static void print(char *fmt);
+
#ifndef SIGPWR
# define SIGPWR SIGUSR2
#endif
@@ -84,11 +90,15 @@
/* Set a signal handler. */
#define SETSIG(sa, sig, fun, flags) \
do { \
+ memset(&sa, 0, sizeof(sa)); \
sa.sa_handler = fun; \
sa.sa_flags = flags; \
sigemptyset(&sa.sa_mask); \
sigaction(sig, &sa, NULL); \
} while(0)
+#ifndef mem_barrier
+# define mem_barrier() __asm__ __volatile__("": : :"memory")
+#endif
/* Version information */
char *Version = "@(#) init " VERSION " " DATE " miquels@cistron.nl";
@@ -212,6 +222,7 @@ char *extra_env[NR_EXTRA_ENV];
* This only works correctly because the linux select updates
* the elapsed time in the struct timeval passed to select!
*/
+static
void do_sleep(int sec)
{
struct timeval tv;
@@ -220,13 +231,14 @@ void do_sleep(int sec)
tv.tv_usec = 0;
while(select(0, NULL, NULL, NULL, &tv) < 0 && errno == EINTR)
- ;
+ mem_barrier();
}
/*
* Non-failing allocation routines (init cannot fail).
*/
+static
void *imalloc(size_t size)
{
void *m;
@@ -239,7 +251,7 @@ void *imalloc(size_t size)
return m;
}
-
+static
char *istrdup(char *s)
{
char *m;
@@ -256,6 +268,7 @@ char *istrdup(char *s)
* Send the state info of the previous running init to
* the new one, in a version-independant way.
*/
+static
void send_state(int fd)
{
FILE *fp;
@@ -320,7 +333,7 @@ static int get_void(FILE *f)
int c;
while ((c = getc(f)) != EOF && c != '\n')
- ;
+ mem_barrier();
return (c != EOF);
}
@@ -337,7 +350,7 @@ static int get_cmd(FILE *f)
return C_EOF;
for(i = 0; cmds[i].cmd && strcmp(cmds[i].name, cmd) != 0; i++)
- ;
+ mem_barrier();
return cmds[i].cmd;
}
@@ -448,6 +461,7 @@ static CHILD *get_record(FILE *f)
* Read the complete state info from the state pipe.
* Returns 0 on success
*/
+static
int receive_state(int fd)
{
FILE *f;
@@ -461,7 +475,7 @@ int receive_state(int fd)
get_string(old_version, sizeof(old_version), f);
oops_error = 0;
for (pp = &family; (*pp = get_record(f)) != NULL; pp = &((*pp)->next))
- ;
+ mem_barrier();
fclose(f);
return oops_error;
}
@@ -495,6 +509,7 @@ static int setproctitle(char *fmt, ...)
/*
* Set console_dev to a working console.
*/
+static
void console_init(void)
{
int fd;
@@ -534,6 +549,7 @@ void console_init(void)
/*
* Open the console with retries.
*/
+static
int console_open(int mode)
{
int f, fd = -1;
@@ -563,6 +579,7 @@ int console_open(int mode)
/*
* We got a signal (HUP PWR WINCH ALRM INT)
*/
+static
void signal_handler(int sig)
{
ADDSET(got_signals, sig);
@@ -571,6 +588,7 @@ void signal_handler(int sig)
/*
* SIGCHLD: one of our children has died.
*/
+static
void chld_handler()
{
CHILD *ch;
@@ -610,7 +628,8 @@ void chld_handler()
*
* The SIGCONT handler
*/
-void cont_handler()
+static
+void cont_handler(int sig)
{
got_cont = 1;
}
@@ -618,6 +637,7 @@ void cont_handler()
/*
* Fork and dump core in /.
*/
+static
void coredump(void)
{
static int dumped = 0;
@@ -651,6 +671,7 @@ void coredump(void)
* If we have the info, print where it occured.
* Then sleep 30 seconds and try to continue.
*/
+static
#if defined(STACK_DEBUG) && defined(__linux__)
void segv_handler(int sig, struct sigcontext ctx)
{
@@ -667,7 +688,7 @@ void segv_handler(int sig, struct sigcon
errno = saved_errno;
}
#else
-void segv_handler()
+void segv_handler(int sig)
{
int saved_errno = errno;
@@ -682,7 +703,8 @@ void segv_handler()
/*
* The SIGSTOP & SIGTSTP handler
*/
-void stop_handler()
+static
+void stop_handler(int sig)
{
int saved_errno = errno;
@@ -695,6 +717,7 @@ void stop_handler()
/*
* Set terminal settings to reasonable defaults
*/
+static
void console_stty(void)
{
struct termios tty;
@@ -710,16 +733,23 @@ void console_stty(void)
tty.c_cflag &= CBAUD|CBAUDEX|CSIZE|CSTOPB|PARENB|PARODD;
tty.c_cflag |= HUPCL|CLOCAL|CREAD;
- tty.c_cc[VINTR] = 3; /* ctrl('c') */
- tty.c_cc[VQUIT] = 28; /* ctrl('\\') */
- tty.c_cc[VERASE] = 127;
- tty.c_cc[VKILL] = 24; /* ctrl('x') */
- tty.c_cc[VEOF] = 4; /* ctrl('d') */
- tty.c_cc[VTIME] = 0;
- tty.c_cc[VMIN] = 1;
- tty.c_cc[VSTART] = 17; /* ctrl('q') */
- tty.c_cc[VSTOP] = 19; /* ctrl('s') */
- tty.c_cc[VSUSP] = 26; /* ctrl('z') */
+ tty.c_cc[VTIME] = 0;
+ tty.c_cc[VMIN] = 1;
+ tty.c_cc[VINTR] = CINTR;
+ tty.c_cc[VQUIT] = CQUIT;
+ tty.c_cc[VERASE] = CERASE; /* ASCII DEL (0177) */
+ tty.c_cc[VKILL] = CKILL;
+ tty.c_cc[VEOF] = CEOF;
+ tty.c_cc[VSWTC] = _POSIX_VDISABLE;
+ tty.c_cc[VSTART] = CSTART;
+ tty.c_cc[VSTOP] = CSTOP;
+ tty.c_cc[VSUSP] = CSUSP;
+ tty.c_cc[VEOL] = _POSIX_VDISABLE;
+ tty.c_cc[VREPRINT] = CREPRINT;
+ tty.c_cc[VDISCARD] = CDISCARD;
+ tty.c_cc[VWERASE] = CWERASE;
+ tty.c_cc[VLNEXT] = CLNEXT;
+ tty.c_cc[VEOL2] = _POSIX_VDISABLE;
/*
* Set pre and post processing
@@ -729,6 +759,14 @@ void console_stty(void)
tty.c_lflag = ISIG|ICANON|ECHO|ECHOCTL|ECHOPRT|ECHOKE;
/*
+ * Setting for SuSE: No flow control (-ixon), ignore break (ignbrk),
+ * and make nl/cr more usable (sane).
+ */
+ tty.c_iflag |= IGNBRK;
+ tty.c_iflag &= ~(BRKINT|INLCR|IGNCR|IXON);
+ tty.c_oflag &= ~(OCRNL|ONLRET);
+
+ /*
* Now set the terminal line.
* We don't care about non-transmitted output data
* and non-read input data.
@@ -741,6 +779,7 @@ void console_stty(void)
/*
* Print to the system console
*/
+static
void print(char *s)
{
int fd;
@@ -757,6 +796,7 @@ void print(char *s)
#ifdef __GNUC__
__attribute__ ((format (printf, 2, 3)))
#endif
+static
void initlog(int loglevel, char *s, ...)
{
va_list va_alist;
@@ -799,6 +839,7 @@ char **init_buildenv(int child)
char i_lvl[] = "RUNLEVEL=x";
char i_prev[] = "PREVLEVEL=x";
char i_cons[32];
+ char i_shell[] = "SHELL=" SHELL;
char **e;
int n, i;
@@ -818,6 +859,7 @@ char **init_buildenv(int child)
snprintf(i_cons, sizeof(i_cons), "CONSOLE=%s", console_dev);
i_lvl[9] = thislevel;
i_prev[10] = prevlevel;
+ e[n++] = istrdup(i_shell);
e[n++] = istrdup(i_lvl);
e[n++] = istrdup(i_prev);
e[n++] = istrdup(i_cons);
@@ -846,6 +888,7 @@ void init_freeenv(char **e)
* This function is too long and indents too deep.
*
*/
+static
int spawn(CHILD *ch, int *res)
{
char *args[16]; /* Argv array */
@@ -988,7 +1031,7 @@ int spawn(CHILD *ch, int *res)
}
SETSIG(sa, SIGCHLD, SIG_DFL, SA_RESTART);
if ((pid = fork()) < 0) {
- initlog(L_VB, "cannot fork");
+ initlog(L_VB, "cannot fork: %s", strerror(errno));
exit(1);
}
if (pid > 0) {
@@ -1017,7 +1060,7 @@ int spawn(CHILD *ch, int *res)
* this with a temporary process.
*/
if ((pid = fork()) < 0) {
- initlog(L_VB, "cannot fork");
+ initlog(L_VB, "cannot fork: %s", strerror(errno));
exit(1);
}
if (pid == 0) {
@@ -1083,6 +1126,7 @@ int spawn(CHILD *ch, int *res)
/*
* Start a child running!
*/
+static
void startup(CHILD *ch)
{
/*
@@ -1125,6 +1169,7 @@ void startup(CHILD *ch)
/*
* Read the inittab file.
*/
+static
void read_inittab(void)
{
FILE *fp; /* The INITTAB file */
@@ -1182,7 +1227,7 @@ void read_inittab(void)
* Skip comments and empty lines
*/
for(p = buf; *p == ' ' || *p == '\t'; p++)
- ;
+ mem_barrier();
if (*p == '#' || *p == '\n') continue;
/*
@@ -1505,6 +1550,7 @@ void read_inittab(void)
* The entries that do not belong here at all are removed
* from the list.
*/
+static
void start_if_needed(void)
{
CHILD *ch; /* Pointer to child */
@@ -1550,6 +1596,7 @@ void start_if_needed(void)
/*
* Ask the user on the console for a runlevel
*/
+static
int ask_runlevel(void)
{
const char prompt[] = "\nEnter runlevel: ";
@@ -1578,6 +1625,7 @@ int ask_runlevel(void)
* Search the INITTAB file for the 'initdefault' field, with the default
* runlevel. If this fails, ask the user to supply a runlevel.
*/
+static
int get_init_default(void)
{
CHILD *ch;
@@ -1626,6 +1674,7 @@ int get_init_default(void)
* the "old" INITLVL and arg == 0, try to read the new
* runlevel from that file first.
*/
+static
int read_level(int arg)
{
CHILD *ch; /* Walk through list */
@@ -1694,7 +1743,16 @@ int read_level(int arg)
initlog(L_VB, "Switching to runlevel: %c", foo);
}
- if (foo == 'Q') return runlevel;
+ if (foo == 'Q') {
+ struct sigaction sa;
+
+ /*
+ * Re-enable SIGINT's, which may disabled by
+ * an former Ctrl-Alt-Del action in process_signals().
+ */
+ SETSIG(sa, SIGINT, signal_handler, 0);
+ return(runlevel);
+ }
/* Check if this is a runlevel a, b or c */
if (strchr("ABC", foo)) {
@@ -1733,6 +1791,7 @@ int read_level(int arg)
* longer than 5 minutes, or inittab was read again due
* to user interaction.
*/
+static
void fail_check(void)
{
CHILD *ch; /* Pointer to child structure */
@@ -1765,6 +1824,7 @@ void fail_check(void)
}
/* Set all 'Fail' timers to 0 */
+static
void fail_cancel(void)
{
CHILD *ch;
@@ -1779,6 +1839,7 @@ void fail_cancel(void)
/*
* Start up powerfail entries.
*/
+static
void do_power_fail(int pwrstat)
{
CHILD *ch;
@@ -1812,6 +1873,7 @@ void do_power_fail(int pwrstat)
/*
* Check for state-pipe presence
*/
+static
int check_pipe(int fd)
{
struct timeval t;
@@ -1832,6 +1894,7 @@ int check_pipe(int fd)
/*
* Make a state-pipe.
*/
+static
int make_pipe(int fd)
{
int fds[2];
@@ -1849,6 +1912,7 @@ int make_pipe(int fd)
/*
* Attempt to re-exec.
*/
+static
void re_exec(void)
{
CHILD *ch;
@@ -1906,7 +1970,7 @@ void re_exec(void)
* The existing init process execs a new init binary.
*/
env = init_buildenv(0);
- execl(myname, myname, "--init", NULL, env);
+ execle(myname, myname, "--init", NULL, env);
/*
* We shouldn't be here, something failed.
@@ -1943,6 +2007,7 @@ void redo_utmp_wtmp(void)
* We got a change runlevel request through the
* init.fifo. Process it.
*/
+static
void fifo_new_level(int level)
{
#if CHANGE_WAIT
@@ -1972,7 +2037,7 @@ void fifo_new_level(int level)
if (runlevel > '1' && runlevel < '6') redo_utmp_wtmp();
read_inittab();
fail_cancel();
- setproctitle("init [%c]", runlevel);
+ setproctitle("init [%c]", (int)runlevel);
}
}
}
@@ -2040,6 +2105,7 @@ void initcmd_setenv(char *data, int size
* the 2.2 kernel credential stuff to see who we're talking to.
*
*/
+static
void check_init_fifo(void)
{
struct init_request request;
@@ -2105,7 +2171,7 @@ void check_init_fifo(void)
tv.tv_usec = 0;
n = select(pipe_fd + 1, &fds, NULL, NULL, &tv);
if (n <= 0) {
- if (n == 0 || errno == EINTR) return;
+ if (n == 0 || errno == EINTR || errno == EAGAIN) return;
continue;
}
@@ -2122,7 +2188,7 @@ void check_init_fifo(void)
return;
}
if (n <= 0) {
- if (errno == EINTR) return;
+ if (errno == EINTR || errno == EAGAIN) return;
initlog(L_VB, "error reading initrequest");
continue;
}
@@ -2194,6 +2260,7 @@ void check_init_fifo(void)
* This function is used in the transition
* sysinit (-> single user) boot -> multi-user.
*/
+static
void boot_transitions()
{
CHILD *ch;
@@ -2270,7 +2337,7 @@ void boot_transitions()
write_utmp_wtmp("runlevel", "~~", runlevel + 256 * oldlevel, RUN_LVL, "~");
thislevel = runlevel;
prevlevel = oldlevel;
- setproctitle("init [%c]", runlevel);
+ setproctitle("init [%c]", (int)runlevel);
}
}
}
@@ -2279,6 +2346,7 @@ void boot_transitions()
* Init got hit by a signal. See which signal it is,
* and act accordingly.
*/
+static
void process_signals()
{
CHILD *ch;
@@ -2303,7 +2371,12 @@ void process_signals()
}
if (ISMEMBER(got_signals, SIGINT)) {
+ struct sigaction sa;
INITDBG(L_VB, "got SIGINT");
+
+ /* we don't want any more SIGINT's */
+ SETSIG(sa, SIGINT, SIG_IGN, SA_RESTART);
+
/* Tell ctrlaltdel entry to start up */
for(ch = family; ch; ch = ch->next)
if (ch->action == CTRLALTDEL)
@@ -2365,7 +2438,7 @@ void process_signals()
runlevel == '1') console_stty();
read_inittab();
fail_cancel();
- setproctitle("init [%c]", runlevel);
+ setproctitle("init [%c]", (int)runlevel);
DELSET(got_signals, SIGHUP);
}
}
@@ -2384,7 +2457,8 @@ void process_signals()
/*
* The main loop
*/
-int init_main()
+static
+void init_main(void)
{
CHILD *ch;
struct sigaction sa;
@@ -2539,6 +2613,7 @@ int init_main()
/*
* Tell the user about the syntax we expect.
*/
+static
void usage(char *s)
{
fprintf(stderr, "Usage: %s 0123456SsQqAaBbCcUu\n", s);
@@ -2596,12 +2671,38 @@ int telinit(char *progname, int argc, ch
request.sleeptime = sltime;
}
+ /* Catch some common signals. */
+ signal(SIGQUIT, SIG_IGN);
+ signal(SIGCHLD, SIG_IGN);
+ signal(SIGHUP, SIG_IGN);
+ signal(SIGTSTP, SIG_IGN);
+ signal(SIGTTIN, SIG_IGN);
+ signal(SIGTTOU, SIG_IGN);
+ signal(SIGINT, SIG_IGN);
+
+ /* Go to the root directory. */
+ chdir("/");
+
/* Open the fifo and write a command. */
+
/* Make sure we don't hang on opening /dev/initctl */
SETSIG(sa, SIGALRM, signal_handler, 0);
alarm(3);
- if ((fd = open(INIT_FIFO, O_WRONLY)) >= 0 &&
- write(fd, &request, sizeof(request)) == sizeof(request)) {
+ if ((fd = open(INIT_FIFO, O_WRONLY)) >= 0) {
+ ssize_t p = 0;
+ size_t s = sizeof(request);
+ void *ptr = &request;
+
+ while (s > 0) {
+ p = write(fd, ptr, s);
+ if (p < 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ break;
+ }
+ ptr += p;
+ s -= p;
+ }
close(fd);
alarm(0);
return 0;
@@ -2652,6 +2753,8 @@ int main(int argc, char **argv)
p++;
else
p = argv[0];
+
+ /* Common umask */
umask(022);
/* Quick check */
@@ -2684,7 +2787,7 @@ int main(int argc, char **argv)
for (f = 0; f < argc; f++)
maxproclen += strlen(argv[f]) + 1;
reload = 1;
- setproctitle("init [%c]",runlevel);
+ setproctitle("init [%c]", (int)runlevel);
init_main();
}
@@ -2727,7 +2830,7 @@ int main(int argc, char **argv)
argv0 = argv[0];
argv[1] = NULL;
setproctitle("init boot");
- init_main(dfl_level);
+ init_main();
/*NOTREACHED*/
return 0;
--- src/init.h
+++ src/init.h 2006-08-18 14:45:28.000000000 +0200
@@ -30,12 +30,6 @@
/* Prototypes. */
void write_utmp_wtmp(char *user, char *id, int pid, int type, char *line);
void write_wtmp(char *user, char *id, int pid, int type, char *line);
-#ifdef __GNUC__
-__attribute__ ((format (printf, 2, 3)))
-#endif
-void initlog(int loglevel, char *fmt, ...);
-void set_term(int how);
-void print(char *fmt);
#if DEBUG
# define INITDBG(level, fmt, args...) initlog(level, fmt, ##args)
--- src/shutdown.c
+++ src/shutdown.c 2006-08-18 14:45:28.000000000 +0200
@@ -60,6 +60,7 @@ char *clean_env[] = {
"HOME=/",
"PATH=/bin:/usr/bin:/sbin:/usr/sbin",
"TERM=dumb",
+ "SHELL=/bin/sh",
NULL,
};
@@ -159,11 +160,24 @@ int init_setenv(char *name, char *value)
sigaction(SIGALRM, &sa, NULL);
got_alrm = 0;
alarm(3);
- if ((fd = open(INIT_FIFO, O_WRONLY)) >= 0 &&
- write(fd, &request, sizeof(request)) == sizeof(request)) {
- close(fd);
- alarm(0);
- return 0;
+ if ((fd = open(INIT_FIFO, O_WRONLY)) >= 0) {
+ ssize_t p = 0;
+ size_t s = sizeof(request);
+ void *ptr = &request;
+
+ while (s > 0) {
+ p = write(fd, ptr, s);
+ if (p < 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ break;
+ }
+ ptr += p;
+ s -= p;
+ }
+ close(fd);
+ alarm(0);
+ return 0;
}
fprintf(stderr, "shutdown: ");
--- src/utmp.c
+++ src/utmp.c 2006-08-18 14:45:28.000000000 +0200
@@ -47,6 +47,9 @@ char *line) /* Which line is this */
int fd;
struct utmp utmp;
struct utsname uname_buf;
+#if __WORDSIZE == 64 && defined __WORDSIZE_COMPAT32
+ struct timeval tv;
+#endif
/*
* Can't do much if WTMP_FILE is not present or not writable.
@@ -99,7 +102,13 @@ char *line) /* Which line is this */
*/
memset(&utmp, 0, sizeof(utmp));
#if defined(__GLIBC__)
+# if __WORDSIZE == 64 && defined __WORDSIZE_COMPAT32
+ gettimeofday(&tv, NULL);
+ utmp.ut_tv.tv_sec = (int32_t)tv.tv_sec;
+ utmp.ut_tv.tv_usec = (int32_t)tv.tv_usec;
+# else
gettimeofday(&utmp.ut_tv, NULL);
+# endif
#else
time(&utmp.ut_time);
#endif
@@ -136,6 +145,9 @@ char *oldline) /* Line of old utmp ent
struct utmp utmp;
struct utmp tmp;
struct utmp *utmptr;
+#if __WORDSIZE == 64 && defined __WORDSIZE_COMPAT32
+ struct timeval tv;
+#endif
/*
* Can't do much if UTMP_FILE is not present or not writable.
@@ -184,7 +196,13 @@ char *oldline) /* Line of old utmp ent
utmp.ut_pid = pid;
strncpy(utmp.ut_id, id, sizeof(utmp.ut_id));
#if defined(__GLIBC__)
+# if __WORDSIZE == 64 && defined __WORDSIZE_COMPAT32
+ gettimeofday(&tv, NULL);
+ utmp.ut_tv.tv_sec = (int32_t)tv.tv_sec;
+ utmp.ut_tv.tv_usec = (int32_t)tv.tv_usec;
+# else
gettimeofday(&utmp.ut_tv, NULL);
+# endif
#else
time(&utmp.ut_time);
#endif
--- doc/utmpdump.1
+++ doc/utmpdump.1 2010-02-08 13:41:51.154825000 +0000
@@ -0,0 +1,45 @@
+.TH UTMPDUMP 1 "Februar 8, 2010" "" "Linux System Administrator's Manual"
+.SH NAME
+utmpdump \- dump UTMP and WTMP files in raw format
+.SH SYNOPSIS
+.B utmpdump
+.RB [ \-froh ]
+.I filename
+.SH DESCRIPTION
+\fButmpdump\fP is a simple program to dump UTMP and WTMP files
+in raw format, so they can be examined.
+.SH OPTIONS
+.IP \fB\-f\fP
+output appended data as the file grows.
+.IP "\fB\-r\fP"
+reverse. Write back edited login information into utmp or wtmp files.
+.IP \fB\-o\fP
+use old libc5 format.
+.IP \fB\-h\fP
+usage information.
+.PP
+utmpdump can be useful in cases of corrupted utmp or wtmp entries.
+It can dump out utmp/wtmp to an ASCII file, then that file can
+be edited to remove bogus entries and reintegrated, using
+.PP
+.sp 1
+.in +1c
+.nf
+\fButmpdump -r < ascii file > wtmp\fP
+.fi
+.in -1c
+.sp 1
+but be warned as
+.B utmpdump
+was written for debugging purpose only.
+.SH BUGS
+You may
+.B not
+use the option \fB\-r\fP as the format for the
+utmp/wtmp files strongly depends on the
+input format.
+.SH "SEE ALSO"
+.BR last (1),
+.BR w (1),
+.BR who (1),
+.BR utmp (5),