home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1989, 1990, John F. Haugh II
- * All rights reserved.
- *
- * Use, duplication, and disclosure prohibited without
- * the express written permission of the author.
- */
-
- #include <sys/types.h>
- #include <stdio.h>
- #include <pwd.h>
- #ifndef BSD
- #include <string.h>
- #include <memory.h>
- #include <termio.h>
- #else
- #include <strings.h>
- #include <sgtty.h>
- #define strchr index
- #define strrchr rindex
- #endif
- #include <signal.h>
- #include "config.h"
- #include "lastlog.h"
-
- #ifdef SHADOWPWD
- #include "shadow.h"
- #endif
-
- #ifndef lint
- static char _sccsid[] = "@(#)smain.c 2.7 10:20:06 11/9/90";
- #endif
-
- #ifndef MAXENV
- #define MAXENV 64
- #endif
-
- #ifndef PATH
- #define PATH ":/bin:/usr/bin"
- #endif
-
- #ifndef SUPATH
- #define SUPATH ":/bin:/usr/bin:/etc"
- #endif
-
- #ifdef HUSHLOGIN
- char hush[BUFSIZ];
- int hushed;
- #endif
-
- char name[BUFSIZ];
- char pass[BUFSIZ];
- char home[BUFSIZ];
- char prog[BUFSIZ];
- char mail[BUFSIZ];
- char oldname[BUFSIZ];
- char *newenvp[MAXENV];
- int newenvc = 0;
- int maxenv = MAXENV;
- struct passwd pwent;
-
- #ifdef TZ
- FILE *tzfile;
- char tzbuf[16] = TZ;
- #endif
-
- void addenv ();
- void entry ();
- void sulog ();
- void subsystem ();
- void setup ();
- void motd ();
- void mailcheck ();
- void shell ();
- void expire ();
-
- extern char **environ;
-
- int main (argc, argv, envp)
- int argc;
- char **argv;
- char **envp;
- {
- void die ();
- char *getenv ();
- char *cp;
- int doshell;
- int fakelogin = 0;
- int amroot;
- struct passwd *pw;
- struct passwd *getpwuid ();
- #ifdef SHADOWPWD
- struct spwd *spwd;
- struct spwd *getspnam();
- #endif
-
- while (*envp) /* add inherited environment, */
- addenv (*envp++); /* some variables change later */
-
- #ifdef TZ
- if (tzbuf[0] == '/') {
- if ((tzfile = fopen (tzbuf, "r")) != (FILE *) 0) {
- if (fgets (tzbuf, sizeof tzbuf, tzfile)) {
- tzbuf[strlen (tzbuf) - 1] = '\0';
- addenv (tzbuf);
- }
- fclose (tzfile);
- }
- } else {
- addenv (tzbuf);
- }
- #endif
- #ifdef HZ
- addenv (HZ); /* set the default $HZ, if one */
- #endif
- argc--; argv++; /* shift out command name */
-
- if (argc > 0 && argv[0][0] == '-' && argv[0][1] == '\0') {
- fakelogin = 1;
- argc--; argv++; /* shift ... */
- }
- if (argc > 0 && argv[0][0] != '-') {
- (void) strcpy (name, argv[0]); /* use this login id */
- argc--; argv++; /* shift ... */
- }
- doshell = argc == 0; /* any arguments remaining? */
-
- if (pw = getpwuid (getuid ())) /* need old user name */
- (void) strcpy (oldname, pw->pw_name);
- else /* user ID MUST exist */
- goto failure;
-
- amroot = getuid () == 0; /* currently am super user */
-
- if (! name[0]) /* use default user ID */
- (void) strcpy (name, "root");
-
- entry (name, &pwent); /* get password file entry */
- if (pwent.pw_shell == (char *) 0 || pwent.pw_shell[0] == '\0')
- pwent.pw_shell = "/bin/sh";
-
- if (pwent.pw_name == (char *) 0) { /* unknown user */
- (void) fprintf (stderr, "Unknown id: %s\n", name);
- exit (1);
- }
- #ifdef NOUSE
- if (strcmp (pwent.pw_shell, NOUSE) == 0)
- goto failure;
- #endif
- #ifdef NOLOGIN
- if (strcmp (pwent.pw_shell, NOLOGIN) == 0)
- if (! (pwent.pw_shell = getenv ("SHELL")))
- pwent.pw_shell = "/bin/sh";
- #endif
-
- /*
- * Here we have a sticky situation. Some accounts may have no
- * password entry in the password file. So, we don't ask for a
- * password. Others, have a blank password entered - you be the
- * judge. The conditional compilation NOBLANK requires even
- * blank passwords to be prompted for. This may well break
- * quite a few systems. Use with discretion.
- */
-
- die (0);
-
- signal (SIGHUP, die);
- signal (SIGINT, die);
- signal (SIGQUIT, die);
- signal (SIGTERM, die);
-
- #ifdef NOBLANK
- if (! amroot && ! password ("Password:", pass))
- goto failure;
- #else
- if (! amroot && (pwent.pw_name == (char *) 0 || *pwent.pw_passwd)
- && ! password ("Password:", pass))
- goto failure;
- #endif
- /* check encrypted passwords ... */
- if (! amroot && ! valid (pass, &pwent)) {
- failure: sulog (0); /* log failed attempt */
- puts ("Sorry.");
- exit (1);
- }
- signal (SIGHUP, SIG_DFL);
- signal (SIGINT, SIG_DFL);
- signal (SIGQUIT, SIG_DFL);
- signal (SIGTERM, SIG_DFL);
-
- #ifdef SHADOWPWD
- /*
- * Need to get expiration information before changing UID
- */
-
- setspent ();
- spwd = getspnam (pwent.pw_name);
- endspent ();
- #endif
- #ifdef AGING
-
- /*
- * Check to see if the account is expired. root gets to
- * ignore any expired accounts, but normal users can't become
- * a user with an expired password.
- */
-
- if (! amroot &&
- pwent.pw_age && pwent.pw_age[0]) {
- #ifdef SHADOWPWD
- if (spwd)
- expire (spwd->sp_namp, spwd->sp_lstchg,
- spwd->sp_min, spwd->sp_max);
- else
- #endif
- expire (pwent.pw_name, (strlen (pwent.pw_age) == 4 ?
- a64l (pwent.pw_age + 2):0L) * 7,
- c64i (pwent.pw_age[1]), c64i (pwent.pw_age[0]));
- }
- #endif
- #ifdef SULOG
- sulog (1); /* save SU information */
- #endif
- if (pwent.pw_uid == 0)
- addenv (SUPATH);
- else
- addenv (PATH);
-
- environ = newenvp; /* make new environment active */
-
- if (getenv ("IFS")) /* don't export user IFS ... */
- addenv ("IFS= \t\n"); /* ... instead, set a safe IFS */
-
- if (doshell && pwent.pw_shell[0] == '*') /* subsystem root required */
- subsystem (); /* figure out what to execute */
-
- if (fakelogin)
- setup (&pwent); /* set UID, GID, HOME, etc ... */
- else {
- if (setgid (pwent.pw_gid) || setuid (pwent.pw_uid)) {
- perror ("Can't set ID");
- exit (1);
- }
- }
- if (! doshell) { /* execute arguments as command */
- if (cp = getenv ("SHELL"))
- pwent.pw_shell = cp;
- argv[-1] = pwent.pw_shell;
- (void) execv (pwent.pw_shell, &argv[-1]);
- (void) fprintf (stderr, "No shell\n");
- exit (1);
- }
- if (fakelogin) {
- #ifdef HUSHLOGIN
- sprintf (hush, "%s/.hushlogin", strchr (home, '=') + 1);
- hushed = access (hush, 0) != -1;
- #endif
- #ifdef MOTD
- motd (); /* print the message of the day */
- #endif
- #ifdef MAILCHECK
- mailcheck (); /* report on the status of mail */
- #endif
- shell (pwent.pw_shell); /* exec the shell finally. */
- } else {
- if (cp = strrchr (pwent.pw_shell, '/'))
- cp++;
- else
- cp = pwent.pw_shell;
-
- execl (pwent.pw_shell, cp, (char *) 0);
- perror (pwent.pw_shell);
- exit (1);
- }
- /*NOTREACHED*/
- }
-
- /*
- * die - set or reset termio modes.
- *
- * die() is called before processing begins. signal() is then
- * called with die() as the signal handler. If signal later
- * calls die() with a signal number, the terminal modes are
- * then reset.
- */
-
- void die (killed)
- int killed;
- {
- #ifdef BSD
- static struct sgtty sgtty;
-
- if (killed)
- stty (0, &sgtty);
- else
- gtty (0, &sgtty);
- #else
- static struct termio sgtty;
-
- if (killed)
- ioctl (0, TCSETA, &sgtty);
- else
- ioctl (0, TCGETA, &sgtty);
- #endif
- if (killed)
- exit (killed);
- }
-