* 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
#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 */
/* 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 *);
/*
* 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);
}
/*
#ifdef HAVE_GETUSERSHELL
setusershell ();
while ((cp = getusershell ())) {
- if (*cp == '#') {
- continue;
- }
-
if (strcmp (cp, sh) == 0) {
found = true;
break;
&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);
}
}
* be the user's name.
*/
if (argc > (optind + 1)) {
- usage ();
+ usage (E_USAGE);
}
}
#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);
}
* 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));