mirror of
https://github.com/troglobit/finit.git
synced 2026-10-02 14:02:52 +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:
+62
-6
@@ -50,6 +50,7 @@
|
|||||||
|
|
||||||
static pstyle_t progress_onoff = PROGRESS_DEFAULT;
|
static pstyle_t progress_onoff = PROGRESS_DEFAULT;
|
||||||
static pstyle_t progress_style = PROGRESS_DEFAULT;
|
static pstyle_t progress_style = PROGRESS_DEFAULT;
|
||||||
|
static char last_desc[512]; /* saved description for re-print after interruption */
|
||||||
|
|
||||||
#ifndef HOSTNAME_PATH
|
#ifndef HOSTNAME_PATH
|
||||||
#define HOSTNAME_PATH "/etc/hostname"
|
#define HOSTNAME_PATH "/etc/hostname"
|
||||||
@@ -336,6 +337,8 @@ void printv(const char *fmt, va_list ap)
|
|||||||
len = print_timestamp(buf, sizeof(buf));
|
len = print_timestamp(buf, sizeof(buf));
|
||||||
vsnprintf(&buf[len], sizeof(buf) - len, fmt, ap);
|
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)
|
if (progress_style == PROGRESS_CLASSIC)
|
||||||
cprintf("\r%s ", pad(buf, sizeof(buf), ".", sizeof(buf)));
|
cprintf("\r%s ", pad(buf, sizeof(buf), ".", sizeof(buf)));
|
||||||
else
|
else
|
||||||
@@ -344,24 +347,65 @@ void printv(const char *fmt, va_list ap)
|
|||||||
|
|
||||||
void print(int rc, const char *fmt, ...)
|
void print(int rc, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
|
char buf[ttcols];
|
||||||
|
size_t len;
|
||||||
|
|
||||||
if (progress_style == PROGRESS_SILENT)
|
if (progress_style == PROGRESS_SILENT)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
buf[0] = 0;
|
||||||
|
len = print_timestamp(buf, sizeof(buf));
|
||||||
|
|
||||||
if (fmt) {
|
if (fmt) {
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
printv(fmt, ap);
|
vsnprintf(&buf[len], sizeof(buf) - len, fmt, ap);
|
||||||
va_end(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;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (progress_style == PROGRESS_CLASSIC)
|
/*
|
||||||
cprintf("%s\n", status(rc));
|
* Final status. Emit description + status in a single cprintf() so
|
||||||
else
|
* both reach the console in one write(), preventing kernel messages or
|
||||||
cprintf("\r%s\n", status(rc));
|
* 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)
|
void print_desc(char *action, char *desc)
|
||||||
@@ -375,6 +419,18 @@ int print_result(int fail)
|
|||||||
return 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)
|
void set_hostname(char **hostname)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
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 (int action, const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
|
||||||
void print_desc (char *action, char *desc);
|
void print_desc (char *action, char *desc);
|
||||||
int print_result (int fail);
|
int print_result (int fail);
|
||||||
|
void print_exit (void);
|
||||||
|
|
||||||
void set_hostname (char **hostname);
|
void set_hostname (char **hostname);
|
||||||
void networking (int updown);
|
void networking (int updown);
|
||||||
|
|||||||
@@ -424,14 +424,17 @@ void do_shutdown(shutop_t op)
|
|||||||
}
|
}
|
||||||
|
|
||||||
print(0, "Rebooting ...");
|
print(0, "Rebooting ...");
|
||||||
|
print_exit();
|
||||||
reboot(RB_AUTOBOOT);
|
reboot(RB_AUTOBOOT);
|
||||||
} else if (op == SHUT_OFF) {
|
} else if (op == SHUT_OFF) {
|
||||||
print(0, "Powering down ...");
|
print(0, "Powering down ...");
|
||||||
|
print_exit();
|
||||||
reboot(RB_POWER_OFF);
|
reboot(RB_POWER_OFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Also fallback if any of the other two fails */
|
/* Also fallback if any of the other two fails */
|
||||||
print(0, "Halting ...");
|
print(0, "Halting ...");
|
||||||
|
print_exit();
|
||||||
reboot(RB_HALT_SYSTEM);
|
reboot(RB_HALT_SYSTEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user