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