970 lines
24 KiB
Plaintext
970 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,47 @@
|
|
+.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. This tool is
|
|
+.B not
|
|
+supported, use it at your own risk only.
|
|
+.SH "SEE ALSO"
|
|
+.BR last (1),
|
|
+.BR w (1),
|
|
+.BR who (1),
|
|
+.BR utmp (5),
|