From: Thorsten Kukuk Date: Thu, 23 Nov 2023 13:23:00 +0000 (+0100) Subject: chsh: use libeconf to read /etc/shells X-Git-Tag: v2.40-rc1~144^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b8ecc2d3ef8894f24c6c80835e4abb3e51d16893;p=thirdparty%2Futil-linux.git chsh: use libeconf to read /etc/shells Signed-off-by: Thorsten Kukuk --- diff --git a/include/shells.h b/include/shells.h index ba59ba4fd3..c770a13ba9 100644 --- a/include/shells.h +++ b/include/shells.h @@ -4,6 +4,7 @@ #ifndef UTIL_LINUX_SHELLS_H #define UTIL_LINUX_SHELLS_H +extern void print_shells(FILE *out, const char *format); extern int is_known_shell(const char *shell_name); #endif /* UTIL_LINUX_SHELLS_H */ diff --git a/lib/shells.c b/lib/shells.c index 552b401db9..18e4cca4ab 100644 --- a/lib/shells.c +++ b/lib/shells.c @@ -9,19 +9,10 @@ #include "closestream.h" #include "shells.h" -/* - * is_known_shell() -- if the given shell appears in /etc/shells - * or vendor defined files. - * Return 1 if found and return 0 if not found. - */ -extern int is_known_shell(const char *shell_name) -{ - int ret = 0; - #if defined (HAVE_LIBECONF) && defined (USE_VENDORDIR) - size_t size = 0; +static econf_file *open_etc_shells(void) +{ econf_err error; - char **keys = NULL; econf_file *key_file = NULL; error = econf_readDirs(&key_file, @@ -35,32 +26,84 @@ extern int is_known_shell(const char *shell_name) syslog(LOG_ALERT, _("Cannot parse shells files: %s"), econf_errString(error)); - exit(EXIT_FAILURE); + return NULL; } - error = econf_getKeys(key_file, NULL, &size, &keys); - if (error) { - syslog(LOG_ALERT, - _("Cannot evaluate entries in shells files: %s"), - econf_errString(error)); - econf_free(key_file); - exit(EXIT_FAILURE); - } + return key_file; +} +#endif - for (size_t i = 0; i < size; i++) { - if (strcmp(keys[i], shell_name) == 0) { - ret = 1; - break; - } - } - econf_free(keys); - econf_free(key_file); +/* + * print_shells () -- /etc/shells is outputted to stdout. + */ +extern void print_shells(FILE *out, const char *format) +{ +#if defined (HAVE_LIBECONF) && defined (USE_VENDORDIR) + size_t size = 0; + econf_err error; + char **keys = NULL; + econf_file *key_file = open_etc_shells(); + + if (!key_file) + return; + + error = econf_getKeys(key_file, NULL, &size, &keys); + if (error) { + econf_free(key_file); + errx(EXIT_FAILURE, + _("Cannot evaluate entries in shells files: %s"), + econf_errString(error)); + } + + for (size_t i = 0; i < size; i++) { + fprintf(out, format, keys[i]); + } + econf_free(keys); + econf_free(key_file); #else - char *s; + char *s; + + while ((s = getusershell())) + fprintf(out, format, s); + endusershell(); +#endif +} + + +/* + * is_known_shell() -- if the given shell appears in /etc/shells + * or vendor defined files. + * Return 1 if found and return 0 if not found. + */ +extern int is_known_shell(const char *shell_name) +{ + int ret = 0; if (!shell_name) return 0; +#if defined (HAVE_LIBECONF) && defined (USE_VENDORDIR) + char *val = NULL; + econf_err error; + econf_file *key_file = open_etc_shells(); + + if (!key_file) + return 0; + + error = econf_getStringValue (key_file, NULL, shell_name, &val); + if (error) { + if (error != ECONF_NOKEY) + syslog(LOG_ALERT, + _("Cannot evaluate entries in shells files: %s"), + econf_errString(error)); + } else + ret = 1; + + free(val); + econf_free(key_file); +#else + char *s; + setusershell(); while ((s = getusershell())) { if (*s != '#' && strcmp(shell_name, s) == 0) { @@ -72,4 +115,3 @@ extern int is_known_shell(const char *shell_name) #endif return ret; } - diff --git a/login-utils/chsh.c b/login-utils/chsh.c index f076d36e56..19f0915348 100644 --- a/login-utils/chsh.c +++ b/login-utils/chsh.c @@ -83,18 +83,6 @@ static void __attribute__((__noreturn__)) usage(void) exit(EXIT_SUCCESS); } -/* - * print_shells () -- /etc/shells is outputted to stdout. - */ -static void print_shells(void) -{ - char *s; - - while ((s = getusershell())) - printf("%s\n", s); - endusershell(); -} - /* * parse_argv () -- * parse the command line arguments, and fill in "pinfo" with any @@ -120,7 +108,7 @@ static void parse_argv(int argc, char **argv, struct sinfo *pinfo) case 'h': usage(); case 'l': - print_shells(); + print_shells(stdout, "%s\n"); exit(EXIT_SUCCESS); case 's': pinfo->shell = optarg;