--- .pkgextract +++ .pkgextract 2006-08-18 14:45:28.000000000 +0200 @@ -0,0 +1,15 @@ +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 +patch -p0 -b -s --suffix=.mdmon < ../sysvinit-2.86-mdmon-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 #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 +# elif ( __GLIBC__ > 2) && ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 1)) +# include # 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),