386BSD 0.0 development
[unix-history] / usr / src / libexec / getty / main.c
CommitLineData
35be9d13
WJ
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;
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, &ltc);
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
288getname()
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
368static
369short tmspc10[] = {
370 0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15
371};
372
373putpad(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
414puts(s)
415 register char *s;
416{
417 while (*s)
418 putchr(*s++);
419}
420
421char outbuf[OBUFSIZ];
422int obufcnt = 0;
423
424putchr(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
442oflush()
443{
444 if (obufcnt)
445 write(STDOUT_FILENO, outbuf, obufcnt);
446 obufcnt = 0;
447}
448
449prompt()
450{
451
452 putf(LM);
453 if (CO)
454 putchr('\n');
455}
456
457putf(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}