This commit was generated by cvs2svn to track changes on a CVS vendor
[unix-history] / libexec / getty / main.c
CommitLineData
15637ed4
RG
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
35char 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
41static 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
62struct sgttyb tmode = {
63 0, 0, CERASE, CKILL, 0
64};
65struct tchars tc = {
66 CINTR, CQUIT, CSTART,
67 CSTOP, CEOF, CBRK,
68};
69struct ltchars ltc = {
70 CSUSP, CDSUSP, CRPRNT,
71 CFLUSH, CWERASE, CLNEXT
72};
73
74int crmod, digit, lower, upper;
75
76char hostname[MAXHOSTNAMELEN];
77char name[16];
78char dev[] = _PATH_DEV;
79char ttyn[32];
80char *portselector();
81char *ttyname();
82
83#define OBUFSIZ 128
84#define TABBUFSIZ 512
85
86char defent[TABBUFSIZ];
87char defstrs[TABBUFSIZ];
88char tabent[TABBUFSIZ];
89char tabstrs[TABBUFSIZ];
90
91char *env[128];
92
93char 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
116jmp_buf timeout;
117
118static void
119dingdong()
120{
121
122 alarm(0);
123 signal(SIGALRM, SIG_DFL);
124 longjmp(timeout, 1);
125}
126
127jmp_buf intrupt;
128
129static void
130interrupt()
131{
132
133 signal(SIGINT, interrupt);
134 longjmp(intrupt, 1);
135}
136
137main(argc, argv)
138 int argc;
139 char **argv;
140{
141 extern char **environ;
142 char *tname;
15637ed4
RG
143 int repcnt = 0;
144
145 signal(SIGINT, SIG_IGN);
146/*
147 signal(SIGQUIT, SIG_DFL);
148*/
149 openlog("getty", LOG_ODELAY|LOG_CONS, LOG_AUTH);
150 gethostname(hostname, sizeof(hostname));
151 if (hostname[0] == '\0')
152 strcpy(hostname, "Amnesiac");
153 /*
154 * The following is a work around for vhangup interactions
155 * which cause great problems getting window systems started.
156 * If the tty line is "-", we do the old style getty presuming
157 * that the file descriptors are already set up for us.
158 * J. Gettys - MIT Project Athena.
159 */
160 if (argc <= 2 || strcmp(argv[2], "-") == 0)
161 strcpy(ttyn, ttyname(0));
162 else {
163 int i;
164
165 strcpy(ttyn, dev);
166 strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev));
167 if (strcmp(argv[0], "+") != 0) {
168 chown(ttyn, 0, 0);
169 chmod(ttyn, 0600);
170 revoke(ttyn);
171 /*
172 * Delay the open so DTR stays down long enough to be detected.
173 */
174 sleep(2);
175 while ((i = open(ttyn, O_RDWR)) == -1) {
176 if (repcnt % 10 == 0) {
177 syslog(LOG_ERR, "%s: %m", ttyn);
178 closelog();
179 }
180 repcnt++;
181 sleep(60);
182 }
183 login_tty(i);
184 }
185 }
186
187 gettable("default", defent, defstrs);
188 gendefaults();
189 tname = "default";
190 if (argc > 1)
191 tname = argv[1];
192 for (;;) {
15637ed4 193 int off = 0;
110963ec
DG
194 int flushboth = 0;
195 struct sgttyb fake;
15637ed4
RG
196
197 gettable(tname, tabent, tabstrs);
198 if (OPset || EPset || APset)
199 APset++, OPset++, EPset++;
200 setdefaults();
110963ec 201 ioctl(0, TIOCFLUSH, &flushboth); /* clear out the crap */
15637ed4
RG
202 ioctl(0, FIONBIO, &off); /* turn off non-blocking mode */
203 ioctl(0, FIOASYNC, &off); /* ditto for async mode */
110963ec 204 ioctl(0, TIOCGETP, &fake); /* initialize kernel termios */
15637ed4
RG
205 if (IS)
206 tmode.sg_ispeed = speed(IS);
207 else if (SP)
208 tmode.sg_ispeed = speed(SP);
209 if (OS)
210 tmode.sg_ospeed = speed(OS);
211 else if (SP)
212 tmode.sg_ospeed = speed(SP);
110963ec 213 set_tmode(0);
15637ed4
RG
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;
110963ec 254 set_tmode(2);
15637ed4 255 ioctl(0, TIOCSLTC, &ltc);
15637ed4
RG
256 signal(SIGINT, SIG_DFL);
257 for (i = 0; environ[i] != (char *)0; i++)
258 env[i] = environ[i];
259 makeenv(&env[i]);
260
15637ed4
RG
261 execle(LO, "login", "-p", name, (char *) 0, env);
262 syslog(LOG_ERR, "%s: %m", LO);
263 exit(1);
264 }
265 alarm(0);
266 signal(SIGALRM, SIG_DFL);
267 signal(SIGINT, SIG_IGN);
268 if (NX && *NX)
269 tname = NX;
270 }
271}
272
273getname()
274{
275 register int c;
276 register char *np;
277 char cs;
110963ec 278 int flushin = 1 /*FREAD*/;
15637ed4
RG
279
280 /*
281 * Interrupt may happen if we use CBREAK mode
282 */
283 if (setjmp(intrupt)) {
284 signal(SIGINT, SIG_IGN);
285 return (0);
286 }
287 signal(SIGINT, interrupt);
110963ec 288 ioctl(0, TIOCFLUSH, &flushin); /* purge any input */
15637ed4 289 prompt();
110963ec 290 oflush();
15637ed4 291 if (PF > 0) {
15637ed4
RG
292 sleep(PF);
293 PF = 0;
294 }
110963ec 295 set_tmode(1);
15637ed4
RG
296 crmod = digit = lower = upper = 0;
297 np = name;
298 for (;;) {
299 oflush();
300 if (read(STDIN_FILENO, &cs, 1) <= 0)
301 exit(0);
302 if ((c = cs&0177) == 0)
303 return (0);
110963ec 304 if (c == EOT || c == 4 /*^D*/)
15637ed4
RG
305 exit(1);
306 if (c == '\r' || c == '\n' || np >= &name[sizeof name]) {
307 putf("\r\n");
308 break;
309 }
310 if (islower(c))
311 lower = 1;
312 else if (isupper(c))
313 upper = 1;
110963ec 314 else if (c == ERASE || c == '\b' || c == 0177) {
15637ed4
RG
315 if (np > name) {
316 np--;
317 if (tmode.sg_ospeed >= B1200)
318 puts("\b \b");
319 else
320 putchr(cs);
321 }
322 continue;
110963ec 323 } else if (c == KILL || c == 025 /*^U*/) {
15637ed4
RG
324 putchr('\r');
325 if (tmode.sg_ospeed < B1200)
326 putchr('\n');
327 /* this is the way they do it down under ... */
328 else if (np > name)
329 puts(" \r");
330 prompt();
331 np = name;
332 continue;
333 } else if (isdigit(c))
334 digit++;
335 if (IG && (c <= ' ' || c > 0176))
336 continue;
337 *np++ = c;
338 putchr(cs);
339 }
340 signal(SIGINT, SIG_IGN);
341 *np = 0;
342 if (c == '\r')
343 crmod = 1;
344 if (upper && !lower && !LC || UC)
345 for (np = name; *np; np++)
346 if (isupper(*np))
347 *np = tolower(*np);
348 return (1);
349}
350
351static
352short tmspc10[] = {
353 0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15
354};
355
356putpad(s)
357 register char *s;
358{
359 register pad = 0;
360 register mspc10;
361
362 if (isdigit(*s)) {
363 while (isdigit(*s)) {
364 pad *= 10;
365 pad += *s++ - '0';
366 }
367 pad *= 10;
368 if (*s == '.' && isdigit(s[1])) {
369 pad += s[1] - '0';
370 s += 2;
371 }
372 }
373
374 puts(s);
375 /*
376 * If no delay needed, or output speed is
377 * not comprehensible, then don't try to delay.
378 */
379 if (pad == 0)
380 return;
381 if (tmode.sg_ospeed <= 0 ||
382 tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0]))
383 return;
384
385 /*
386 * Round up by a half a character frame, and then do the delay.
387 * Too bad there are no user program accessible programmed delays.
388 * Transmitting pad characters slows many terminals down and also
389 * loads the system.
390 */
391 mspc10 = tmspc10[tmode.sg_ospeed];
392 pad += mspc10 / 2;
393 for (pad /= mspc10; pad > 0; pad--)
394 putchr(*PC);
395}
396
397puts(s)
398 register char *s;
399{
400 while (*s)
401 putchr(*s++);
402}
403
404char outbuf[OBUFSIZ];
405int obufcnt = 0;
406
407putchr(cc)
408{
409 char c;
410
411 c = cc;
412 if (!NP) {
413 c |= partab[c&0177] & 0200;
414 if (OP)
415 c ^= 0200;
416 }
417 if (!UB) {
418 outbuf[obufcnt++] = c;
419 if (obufcnt >= OBUFSIZ)
420 oflush();
421 } else
422 write(STDOUT_FILENO, &c, 1);
423}
424
425oflush()
426{
427 if (obufcnt)
428 write(STDOUT_FILENO, outbuf, obufcnt);
429 obufcnt = 0;
430}
431
432prompt()
433{
434
435 putf(LM);
436 if (CO)
437 putchr('\n');
438}
439
440putf(cp)
441 register char *cp;
442{
443 extern char editedhost[];
444 time_t t;
445 char *slash, db[100];
446
447 while (*cp) {
448 if (*cp != '%') {
449 putchr(*cp++);
450 continue;
451 }
452 switch (*++cp) {
453
454 case 't':
455 slash = rindex(ttyn, '/');
456 if (slash == (char *) 0)
457 puts(ttyn);
458 else
459 puts(&slash[1]);
460 break;
461
462 case 'h':
463 puts(editedhost);
464 break;
465
466 case 'd': {
467 static char fmt[] = "%l:% %P on %A, %d %B %Y";
468
469 fmt[4] = 'M'; /* I *hate* SCCS... */
470 (void)time(&t);
471 (void)strftime(db, sizeof(db), fmt, localtime(&t));
472 puts(db);
473 break;
474 }
475
476 case '%':
477 putchr('%');
478 break;
479 }
480 cp++;
481 }
482}
110963ec
DG
483
484/*
485 * The conversions from sgttyb to termios make LITOUT and PASS8 affect
486 * the parity. So every TIOCSETP ioctl has to be paired with a TIOCLSET
487 * ioctl (at least if LITOUT or PASS8 has changed, and PASS8 may vary
488 * with 'n').
489 */
490set_tmode(n)
491 int n;
492{
493 long allflags;
494
495 allflags = setflags(n);
496 tmode.sg_flags = allflags & 0xffff;
497 allflags >>= 16;
498 if (n == 2) {
499 if (crmod || NL)
500 tmode.sg_flags |= CRMOD;
501 if (upper || UC)
502 tmode.sg_flags |= LCASE;
503 if (lower || LC)
504 tmode.sg_flags &= ~LCASE;
505 }
506 ioctl(0, TIOCSETP, &tmode);
507 ioctl(0, TIOCLSET, &allflags);
508}