Add the comment from Andrea Arcangeli about the correct
place of setting the default childhandler within spawn(). Make sure that newline is printed out for last(1) even if an utmp record entry is truncated. Check if utmp not only exists but is writable and delay writing out of the utmp runlevel record if utmp is not writable. Be able to find libcrypt also on 64 bit based architectures.
This commit is contained in:
parent
1e43b0911c
commit
13de2e9e05
@ -64,7 +64,7 @@ endif
|
||||
|
||||
|
||||
# Additional libs for GNU libc.
|
||||
ifneq ($(wildcard /usr/lib/libcrypt.a),)
|
||||
ifneq ($(wildcard /usr/lib*/libcrypt.a),)
|
||||
LCRYPT = -lcrypt
|
||||
endif
|
||||
|
||||
|
46
src/init.c
46
src/init.c
@ -121,6 +121,8 @@ sig_atomic_t got_signals; /* Set if we received a signal. */
|
||||
int emerg_shell = 0; /* Start emergency shell? */
|
||||
int wrote_wtmp_reboot = 1; /* Set when we wrote the reboot record */
|
||||
int wrote_utmp_reboot = 1; /* Set when we wrote the reboot record */
|
||||
int wrote_wtmp_rlevel = 1; /* Set when we wrote the runlevel record */
|
||||
int wrote_utmp_rlevel = 1; /* Set when we wrote the runlevel record */
|
||||
int sltime = 5; /* Sleep time between TERM and KILL */
|
||||
char *argv0; /* First arguments; show up in ps listing */
|
||||
int maxproclen; /* Maximal length of argv[0] with \0 */
|
||||
@ -189,6 +191,8 @@ struct {
|
||||
{ "-WU", D_WROTE_UTMP_REBOOT},
|
||||
{ "-ST", D_SLTIME },
|
||||
{ "-DB", D_DIDBOOT },
|
||||
{ "-LW", D_WROTE_WTMP_RLEVEL},
|
||||
{ "-LU", D_WROTE_UTMP_RLEVEL},
|
||||
{ "", 0 }
|
||||
};
|
||||
struct {
|
||||
@ -385,6 +389,12 @@ static CHILD *get_record(FILE *f)
|
||||
case D_DIDBOOT:
|
||||
fscanf(f, "%d\n", &did_boot);
|
||||
break;
|
||||
case D_WROTE_WTMP_RLEVEL:
|
||||
fscanf(f, "%d\n", &wrote_wtmp_rlevel);
|
||||
break;
|
||||
case D_WROTE_UTMP_RLEVEL:
|
||||
fscanf(f, "%d\n", &wrote_utmp_rlevel);
|
||||
break;
|
||||
default:
|
||||
if (cmd > 0 || cmd == C_EOF) {
|
||||
oops_error = -1;
|
||||
@ -1004,6 +1014,14 @@ int spawn(CHILD *ch, int *res)
|
||||
dup(f);
|
||||
dup(f);
|
||||
}
|
||||
|
||||
/*
|
||||
* 4 Sep 2001, Andrea Arcangeli:
|
||||
* Fix a race in spawn() that is used to deadlock init in a
|
||||
* waitpid() loop: must set the childhandler as default before forking
|
||||
* off the child or the chld_handler could run before the waitpid loop
|
||||
* has a chance to find its zombie-child.
|
||||
*/
|
||||
SETSIG(sa, SIGCHLD, SIG_DFL, SA_RESTART);
|
||||
if ((pid = fork()) < 0) {
|
||||
initlog(L_VB, "cannot fork: %s",
|
||||
@ -1729,6 +1747,8 @@ int read_level(int arg)
|
||||
}
|
||||
|
||||
/* Store both the old and the new runlevel. */
|
||||
wrote_utmp_rlevel = 0;
|
||||
wrote_wtmp_rlevel = 0;
|
||||
write_utmp_wtmp("runlevel", "~~", foo + 256*runlevel, RUN_LVL, "~");
|
||||
thislevel = foo;
|
||||
prevlevel = runlevel;
|
||||
@ -1929,6 +1949,25 @@ void re_exec(void)
|
||||
initlog(L_CO, "Attempt to re-exec failed");
|
||||
}
|
||||
|
||||
/*
|
||||
* Redo utmp/wtmp entries if required or requested
|
||||
* Check for written records and size of utmp
|
||||
*/
|
||||
static
|
||||
void redo_utmp_wtmp(void)
|
||||
{
|
||||
struct stat ustat;
|
||||
const int ret = stat(UTMP_FILE, &ustat);
|
||||
|
||||
if ((ret < 0) || (ustat.st_size == 0))
|
||||
wrote_utmp_rlevel = wrote_utmp_reboot = 0;
|
||||
|
||||
if ((wrote_wtmp_reboot == 0) || (wrote_utmp_reboot == 0))
|
||||
write_utmp_wtmp("reboot", "~~", 0, BOOT_TIME, "~");
|
||||
|
||||
if ((wrote_wtmp_rlevel == 0) || (wrote_wtmp_rlevel == 0))
|
||||
write_utmp_wtmp("runlevel", "~~", thislevel + 256 * prevlevel, RUN_LVL, "~");
|
||||
}
|
||||
|
||||
/*
|
||||
* We got a change runlevel request through the
|
||||
@ -1960,6 +1999,7 @@ void fifo_new_level(int level)
|
||||
if (oldlevel != 'S' && runlevel == 'S') console_stty();
|
||||
if (runlevel == '6' || runlevel == '0' ||
|
||||
runlevel == '1') console_stty();
|
||||
if (runlevel > '1' && runlevel < '6') redo_utmp_wtmp();
|
||||
read_inittab();
|
||||
fail_cancel();
|
||||
setproctitle("init [%c]", runlevel);
|
||||
@ -2243,6 +2283,8 @@ void boot_transitions()
|
||||
}
|
||||
if (loglevel > 0) {
|
||||
initlog(L_VB, "Entering runlevel: %c", runlevel);
|
||||
wrote_utmp_rlevel = 0;
|
||||
wrote_wtmp_rlevel = 0;
|
||||
write_utmp_wtmp("runlevel", "~~", runlevel + 256 * oldlevel, RUN_LVL, "~");
|
||||
thislevel = runlevel;
|
||||
prevlevel = oldlevel;
|
||||
@ -2421,6 +2463,7 @@ int init_main()
|
||||
console_init();
|
||||
|
||||
if (!reload) {
|
||||
int fd;
|
||||
|
||||
/* Close whatever files are open, and reset the console. */
|
||||
close(0);
|
||||
@ -2438,7 +2481,8 @@ int init_main()
|
||||
* Initialize /var/run/utmp (only works if /var is on
|
||||
* root and mounted rw)
|
||||
*/
|
||||
(void) close(open(UTMP_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0644));
|
||||
if ((fd = open(UTMP_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0644)) >= 0)
|
||||
close(fd);
|
||||
|
||||
/*
|
||||
* Say hello to the world
|
||||
|
@ -118,6 +118,10 @@ typedef struct _child_ {
|
||||
extern CHILD *family;
|
||||
extern int wrote_wtmp_reboot;
|
||||
extern int wrote_utmp_reboot;
|
||||
extern int wrote_wtmp_rlevel;
|
||||
extern int wrote_utmp_rlevel;
|
||||
extern char thislevel;
|
||||
extern char prevlevel;
|
||||
|
||||
/* Tokens in state parser */
|
||||
#define C_VER 1
|
||||
@ -139,4 +143,6 @@ extern int wrote_utmp_reboot;
|
||||
#define D_WROTE_UTMP_REBOOT -7
|
||||
#define D_SLTIME -8
|
||||
#define D_DIDBOOT -9
|
||||
#define D_WROTE_WTMP_RLEVEL -16
|
||||
#define D_WROTE_UTMP_RLEVEL -17
|
||||
|
||||
|
15
src/last.c
15
src/last.c
@ -476,14 +476,14 @@ int list(struct utmp *p, time_t t, int what)
|
||||
strcmp(s + 1, domainname) == 0) *s = 0;
|
||||
#endif
|
||||
if (!altlist) {
|
||||
snprintf(final, sizeof(final),
|
||||
len = snprintf(final, sizeof(final),
|
||||
fulltime ?
|
||||
"%-8.8s %-12.12s %-16.16s %-24.24s %-26.26s %-12.12s\n" :
|
||||
"%-8.8s %-12.12s %-16.16s %-16.16s %-7.7s %-12.12s\n",
|
||||
p->ut_name, utline,
|
||||
domain, logintime, logouttime, length);
|
||||
} else {
|
||||
snprintf(final, sizeof(final),
|
||||
len = snprintf(final, sizeof(final),
|
||||
fulltime ?
|
||||
"%-8.8s %-12.12s %-24.24s %-26.26s %-12.12s %s\n" :
|
||||
"%-8.8s %-12.12s %-16.16s %-7.7s %-12.12s %s\n",
|
||||
@ -491,13 +491,19 @@ int list(struct utmp *p, time_t t, int what)
|
||||
logintime, logouttime, length, domain);
|
||||
}
|
||||
} else
|
||||
snprintf(final, sizeof(final),
|
||||
len = snprintf(final, sizeof(final),
|
||||
fulltime ?
|
||||
"%-8.8s %-12.12s %-24.24s %-26.26s %-12.12s\n" :
|
||||
"%-8.8s %-12.12s %-16.16s %-7.7s %-12.12s\n",
|
||||
p->ut_name, utline,
|
||||
logintime, logouttime, length);
|
||||
|
||||
#if defined(__GLIBC__)
|
||||
# if (__GLIBC__ == 2) && (__GLIBC_MINOR__ == 0)
|
||||
final[sizeof(final)-1] = '\0';
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Print out "final" string safely.
|
||||
*/
|
||||
@ -508,6 +514,9 @@ int list(struct utmp *p, time_t t, int what)
|
||||
putchar('*');
|
||||
}
|
||||
|
||||
if (len < 0 || len >= sizeof(final))
|
||||
putchar('\n');
|
||||
|
||||
recsdone++;
|
||||
if (maxrecs && recsdone >= maxrecs)
|
||||
return 1;
|
||||
|
46
src/utmp.c
46
src/utmp.c
@ -65,6 +65,12 @@ char *line) /* Which line is this */
|
||||
struct utsname uname_buf;
|
||||
struct timeval tv;
|
||||
|
||||
/*
|
||||
* Can't do much if WTMP_FILE is not present or not writable.
|
||||
*/
|
||||
if (access(WTMP_FILE, W_OK) < 0)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Try to open the wtmp file. Note that we even try
|
||||
* this if we have updwtmp() so we can see if the
|
||||
@ -86,6 +92,23 @@ char *line) /* Which line is this */
|
||||
*/
|
||||
if (wrote_wtmp_reboot == 0 && type != BOOT_TIME)
|
||||
write_wtmp("reboot", "~~", 0, BOOT_TIME, "~");
|
||||
|
||||
/*
|
||||
* Note if we are going to write a runlevel record.
|
||||
*/
|
||||
if (type == RUN_LVL) wrote_wtmp_rlevel++;
|
||||
|
||||
/*
|
||||
* See if we need to write a runlevel record. The reason that
|
||||
* we are being so paranoid is that when we first tried to
|
||||
* write the reboot record, /var was possibly not mounted
|
||||
* yet. As soon as we can open WTMP we write a delayed runlevel record.
|
||||
*/
|
||||
if (wrote_wtmp_rlevel == 0 && type != RUN_LVL) {
|
||||
int runlevel = thislevel;
|
||||
int oldlevel = prevlevel;
|
||||
write_wtmp("runlevel", "~~", runlevel + 256 * oldlevel, RUN_LVL, "~");
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -135,9 +158,9 @@ char *oldline) /* Line of old utmp entry. */
|
||||
struct timeval tv;
|
||||
|
||||
/*
|
||||
* Can't do much if UTMP_FILE is not present.
|
||||
* Can't do much if UTMP_FILE is not present or not writable.
|
||||
*/
|
||||
if (access(UTMP_FILE, F_OK) < 0)
|
||||
if (access(UTMP_FILE, W_OK) < 0)
|
||||
return;
|
||||
|
||||
#ifdef INIT_MAIN
|
||||
@ -150,10 +173,27 @@ char *oldline) /* Line of old utmp entry. */
|
||||
* See if we need to write a reboot record. The reason that
|
||||
* we are being so paranoid is that when we first tried to
|
||||
* write the reboot record, /var was possibly not mounted
|
||||
* yet. As soon as we can open WTMP we write a delayed boot record.
|
||||
* yet. As soon as we can open UTMP we write a delayed boot record.
|
||||
*/
|
||||
if (wrote_utmp_reboot == 0 && type != BOOT_TIME)
|
||||
write_utmp("reboot", "~~", 0, BOOT_TIME, "~", NULL);
|
||||
|
||||
/*
|
||||
* Note if we are going to write a runlevel record.
|
||||
*/
|
||||
if (type == RUN_LVL) wrote_utmp_rlevel++;
|
||||
|
||||
/*
|
||||
* See if we need to write a runlevel record. The reason that
|
||||
* we are being so paranoid is that when we first tried to
|
||||
* write the reboot record, /var was possibly not mounted
|
||||
* yet. As soon as we can open UTMP we write a delayed runlevel record.
|
||||
*/
|
||||
if (wrote_utmp_rlevel == 0 && type != RUN_LVL) {
|
||||
int runlevel = thislevel;
|
||||
int oldlevel = prevlevel;
|
||||
write_utmp("runlevel", "~~", runlevel + 256 * oldlevel, RUN_LVL, "~", NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user