Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-15-SP1:GA
util-linux.15798
util-linux-agetty-smart-reload-03.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File util-linux-agetty-smart-reload-03.patch of Package util-linux.15798
Backport, rewrite. From 6522d88d08ffbba528e15ab4e081fb2846bac03d Mon Sep 17 00:00:00 2001 From: Stanislav Brabec <sbrabec@suse.cz> Date: Wed, 10 Oct 2018 19:26:34 +0200 Subject: [PATCH 03/14] agetty: Reload only if it is really needed If netlink event arrives and related escapes are part of issue, agetty reloads and re-display the prompt. Reload is triggered not only by IP address change, but also by IPv6 RAs. In some environments it causes reload several times in a minute, and even complicates the login. To prevent this, reload only if a real change appears. This consists of: split print_issue_file() to several functions: eval_issue_file() prints issue to memory. It does not affect terminal in any way. print_issue_file() prints issue file from memory. cmp_issue_file() compares the issue file and returns true, if reload is needed. The implementation requires additional change: do_prompt() does not evaluate the issue file. It is responsibility of calling function. Test suite: Use issue that contais \4 and/or \6 escape. After installing new instance, restart agetty by typing a letter and then Enter 6 times. To check whether reload happens, type a letter. When reload happens, letter disappears. 1. Unplug network cable. Wait a while and re-plug network cable. You should see 2 reloads on single stack and 3 reloads on dual stack. 2. Run a loop while : ; do sed -i '$areload_test' /etc/issue agetty --reload sleep 3 sed -i '/reload_test/d' /etc/issue agetty --reload sleep 3 done You should see regular reload every 3 seconds. 3. Run a loop while : ; do agetty --reload sleep 3 done Before: You see regular reload every 3 seconds. After: No reloads. 4. Run a loop while : ; do ifconfig lo 127.0.0.1 netmask 255.0.0.0 sleep 3 ifconfig lo 127.0.0.2 netmask 255.0.0.0 sleep 3 done Before: You see regular reload every 3 seconds. After: No reloads. Signed-off-by: Stanislav Brabec <sbrabec@suse.cz> --- term-utils/agetty.c | 141 +++++++++++++++++++++++++++++++------------- 1 file changed, 100 insertions(+), 41 deletions(-) Index: util-linux-2.31.1/term-utils/agetty.c =================================================================== --- util-linux-2.31.1.orig/term-utils/agetty.c +++ util-linux-2.31.1/term-utils/agetty.c @@ -28,6 +28,7 @@ #include <utmpx.h> #include <getopt.h> #include <time.h> +#include <stdbool.h> #include <sys/socket.h> #include <langinfo.h> #include <grp.h> @@ -320,6 +321,7 @@ static void check_username (const char* static void login_options_to_argv(char *argv[], int *argc, char *str, char *username); static void reload_agettys(void); static void print_issue_file(struct options *op, struct termios *tp); +static void eval_issue_file(struct options *op, struct termios *tp); /* Fake hostname for ut_host specified on command line. */ static char *fakehost; @@ -456,10 +458,12 @@ int main(int argc, char **argv) } if (options.flags & F_NOPROMPT) { /* --skip-login */ + eval_issue_file(&options, &termios); print_issue_file(&options, &termios); } else { /* regular (auto)login */ if (options.autolog) { /* Autologin prompt */ + eval_issue_file(&options, &termios); do_prompt(&options, &termios); printf(_("%s%s (automatic login)\n"), LOGIN, options.autolog); } else { @@ -1659,49 +1663,95 @@ static int wait_for_term_input(int fd) } } #endif /* AGETTY_RELOAD */ -static void print_issue_file(struct options *op, struct termios *tp) -{ #ifdef ISSUE - FILE *fd; +static FILE *issue_f; +static char *issue_mem = NULL; +static size_t issue_mem_sz; +static bool do_tcsetattr; +static bool do_tcrestore; #ifdef AGETTY_RELOAD - netlink_groups = 0; +static char *issue_mem_old = NULL; #endif +static bool cmp_issue_file(void) { + if (issue_mem_old && issue_mem) { + if (!strcmp(issue_mem_old, issue_mem)) { + free(issue_mem_old); + issue_mem_old = issue_mem; + issue_mem = NULL; + return false; + } + } else + return true; + return true; +} #endif +static void print_issue_file(struct options *op, struct termios *tp) +{ + int oflag = tp->c_oflag; /* Save current setting. */ + if ((op->flags & F_NONL) == 0) { /* Issue not in use, start with a new line. */ write_all(STDOUT_FILENO, "\r\n", 2); } -#ifdef ISSUE - if ((op->flags & F_ISSUE) && (fd = fopen(op->issue, "r"))) { - int c, oflag = tp->c_oflag; /* Save current setting. */ - + if (do_tcsetattr) { if ((op->flags & F_VCONSOLE) == 0) { /* Map new line in output to carriage return & new line. */ tp->c_oflag |= (ONLCR | OPOST); tcsetattr(STDIN_FILENO, TCSADRAIN, tp); } + } + + write_all(STDOUT_FILENO, issue_mem, issue_mem_sz); + if (do_tcrestore) { + /* Restore settings. */ + tp->c_oflag = oflag; + /* Wait till output is gone. */ + tcsetattr(STDIN_FILENO, TCSADRAIN, tp); + } +#ifdef AGETTY_RELOAD + free(issue_mem_old); + issue_mem_old = issue_mem; + issue_mem = NULL; +#else + free(issue_mem); + issue_mem = NULL; +#endif +} + +static void eval_issue_file(struct options *op, struct termios *tp) +{ +#ifdef ISSUE + FILE *fd; +#ifdef AGETTY_RELOAD + netlink_groups = 0; +#endif +#endif + +#ifdef ISSUE + issue_f = open_memstream(&issue_mem, &issue_mem_sz); + if ((op->flags & F_ISSUE) && (fd = fopen(op->issue, "r"))) { + int c; + + do_tcsetattr = true; while ((c = getc(fd)) != EOF) { if (c == '\\') output_special_char(getc(fd), op, tp, fd); else - putchar(c); + putc(c, issue_f); } fflush(stdout); - if ((op->flags & F_VCONSOLE) == 0) { - /* Restore settings. */ - tp->c_oflag = oflag; - /* Wait till output is gone. */ - tcsetattr(STDIN_FILENO, TCSADRAIN, tp); - } + if ((op->flags & F_VCONSOLE) == 0) + do_tcrestore = true; fclose(fd); } #ifdef AGETTY_RELOAD if (netlink_groups != 0) open_netlink(); #endif + fclose(issue_f); #endif /* ISSUE */ } @@ -1717,10 +1767,12 @@ again: puts(_("[press ENTER to login]")); #ifdef AGETTY_RELOAD if (!wait_for_term_input(STDIN_FILENO)) { - /* reload issue */ - if (op->flags & F_VCONSOLE) - termio_clear(STDOUT_FILENO); - goto again; + eval_issue_file(op, tp); + if (cmp_issue_file()) { + if (op->flags & F_VCONSOLE) + termio_clear(STDOUT_FILENO); + goto again; + } } #endif getc(stdin); @@ -1841,17 +1893,22 @@ static char *get_logname(struct options bp = logname; *bp = '\0'; + eval_issue_file(op, tp); while (*logname == '\0') { /* Write issue file and prompt */ do_prompt(op, tp); #ifdef AGETTY_RELOAD + no_reload: if (!wait_for_term_input(STDIN_FILENO)) { /* refresh prompt -- discard input data, clear terminal * and call do_prompt() again */ if ((op->flags & F_VCONSOLE) == 0) sleep(1); + eval_issue_file(op, tp); + if (!cmp_issue_file()) + goto no_reload; tcflush(STDIN_FILENO, TCIFLUSH); if (op->flags & F_VCONSOLE) termio_clear(STDOUT_FILENO); @@ -2227,7 +2284,7 @@ static void print_addr(sa_family_t famil char buff[INET6_ADDRSTRLEN + 1]; inet_ntop(family, addr, buff, sizeof(buff)); - printf("%s", buff); + fprintf(issue_f, "%s", buff); } /* @@ -2349,36 +2406,36 @@ static void output_special_char(unsigned if (get_escape_argument(fp, escname, sizeof(escname))) { const char *esc = color_sequence_from_colorname(escname); if (esc) - fputs(esc, stdout); + fputs(esc, issue_f); } else - fputs("\033", stdout); + fputs("\033", issue_f); break; } case 's': uname(&uts); - printf("%s", uts.sysname); + fprintf(issue_f, "%s", uts.sysname); break; case 'n': uname(&uts); - printf("%s", uts.nodename); + fprintf(issue_f, "%s", uts.nodename); break; case 'r': uname(&uts); - printf("%s", uts.release); + fprintf(issue_f, "%s", uts.release); break; case 'v': uname(&uts); - printf("%s", uts.version); + fprintf(issue_f, "%s", uts.version); break; case 'm': uname(&uts); - printf("%s", uts.machine); + fprintf(issue_f, "%s", uts.machine); break; case 'o': { char *dom = xgetdomainname(); - fputs(dom ? dom : "unknown_domain", stdout); + fputs(dom ? dom : "unknown_domain", issue_f); free(dom); break; } @@ -2398,7 +2455,7 @@ static void output_special_char(unsigned (canon = strchr(info->ai_canonname, '.'))) dom = canon + 1; } - fputs(dom ? dom : "unknown_domain", stdout); + fputs(dom ? dom : "unknown_domain", issue_f); if (info) freeaddrinfo(info); free(host); @@ -2417,19 +2474,19 @@ static void output_special_char(unsigned break; if (c == 'd') /* ISO 8601 */ - printf("%s %s %d %d", + fprintf(issue_f, "%s %s %d %d", nl_langinfo(ABDAY_1 + tm->tm_wday), nl_langinfo(ABMON_1 + tm->tm_mon), tm->tm_mday, tm->tm_year < 70 ? tm->tm_year + 2000 : tm->tm_year + 1900); else - printf("%02d:%02d:%02d", + fprintf(issue_f, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec); break; } case 'l': - printf ("%s", op->tty); + fprintf (issue_f, "%s", op->tty); break; case 'b': { @@ -2438,7 +2495,7 @@ static void output_special_char(unsigned for (i = 0; speedtab[i].speed; i++) { if (speedtab[i].code == speed) { - printf("%ld", speedtab[i].speed); + fprintf(issue_f, "%ld", speedtab[i].speed); break; } } @@ -2453,18 +2510,18 @@ static void output_special_char(unsigned var = read_os_release(op, varname); if (var) { if (strcmp(varname, "ANSI_COLOR") == 0) - printf("\033[%sm", var); + fprintf(issue_f, "\033[%sm", var); else - fputs(var, stdout); + fputs(var, issue_f); } /* \S */ } else if ((var = read_os_release(op, "PRETTY_NAME"))) { - fputs(var, stdout); + fputs(var, issue_f); /* \S and PRETTY_NAME not found */ } else { uname(&uts); - fputs(uts.sysname, stdout); + fputs(uts.sysname, issue_f); } free(var); @@ -2482,9 +2539,9 @@ static void output_special_char(unsigned users++; endutxent(); if (c == 'U') - printf(P_("%d user", "%d users", users), users); + fprintf(issue_f, P_("%d user", "%d users", users), users); else - printf ("%d ", users); + fprintf (issue_f, "%d ", users); break; } case '4':
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor