home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2287 / smain.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-28  |  6.4 KB  |  308 lines

  1. /*
  2.  * Copyright 1989, 1990, John F. Haugh II
  3.  * All rights reserved.
  4.  *
  5.  * Use, duplication, and disclosure prohibited without
  6.  * the express written permission of the author.
  7.  */
  8.  
  9. #include <sys/types.h>
  10. #include <stdio.h>
  11. #include <pwd.h>
  12. #ifndef    BSD
  13. #include <string.h>
  14. #include <memory.h>
  15. #include <termio.h>
  16. #else
  17. #include <strings.h>
  18. #include <sgtty.h>
  19. #define    strchr    index
  20. #define    strrchr    rindex
  21. #endif
  22. #include <signal.h>
  23. #include "config.h"
  24. #include "lastlog.h"
  25.  
  26. #ifdef    SHADOWPWD
  27. #include "shadow.h"
  28. #endif
  29.  
  30. #ifndef    lint
  31. static    char    _sccsid[] = "@(#)smain.c    2.7    10:20:06    11/9/90";
  32. #endif
  33.  
  34. #ifndef    MAXENV
  35. #define    MAXENV    64
  36. #endif
  37.  
  38. #ifndef    PATH
  39. #define    PATH    ":/bin:/usr/bin"
  40. #endif
  41.  
  42. #ifndef    SUPATH
  43. #define    SUPATH    ":/bin:/usr/bin:/etc"
  44. #endif
  45.  
  46. #ifdef    HUSHLOGIN
  47. char    hush[BUFSIZ];
  48. int    hushed;
  49. #endif
  50.  
  51. char    name[BUFSIZ];
  52. char    pass[BUFSIZ];
  53. char    home[BUFSIZ];
  54. char    prog[BUFSIZ];
  55. char    mail[BUFSIZ];
  56. char    oldname[BUFSIZ];
  57. char    *newenvp[MAXENV];
  58. int    newenvc = 0;
  59. int    maxenv = MAXENV;
  60. struct    passwd    pwent;
  61.  
  62. #ifdef    TZ
  63. FILE    *tzfile;
  64. char    tzbuf[16] = TZ;
  65. #endif
  66.  
  67. void    addenv ();
  68. void    entry ();
  69. void    sulog ();
  70. void    subsystem ();
  71. void    setup ();
  72. void    motd ();
  73. void    mailcheck ();
  74. void    shell ();
  75. void    expire ();
  76.  
  77. extern    char    **environ;
  78.  
  79. int    main (argc, argv, envp)
  80. int    argc;
  81. char    **argv;
  82. char    **envp;
  83. {
  84.     void    die ();
  85.     char    *getenv ();
  86.     char    *cp;
  87.     int    doshell;
  88.     int    fakelogin = 0;
  89.     int    amroot;
  90.     struct    passwd    *pw;
  91.     struct    passwd    *getpwuid ();
  92. #ifdef    SHADOWPWD
  93.     struct    spwd    *spwd;
  94.     struct    spwd    *getspnam();
  95. #endif
  96.  
  97.     while (*envp)            /* add inherited environment, */
  98.         addenv (*envp++);    /* some variables change later */
  99.  
  100. #ifdef    TZ
  101.     if (tzbuf[0] == '/') {
  102.         if ((tzfile = fopen (tzbuf, "r")) != (FILE *) 0) {
  103.             if (fgets (tzbuf, sizeof tzbuf, tzfile)) {
  104.                 tzbuf[strlen (tzbuf) - 1] = '\0';
  105.                 addenv (tzbuf);
  106.             }
  107.             fclose (tzfile);
  108.         }
  109.     } else {
  110.         addenv (tzbuf);
  111.     }
  112. #endif
  113. #ifdef    HZ
  114.     addenv (HZ);            /* set the default $HZ, if one */
  115. #endif
  116.     argc--; argv++;            /* shift out command name */
  117.  
  118.     if (argc > 0 && argv[0][0] == '-' && argv[0][1] == '\0') {
  119.         fakelogin = 1;
  120.         argc--; argv++;        /* shift ... */
  121.     }
  122.     if (argc > 0 && argv[0][0] != '-') {
  123.         (void) strcpy (name, argv[0]);    /* use this login id */
  124.         argc--; argv++;        /* shift ... */
  125.     }
  126.     doshell = argc == 0;        /* any arguments remaining? */
  127.  
  128.     if (pw = getpwuid (getuid ()))    /* need old user name */
  129.         (void) strcpy (oldname, pw->pw_name);
  130.     else                /* user ID MUST exist */
  131.         goto failure;
  132.  
  133.     amroot = getuid () == 0;    /* currently am super user */
  134.  
  135.     if (! name[0])             /* use default user ID */
  136.         (void) strcpy (name, "root");
  137.  
  138.     entry (name, &pwent);        /* get password file entry */
  139.     if (pwent.pw_shell == (char *) 0 || pwent.pw_shell[0] == '\0')
  140.         pwent.pw_shell = "/bin/sh";
  141.  
  142.     if (pwent.pw_name == (char *) 0) { /* unknown user */
  143.         (void) fprintf (stderr, "Unknown id: %s\n", name);
  144.         exit (1);
  145.     }
  146. #ifdef    NOUSE
  147.     if (strcmp (pwent.pw_shell, NOUSE) == 0)
  148.         goto failure;
  149. #endif
  150. #ifdef    NOLOGIN
  151.     if (strcmp (pwent.pw_shell, NOLOGIN) == 0)
  152.         if (! (pwent.pw_shell = getenv ("SHELL")))
  153.             pwent.pw_shell = "/bin/sh";
  154. #endif
  155.  
  156.     /*
  157.      * Here we have a sticky situation.  Some accounts may have no
  158.      * password entry in the password file.  So, we don't ask for a
  159.      * password.  Others, have a blank password entered - you be the
  160.      * judge.  The conditional compilation NOBLANK requires even
  161.      * blank passwords to be prompted for.  This may well break
  162.      * quite a few systems.  Use with discretion.
  163.      */
  164.  
  165.     die (0);
  166.  
  167.     signal (SIGHUP, die);
  168.     signal (SIGINT, die);
  169.     signal (SIGQUIT, die);
  170.     signal (SIGTERM, die);
  171.  
  172. #ifdef    NOBLANK
  173.     if (! amroot && ! password ("Password:", pass))
  174.         goto failure;
  175. #else
  176.     if (! amroot && (pwent.pw_name == (char *) 0 || *pwent.pw_passwd)
  177.             && ! password ("Password:", pass))
  178.         goto failure;
  179. #endif
  180.                     /* check encrypted passwords ... */
  181.     if (! amroot && ! valid (pass, &pwent)) {
  182. failure:    sulog (0);        /* log failed attempt */
  183.         puts ("Sorry.");
  184.         exit (1);
  185.     }
  186.     signal (SIGHUP, SIG_DFL);
  187.     signal (SIGINT, SIG_DFL);
  188.     signal (SIGQUIT, SIG_DFL);
  189.     signal (SIGTERM, SIG_DFL);
  190.  
  191. #ifdef    SHADOWPWD
  192.     /*
  193.      * Need to get expiration information before changing UID
  194.      */
  195.  
  196.     setspent ();
  197.     spwd = getspnam (pwent.pw_name);
  198.     endspent ();
  199. #endif
  200. #ifdef    AGING
  201.  
  202.     /*
  203.      * Check to see if the account is expired.  root gets to
  204.      * ignore any expired accounts, but normal users can't become
  205.      * a user with an expired password.
  206.      */
  207.  
  208.     if (! amroot &&
  209.             pwent.pw_age && pwent.pw_age[0]) {
  210. #ifdef    SHADOWPWD
  211.         if (spwd)
  212.             expire (spwd->sp_namp, spwd->sp_lstchg,
  213.                 spwd->sp_min, spwd->sp_max);
  214.         else
  215. #endif
  216.         expire (pwent.pw_name, (strlen (pwent.pw_age) == 4 ?
  217.             a64l (pwent.pw_age + 2):0L) * 7,
  218.             c64i (pwent.pw_age[1]), c64i (pwent.pw_age[0]));
  219.     }
  220. #endif
  221. #ifdef    SULOG
  222.     sulog (1);            /* save SU information */
  223. #endif
  224.     if (pwent.pw_uid == 0)
  225.         addenv (SUPATH);
  226.     else
  227.         addenv (PATH);
  228.  
  229.     environ = newenvp;        /* make new environment active */
  230.  
  231.     if (getenv ("IFS"))        /* don't export user IFS ... */
  232.         addenv ("IFS= \t\n");    /* ... instead, set a safe IFS */
  233.  
  234.     if (doshell && pwent.pw_shell[0] == '*') /* subsystem root required */
  235.         subsystem ();        /* figure out what to execute */
  236.  
  237.     if (fakelogin)
  238.         setup (&pwent);        /* set UID, GID, HOME, etc ... */
  239.     else {
  240.         if (setgid (pwent.pw_gid) || setuid (pwent.pw_uid))  {
  241.             perror ("Can't set ID");
  242.             exit (1);
  243.         }
  244.     }
  245.     if (! doshell) {        /* execute arguments as command */
  246.         if (cp = getenv ("SHELL"))
  247.             pwent.pw_shell = cp;
  248.         argv[-1] = pwent.pw_shell;
  249.         (void) execv (pwent.pw_shell, &argv[-1]);
  250.         (void) fprintf (stderr, "No shell\n");
  251.         exit (1);
  252.     }
  253.     if (fakelogin) {
  254. #ifdef    HUSHLOGIN
  255.         sprintf (hush, "%s/.hushlogin", strchr (home, '=') + 1);
  256.         hushed = access (hush, 0) != -1;
  257. #endif
  258. #ifdef    MOTD
  259.         motd ();        /* print the message of the day */
  260. #endif
  261. #ifdef    MAILCHECK
  262.         mailcheck ();        /* report on the status of mail */
  263. #endif
  264.         shell (pwent.pw_shell);    /* exec the shell finally. */
  265.     } else {
  266.         if (cp = strrchr (pwent.pw_shell, '/'))
  267.             cp++;
  268.         else
  269.             cp = pwent.pw_shell;
  270.  
  271.         execl (pwent.pw_shell, cp, (char *) 0);
  272.         perror (pwent.pw_shell);
  273.         exit (1);
  274.     }
  275.     /*NOTREACHED*/
  276. }
  277.  
  278. /*
  279.  * die - set or reset termio modes.
  280.  *
  281.  *    die() is called before processing begins.  signal() is then
  282.  *    called with die() as the signal handler.  If signal later
  283.  *    calls die() with a signal number, the terminal modes are
  284.  *    then reset.
  285.  */
  286.  
  287. void    die (killed)
  288. int    killed;
  289. {
  290. #ifdef    BSD
  291.     static    struct    sgtty    sgtty;
  292.  
  293.     if (killed)
  294.         stty (0, &sgtty);
  295.     else
  296.         gtty (0, &sgtty);
  297. #else
  298.     static    struct    termio    sgtty;
  299.  
  300.     if (killed)
  301.         ioctl (0, TCSETA, &sgtty);
  302.     else
  303.         ioctl (0, TCGETA, &sgtty);
  304. #endif
  305.     if (killed)
  306.         exit (killed);
  307. }
  308.