UNIX Power Tools

UNIX Power ToolsSearch this book
Previous: 2.15 Unclutter Logins: Show Login Messages Just Once Chapter 2
Logging In
Next: 3. Logging Out
 

2.16 Approved Shells: Using Unapproved Login Shell

Since 4.2BSD, Berkeley UNIX systems have restricted chsh (or a command like it) to change your login shell only to a shell that's listed in the file /etc/shells. That's partly a safety feature, like requiring you to type your old password before you can change to a new one: it keeps other people from giving you a strange login shell as a joke. It's also for security - a way for the system administrator to give a list of shells that are robust enough to run peoples' accounts.

The usual "approved" shells are the Bourne and C shells. If you want to use another shell as your login shell and your system has /etc/shells, ask the system administrator to add your shell. The shell will need to be stored in a secure system directory to make it harder for system crackers to corrupt the shell.

If the system administrator won't approve your login shell, here's a work-around. It lets you log in with an approved shell, then automatically replace the shell with whatever you want. (For background, see article 51.9.)

  1. If your login shell isn't C shell, use chsh or a command like it to change it to the C shell.

  2. If your new shell will be bash, you can skip this step. Otherwise:

    In your home directory, make a hard or symbolic link (18.4)directory, to your shell. Use a name starting with a minus sign (-); this makes the shell act like a login shell (51.9). For example, to make a symbolic link in your home directory named -ksh to the shell /usr/local/bin/ksh, type this command:

    ./ 
    % ln -s /usr/local/bin/ksh ./-ksh

  3. Add lines to the top of the .cshrc (2.2) file that replace the csh process with your login shell. (The exec (45.7) command replaces a process.)

    • If you use a Bourne-type shell that reads the .profile file at login time, use lines like these:

      
      TERM 
      su 
      if $? 
      
      
      
      
      
      # OVERRIDE DEFAULT LOGIN C SHELL TO USE ksh.
      setenv SHELL /usr/local/bin/ksh
      # IF $TERM SET (BY login OR rlogin), START LOGIN SHELL.
      # UNFORTUNATELY, THIS MAKES su USE A LOGIN SHELL TOO.
      if ($?TERM) then
         cd
         exec -ksh   # USE "LOGIN SHELL" SYMLINK IN $HOME
      else
         exec $SHELL
      endif
      echo "******** WARNING: exec ksh FAILED ********"

      If your new login shell will be bash, you can replace the line exec -ksh above with:

      exec $SHELL -login

      because bash has a -login option that tells it to act like a login shell. Simple, eh?

    • If your new login shell is a csh-type shell that also reads .cshrc, you need to add a test to .cshrc that prevents an infinite loop. This test uses the SH_EXECD environment variable (6.1) as a flag:

      # OVERRIDE DEFAULT LOGIN C SHELL TO USE tcsh.
      if (! $?SH_EXECD) then
         setenv SH_EXECD yes
         setenv SHELL /usr/local/bin/tcsh
         # IF $TERM SET (BY login OR rlogin), START LOGIN SHELL.
         # USE switch, NOT if, DUE TO csh BUG WITH IMBEDDED else.
         # UNFORTUNATELY, THIS MAKES su USE A LOGIN SHELL TOO.
         switch ($?TERM)
         case 1:
            cd 
            exec -tcsh    # USE "LOGIN SHELL" SYMLINK IN $HOME
            breaksw
         default:
            exec $SHELL   # USE NON-LOGIN SHELL
            breaksw
         endsw
         echo "******** WARNING: exec tcsh FAILED ********"
      endif

    • The C shell may not find your new shell (-ksh or -tcsh) unless you have the current directory (.) in your search path (8.7) (put it at the end of your path!). You may also be able to use an absolute pathname (14.2) to the new shell, but that could hide the leading minus sign (-) and the shell might not act like a login shell.

    • Is there a chance that your new shell might be missing some day? For instance, is it on a network filesystem that might be unavailable? Then it's a good idea to wrap the new code above with a test:

      -e 
      
      
      
      if (-e my-new-shell) then
          ...code to start new shell...
      else
          echo "*** WARNING: new shell failed.  Using csh. ***"
      endif

  4. Test your new setup:

    • Try commands that start subshells (38.4), like su, rsh, and so on (2.7), to be sure that they start your new shell.

    • Put the csh command set echo (8.17) at the top of your .cshrc file to be sure your commands there are working.

    • Type a command that will work only in your new shell (not in a C shell).

    • Use the ps (38.5) command ps $$ (on System V, ps -f -p $$) to look at your new shell process ($$ is your shell's process ID number (38.3)).

    • Before you log out of this shell, try logging in from somewhere else (2.4) to be sure your new shell startup files work.

  5. You're set to go.

If your login shell isn't listed in /etc/shells, the ftp (52.7) program (actually, the ftpd daemon (1.14)) may refuse to transfer files to your account. That's partly to stop ftp access to your system through special accounts that don't have passwords, like sync, who, finger, and so on. If you use the workaround steps above, though, that shouldn't be a problem; you'll have an approved shell listed in /etc/passwd and ftp usually doesn't run your login shell, anyway.

- JP


Previous: 2.15 Unclutter Logins: Show Login Messages Just Once UNIX Power ToolsNext: 3. Logging Out
2.15 Unclutter Logins: Show Login Messages Just Once Book Index3. Logging Out

The UNIX CD Bookshelf NavigationThe UNIX CD BookshelfUNIX Power ToolsUNIX in a NutshellLearning the vi Editorsed & awkLearning the Korn ShellLearning the UNIX Operating System