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:
Werner Fink 2009-11-24 10:03:19 +00:00
parent 1e43b0911c
commit 13de2e9e05
5 changed files with 107 additions and 8 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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
/*