X-Git-Url: https://git.saurik.com/apple/system_cmds.git/blobdiff_plain/6d658acdb5f61932718109ed8f339604b778ab80..b58caf92d598c70ddd398b3909b0a2b8b5a110e1:/getty.tproj/main.c diff --git a/getty.tproj/main.c b/getty.tproj/main.c index cafc07d..12c78b6 100644 --- a/getty.tproj/main.c +++ b/getty.tproj/main.c @@ -1,30 +1,7 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ /*- * Copyright (c) 1980, 1993 * The Regents of the University of California. All rights reserved. + * Portions copyright (c) 2007 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -55,39 +32,54 @@ * SUCH DAMAGE. */ +#include #ifndef lint -static char copyright[] = +__unused static const char copyright[] = "@(#) Copyright (c) 1980, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint -/*static char sccsid[] = "from: @(#)main.c 8.1 (Berkeley) 6/20/93";*/ -static char rcsid[] = "$Id: main.c,v 1.1.1.2 2000/01/11 02:10:14 wsanchez Exp $"; +#if 0 +static char sccsid[] = "@(#)from: main.c 8.1 (Berkeley) 6/20/93"; +#endif +__unused static const char rcsid[] = + "$FreeBSD: src/libexec/getty/main.c,v 1.47 2005/04/06 17:42:24 stefanf Exp $"; #endif /* not lint */ #include -#include -#include #include +#include #include +#include +#include #include -#include -#include -#include + #include +#include #include +#include +#ifdef __APPLE__ +#include +#else +#include +#endif #include #include #include #include #include +#include #include #include +#ifdef __APPLE__ +#include +#endif + #include "gettytab.h" -#include "pathnames.h" #include "extern.h" +#include "pathnames.h" /* * Set the amount of running time that getty should accumulate @@ -95,23 +87,35 @@ static char rcsid[] = "$Id: main.c,v 1.1.1.2 2000/01/11 02:10:14 wsanchez Exp $" */ #define GETTY_TIMEOUT 60 /* seconds */ -struct termios tmode, omode; +#undef CTRL +#define CTRL(x) (x&037) + +/* defines for auto detection of incoming PPP calls (->PAP/CHAP) */ + +#define PPP_FRAME 0x7e /* PPP Framing character */ +#define PPP_STATION 0xff /* "All Station" character */ +#define PPP_ESCAPE 0x7d /* Escape Character */ +#define PPP_CONTROL 0x03 /* PPP Control Field */ +#define PPP_CONTROL_ESCAPED 0x23 /* PPP Control Field, escaped */ +#define PPP_LCP_HI 0xc0 /* LCP protocol - high byte */ +#define PPP_LCP_LOW 0x21 /* LCP protocol - low byte */ + +/* original mode; flags've been reset using values from */ +struct termios omode; +/* current mode */ +struct termios tmode; int crmod, digit, lower, upper; char hostname[MAXHOSTNAMELEN]; -struct utsname kerninfo; -char name[16]; +char name[MAXLOGNAME*3]; char dev[] = _PATH_DEV; char ttyn[32]; -char *portselector(); -char *ttyname(); #define OBUFSIZ 128 #define TABBUFSIZ 512 -char defent[TABBUFSIZ]; -char tabent[TABBUFSIZ]; +const char *tname; char *env[128]; @@ -138,68 +142,71 @@ char partab[] = { #define KILL tmode.c_cc[VKILL] #define EOT tmode.c_cc[VEOF] +#define puts Gputs + +static void defttymode(void); +static void dingdong(int); +static void dogettytab(void); +static int getname(void); +static void interrupt(int); +static void oflush(void); +static void prompt(void); +static void putchr(int); +static void putf(const char *); +static void putpad(const char *); +static void puts(const char *); +static void timeoverrun(int); +static char *getty_getline(int); +static void setttymode(int); +static int opentty(const char *, int); + jmp_buf timeout; static void -dingdong() +dingdong(int signo __unused) { - alarm(0); - signal(SIGALRM, SIG_DFL); longjmp(timeout, 1); } jmp_buf intrupt; static void -interrupt() +interrupt(int signo __unused) { - - signal(SIGINT, interrupt); longjmp(intrupt, 1); } /* * Action to take when getty is running too long. */ -void -timeoverrun(signo) - int signo; +static void +timeoverrun(int signo __unused) { - syslog(LOG_ERR, "getty exiting due to excessive running time\n"); + syslog(LOG_ERR, "getty exiting due to excessive running time"); exit(1); } -static int getname __P((void)); -static void oflush __P((void)); -static void prompt __P((void)); -static void putchr __P((int)); -static void putf __P((char *)); -static void putpad __P((char *)); -static void puts __P((char *)); - int -main(argc, argv) - int argc; - char *argv[]; +main(int argc, char *argv[]) { - extern char **environ; - char *tname; - long allflags; - int repcnt = 0; + extern char **environ; + int first_sleep = 1, first_time = 1; struct rlimit limit; - int ttyopenmode; + int rval; +#ifdef __APPLE__ + int ttyopenmode = O_RDWR; +#endif signal(SIGINT, SIG_IGN); -/* - signal(SIGQUIT, SIG_DFL); -*/ - openlog("getty", LOG_ODELAY|LOG_CONS, LOG_AUTH); - gethostname(hostname, sizeof(hostname)); + signal(SIGQUIT, SIG_IGN); + + openlog("getty", LOG_ODELAY|LOG_CONS|LOG_PID, LOG_AUTH); + gethostname(hostname, sizeof(hostname) - 1); + hostname[sizeof(hostname) - 1] = '\0'; if (hostname[0] == '\0') strcpy(hostname, "Amnesiac"); - uname(&kerninfo); /* * Limit running time to deal with broken or dead lines. @@ -209,134 +216,225 @@ main(argc, argv) limit.rlim_cur = GETTY_TIMEOUT; (void)setrlimit(RLIMIT_CPU, &limit); + gettable("default"); + gendefaults(); + tname = "default"; + if (argc > 1) + tname = argv[1]; + /* * The following is a work around for vhangup interactions * which cause great problems getting window systems started. * If the tty line is "-", we do the old style getty presuming - * that the file descriptors are already set up for us. + * that the file descriptors are already set up for us. * J. Gettys - MIT Project Athena. */ if (argc <= 2 || strcmp(argv[2], "-") == 0) - strcpy(ttyn, ttyname(0)); +#ifdef __APPLE__ + { + // + char* n = ttyname(STDIN_FILENO); + if (n) { + strlcpy(ttyn, n, sizeof(ttyn)); + } else { + syslog(LOG_ERR, "ttyname %m"); + exit(1); + } + } +#else + strcpy(ttyn, ttyname(STDIN_FILENO)); +#endif else { - int i; - strcpy(ttyn, dev); strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev)); if (strcmp(argv[0], "+") != 0) { chown(ttyn, 0, 0); chmod(ttyn, 0600); revoke(ttyn); + + /* + * Do the first scan through gettytab. + * Terminal mode parameters will be wrong until + * defttymode() called, but they're irrelevant for + * the initial setup of the terminal device. + */ + dogettytab(); + +#if defined(__APPLE__) && !TARGET_OS_EMBEDDED + if (strncmp(ttyn, _PATH_CONSOLE, sizeof(ttyn)) == 0) + ttyopenmode |= O_POPUP; +#endif /* - * Delay the open so DTR stays down long enough to be detected. + * Init or answer modem sequence has been specified. */ - sleep(2); + if (IC || AC) { #ifdef __APPLE__ - ttyopenmode = ((strcmp(ttyn, _PATH_CONSOLE)==0) - ? (O_RDWR |O_POPUP): O_RDWR); -#else /* __APPLE __ */ - ttyopenmode = O_RDWR; -#endif /* __APPLE__ */ - - while ((i = open(ttyn, ttyopenmode)) == -1) { - if (repcnt % 10 == 0) { - syslog(LOG_ERR, "%s: %m", ttyn); - closelog(); + if (!opentty(ttyn, ttyopenmode)) +#else + if (!opentty(ttyn, O_RDWR|O_NONBLOCK)) +#endif + exit(1); + defttymode(); + setttymode(1); + } + + if (IC) { + if (getty_chat(IC, CT, DC) > 0) { + syslog(LOG_ERR, "modem init problem on %s", ttyn); + (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode); + exit(1); } - repcnt++; - sleep(60); } - login_tty(i); - } - } - /* Start with default tty settings */ - if (tcgetattr(0, &tmode) < 0) { - syslog(LOG_ERR, "%s: %m", ttyn); - exit(1); + if (AC) { + int i, rfds; + struct timeval to; + + rfds = 1 << 0; /* FD_SET */ + to.tv_sec = RT; + to.tv_usec = 0; + i = select(32, (fd_set*)&rfds, (fd_set*)NULL, + (fd_set*)NULL, RT ? &to : NULL); + if (i < 0) { + syslog(LOG_ERR, "select %s: %m", ttyn); + } else if (i == 0) { + syslog(LOG_NOTICE, "recycle tty %s", ttyn); + (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode); + exit(0); /* recycle for init */ + } + i = getty_chat(AC, CT, DC); + if (i > 0) { + syslog(LOG_ERR, "modem answer problem on %s", ttyn); + (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode); + exit(1); + } + } else { /* maybe blocking open */ +#ifdef __APPLE__ + if (!opentty(ttyn, ttyopenmode | (NC ? O_NONBLOCK : 0 ))) +#else + if (!opentty(ttyn, O_RDWR | (NC ? O_NONBLOCK : 0 ))) +#endif + exit(1); + } + } } - omode = tmode; - gettable("default", defent); - gendefaults(); - tname = "default"; - if (argc > 1) - tname = argv[1]; + defttymode(); for (;;) { - int off; - - gettable(tname, tabent); - if (OPset || EPset || APset) - APset++, OPset++, EPset++; - setdefaults(); - off = 0; - ioctl(0, TIOCFLUSH, &off); /* clear out the crap */ - ioctl(0, FIONBIO, &off); /* turn off non-blocking mode */ - ioctl(0, FIOASYNC, &off); /* ditto for async mode */ - - if (IS) - cfsetispeed(&tmode, IS); - else if (SP) - cfsetispeed(&tmode, SP); - if (OS) - cfsetospeed(&tmode, OS); - else if (SP) - cfsetospeed(&tmode, SP); - setflags(0); - setchars(); - if (tcsetattr(0, TCSANOW, &tmode) < 0) { - syslog(LOG_ERR, "%s: %m", ttyn); - exit(1); + + /* + * if a delay was specified then sleep for that + * number of seconds before writing the initial prompt + */ + if (first_sleep && DE) { + sleep(DE); + /* remove any noise */ + (void)tcflush(STDIN_FILENO, TCIOFLUSH); } - if (AB) { - extern char *autobaud(); + first_sleep = 0; + setttymode(0); + if (AB) { tname = autobaud(); + dogettytab(); continue; } if (PS) { tname = portselector(); + dogettytab(); continue; } if (CL && *CL) putpad(CL); edithost(HE); - if (IM && *IM) + + /* if this is the first time through this, and an + issue file has been given, then send it */ + if (first_time && IF) { + int fd; + + if ((fd = open(IF, O_RDONLY)) != -1) { + char * cp; + + while ((cp = getty_getline(fd)) != NULL) { + putf(cp); + } + close(fd); + } + } + first_time = 0; + + if (IM && *IM && !(PL && PP)) putf(IM); if (setjmp(timeout)) { - tmode.c_ispeed = tmode.c_ospeed = 0; - (void)tcsetattr(0, TCSANOW, &tmode); + cfsetispeed(&tmode, B0); + cfsetospeed(&tmode, B0); + (void)tcsetattr(STDIN_FILENO, TCSANOW, &tmode); exit(1); } if (TO) { signal(SIGALRM, dingdong); alarm(TO); } - if (getname()) { - register int i; + + rval = 0; + if (AL) { + const char *p = AL; + char *q = name; + + while (*p && q < &name[sizeof name - 1]) { + if (isupper(*p)) + upper = 1; + else if (islower(*p)) + lower = 1; + else if (isdigit(*p)) + digit = 1; + *q++ = *p++; + } + } else if (!(PL && PP)) + rval = getname(); + if (rval == 2 || (PL && PP)) { + oflush(); + alarm(0); + limit.rlim_max = RLIM_INFINITY; + limit.rlim_cur = RLIM_INFINITY; + (void)setrlimit(RLIMIT_CPU, &limit); + execle(PP, "ppplogin", ttyn, (char *) 0, env); + syslog(LOG_ERR, "%s: %m", PP); + exit(1); + } else if (rval || AL) { + int i; oflush(); alarm(0); signal(SIGALRM, SIG_DFL); + if (name[0] == '\0') + continue; if (name[0] == '-') { puts("user names may not start with '-'."); continue; } - if (!(upper || lower || digit)) - continue; - setflags(2); + if (!(upper || lower || digit)) { + if (AL) { + syslog(LOG_ERR, + "invalid auto-login name: %s", AL); + exit(1); + } else + continue; + } + set_flags(2); if (crmod) { tmode.c_iflag |= ICRNL; tmode.c_oflag |= ONLCR; } -#if XXX +#if REALLY_OLD_TTYS if (upper || UC) tmode.sg_flags |= LCASE; if (lower || LC) tmode.sg_flags &= ~LCASE; #endif - if (tcsetattr(0, TCSANOW, &tmode) < 0) { - syslog(LOG_ERR, "%s: %m", ttyn); + if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) { + syslog(LOG_ERR, "tcsetattr %s: %m", ttyn); exit(1); } signal(SIGINT, SIG_DFL); @@ -347,24 +445,120 @@ main(argc, argv) limit.rlim_max = RLIM_INFINITY; limit.rlim_cur = RLIM_INFINITY; (void)setrlimit(RLIMIT_CPU, &limit); - execle(LO, "login", "-p", name, (char *) 0, env); +#ifdef __APPLE__ + // + execle(LO, "login", AL ? "-fp1" : "-p1", name, +#else + execle(LO, "login", AL ? "-fp" : "-p", name, +#endif + (char *) 0, env); syslog(LOG_ERR, "%s: %m", LO); exit(1); } alarm(0); signal(SIGALRM, SIG_DFL); signal(SIGINT, SIG_IGN); - if (NX && *NX) + if (NX && *NX) { tname = NX; + dogettytab(); + } + } +} + +static int +opentty(const char *tty, int flags) +{ + int i; + int failopenlogged = 0; + + while ((i = open(tty, flags)) == -1) + { + if (!failopenlogged) { + syslog(LOG_ERR, "open %s: %m", tty); + failopenlogged = 1; + } + sleep(60); + } + if (login_tty(i) < 0) { +#ifndef __APPLE__ + if (daemon(0,0) < 0) { + syslog(LOG_ERR,"daemon: %m"); + close(i); + return 0; + } +#endif + if (login_tty(i) < 0) { + syslog(LOG_ERR, "login_tty %s: %m", tty); + close(i); + return 0; + } + } + return 1; +} + +static void +defttymode(void) +{ + + /* Start with default tty settings. */ + if (tcgetattr(STDIN_FILENO, &tmode) < 0) { + syslog(LOG_ERR, "tcgetattr %s: %m", ttyn); + exit(1); + } + omode = tmode; /* fill c_cc for dogettytab() */ + dogettytab(); + /* + * Don't rely on the driver too much, and initialize crucial + * things according to . Avoid clobbering + * the c_cc[] settings however, the console drivers might wish + * to leave their idea of the preferred VERASE key value + * there. + */ + tmode.c_iflag = TTYDEF_IFLAG; + tmode.c_oflag = TTYDEF_OFLAG; + tmode.c_lflag = TTYDEF_LFLAG; + tmode.c_cflag = TTYDEF_CFLAG; + if (NC) + tmode.c_cflag |= CLOCAL; + omode = tmode; +} + +static void +setttymode(int raw) +{ + int off = 0; + + (void)tcflush(STDIN_FILENO, TCIOFLUSH); /* clear out the crap */ + ioctl(STDIN_FILENO, FIONBIO, &off); /* turn off non-blocking mode */ + ioctl(STDIN_FILENO, FIOASYNC, &off); /* ditto for async mode */ + + if (IS) + cfsetispeed(&tmode, speed(IS)); + else if (SP) + cfsetispeed(&tmode, speed(SP)); + if (OS) + cfsetospeed(&tmode, speed(OS)); + else if (SP) + cfsetospeed(&tmode, speed(SP)); + set_flags(0); + setchars(); + if (raw) + cfmakeraw(&tmode); + if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) { + syslog(LOG_ERR, "tcsetattr %s: %m", ttyn); + exit(1); } } + static int -getname() +getname(void) { - register int c; - register char *np; - char cs; + int c; + char *np; + unsigned char cs; + int ppp_state = 0; + int ppp_connection = 0; /* * Interrupt may happen if we use CBREAK mode @@ -374,14 +568,14 @@ getname() return (0); } signal(SIGINT, interrupt); - setflags(1); + set_flags(1); prompt(); + oflush(); if (PF > 0) { - oflush(); sleep(PF); PF = 0; } - if (tcsetattr(0, TCSANOW, &tmode) < 0) { + if (tcsetattr(STDIN_FILENO, TCSANOW, &tmode) < 0) { syslog(LOG_ERR, "%s: %m", ttyn); exit(1); } @@ -393,9 +587,37 @@ getname() exit(0); if ((c = cs&0177) == 0) return (0); - if (c == EOT) - exit(1); - if (c == '\r' || c == '\n' || np >= &name[sizeof name]) { + + /* PPP detection state machine.. + Look for sequences: + PPP_FRAME, PPP_STATION, PPP_ESCAPE, PPP_CONTROL_ESCAPED or + PPP_FRAME, PPP_STATION, PPP_CONTROL (deviant from RFC) + See RFC1662. + Derived from code from Michael Hancock, + and Erik 'PPP' Olson, + */ + + if (PP && (cs == PPP_FRAME)) { + ppp_state = 1; + } else if (ppp_state == 1 && cs == PPP_STATION) { + ppp_state = 2; + } else if (ppp_state == 2 && cs == PPP_ESCAPE) { + ppp_state = 3; + } else if ((ppp_state == 2 && cs == PPP_CONTROL) + || (ppp_state == 3 && cs == PPP_CONTROL_ESCAPED)) { + ppp_state = 4; + } else if (ppp_state == 4 && cs == PPP_LCP_HI) { + ppp_state = 5; + } else if (ppp_state == 5 && cs == PPP_LCP_LOW) { + ppp_connection = 1; + break; + } else { + ppp_state = 0; + } + + if (c == EOT || c == CTRL('d')) + exit(0); + if (c == '\r' || c == '\n' || np >= &name[sizeof name-1]) { putf("\r\n"); break; } @@ -403,7 +625,7 @@ getname() lower = 1; else if (isupper(c)) upper = 1; - else if (c == ERASE || c == '#' || c == '\b') { + else if (c == ERASE || c == '\b' || c == 0177) { if (np > name) { np--; if (cfgetospeed(&tmode) >= 1200) @@ -412,8 +634,7 @@ getname() putchr(cs); } continue; - } else if (c == KILL || c == '@') { - putchr(cs); + } else if (c == KILL || c == CTRL('u')) { putchr('\r'); if (cfgetospeed(&tmode) < 1200) putchr('\n'); @@ -421,10 +642,11 @@ getname() else if (np > name) puts(" \r"); prompt(); + digit = lower = upper = 0; np = name; continue; } else if (isdigit(c)) - digit++; + digit = 1; if (IG && (c <= ' ' || c > 0176)) continue; *np++ = c; @@ -434,18 +656,17 @@ getname() *np = 0; if (c == '\r') crmod = 1; - if (upper && !lower && !LC || UC) + if ((upper && !lower && !LC) || UC) for (np = name; *np; np++) if (isupper(*np)) *np = tolower(*np); - return (1); + return (1 + ppp_connection); } static void -putpad(s) - register char *s; +putpad(const char *s) { - register pad = 0; + int pad = 0; speed_t ospeed = cfgetospeed(&tmode); if (isdigit(*s)) { @@ -480,8 +701,7 @@ putpad(s) } static void -puts(s) - register char *s; +puts(const char *s) { while (*s) putchr(*s++); @@ -491,8 +711,7 @@ char outbuf[OBUFSIZ]; int obufcnt = 0; static void -putchr(cc) - int cc; +putchr(int cc) { char c; @@ -511,7 +730,7 @@ putchr(cc) } static void -oflush() +oflush(void) { if (obufcnt) write(STDOUT_FILENO, outbuf, obufcnt); @@ -519,7 +738,7 @@ oflush() } static void -prompt() +prompt(void) { putf(LM); @@ -527,14 +746,43 @@ prompt() putchr('\n'); } + +static char * +getty_getline(int fd) +{ + int i = 0; + static char linebuf[512]; + + /* + * This is certainly slow, but it avoids having to include + * stdio.h unnecessarily. Issue files should be small anyway. + */ + while (i < (sizeof linebuf - 3) && read(fd, linebuf+i, 1)==1) { + if (linebuf[i] == '\n') { + /* Don't rely on newline mode, assume raw */ + linebuf[i++] = '\r'; + linebuf[i++] = '\n'; + linebuf[i] = '\0'; + return linebuf; + } + ++i; + } + linebuf[i] = '\0'; + return i ? linebuf : 0; +} + static void -putf(cp) - register char *cp; +putf(const char *cp) { extern char editedhost[]; time_t t; char *slash, db[100]; + static struct utsname kerninfo; + + if (!*kerninfo.sysname) + uname(&kerninfo); + while (*cp) { if (*cp != '%') { putchr(*cp++); @@ -555,11 +803,11 @@ putf(cp) break; case 'd': { - static char fmt[] = "%l:% %P on %A, %d %B %Y"; - - fmt[4] = 'M'; /* I *hate* SCCS... */ + t = (time_t)0; (void)time(&t); - (void)strftime(db, sizeof(db), fmt, localtime(&t)); + if (Lo) + (void)setlocale(LC_TIME, Lo); + (void)strftime(db, sizeof(db), DF, localtime(&t)); puts(db); break; @@ -587,3 +835,24 @@ putf(cp) cp++; } } + +/* + * Read a gettytab database entry and perform necessary quirks. + */ +static void +dogettytab() +{ + /* Read the database entry. */ + gettable(tname); + + /* + * Avoid inheriting the parity values from the default entry + * if any of them is set in the current entry. + * Mixing different parity settings is unreasonable. + */ + if (OPset || EPset || APset || NPset) + OPset = EPset = APset = NPset = 1; + + /* Fill in default values for unset capabilities. */ + setdefaults(); +}