home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / libexec / getty / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-06  |  10.5 KB  |  500 lines

  1. /*-
  2.  * Copyright (c) 1980 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. char copyright[] =
  36. "@(#) Copyright (c) 1980 The Regents of the University of California.\n\
  37.  All rights reserved.\n";
  38. #endif /* not lint */
  39.  
  40. #ifndef lint
  41. static char sccsid[] = "@(#)main.c    5.16 (Berkeley) 3/27/91";
  42. #endif /* not lint */
  43.  
  44. #define USE_OLD_TTY
  45.  
  46. #include <sys/param.h>
  47. #include <sys/stat.h>
  48. #include <signal.h>
  49. #include <fcntl.h>
  50. #include <sgtty.h>
  51. #include <time.h>
  52. #include <ctype.h>
  53. #include <setjmp.h>
  54. #include <syslog.h>
  55. #include <unistd.h>
  56. #include <ctype.h>
  57. #include <stdlib.h>
  58. #include <string.h>
  59. #include "gettytab.h"
  60. #include "pathnames.h"
  61.  
  62. struct    sgttyb tmode = {
  63.     0, 0, CERASE, CKILL, 0
  64. };
  65. struct    tchars tc = {
  66.     CINTR, CQUIT, CSTART,
  67.     CSTOP, CEOF, CBRK,
  68. };
  69. struct    ltchars ltc = {
  70.     CSUSP, CDSUSP, CRPRNT,
  71.     CFLUSH, CWERASE, CLNEXT
  72. };
  73.  
  74. int crmod, digit, lower, upper;
  75.  
  76. char    hostname[MAXHOSTNAMELEN];
  77. char    name[16];
  78. char    dev[] = _PATH_DEV;
  79. char    ttyn[32];
  80. char    *portselector();
  81. char    *ttyname();
  82.  
  83. #define    OBUFSIZ        128
  84. #define    TABBUFSIZ    512
  85.  
  86. char    defent[TABBUFSIZ];
  87. char    defstrs[TABBUFSIZ];
  88. char    tabent[TABBUFSIZ];
  89. char    tabstrs[TABBUFSIZ];
  90.  
  91. char    *env[128];
  92.  
  93. char partab[] = {
  94.     0001,0201,0201,0001,0201,0001,0001,0201,
  95.     0202,0004,0003,0205,0005,0206,0201,0001,
  96.     0201,0001,0001,0201,0001,0201,0201,0001,
  97.     0001,0201,0201,0001,0201,0001,0001,0201,
  98.     0200,0000,0000,0200,0000,0200,0200,0000,
  99.     0000,0200,0200,0000,0200,0000,0000,0200,
  100.     0000,0200,0200,0000,0200,0000,0000,0200,
  101.     0200,0000,0000,0200,0000,0200,0200,0000,
  102.     0200,0000,0000,0200,0000,0200,0200,0000,
  103.     0000,0200,0200,0000,0200,0000,0000,0200,
  104.     0000,0200,0200,0000,0200,0000,0000,0200,
  105.     0200,0000,0000,0200,0000,0200,0200,0000,
  106.     0000,0200,0200,0000,0200,0000,0000,0200,
  107.     0200,0000,0000,0200,0000,0200,0200,0000,
  108.     0200,0000,0000,0200,0000,0200,0200,0000,
  109.     0000,0200,0200,0000,0200,0000,0000,0201
  110. };
  111.  
  112. #define    ERASE    tmode.sg_erase
  113. #define    KILL    tmode.sg_kill
  114. #define    EOT    tc.t_eofc
  115.  
  116. jmp_buf timeout;
  117.  
  118. static void
  119. dingdong()
  120. {
  121.  
  122.     alarm(0);
  123.     signal(SIGALRM, SIG_DFL);
  124.     longjmp(timeout, 1);
  125. }
  126.  
  127. jmp_buf    intrupt;
  128.  
  129. static void
  130. interrupt()
  131. {
  132.  
  133.     signal(SIGINT, interrupt);
  134.     longjmp(intrupt, 1);
  135. }
  136.  
  137. main(argc, argv)
  138.     int argc;
  139.     char **argv;
  140. {
  141.     extern    char **environ;
  142.     char *tname;
  143.     long allflags;
  144.     int repcnt = 0;
  145.  
  146.     signal(SIGINT, SIG_IGN);
  147. /*
  148.     signal(SIGQUIT, SIG_DFL);
  149. */
  150.     openlog("getty", LOG_ODELAY|LOG_CONS, LOG_AUTH);
  151.     gethostname(hostname, sizeof(hostname));
  152.     if (hostname[0] == '\0')
  153.         strcpy(hostname, "Amnesiac");
  154.     /*
  155.      * The following is a work around for vhangup interactions
  156.      * which cause great problems getting window systems started.
  157.      * If the tty line is "-", we do the old style getty presuming
  158.      * that the file descriptors are already set up for us. 
  159.      * J. Gettys - MIT Project Athena.
  160.      */
  161.     if (argc <= 2 || strcmp(argv[2], "-") == 0)
  162.         strcpy(ttyn, ttyname(0));
  163.     else {
  164.         int i;
  165.  
  166.         strcpy(ttyn, dev);
  167.         strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev));
  168.         if (strcmp(argv[0], "+") != 0) {
  169.         chown(ttyn, 0, 0);
  170.         chmod(ttyn, 0600);
  171.         revoke(ttyn);
  172.         /*
  173.          * Delay the open so DTR stays down long enough to be detected.
  174.          */
  175.         sleep(2);
  176.         while ((i = open(ttyn, O_RDWR)) == -1) {
  177.             if (repcnt % 10 == 0) {
  178.                 syslog(LOG_ERR, "%s: %m", ttyn);
  179.                 closelog();
  180.             }
  181.             repcnt++;
  182.             sleep(60);
  183.         }
  184.         login_tty(i);
  185.         }
  186.     }
  187.  
  188.     gettable("default", defent, defstrs);
  189.     gendefaults();
  190.     tname = "default";
  191.     if (argc > 1)
  192.         tname = argv[1];
  193.     for (;;) {
  194.         int ldisp = OTTYDISC;
  195.         int off = 0;
  196.  
  197.         gettable(tname, tabent, tabstrs);
  198.         if (OPset || EPset || APset)
  199.             APset++, OPset++, EPset++;
  200.         setdefaults();
  201.         ioctl(0, TIOCFLUSH, 0);        /* clear out the crap */
  202.         ioctl(0, FIONBIO, &off);    /* turn off non-blocking mode */
  203.         ioctl(0, FIOASYNC, &off);    /* ditto for async mode */
  204.         if (IS)
  205.             tmode.sg_ispeed = speed(IS);
  206.         else if (SP)
  207.             tmode.sg_ispeed = speed(SP);
  208.         if (OS)
  209.             tmode.sg_ospeed = speed(OS);
  210.         else if (SP)
  211.             tmode.sg_ospeed = speed(SP);
  212.         tmode.sg_flags = setflags(0);
  213.         ioctl(0, TIOCSETP, &tmode);
  214.         setchars();
  215.         ioctl(0, TIOCSETC, &tc);
  216.         if (HC)
  217.             ioctl(0, TIOCHPCL, 0);
  218.         if (AB) {
  219.             extern char *autobaud();
  220.  
  221.             tname = autobaud();
  222.             continue;
  223.         }
  224.         if (PS) {
  225.             tname = portselector();
  226.             continue;
  227.         }
  228.         if (CL && *CL)
  229.             putpad(CL);
  230.         edithost(HE);
  231.         if (IM && *IM)
  232.             putf(IM);
  233.         if (setjmp(timeout)) {
  234.             tmode.sg_ispeed = tmode.sg_ospeed = 0;
  235.             ioctl(0, TIOCSETP, &tmode);
  236.             exit(1);
  237.         }
  238.         if (TO) {
  239.             signal(SIGALRM, dingdong);
  240.             alarm(TO);
  241.         }
  242.         if (getname()) {
  243.             register int i;
  244.  
  245.             oflush();
  246.             alarm(0);
  247.             signal(SIGALRM, SIG_DFL);
  248.             if (name[0] == '-') {
  249.                 puts("user names may not start with '-'.");
  250.                 continue;
  251.             }
  252.             if (!(upper || lower || digit))
  253.                 continue;
  254.             allflags = setflags(2);
  255.             tmode.sg_flags = allflags & 0xffff;
  256.             allflags >>= 16;
  257.             if (crmod || NL)
  258.                 tmode.sg_flags |= CRMOD;
  259.             if (upper || UC)
  260.                 tmode.sg_flags |= LCASE;
  261.             if (lower || LC)
  262.                 tmode.sg_flags &= ~LCASE;
  263.             ioctl(0, TIOCSETP, &tmode);
  264.             ioctl(0, TIOCSLTC, <c);
  265.             ioctl(0, TIOCLSET, &allflags);
  266.             signal(SIGINT, SIG_DFL);
  267.             for (i = 0; environ[i] != (char *)0; i++)
  268.                 env[i] = environ[i];
  269.             makeenv(&env[i]);
  270.  
  271.             /* 
  272.              * this is what login was doing anyway.
  273.              * soon we rewrite getty completely.
  274.              */
  275.             set_ttydefaults(0);
  276.             execle(LO, "login", "-p", name, (char *) 0, env);
  277.             syslog(LOG_ERR, "%s: %m", LO);
  278.             exit(1);
  279.         }
  280.         alarm(0);
  281.         signal(SIGALRM, SIG_DFL);
  282.         signal(SIGINT, SIG_IGN);
  283.         if (NX && *NX)
  284.             tname = NX;
  285.     }
  286. }
  287.  
  288. getname()
  289. {
  290.     register int c;
  291.     register char *np;
  292.     char cs;
  293.  
  294.     /*
  295.      * Interrupt may happen if we use CBREAK mode
  296.      */
  297.     if (setjmp(intrupt)) {
  298.         signal(SIGINT, SIG_IGN);
  299.         return (0);
  300.     }
  301.     signal(SIGINT, interrupt);
  302.     tmode.sg_flags = setflags(0);
  303.     ioctl(0, TIOCSETP, &tmode);
  304.     tmode.sg_flags = setflags(1);
  305.     prompt();
  306.     if (PF > 0) {
  307.         oflush();
  308.         sleep(PF);
  309.         PF = 0;
  310.     }
  311.     ioctl(0, TIOCSETP, &tmode);
  312.     crmod = digit = lower = upper = 0;
  313.     np = name;
  314.     for (;;) {
  315.         oflush();
  316.         if (read(STDIN_FILENO, &cs, 1) <= 0)
  317.             exit(0);
  318.         if ((c = cs&0177) == 0)
  319.             return (0);
  320.         if (c == EOT)
  321.             exit(1);
  322.         if (c == '\r' || c == '\n' || np >= &name[sizeof name]) {
  323.             putf("\r\n");
  324.             break;
  325.         }
  326.         if (islower(c))
  327.             lower = 1;
  328.         else if (isupper(c))
  329.             upper = 1;
  330.         else if (c == ERASE || c == '#' || c == '\b') {
  331.             if (np > name) {
  332.                 np--;
  333.                 if (tmode.sg_ospeed >= B1200)
  334.                     puts("\b \b");
  335.                 else
  336.                     putchr(cs);
  337.             }
  338.             continue;
  339.         } else if (c == KILL || c == '@') {
  340.             putchr(cs);
  341.             putchr('\r');
  342.             if (tmode.sg_ospeed < B1200)
  343.                 putchr('\n');
  344.             /* this is the way they do it down under ... */
  345.             else if (np > name)
  346.                 puts("                                     \r");
  347.             prompt();
  348.             np = name;
  349.             continue;
  350.         } else if (isdigit(c))
  351.             digit++;
  352.         if (IG && (c <= ' ' || c > 0176))
  353.             continue;
  354.         *np++ = c;
  355.         putchr(cs);
  356.     }
  357.     signal(SIGINT, SIG_IGN);
  358.     *np = 0;
  359.     if (c == '\r')
  360.         crmod = 1;
  361.     if (upper && !lower && !LC || UC)
  362.         for (np = name; *np; np++)
  363.             if (isupper(*np))
  364.                 *np = tolower(*np);
  365.     return (1);
  366. }
  367.  
  368. static
  369. short    tmspc10[] = {
  370.     0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15
  371. };
  372.  
  373. putpad(s)
  374.     register char *s;
  375. {
  376.     register pad = 0;
  377.     register mspc10;
  378.  
  379.     if (isdigit(*s)) {
  380.         while (isdigit(*s)) {
  381.             pad *= 10;
  382.             pad += *s++ - '0';
  383.         }
  384.         pad *= 10;
  385.         if (*s == '.' && isdigit(s[1])) {
  386.             pad += s[1] - '0';
  387.             s += 2;
  388.         }
  389.     }
  390.  
  391.     puts(s);
  392.     /*
  393.      * If no delay needed, or output speed is
  394.      * not comprehensible, then don't try to delay.
  395.      */
  396.     if (pad == 0)
  397.         return;
  398.     if (tmode.sg_ospeed <= 0 ||
  399.         tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0]))
  400.         return;
  401.  
  402.     /*
  403.      * Round up by a half a character frame, and then do the delay.
  404.      * Too bad there are no user program accessible programmed delays.
  405.      * Transmitting pad characters slows many terminals down and also
  406.      * loads the system.
  407.      */
  408.     mspc10 = tmspc10[tmode.sg_ospeed];
  409.     pad += mspc10 / 2;
  410.     for (pad /= mspc10; pad > 0; pad--)
  411.         putchr(*PC);
  412. }
  413.  
  414. puts(s)
  415.     register char *s;
  416. {
  417.     while (*s)
  418.         putchr(*s++);
  419. }
  420.  
  421. char    outbuf[OBUFSIZ];
  422. int    obufcnt = 0;
  423.  
  424. putchr(cc)
  425. {
  426.     char c;
  427.  
  428.     c = cc;
  429.     if (!NP) {
  430.         c |= partab[c&0177] & 0200;
  431.         if (OP)
  432.             c ^= 0200;
  433.     }
  434.     if (!UB) {
  435.         outbuf[obufcnt++] = c;
  436.         if (obufcnt >= OBUFSIZ)
  437.             oflush();
  438.     } else
  439.         write(STDOUT_FILENO, &c, 1);
  440. }
  441.  
  442. oflush()
  443. {
  444.     if (obufcnt)
  445.         write(STDOUT_FILENO, outbuf, obufcnt);
  446.     obufcnt = 0;
  447. }
  448.  
  449. prompt()
  450. {
  451.  
  452.     putf(LM);
  453.     if (CO)
  454.         putchr('\n');
  455. }
  456.  
  457. putf(cp)
  458.     register char *cp;
  459. {
  460.     extern char editedhost[];
  461.     time_t t;
  462.     char *slash, db[100];
  463.  
  464.     while (*cp) {
  465.         if (*cp != '%') {
  466.             putchr(*cp++);
  467.             continue;
  468.         }
  469.         switch (*++cp) {
  470.  
  471.         case 't':
  472.             slash = rindex(ttyn, '/');
  473.             if (slash == (char *) 0)
  474.                 puts(ttyn);
  475.             else
  476.                 puts(&slash[1]);
  477.             break;
  478.  
  479.         case 'h':
  480.             puts(editedhost);
  481.             break;
  482.  
  483.         case 'd': {
  484.             static char fmt[] = "%l:% %P on %A, %d %B %Y";
  485.  
  486.             fmt[4] = 'M';        /* I *hate* SCCS... */
  487.             (void)time(&t);
  488.             (void)strftime(db, sizeof(db), fmt, localtime(&t));
  489.             puts(db);
  490.             break;
  491.         }
  492.  
  493.         case '%':
  494.             putchr('%');
  495.             break;
  496.         }
  497.         cp++;
  498.     }
  499. }
  500.