]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
chsh: use libeconf to read /etc/shells
authorThorsten Kukuk <kukuk@suse.com>
Thu, 23 Nov 2023 13:23:00 +0000 (14:23 +0100)
committerThorsten Kukuk <kukuk@suse.com>
Tue, 28 Nov 2023 15:37:32 +0000 (16:37 +0100)
Signed-off-by: Thorsten Kukuk <kukuk@suse.com>
include/shells.h
lib/shells.c
login-utils/chsh.c

index ba59ba4fd3246b3b218c2b12efbf3ec04b3d6e30..c770a13ba980597329f7890816b6b5449014a568 100644 (file)
@@ -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 */
index 552b401db9e8585be375416b8070121752a79f30..18e4cca4abd06945b803005be2c90bf60f89bd39 100644 (file)
@@ -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;
 }
-
index f076d36e568d6c3c72504ed5025ad3a451558903..19f0915348e2e99573fbcd0a2ed44a0daa88531f 100644 (file)
@@ -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;