]> git.saurik.com Git - apple/system_cmds.git/blob - getty.tproj/main.c
system_cmds-336.6.tar.gz
[apple/system_cmds.git] / getty.tproj / main.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License."
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 /*-
25 * Copyright (c) 1980, 1993
26 * The Regents of the University of California. All rights reserved.
27 *
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
30 * are met:
31 * 1. Redistributions of source code must retain the above copyright
32 * notice, this list of conditions and the following disclaimer.
33 * 2. Redistributions in binary form must reproduce the above copyright
34 * notice, this list of conditions and the following disclaimer in the
35 * documentation and/or other materials provided with the distribution.
36 * 3. All advertising materials mentioning features or use of this software
37 * must display the following acknowledgement:
38 * This product includes software developed by the University of
39 * California, Berkeley and its contributors.
40 * 4. Neither the name of the University nor the names of its contributors
41 * may be used to endorse or promote products derived from this software
42 * without specific prior written permission.
43 *
44 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 * SUCH DAMAGE.
55 */
56
57 #ifndef lint
58 static char copyright[] =
59 "@(#) Copyright (c) 1980, 1993\n\
60 The Regents of the University of California. All rights reserved.\n";
61 #endif /* not lint */
62
63 #ifndef lint
64 /*static char sccsid[] = "from: @(#)main.c 8.1 (Berkeley) 6/20/93";*/
65 static char rcsid[] = "$Id: main.c,v 1.3 2004/08/26 00:32:22 lindak Exp $";
66 #endif /* not lint */
67
68 #include <sys/param.h>
69 #include <sys/stat.h>
70 #include <sys/termios.h>
71 #include <sys/ioctl.h>
72 #include <sys/resource.h>
73 #include <sys/utsname.h>
74 #include <signal.h>
75 #include <fcntl.h>
76 #include <time.h>
77 #include <ctype.h>
78 #include <fcntl.h>
79 #include <setjmp.h>
80 #include <signal.h>
81 #include <stdlib.h>
82 #include <string.h>
83 #include <syslog.h>
84 #include <time.h>
85 #include <unistd.h>
86
87 #include "gettytab.h"
88 #include "pathnames.h"
89 #include "extern.h"
90
91 /*
92 * Set the amount of running time that getty should accumulate
93 * before deciding that something is wrong and exit.
94 */
95 #define GETTY_TIMEOUT 60 /* seconds */
96
97 struct termios tmode, omode;
98
99 int crmod, digit, lower, upper;
100
101 char hostname[MAXHOSTNAMELEN];
102 struct utsname kerninfo;
103 char name[MAXLOGNAME+1];
104 char dev[] = _PATH_DEV;
105 char ttyn[32];
106 char *portselector();
107 char *ttyname();
108
109 #define OBUFSIZ 128
110 #define TABBUFSIZ 512
111
112 char defent[TABBUFSIZ];
113 char tabent[TABBUFSIZ];
114
115 char *env[128];
116
117 char partab[] = {
118 0001,0201,0201,0001,0201,0001,0001,0201,
119 0202,0004,0003,0205,0005,0206,0201,0001,
120 0201,0001,0001,0201,0001,0201,0201,0001,
121 0001,0201,0201,0001,0201,0001,0001,0201,
122 0200,0000,0000,0200,0000,0200,0200,0000,
123 0000,0200,0200,0000,0200,0000,0000,0200,
124 0000,0200,0200,0000,0200,0000,0000,0200,
125 0200,0000,0000,0200,0000,0200,0200,0000,
126 0200,0000,0000,0200,0000,0200,0200,0000,
127 0000,0200,0200,0000,0200,0000,0000,0200,
128 0000,0200,0200,0000,0200,0000,0000,0200,
129 0200,0000,0000,0200,0000,0200,0200,0000,
130 0000,0200,0200,0000,0200,0000,0000,0200,
131 0200,0000,0000,0200,0000,0200,0200,0000,
132 0200,0000,0000,0200,0000,0200,0200,0000,
133 0000,0200,0200,0000,0200,0000,0000,0201
134 };
135
136 #define ERASE tmode.c_cc[VERASE]
137 #define KILL tmode.c_cc[VKILL]
138 #define EOT tmode.c_cc[VEOF]
139
140 jmp_buf timeout;
141
142 static void
143 dingdong()
144 {
145
146 alarm(0);
147 signal(SIGALRM, SIG_DFL);
148 longjmp(timeout, 1);
149 }
150
151 jmp_buf intrupt;
152
153 static void
154 interrupt()
155 {
156
157 signal(SIGINT, interrupt);
158 longjmp(intrupt, 1);
159 }
160
161 /*
162 * Action to take when getty is running too long.
163 */
164 void
165 timeoverrun(signo)
166 int signo;
167 {
168
169 syslog(LOG_ERR, "getty exiting due to excessive running time\n");
170 exit(1);
171 }
172
173 static int getname __P((void));
174 static void oflush __P((void));
175 static void prompt __P((void));
176 static void putchr __P((int));
177 static void putf __P((char *));
178 static void putpad __P((char *));
179 static void puts __P((char *));
180
181 int
182 main(argc, argv)
183 int argc;
184 char *argv[];
185 {
186 extern char **environ;
187 char *tname;
188 long allflags;
189 int repcnt = 0;
190 struct rlimit limit;
191 int ttyopenmode;
192
193 signal(SIGINT, SIG_IGN);
194 /*
195 signal(SIGQUIT, SIG_DFL);
196 */
197 openlog("getty", LOG_ODELAY|LOG_CONS, LOG_AUTH);
198 gethostname(hostname, sizeof(hostname));
199 if (hostname[0] == '\0')
200 strcpy(hostname, "Amnesiac");
201 uname(&kerninfo);
202
203 /*
204 * Limit running time to deal with broken or dead lines.
205 */
206 (void)signal(SIGXCPU, timeoverrun);
207 limit.rlim_max = RLIM_INFINITY;
208 limit.rlim_cur = GETTY_TIMEOUT;
209 (void)setrlimit(RLIMIT_CPU, &limit);
210
211 /*
212 * The following is a work around for vhangup interactions
213 * which cause great problems getting window systems started.
214 * If the tty line is "-", we do the old style getty presuming
215 * that the file descriptors are already set up for us.
216 * J. Gettys - MIT Project Athena.
217 */
218 if (argc <= 2 || strcmp(argv[2], "-") == 0)
219 strcpy(ttyn, ttyname(0));
220 else {
221 int i;
222
223 strcpy(ttyn, dev);
224 strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev));
225 if (strcmp(argv[0], "+") != 0) {
226 chown(ttyn, 0, 0);
227 chmod(ttyn, 0600);
228 revoke(ttyn);
229 /*
230 * Delay the open so DTR stays down long enough to be detected.
231 */
232 sleep(2);
233 #ifdef __APPLE__
234 ttyopenmode = ((strcmp(ttyn, _PATH_CONSOLE)==0)
235 ? (O_RDWR |O_POPUP): O_RDWR);
236 #else /* __APPLE __ */
237 ttyopenmode = O_RDWR;
238 #endif /* __APPLE__ */
239
240 while ((i = open(ttyn, ttyopenmode)) == -1) {
241 if (repcnt % 10 == 0) {
242 syslog(LOG_ERR, "%s: %m", ttyn);
243 closelog();
244 }
245 repcnt++;
246 sleep(60);
247 }
248 login_tty(i);
249 }
250 }
251
252 /* Start with default tty settings */
253 if (tcgetattr(0, &tmode) < 0) {
254 syslog(LOG_ERR, "%s: %m", ttyn);
255 exit(1);
256 }
257 omode = tmode;
258
259 gettable("default", defent);
260 gendefaults();
261 tname = "default";
262 if (argc > 1)
263 tname = argv[1];
264 for (;;) {
265 int off;
266
267 gettable(tname, tabent);
268 if (OPset || EPset || APset)
269 APset++, OPset++, EPset++;
270 setdefaults();
271 off = 0;
272 ioctl(0, TIOCFLUSH, &off); /* clear out the crap */
273 ioctl(0, FIONBIO, &off); /* turn off non-blocking mode */
274 ioctl(0, FIOASYNC, &off); /* ditto for async mode */
275
276 if (IS)
277 cfsetispeed(&tmode, IS);
278 else if (SP)
279 cfsetispeed(&tmode, SP);
280 if (OS)
281 cfsetospeed(&tmode, OS);
282 else if (SP)
283 cfsetospeed(&tmode, SP);
284 setflags(0);
285 setchars();
286 if (tcsetattr(0, TCSANOW, &tmode) < 0) {
287 syslog(LOG_ERR, "%s: %m", ttyn);
288 exit(1);
289 }
290 if (AB) {
291 extern char *autobaud();
292
293 tname = autobaud();
294 continue;
295 }
296 if (PS) {
297 tname = portselector();
298 continue;
299 }
300 if (CL && *CL)
301 putpad(CL);
302 edithost(HE);
303 if (IM && *IM)
304 putf(IM);
305 if (setjmp(timeout)) {
306 tmode.c_ispeed = tmode.c_ospeed = 0;
307 (void)tcsetattr(0, TCSANOW, &tmode);
308 exit(1);
309 }
310 if (TO) {
311 signal(SIGALRM, dingdong);
312 alarm(TO);
313 }
314 if (getname()) {
315 register int i;
316
317 oflush();
318 alarm(0);
319 signal(SIGALRM, SIG_DFL);
320 if (name[0] == '-') {
321 puts("user names may not start with '-'.");
322 continue;
323 }
324 if (!(upper || lower || digit))
325 continue;
326 setflags(2);
327 if (crmod) {
328 tmode.c_iflag |= ICRNL;
329 tmode.c_oflag |= ONLCR;
330 }
331 #if XXX
332 if (upper || UC)
333 tmode.sg_flags |= LCASE;
334 if (lower || LC)
335 tmode.sg_flags &= ~LCASE;
336 #endif
337 if (tcsetattr(0, TCSANOW, &tmode) < 0) {
338 syslog(LOG_ERR, "%s: %m", ttyn);
339 exit(1);
340 }
341 signal(SIGINT, SIG_DFL);
342 for (i = 0; environ[i] != (char *)0; i++)
343 env[i] = environ[i];
344 makeenv(&env[i]);
345
346 limit.rlim_max = RLIM_INFINITY;
347 limit.rlim_cur = RLIM_INFINITY;
348 (void)setrlimit(RLIMIT_CPU, &limit);
349 execle(LO, "login", "-p1", name, (char *) 0, env);
350 syslog(LOG_ERR, "%s: %m", LO);
351 exit(1);
352 }
353 alarm(0);
354 signal(SIGALRM, SIG_DFL);
355 signal(SIGINT, SIG_IGN);
356 if (NX && *NX)
357 tname = NX;
358 }
359 }
360
361 static int
362 getname()
363 {
364 register int c;
365 register char *np;
366 char cs;
367
368 /*
369 * Interrupt may happen if we use CBREAK mode
370 */
371 if (setjmp(intrupt)) {
372 signal(SIGINT, SIG_IGN);
373 return (0);
374 }
375 signal(SIGINT, interrupt);
376 setflags(1);
377 prompt();
378 if (PF > 0) {
379 oflush();
380 sleep(PF);
381 PF = 0;
382 }
383 if (tcsetattr(0, TCSANOW, &tmode) < 0) {
384 syslog(LOG_ERR, "%s: %m", ttyn);
385 exit(1);
386 }
387 crmod = digit = lower = upper = 0;
388 np = name;
389 for (;;) {
390 oflush();
391 if (read(STDIN_FILENO, &cs, 1) <= 0)
392 exit(0);
393 if ((c = cs&0177) == 0)
394 return (0);
395 if (c == EOT)
396 exit(1);
397 if (c == '\r' || c == '\n' || np >= &name[sizeof name-1]) {
398 putf("\r\n");
399 break;
400 }
401 if (islower(c))
402 lower = 1;
403 else if (isupper(c))
404 upper = 1;
405 else if (c == ERASE || c == '#' || c == '\b') {
406 if (np > name) {
407 np--;
408 if (cfgetospeed(&tmode) >= 1200)
409 puts("\b \b");
410 else
411 putchr(cs);
412 }
413 continue;
414 } else if (c == KILL || c == '@') {
415 putchr(cs);
416 putchr('\r');
417 if (cfgetospeed(&tmode) < 1200)
418 putchr('\n');
419 /* this is the way they do it down under ... */
420 else if (np > name)
421 puts(" \r");
422 prompt();
423 np = name;
424 continue;
425 } else if (isdigit(c))
426 digit++;
427 if (IG && (c <= ' ' || c > 0176))
428 continue;
429 *np++ = c;
430 putchr(cs);
431 }
432 signal(SIGINT, SIG_IGN);
433 *np = 0;
434 if (c == '\r')
435 crmod = 1;
436 if (upper && !lower && !LC || UC)
437 for (np = name; *np; np++)
438 if (isupper(*np))
439 *np = tolower(*np);
440 return (1);
441 }
442
443 static void
444 putpad(s)
445 register char *s;
446 {
447 register pad = 0;
448 speed_t ospeed = cfgetospeed(&tmode);
449
450 if (isdigit(*s)) {
451 while (isdigit(*s)) {
452 pad *= 10;
453 pad += *s++ - '0';
454 }
455 pad *= 10;
456 if (*s == '.' && isdigit(s[1])) {
457 pad += s[1] - '0';
458 s += 2;
459 }
460 }
461
462 puts(s);
463 /*
464 * If no delay needed, or output speed is
465 * not comprehensible, then don't try to delay.
466 */
467 if (pad == 0 || ospeed <= 0)
468 return;
469
470 /*
471 * Round up by a half a character frame, and then do the delay.
472 * Too bad there are no user program accessible programmed delays.
473 * Transmitting pad characters slows many terminals down and also
474 * loads the system.
475 */
476 pad = (pad * ospeed + 50000) / 100000;
477 while (pad--)
478 putchr(*PC);
479 }
480
481 static void
482 puts(s)
483 register char *s;
484 {
485 while (*s)
486 putchr(*s++);
487 }
488
489 char outbuf[OBUFSIZ];
490 int obufcnt = 0;
491
492 static void
493 putchr(cc)
494 int cc;
495 {
496 char c;
497
498 c = cc;
499 if (!NP) {
500 c |= partab[c&0177] & 0200;
501 if (OP)
502 c ^= 0200;
503 }
504 if (!UB) {
505 outbuf[obufcnt++] = c;
506 if (obufcnt >= OBUFSIZ)
507 oflush();
508 } else
509 write(STDOUT_FILENO, &c, 1);
510 }
511
512 static void
513 oflush()
514 {
515 if (obufcnt)
516 write(STDOUT_FILENO, outbuf, obufcnt);
517 obufcnt = 0;
518 }
519
520 static void
521 prompt()
522 {
523
524 putf(LM);
525 if (CO)
526 putchr('\n');
527 }
528
529 static void
530 putf(cp)
531 register char *cp;
532 {
533 extern char editedhost[];
534 time_t t;
535 char *slash, db[100];
536
537 while (*cp) {
538 if (*cp != '%') {
539 putchr(*cp++);
540 continue;
541 }
542 switch (*++cp) {
543
544 case 't':
545 slash = strrchr(ttyn, '/');
546 if (slash == (char *) 0)
547 puts(ttyn);
548 else
549 puts(&slash[1]);
550 break;
551
552 case 'h':
553 puts(editedhost);
554 break;
555
556 case 'd': {
557 static char fmt[] = "%l:% %P on %A, %d %B %Y";
558
559 fmt[4] = 'M'; /* I *hate* SCCS... */
560 (void)time(&t);
561 (void)strftime(db, sizeof(db), fmt, localtime(&t));
562 puts(db);
563 break;
564
565 case 's':
566 puts(kerninfo.sysname);
567 break;
568
569 case 'm':
570 puts(kerninfo.machine);
571 break;
572
573 case 'r':
574 puts(kerninfo.release);
575 break;
576
577 case 'v':
578 puts(kerninfo.version);
579 break;
580 }
581
582 case '%':
583 putchr('%');
584 break;
585 }
586 cp++;
587 }
588 }