date and time created 88/07/22 16:08:01 by bostic
[unix-history] / usr / src / libexec / getty / main.c
CommitLineData
810b1430
DF
1/*
2 * Copyright (c) 1980 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
6
7#ifndef lint
8char copyright[] =
9"@(#) Copyright (c) 1980 Regents of the University of California.\n\
10 All rights reserved.\n";
11#endif not lint
12
21017259 13#ifndef lint
dee9e7bf 14static char sccsid[] = "@(#)main.c 5.7 (Berkeley) %G%";
810b1430 15#endif not lint
21017259
SL
16
17/*
18 * getty -- adapt to terminal speed on dialup, and call login
19 *
20 * Melbourne getty, June 83, kre.
21 */
22
23#include <sgtty.h>
24#include <signal.h>
25#include <ctype.h>
26#include <setjmp.h>
a7b4ee2b
RC
27#include <syslog.h>
28#include <sys/file.h>
21017259
SL
29#include "gettytab.h"
30
a7b4ee2b
RC
31extern char **environ;
32
21017259
SL
33struct sgttyb tmode = {
34 0, 0, CERASE, CKILL, 0
35};
36struct tchars tc = {
37 CINTR, CQUIT, CSTART,
38 CSTOP, CEOF, CBRK,
39};
40struct ltchars ltc = {
41 CSUSP, CDSUSP, CRPRNT,
42 CFLUSH, CWERASE, CLNEXT
43};
44
45int crmod;
46int upper;
47int lower;
48int digit;
49
50char hostname[32];
51char name[16];
a7b4ee2b
RC
52char dev[] = "/dev/";
53char ctty[] = "/dev/console";
54char ttyn[32];
21017259 55char *portselector();
a7b4ee2b 56char *ttyname();
21017259 57
14f797c6 58#define OBUFSIZ 128
21017259
SL
59#define TABBUFSIZ 512
60
61char defent[TABBUFSIZ];
62char defstrs[TABBUFSIZ];
63char tabent[TABBUFSIZ];
64char tabstrs[TABBUFSIZ];
65
66char *env[128];
67
68char partab[] = {
69 0001,0201,0201,0001,0201,0001,0001,0201,
70 0202,0004,0003,0205,0005,0206,0201,0001,
71 0201,0001,0001,0201,0001,0201,0201,0001,
72 0001,0201,0201,0001,0201,0001,0001,0201,
73 0200,0000,0000,0200,0000,0200,0200,0000,
74 0000,0200,0200,0000,0200,0000,0000,0200,
75 0000,0200,0200,0000,0200,0000,0000,0200,
76 0200,0000,0000,0200,0000,0200,0200,0000,
77 0200,0000,0000,0200,0000,0200,0200,0000,
78 0000,0200,0200,0000,0200,0000,0000,0200,
79 0000,0200,0200,0000,0200,0000,0000,0200,
80 0200,0000,0000,0200,0000,0200,0200,0000,
81 0000,0200,0200,0000,0200,0000,0000,0200,
82 0200,0000,0000,0200,0000,0200,0200,0000,
83 0200,0000,0000,0200,0000,0200,0200,0000,
84 0000,0200,0200,0000,0200,0000,0000,0201
85};
86
87#define ERASE tmode.sg_erase
88#define KILL tmode.sg_kill
89#define EOT tc.t_eofc
90
91jmp_buf timeout;
92
93dingdong()
94{
95
96 alarm(0);
97 signal(SIGALRM, SIG_DFL);
98 longjmp(timeout, 1);
99}
100
14f797c6
RE
101jmp_buf intrupt;
102
103interrupt()
104{
105
106 signal(SIGINT, interrupt);
107 longjmp(intrupt, 1);
108}
109
21017259
SL
110main(argc, argv)
111 char *argv[];
112{
113 char *tname;
114 long allflags;
a7b4ee2b 115 int repcnt = 0;
21017259 116
21017259 117 signal(SIGINT, SIG_IGN);
14f797c6 118/*
21017259
SL
119 signal(SIGQUIT, SIG_DFL);
120*/
46f66db5 121 openlog("getty", LOG_ODELAY|LOG_CONS, LOG_AUTH);
21017259
SL
122 gethostname(hostname, sizeof(hostname));
123 if (hostname[0] == '\0')
124 strcpy(hostname, "Amnesiac");
a7b4ee2b
RC
125 /*
126 * The following is a work around for vhangup interactions
127 * which cause great problems getting window systems started.
128 * If the tty line is "-", we do the old style getty presuming
129 * that the file descriptors are already set up for us.
130 * J. Gettys - MIT Project Athena.
131 */
132 if (argc <= 2 || strcmp(argv[2], "-") == 0)
fc683e47 133 strcpy(ttyn, ttyname(0));
a7b4ee2b 134 else {
fc683e47
JB
135 strcpy(ttyn, dev);
136 strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev));
137 if (strcmp(argv[0], "+") != 0) {
a7b4ee2b
RC
138 chown(ttyn, 0, 0);
139 chmod(ttyn, 0622);
1b5c9172
KM
140 /*
141 * Delay the open so DTR stays down long enough to be detected.
142 */
143 sleep(2);
a7b4ee2b
RC
144 while (open(ttyn, O_RDWR) != 0) {
145 if (repcnt % 10 == 0) {
da31c6da 146 syslog(LOG_ERR, "%s: %m", ttyn);
a7b4ee2b
RC
147 closelog();
148 }
149 repcnt++;
150 sleep(60);
151 }
152 signal(SIGHUP, SIG_IGN);
153 vhangup();
154 (void) open(ttyn, O_RDWR);
155 close(0);
156 dup(1);
157 dup(0);
158 signal(SIGHUP, SIG_DFL);
fc683e47 159 }
a7b4ee2b
RC
160 }
161
21017259
SL
162 gettable("default", defent, defstrs);
163 gendefaults();
164 tname = "default";
165 if (argc > 1)
166 tname = argv[1];
167 for (;;) {
168 int ldisp = OTTYDISC;
e40c2ab7 169 int off = 0;
21017259
SL
170
171 gettable(tname, tabent, tabstrs);
14f797c6
RE
172 if (OPset || EPset || APset)
173 APset++, OPset++, EPset++;
21017259
SL
174 setdefaults();
175 ioctl(0, TIOCFLUSH, 0); /* clear out the crap */
e40c2ab7
KB
176 ioctl(0, FIONBIO, &off); /* turn off non-blocking mode */
177 ioctl(0, FIOASYNC, &off); /* ditto for asynchronous mode */
21017259
SL
178 if (IS)
179 tmode.sg_ispeed = speed(IS);
180 else if (SP)
181 tmode.sg_ispeed = speed(SP);
182 if (OS)
183 tmode.sg_ospeed = speed(OS);
184 else if (SP)
185 tmode.sg_ospeed = speed(SP);
186 tmode.sg_flags = setflags(0);
187 ioctl(0, TIOCSETP, &tmode);
188 setchars();
189 ioctl(0, TIOCSETC, &tc);
190 ioctl(0, TIOCSETD, &ldisp);
191 if (HC)
192 ioctl(0, TIOCHPCL, 0);
a7b4ee2b
RC
193 if (AB) {
194 extern char *autobaud();
195
196 tname = autobaud();
197 continue;
198 }
21017259
SL
199 if (PS) {
200 tname = portselector();
201 continue;
202 }
203 if (CL && *CL)
204 putpad(CL);
205 edithost(HE);
206 if (IM && *IM)
207 putf(IM);
208 if (setjmp(timeout)) {
209 tmode.sg_ispeed = tmode.sg_ospeed = 0;
210 ioctl(0, TIOCSETP, &tmode);
211 exit(1);
212 }
213 if (TO) {
214 signal(SIGALRM, dingdong);
215 alarm(TO);
216 }
217 if (getname()) {
a7b4ee2b
RC
218 register int i;
219
220 oflush();
21017259
SL
221 alarm(0);
222 signal(SIGALRM, SIG_DFL);
dee9e7bf
KB
223 if (name[0] == '-') {
224 puts("login names may not start with '-'.");
225 continue;
226 }
76ba6586 227 if (!(upper || lower || digit))
21017259
SL
228 continue;
229 allflags = setflags(2);
230 tmode.sg_flags = allflags & 0xffff;
231 allflags >>= 16;
232 if (crmod || NL)
233 tmode.sg_flags |= CRMOD;
234 if (upper || UC)
235 tmode.sg_flags |= LCASE;
236 if (lower || LC)
237 tmode.sg_flags &= ~LCASE;
238 ioctl(0, TIOCSETP, &tmode);
239 ioctl(0, TIOCSLTC, &ltc);
240 ioctl(0, TIOCLSET, &allflags);
14f797c6 241 signal(SIGINT, SIG_DFL);
a7b4ee2b
RC
242 for (i = 0; environ[i] != (char *)0; i++)
243 env[i] = environ[i];
244 makeenv(&env[i]);
245 execle(LO, "login", "-p", name, (char *) 0, env);
e40c2ab7 246 syslog(LOG_ERR, "%s: %m", LO);
21017259
SL
247 exit(1);
248 }
249 alarm(0);
250 signal(SIGALRM, SIG_DFL);
14f797c6 251 signal(SIGINT, SIG_IGN);
21017259
SL
252 if (NX && *NX)
253 tname = NX;
254 }
255}
256
257getname()
258{
259 register char *np;
260 register c;
261 char cs;
262
14f797c6 263 /*
76ba6586 264 * Interrupt may happen if we use CBREAK mode
14f797c6
RE
265 */
266 if (setjmp(intrupt)) {
267 signal(SIGINT, SIG_IGN);
268 return (0);
269 }
270 signal(SIGINT, interrupt);
21017259
SL
271 tmode.sg_flags = setflags(0);
272 ioctl(0, TIOCSETP, &tmode);
273 tmode.sg_flags = setflags(1);
274 prompt();
b3afc78c 275 if (PF > 0) {
f0628629 276 oflush();
b3afc78c
SL
277 sleep(PF);
278 PF = 0;
279 }
21017259
SL
280 ioctl(0, TIOCSETP, &tmode);
281 crmod = 0;
282 upper = 0;
283 lower = 0;
284 digit = 0;
285 np = name;
286 for (;;) {
14f797c6 287 oflush();
21017259
SL
288 if (read(0, &cs, 1) <= 0)
289 exit(0);
290 if ((c = cs&0177) == 0)
291 return (0);
76ba6586 292 if (c == EOT)
21017259 293 exit(1);
a7b4ee2b
RC
294 if (c == '\r' || c == '\n' || np >= &name[sizeof name]) {
295 putf("\r\n");
21017259 296 break;
a7b4ee2b 297 }
76ba6586 298 if (c >= 'a' && c <= 'z')
21017259 299 lower++;
a7b4ee2b 300 else if (c >= 'A' && c <= 'Z')
21017259 301 upper++;
a7b4ee2b 302 else if (c == ERASE || c == '#' || c == '\b') {
21017259
SL
303 if (np > name) {
304 np--;
305 if (tmode.sg_ospeed >= B1200)
306 puts("\b \b");
307 else
308 putchr(cs);
309 }
310 continue;
76ba6586 311 } else if (c == KILL || c == '@') {
21017259
SL
312 putchr(cs);
313 putchr('\r');
314 if (tmode.sg_ospeed < B1200)
315 putchr('\n');
316 /* this is the way they do it down under ... */
317 else if (np > name)
318 puts(" \r");
319 prompt();
320 np = name;
321 continue;
a7b4ee2b 322 } else if (c >= '0' && c <= '9')
21017259 323 digit++;
a7b4ee2b 324 if (IG && (c <= ' ' || c > 0176))
21017259
SL
325 continue;
326 *np++ = c;
327 putchr(cs);
328 }
14f797c6 329 signal(SIGINT, SIG_IGN);
21017259
SL
330 *np = 0;
331 if (c == '\r')
332 crmod++;
333 if (upper && !lower && !LC || UC)
334 for (np = name; *np; np++)
335 if (isupper(*np))
336 *np = tolower(*np);
337 return (1);
338}
339
340static
341short tmspc10[] = {
342 0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15
343};
344
345putpad(s)
346 register char *s;
347{
348 register pad = 0;
349 register mspc10;
350
351 if (isdigit(*s)) {
352 while (isdigit(*s)) {
353 pad *= 10;
354 pad += *s++ - '0';
355 }
356 pad *= 10;
357 if (*s == '.' && isdigit(s[1])) {
358 pad += s[1] - '0';
359 s += 2;
360 }
361 }
362
363 puts(s);
364 /*
365 * If no delay needed, or output speed is
366 * not comprehensible, then don't try to delay.
367 */
368 if (pad == 0)
369 return;
370 if (tmode.sg_ospeed <= 0 ||
371 tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0]))
372 return;
373
374 /*
375 * Round up by a half a character frame,
376 * and then do the delay.
377 * Too bad there are no user program accessible programmed delays.
378 * Transmitting pad characters slows many
379 * terminals down and also loads the system.
380 */
381 mspc10 = tmspc10[tmode.sg_ospeed];
382 pad += mspc10 / 2;
383 for (pad /= mspc10; pad > 0; pad--)
384 putchr(*PC);
385}
386
387puts(s)
388 register char *s;
389{
390
391 while (*s)
392 putchr(*s++);
393}
394
14f797c6
RE
395char outbuf[OBUFSIZ];
396int obufcnt = 0;
397
21017259
SL
398putchr(cc)
399{
400 char c;
401
402 c = cc;
403 c |= partab[c&0177] & 0200;
404 if (OP)
405 c ^= 0200;
14f797c6
RE
406 if (!UB) {
407 outbuf[obufcnt++] = c;
408 if (obufcnt >= OBUFSIZ)
409 oflush();
410 } else
411 write(1, &c, 1);
412}
413
414oflush()
415{
416 if (obufcnt)
417 write(1, outbuf, obufcnt);
418 obufcnt = 0;
21017259
SL
419}
420
421prompt()
422{
423
424 putf(LM);
425 if (CO)
426 putchr('\n');
427}
428
429putf(cp)
430 register char *cp;
431{
a7b4ee2b
RC
432 char *ttyn, *slash;
433 char datebuffer[60];
21017259 434 extern char editedhost[];
a7b4ee2b 435 extern char *ttyname(), *rindex();
21017259
SL
436
437 while (*cp) {
438 if (*cp != '%') {
439 putchr(*cp++);
440 continue;
441 }
442 switch (*++cp) {
443
a7b4ee2b
RC
444 case 't':
445 ttyn = ttyname(0);
446 slash = rindex(ttyn, '/');
447 if (slash == (char *) 0)
448 puts(ttyn);
449 else
450 puts(&slash[1]);
451 break;
452
21017259
SL
453 case 'h':
454 puts(editedhost);
455 break;
456
a7b4ee2b
RC
457 case 'd':
458 get_date(datebuffer);
459 puts(datebuffer);
1dec3e0e
RC
460 break;
461
21017259
SL
462 case '%':
463 putchr('%');
464 break;
465 }
466 cp++;
467 }
468}