Commit | Line | Data |
---|---|---|
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 | |
8 | char 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 | 14 | static 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 |
31 | extern char **environ; |
32 | ||
21017259 SL |
33 | struct sgttyb tmode = { |
34 | 0, 0, CERASE, CKILL, 0 | |
35 | }; | |
36 | struct tchars tc = { | |
37 | CINTR, CQUIT, CSTART, | |
38 | CSTOP, CEOF, CBRK, | |
39 | }; | |
40 | struct ltchars ltc = { | |
41 | CSUSP, CDSUSP, CRPRNT, | |
42 | CFLUSH, CWERASE, CLNEXT | |
43 | }; | |
44 | ||
45 | int crmod; | |
46 | int upper; | |
47 | int lower; | |
48 | int digit; | |
49 | ||
50 | char hostname[32]; | |
51 | char name[16]; | |
a7b4ee2b RC |
52 | char dev[] = "/dev/"; |
53 | char ctty[] = "/dev/console"; | |
54 | char ttyn[32]; | |
21017259 | 55 | char *portselector(); |
a7b4ee2b | 56 | char *ttyname(); |
21017259 | 57 | |
14f797c6 | 58 | #define OBUFSIZ 128 |
21017259 SL |
59 | #define TABBUFSIZ 512 |
60 | ||
61 | char defent[TABBUFSIZ]; | |
62 | char defstrs[TABBUFSIZ]; | |
63 | char tabent[TABBUFSIZ]; | |
64 | char tabstrs[TABBUFSIZ]; | |
65 | ||
66 | char *env[128]; | |
67 | ||
68 | char 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 | ||
91 | jmp_buf timeout; | |
92 | ||
93 | dingdong() | |
94 | { | |
95 | ||
96 | alarm(0); | |
97 | signal(SIGALRM, SIG_DFL); | |
98 | longjmp(timeout, 1); | |
99 | } | |
100 | ||
14f797c6 RE |
101 | jmp_buf intrupt; |
102 | ||
103 | interrupt() | |
104 | { | |
105 | ||
106 | signal(SIGINT, interrupt); | |
107 | longjmp(intrupt, 1); | |
108 | } | |
109 | ||
21017259 SL |
110 | main(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, <c); | |
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 | ||
257 | getname() | |
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 | ||
340 | static | |
341 | short tmspc10[] = { | |
342 | 0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15 | |
343 | }; | |
344 | ||
345 | putpad(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 | ||
387 | puts(s) | |
388 | register char *s; | |
389 | { | |
390 | ||
391 | while (*s) | |
392 | putchr(*s++); | |
393 | } | |
394 | ||
14f797c6 RE |
395 | char outbuf[OBUFSIZ]; |
396 | int obufcnt = 0; | |
397 | ||
21017259 SL |
398 | putchr(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 | ||
414 | oflush() | |
415 | { | |
416 | if (obufcnt) | |
417 | write(1, outbuf, obufcnt); | |
418 | obufcnt = 0; | |
21017259 SL |
419 | } |
420 | ||
421 | prompt() | |
422 | { | |
423 | ||
424 | putf(LM); | |
425 | if (CO) | |
426 | putchr('\n'); | |
427 | } | |
428 | ||
429 | putf(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 | } |