mirror of
https://github.com/troglobit/finit.git
synced 2026-10-01 05:22:48 +07:00
Atomic print and re-print desc on status, flush before reboot
Refactor print() to emit description + final status in a single call to cprintf(), preventing kernel messages from splitting the two parts. For two-phase print(-1,...) + print_result() sequences used by, e.g., run_interactive, save the last description and re-print it before the [ OK ] / [FAIL] output so the status is never left stranded on a blank line when command output or kernel messages have scrolled away the original description. Finally, add print_exit() which drains the console output buffer with tcdrain(2) and resets ANSI SGR attributes + cursor visibility before the kernel takes back the console on reboot/halt, preventing escape code leakage into bootloader or early-kernel output. Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
+58
-2
@@ -50,6 +50,7 @@
|
||||
|
||||
static pstyle_t progress_onoff = PROGRESS_DEFAULT;
|
||||
static pstyle_t progress_style = PROGRESS_DEFAULT;
|
||||
static char last_desc[512]; /* saved description for re-print after interruption */
|
||||
|
||||
#ifndef HOSTNAME_PATH
|
||||
#define HOSTNAME_PATH "/etc/hostname"
|
||||
@@ -336,6 +337,8 @@ void printv(const char *fmt, va_list ap)
|
||||
len = print_timestamp(buf, sizeof(buf));
|
||||
vsnprintf(&buf[len], sizeof(buf) - len, fmt, ap);
|
||||
|
||||
strlcpy(last_desc, &buf[len], sizeof(last_desc)); /* save for re-print */
|
||||
|
||||
if (progress_style == PROGRESS_CLASSIC)
|
||||
cprintf("\r%s ", pad(buf, sizeof(buf), ".", sizeof(buf)));
|
||||
else
|
||||
@@ -344,25 +347,66 @@ void printv(const char *fmt, va_list ap)
|
||||
|
||||
void print(int rc, const char *fmt, ...)
|
||||
{
|
||||
char buf[ttcols];
|
||||
size_t len;
|
||||
|
||||
if (progress_style == PROGRESS_SILENT)
|
||||
return;
|
||||
|
||||
buf[0] = 0;
|
||||
len = print_timestamp(buf, sizeof(buf));
|
||||
|
||||
if (fmt) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
printv(fmt, ap);
|
||||
vsnprintf(&buf[len], sizeof(buf) - len, fmt, ap);
|
||||
va_end(ap);
|
||||
strlcpy(last_desc, &buf[len], sizeof(last_desc));
|
||||
} else if (rc >= 0 && last_desc[0]) {
|
||||
/*
|
||||
* No new description, but we have one saved from an earlier
|
||||
* print(-1, ...) call. Re-print it so the final status is not
|
||||
* left stranded if command output or a kernel message scrolled
|
||||
* away the original description line.
|
||||
*/
|
||||
strlcpy(&buf[len], last_desc, sizeof(buf) - len);
|
||||
} else {
|
||||
buf[0] = 0;
|
||||
}
|
||||
|
||||
if (rc < 0)
|
||||
if (rc < 0) {
|
||||
/* Pending state: show description with spinner, no final status yet */
|
||||
if (!buf[0])
|
||||
return;
|
||||
delline();
|
||||
if (progress_style == PROGRESS_CLASSIC)
|
||||
cprintf("\r%s ", pad(buf, sizeof(buf), ".", sizeof(buf)));
|
||||
else
|
||||
cprintf("\r\e[K%s%s", status(3), buf);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Final status. Emit description + status in a single cprintf() so
|
||||
* both reach the console in one write(), preventing kernel messages or
|
||||
* command output from splitting the description from its [ OK ]/[FAIL].
|
||||
*/
|
||||
last_desc[0] = 0;
|
||||
|
||||
if (buf[0]) {
|
||||
delline();
|
||||
if (progress_style == PROGRESS_CLASSIC)
|
||||
cprintf("\r%s %s\n", pad(buf, sizeof(buf), ".", sizeof(buf)), status(rc));
|
||||
else
|
||||
cprintf("\r\e[K%s%s\r%s\n", status(3), buf, status(rc));
|
||||
} else {
|
||||
if (progress_style == PROGRESS_CLASSIC)
|
||||
cprintf("%s\n", status(rc));
|
||||
else
|
||||
cprintf("\r%s\n", status(rc));
|
||||
}
|
||||
}
|
||||
|
||||
void print_desc(char *action, char *desc)
|
||||
{
|
||||
@@ -375,6 +419,18 @@ int print_result(int fail)
|
||||
return fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset console state and drain the output buffer before kernel takeover.
|
||||
* Called just before reboot()/halt() to prevent ANSI escape codes from
|
||||
* leaking into bootloader or early-kernel output.
|
||||
*/
|
||||
void print_exit(void)
|
||||
{
|
||||
tcdrain(STDERR_FILENO);
|
||||
dprint(STDERR_FILENO, "\e[0m\e[?25h", 10); /* reset SGR, show cursor */
|
||||
tcdrain(STDERR_FILENO);
|
||||
}
|
||||
|
||||
void set_hostname(char **hostname)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
@@ -68,6 +68,7 @@ void printv (const char *fmt, va_list ap);
|
||||
void print (int action, const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
|
||||
void print_desc (char *action, char *desc);
|
||||
int print_result (int fail);
|
||||
void print_exit (void);
|
||||
|
||||
void set_hostname (char **hostname);
|
||||
void networking (int updown);
|
||||
|
||||
@@ -424,14 +424,17 @@ void do_shutdown(shutop_t op)
|
||||
}
|
||||
|
||||
print(0, "Rebooting ...");
|
||||
print_exit();
|
||||
reboot(RB_AUTOBOOT);
|
||||
} else if (op == SHUT_OFF) {
|
||||
print(0, "Powering down ...");
|
||||
print_exit();
|
||||
reboot(RB_POWER_OFF);
|
||||
}
|
||||
|
||||
/* Also fallback if any of the other two fails */
|
||||
print(0, "Halting ...");
|
||||
print_exit();
|
||||
reboot(RB_HALT_SYSTEM);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user