]> granicus.if.org Git - shadow/blobdiff - src/chsh.c
* src/chsh.c: No needto remove lines tarting with '#' from
[shadow] / src / chsh.c
index 269b7a150a3cb714e12d68a1dc0e308751b24da5..a2e8fe7f974451d1d4af241ed9f0d39a7f4d9cfd 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (c) 1989 - 1994, Julianne Frances Haugh
  * Copyright (c) 1996 - 2000, Marek Michałkiewicz
  * Copyright (c) 2001 - 2006, Tomasz Kłoczko
- * Copyright (c) 2007 - 2008, Nicolas François
+ * Copyright (c) 2007 - 2011, Nicolas François
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -44,7 +44,6 @@
 #include <selinux/av_permissions.h>
 #endif
 #include "defines.h"
-#include "exitcodes.h"
 #include "getdef.h"
 #include "nscd.h"
 #include "prototypes.h"
 #ifdef USE_PAM
 #include "pam_defs.h"
 #endif
+/*@-exitarg@*/
+#include "exitcodes.h"
+
 #ifndef SHELLS_FILE
 #define SHELLS_FILE "/etc/shells"
 #endif
 /*
  * Global variables
  */
-char *Prog;            /* Program name */
+const char *Prog;              /* Program name */
 static bool amroot;            /* Real UID is root */
 static char loginsh[BUFSIZ];   /* Name of new login shell */
 /* command line options */
@@ -70,7 +72,7 @@ static bool pw_locked = false;
 
 /* local function prototypes */
 static void fail_exit (int code);
-static void usage (void);
+static void usage (int status);
 static void new_fields (void);
 static bool shell_is_listed (const char *);
 static bool is_restricted_shell (const char *);
@@ -99,15 +101,15 @@ static void fail_exit (int code)
 /*
  * usage - print command line syntax and exit
  */
-static void usage (void)
+static void usage (int status)
 {
        fputs (_("Usage: chsh [options] [LOGIN]\n"
                 "\n"
                 "Options:\n"
                 "  -h, --help                    display this help message and exit\n"
                 "  -s, --shell SHELL             new login shell for the user account\n"
-                "\n"), stderr);
-       exit (E_USAGE);
+                "\n"), (E_SUCCESS != status) ? stderr : stdout);
+       exit (status);
 }
 
 /*
@@ -159,10 +161,6 @@ static bool shell_is_listed (const char *sh)
 #ifdef HAVE_GETUSERSHELL
        setusershell ();
        while ((cp = getusershell ())) {
-               if (*cp == '#') {
-                       continue;
-               }
-
                if (strcmp (cp, sh) == 0) {
                        found = true;
                        break;
@@ -215,14 +213,14 @@ static void process_flags (int argc, char **argv)
                             &option_index)) != -1) {
                switch (c) {
                case 'h':
-                       usage ();
+                       usage (E_SUCCESS);
                        break;
                case 's':
                        sflg = true;
                        STRFCPY (loginsh, optarg);
                        break;
                default:
-                       usage ();
+                       usage (E_USAGE);
                }
        }
 
@@ -231,7 +229,7 @@ static void process_flags (int argc, char **argv)
         * be the user's name.
         */
        if (argc > (optind + 1)) {
-               usage ();
+               usage (E_USAGE);
        }
 }
 
@@ -306,11 +304,14 @@ static void check_perms (const struct passwd *pw)
 #else                          /* !USE_PAM */
        pampw = getpwuid (getuid ()); /* local, no need for xgetpwuid */
        if (NULL == pampw) {
-               retval = PAM_USER_UNKNOWN;
-       } else {
-               retval = pam_start ("chsh", pampw->pw_name, &conv, &pamh);
+               fprintf (stderr,
+                        _("%s: Cannot determine your user name.\n"),
+                        Prog);
+               exit (E_NOPERM);
        }
 
+       retval = pam_start ("chsh", pampw->pw_name, &conv, &pamh);
+
        if (PAM_SUCCESS == retval) {
                retval = pam_authenticate (pamh, 0);
        }
@@ -523,17 +524,24 @@ int main (int argc, char **argv)
         * users are restricted to using the shells in /etc/shells.
         * The shell must be executable by the user.
         */
-       if (valid_field (loginsh, ":,=") != 0) {
+       if (valid_field (loginsh, ":,=\n") != 0) {
                fprintf (stderr, _("%s: Invalid entry: %s\n"), Prog, loginsh);
                fail_exit (1);
        }
        if (   !amroot
            && (   is_restricted_shell (loginsh)
                || (access (loginsh, X_OK) != 0))) {
-               fprintf (stderr, _("%s: %s is an invalid shell.\n"), Prog, loginsh);
+               fprintf (stderr, _("%s: %s is an invalid shell\n"), Prog, loginsh);
                fail_exit (1);
        }
 
+       /* Even for root, warn if an invalid shell is specified. */
+       if (access (loginsh, F_OK) != 0) {
+               fprintf (stderr, _("%s: Warning: %s does not exist\n"), Prog, loginsh);
+       } else if (access (loginsh, X_OK) != 0) {
+               fprintf (stderr, _("%s: Warning: %s is not executable\n"), Prog, loginsh);
+       }
+
        update_shell (user, loginsh);
 
        SYSLOG ((LOG_INFO, "changed user '%s' shell to '%s'", user, loginsh));