home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2286 / lmain.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-28  |  8.0 KB  |  372 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 <sys/stat.h>
  11. #include <stdio.h>
  12. #include <pwd.h>
  13. #include <utmp.h>
  14. #include <time.h>
  15. #include <signal.h>
  16. #ifndef    BSD
  17. #include <string.h>
  18. #include <memory.h>
  19. #else
  20. #include <strings.h>
  21. #define    strchr    index
  22. #define    strrchr    rindex
  23. #endif
  24. #ifndef    BSD
  25. #include <termio.h>
  26. #else
  27. #include <sgtty.h>
  28. #endif
  29. #include "config.h"
  30. #include "lastlog.h"
  31. #include "faillog.h"
  32. #ifdef    SHADOWPWD
  33. #include "shadow.h"
  34. #endif
  35.  
  36. #ifndef    lint
  37. static    char    _sccsid[] = "@(#)lmain.c    2.7    10:20:08    11/9/90";
  38. #endif
  39.  
  40. #ifndef    ERASECHAR
  41. #define    ERASECHAR    '\b'        /* backspace */
  42. #endif
  43.  
  44. #ifndef    KILLCHAR
  45. #define    KILLCHAR    '\025'        /* control U */
  46. #endif
  47.  
  48. char    name[BUFSIZ];
  49. char    pass[BUFSIZ];
  50. char    home[BUFSIZ];
  51. char    prog[BUFSIZ];
  52. char    mail[BUFSIZ];
  53. #ifdef    HUSHLOGIN
  54. char    hush[BUFSIZ];
  55. int    hushed;
  56. #endif
  57.  
  58. struct    passwd    pwent;
  59. struct    utmp    utent;
  60. struct    lastlog    lastlog;
  61. #ifndef    BSD
  62. struct    termio    termio;
  63. #endif
  64.  
  65. #ifndef    MAXENV
  66. #define    MAXENV    64
  67. #endif
  68.  
  69. char    *newenvp[MAXENV];
  70. int    newenvc = 0;
  71. int    maxenv = MAXENV;
  72. extern    char    **environ;
  73.  
  74. char    *getenv ();
  75. void    checkutmp ();
  76. void    addenv ();
  77. void    setenv ();
  78. unsigned alarm ();
  79. void    login ();
  80. void    entry ();
  81. void    setutmp ();
  82. void    subsystem ();
  83. void    log ();
  84. void    setup ();
  85. void    expire ();
  86. void    motd ();
  87. void    mailcheck ();
  88. void    shell ();
  89. long    a64l ();
  90. int    c64i ();
  91.  
  92. #ifdef    TZ
  93. FILE    *tzfile;
  94. char    tzbuf[32] = TZ;
  95. #endif
  96.  
  97. #ifndef    ALARM
  98. #define    ALARM    60
  99. #endif
  100.  
  101. #ifndef    RETRIES
  102. #define    RETRIES    3
  103. #endif
  104.  
  105. #ifdef    FAILLOG
  106. struct    faillog    faillog;
  107. #endif
  108. #ifdef    FTMP
  109. struct    utmp    failent;
  110. #endif
  111. #ifndef    WARNAGE
  112. #define    WARNAGE    0
  113. #endif
  114.  
  115. int    main (argc, argv, envp)
  116. int    argc;
  117. char    **argv;
  118. char    **envp;
  119. {
  120.     int    retries = RETRIES;
  121.     int    failed;
  122. #ifdef    CONSOLE
  123.     int    conflag;
  124.     char    console[BUFSIZ];
  125.     FILE    *fp;
  126.     struct    stat    statbuf;
  127. #endif
  128. #ifdef    SHADOWPWD
  129.     struct    spwd    *spwd;
  130.     struct    spwd    *getspnam();
  131. #endif
  132.  
  133.     checkutmp ();            /* must be lowest level shell */
  134.  
  135.     if (! isatty (0))        /* must be a terminal */
  136.         exit (1);
  137.  
  138. #ifndef    BSD
  139.     (void) ioctl (0, TCGETA, &termio); /* get terminal characteristics */
  140.  
  141.     /*
  142.      * Add your favorite terminal modes here ...
  143.      */
  144.  
  145.     termio.c_lflag |= ISIG;
  146.  
  147.     termio.c_cc[VERASE] = ERASECHAR;
  148.     termio.c_cc[VKILL] = KILLCHAR;
  149.     (void) ioctl (0, TCSETAF, &termio); /* set erase and kill characters */
  150. #endif
  151. #ifdef    UMASK
  152.     umask (UMASK);            /* override the default umask */
  153. #endif
  154. #ifdef    ULIMIT
  155.     ulimit (2, (long) ULIMIT);    /* override the default ulimit */
  156. #endif
  157.     while (*envp)            /* add inherited environment, */
  158.         addenv (*envp++);    /* some variables change later */
  159.  
  160. #ifdef    TZ
  161.     if (tzbuf[0] == '/') {
  162.         if ((tzfile = fopen (tzbuf, "r")) != (FILE *) 0) {
  163.             if (fgets (tzbuf, sizeof tzbuf, tzfile)) {
  164.                 tzbuf[strlen (tzbuf) - 1] = '\0';
  165.                 addenv (tzbuf);
  166.             }
  167.             fclose (tzfile);
  168.         }
  169.     } else {
  170.         addenv (tzbuf);
  171.     }
  172. #endif
  173. #ifdef    HZ
  174.     addenv (HZ);            /* set the default $HZ, if one */
  175. #endif
  176.     if (argc >= 2) {        /* now set command line variables */
  177.         setenv (argc - 2, &argv[2]);
  178.         (void) strncpy (name, argv[1], sizeof name);
  179.     }
  180.     (void) alarm (ALARM);        /* only allow ALARM sec. for login */
  181.  
  182.     while (1) {        /* repeatedly get login/password pairs */
  183.         if (! name[0]) {    /* need to get a login id */
  184.             login (name);
  185.             continue;
  186.         }
  187.         entry (name, &pwent);    /* get entry from password file */
  188.         failed = 0;        /* hasn't failed validation yet */
  189.  
  190.     /*
  191.      * Here we have a sticky situation.  Some accounts may have no
  192.      * password entry in the password file.  So, we don't ask for a
  193.      * password.  Others, have a blank password entered - you be the
  194.      * judge.  The conditional compilation NOBLANK requires even
  195.      * blank passwords to be prompted for.  This may well break
  196.      * quite a few systems.  Use with discretion.
  197.      */
  198.  
  199. #ifdef    NOBLANK
  200.                     /* get a password from user */
  201.         if (! password ("Password:", pass))
  202.             continue;
  203. #else
  204.         if ((! pwent.pw_name ||
  205.             (pwent.pw_passwd && strlen (pwent.pw_passwd) > 0))
  206.                     && ! password ("Password:", pass))
  207.             continue;
  208. #endif
  209.         if (! valid (pass, &pwent)) /* check encrypted passwords ... */
  210.             failed = 1;
  211.  
  212. #ifdef    DIALUP
  213.         alarm (30);
  214.         if (! dialcheck (utent.ut_line,
  215.                 pwent.pw_shell ? pwent.pw_shell:"/bin/sh"))
  216.             failed = 1;
  217. #endif
  218. #ifdef    PORTTIME
  219.         if (pwent.pw_name &&
  220.             ! isttytime (utent.ut_line, pwent.pw_name,
  221.                 time ((long *) 0)))
  222.             failed = 1;
  223. #endif
  224. #ifdef    CONSOLE
  225.         if (pwent.pw_uid == 0 && stat (CONSOLE, &statbuf) == 0) {
  226.             if ((statbuf.st_mode & S_IFMT) == S_IFREG) {
  227.                 fp = fopen (CONSOLE, "r");
  228.                 while (fp && fgets (console, BUFSIZ, fp)
  229.                         == console) {
  230.                     console[strlen (console) - 1] = '\0';
  231.                     if (! strcmp (console, utent.ut_line))
  232.                         break;
  233.                 }
  234.                 if (! fp || feof (fp))
  235.                     failed = 1;
  236.  
  237.                 fclose (fp);
  238.             } else {
  239.                 if (strcmp (CONSOLE, utent.ut_line))
  240.                     failed = 1;
  241.             }
  242.         }
  243. #endif
  244. #ifdef    FAILLOG
  245.         if (! failcheck (pwent.pw_uid, &faillog, failed))
  246.             failed = 1;
  247. #endif
  248.         if (! failed)
  249.             break;
  250.  
  251.         puts ("Login incorrect");
  252. #ifdef    FAILLOG
  253.         if (pwent.pw_name)    /* don't log non-existent users */
  254.             failure (pwent.pw_uid, utent.ut_line, &faillog);
  255. #endif
  256. #ifdef FTMP
  257.         failent = utent;
  258.  
  259.         if (pwent.pw_name)
  260.             strncpy (failent.ut_name,
  261.                 pwent.pw_name, sizeof failent.ut_name);
  262.         else
  263. #ifdef    UNKNOWNS
  264.             strcpy (failent.ut_name, name);
  265. #else
  266.             strcpy (failent.ut_name, "UNKNOWN");
  267. #endif
  268.         failent.ut_time = time ((time_t *) 0);
  269.         failent.ut_type = USER_PROCESS;
  270.  
  271.         failtmp (&failent);
  272. #endif /* FTMP */
  273.         if (--retries <= 0)    /* only allow so many failures */
  274.             exit (1);
  275.  
  276. #ifndef    BSD
  277.         (void) memset (name, '\0', sizeof name);
  278.         (void) memset (pass, '\0', sizeof pass);
  279. #else
  280.         bzero (name, sizeof name);
  281.         bzero (pass, sizeof pass);
  282. #endif
  283.     }
  284.     (void) alarm (0);        /* turn off alarm clock */
  285. #ifdef    NOLOGINS
  286.     /*
  287.      * Check to see if system is turned off for non-root users.
  288.      * This would be useful to prevent users from logging in
  289.      * during system maintenance.
  290.      */
  291.  
  292.     if (pwent.pw_uid != 0 && access (NOLOGINS, 0) == 0) {
  293.         printf ("\r\nSystem closed for routine maintenance\n");
  294.         exit (0);
  295.     }
  296. #endif
  297.     environ = newenvp;        /* make new environment active */
  298.  
  299.     if (getenv ("IFS"))        /* don't export user IFS ... */
  300.         addenv ("IFS= \t\n");    /* ... instead, set a safe IFS */
  301.  
  302.     setutmp ();            /* make entry in utmp & wtmp files */
  303.     if (pwent.pw_shell && pwent.pw_shell[0] == '*') /* subsystem root */
  304.         subsystem ();        /* figure out what to execute */
  305.  
  306. #ifdef    LASTLOG
  307.     log ();                /* give last login and log this one */
  308. #endif
  309. #ifdef    SHADOWPWD
  310.     /*
  311.      * Need to get expiration information before changing UID
  312.      */
  313.  
  314.     spwd = getspnam (pwent.pw_name);
  315. #endif
  316.     setup (&pwent);            /* set UID, GID, HOME, etc ... */
  317. #ifdef    AGING
  318. #ifdef    SHADOWPWD
  319.     if (spwd)
  320.         expire (spwd->sp_namp, spwd->sp_lstchg,
  321.             spwd->sp_min, spwd->sp_max);
  322.     else
  323. #endif
  324.     if (pwent.pw_age && pwent.pw_age[0]) { /* check for age of password */
  325.         expire (pwent.pw_name, (strlen (pwent.pw_age) == 4 ?
  326.             a64l (pwent.pw_age + 2):0L) * 7,
  327.             c64i (pwent.pw_age[1]) * 7,
  328.             c64i (pwent.pw_age[0]) * 7);
  329.     }
  330. #endif
  331. #ifdef    HUSHLOGIN
  332.     sprintf (hush, "%s/.hushlogin", strchr (home, '=') + 1);
  333.     hushed = access (hush, 0) != -1;
  334. #endif
  335. #ifdef    MOTD
  336.     motd ();            /* print the message of the day */
  337. #endif
  338. #ifdef    FAILLOG
  339.     if (faillog.fail_cnt != 0)
  340.         failprint (pwent.pw_uid, &faillog);
  341. #endif
  342. #ifdef    LASTLOG
  343.     if (lastlog.ll_time != 0 && ! hushed)
  344.         printf ("Last login: %.19s on %s\n",
  345.             ctime (&lastlog.ll_time), lastlog.ll_line);
  346. #endif
  347. #ifdef    AGING
  348. #ifdef    SHADOWPWD
  349.         if (spwd)
  350.             agecheck (spwd->sp_lstchg,
  351.                 spwd->sp_min, spwd->sp_max, 1);
  352.         else
  353. #endif
  354.         agecheck (strlen (pwent.pw_age) == 4 ?
  355.                 a64l (pwent.pw_age + 2):0L,
  356.             c64i (pwent.pw_age[1]), c64i (pwent.pw_age[0]), 7);
  357. #endif
  358. #ifdef    MAILCHECK
  359.     mailcheck ();            /* report on the status of mail */
  360. #endif
  361. #ifdef    TTYTYPE
  362.     ttytype (utent.ut_line);
  363. #endif
  364.     signal (SIGINT, SIG_DFL);    /* default interrupt signal */
  365.     signal (SIGQUIT, SIG_DFL);    /* default quit signal */
  366.     signal (SIGTERM, SIG_DFL);    /* default terminate signal */
  367.     signal (SIGALRM, SIG_DFL);    /* default alarm signal */
  368.  
  369.     shell (pwent.pw_shell);        /* exec the shell finally. */
  370.     /*NOTREACHED*/
  371. }
  372.