new copyright notice
[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
ebd6cfbb 14static 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
35extern char **environ;
36
21017259
SL
37struct sgttyb tmode = {
38 0, 0, CERASE, CKILL, 0
39};
40struct tchars tc = {
41 CINTR, CQUIT, CSTART,
42 CSTOP, CEOF, CBRK,
43};
44struct ltchars ltc = {
45 CSUSP, CDSUSP, CRPRNT,
46 CFLUSH, CWERASE, CLNEXT
47};
48
49int crmod;
50int upper;
51int lower;
52int digit;
53
a4f3e1c7 54char hostname[MAXHOSTNAMELEN];
21017259 55char name[16];
a4f3e1c7 56char dev[] = _PATH_DEV;
a7b4ee2b 57char ttyn[32];
21017259 58char *portselector();
a7b4ee2b 59char *ttyname();
21017259 60
14f797c6 61#define OBUFSIZ 128
21017259
SL
62#define TABBUFSIZ 512
63
64char defent[TABBUFSIZ];
65char defstrs[TABBUFSIZ];
66char tabent[TABBUFSIZ];
67char tabstrs[TABBUFSIZ];
68
69char *env[128];
70
71char 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
94jmp_buf timeout;
95
96dingdong()
97{
98
99 alarm(0);
100 signal(SIGALRM, SIG_DFL);
101 longjmp(timeout, 1);
102}
103
14f797c6
RE
104jmp_buf intrupt;
105
106interrupt()
107{
108
109 signal(SIGINT, interrupt);
110 longjmp(intrupt, 1);
111}
112
21017259
SL
113main(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, &ltc);
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
262getname()
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
345static
346short tmspc10[] = {
347 0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15
348};
349
350putpad(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
392puts(s)
393 register char *s;
394{
395
396 while (*s)
397 putchr(*s++);
398}
399
14f797c6
RE
400char outbuf[OBUFSIZ];
401int obufcnt = 0;
402
21017259
SL
403putchr(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
419oflush()
420{
421 if (obufcnt)
422 write(1, outbuf, obufcnt);
423 obufcnt = 0;
21017259
SL
424}
425
426prompt()
427{
428
429 putf(LM);
430 if (CO)
431 putchr('\n');
432}
433
434putf(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}