boff is in blocks, and is added elsewhere.
[unix-history] / usr / src / libexec / getty / main.c
CommitLineData
21017259 1#ifndef lint
f0628629 2static char sccsid[] = "@(#)main.c 4.5 (Berkeley) 83/08/01";
21017259
SL
3#endif
4
5/*
6 * getty -- adapt to terminal speed on dialup, and call login
7 *
8 * Melbourne getty, June 83, kre.
9 */
10
11#include <sgtty.h>
12#include <signal.h>
13#include <ctype.h>
14#include <setjmp.h>
15#include "gettytab.h"
16
17struct sgttyb tmode = {
18 0, 0, CERASE, CKILL, 0
19};
20struct tchars tc = {
21 CINTR, CQUIT, CSTART,
22 CSTOP, CEOF, CBRK,
23};
24struct ltchars ltc = {
25 CSUSP, CDSUSP, CRPRNT,
26 CFLUSH, CWERASE, CLNEXT
27};
28
29int crmod;
30int upper;
31int lower;
32int digit;
33
34char hostname[32];
35char name[16];
36char *portselector();
37
14f797c6 38#define OBUFSIZ 128
21017259
SL
39#define TABBUFSIZ 512
40
41char defent[TABBUFSIZ];
42char defstrs[TABBUFSIZ];
43char tabent[TABBUFSIZ];
44char tabstrs[TABBUFSIZ];
45
46char *env[128];
47
48char partab[] = {
49 0001,0201,0201,0001,0201,0001,0001,0201,
50 0202,0004,0003,0205,0005,0206,0201,0001,
51 0201,0001,0001,0201,0001,0201,0201,0001,
52 0001,0201,0201,0001,0201,0001,0001,0201,
53 0200,0000,0000,0200,0000,0200,0200,0000,
54 0000,0200,0200,0000,0200,0000,0000,0200,
55 0000,0200,0200,0000,0200,0000,0000,0200,
56 0200,0000,0000,0200,0000,0200,0200,0000,
57 0200,0000,0000,0200,0000,0200,0200,0000,
58 0000,0200,0200,0000,0200,0000,0000,0200,
59 0000,0200,0200,0000,0200,0000,0000,0200,
60 0200,0000,0000,0200,0000,0200,0200,0000,
61 0000,0200,0200,0000,0200,0000,0000,0200,
62 0200,0000,0000,0200,0000,0200,0200,0000,
63 0200,0000,0000,0200,0000,0200,0200,0000,
64 0000,0200,0200,0000,0200,0000,0000,0201
65};
66
67#define ERASE tmode.sg_erase
68#define KILL tmode.sg_kill
69#define EOT tc.t_eofc
70
71jmp_buf timeout;
72
73dingdong()
74{
75
76 alarm(0);
77 signal(SIGALRM, SIG_DFL);
78 longjmp(timeout, 1);
79}
80
14f797c6
RE
81jmp_buf intrupt;
82
83interrupt()
84{
85
86 signal(SIGINT, interrupt);
87 longjmp(intrupt, 1);
88}
89
21017259
SL
90main(argc, argv)
91 char *argv[];
92{
93 char *tname;
94 long allflags;
95
21017259 96 signal(SIGINT, SIG_IGN);
14f797c6 97/*
21017259
SL
98 signal(SIGQUIT, SIG_DFL);
99*/
100 gethostname(hostname, sizeof(hostname));
101 if (hostname[0] == '\0')
102 strcpy(hostname, "Amnesiac");
103 gettable("default", defent, defstrs);
104 gendefaults();
105 tname = "default";
106 if (argc > 1)
107 tname = argv[1];
108 for (;;) {
109 int ldisp = OTTYDISC;
110
111 gettable(tname, tabent, tabstrs);
14f797c6
RE
112 if (OPset || EPset || APset)
113 APset++, OPset++, EPset++;
21017259
SL
114 setdefaults();
115 ioctl(0, TIOCFLUSH, 0); /* clear out the crap */
116 if (IS)
117 tmode.sg_ispeed = speed(IS);
118 else if (SP)
119 tmode.sg_ispeed = speed(SP);
120 if (OS)
121 tmode.sg_ospeed = speed(OS);
122 else if (SP)
123 tmode.sg_ospeed = speed(SP);
124 tmode.sg_flags = setflags(0);
125 ioctl(0, TIOCSETP, &tmode);
126 setchars();
127 ioctl(0, TIOCSETC, &tc);
128 ioctl(0, TIOCSETD, &ldisp);
129 if (HC)
130 ioctl(0, TIOCHPCL, 0);
131 if (PS) {
132 tname = portselector();
133 continue;
134 }
135 if (CL && *CL)
136 putpad(CL);
137 edithost(HE);
138 if (IM && *IM)
139 putf(IM);
140 if (setjmp(timeout)) {
141 tmode.sg_ispeed = tmode.sg_ospeed = 0;
142 ioctl(0, TIOCSETP, &tmode);
143 exit(1);
144 }
145 if (TO) {
146 signal(SIGALRM, dingdong);
147 alarm(TO);
148 }
149 if (getname()) {
150 alarm(0);
151 signal(SIGALRM, SIG_DFL);
76ba6586 152 if (!(upper || lower || digit))
21017259
SL
153 continue;
154 allflags = setflags(2);
155 tmode.sg_flags = allflags & 0xffff;
156 allflags >>= 16;
157 if (crmod || NL)
158 tmode.sg_flags |= CRMOD;
159 if (upper || UC)
160 tmode.sg_flags |= LCASE;
161 if (lower || LC)
162 tmode.sg_flags &= ~LCASE;
163 ioctl(0, TIOCSETP, &tmode);
164 ioctl(0, TIOCSLTC, &ltc);
165 ioctl(0, TIOCLSET, &allflags);
166 putchr('\n');
76ba6586 167 oflush();
21017259 168 makeenv(env);
14f797c6 169 signal(SIGINT, SIG_DFL);
21017259
SL
170 execle(LO, "login", name, (char *)0, env);
171 exit(1);
172 }
173 alarm(0);
174 signal(SIGALRM, SIG_DFL);
14f797c6 175 signal(SIGINT, SIG_IGN);
21017259
SL
176 if (NX && *NX)
177 tname = NX;
178 }
179}
180
181getname()
182{
183 register char *np;
184 register c;
185 char cs;
186
14f797c6 187 /*
76ba6586 188 * Interrupt may happen if we use CBREAK mode
14f797c6
RE
189 */
190 if (setjmp(intrupt)) {
191 signal(SIGINT, SIG_IGN);
192 return (0);
193 }
194 signal(SIGINT, interrupt);
21017259
SL
195 tmode.sg_flags = setflags(0);
196 ioctl(0, TIOCSETP, &tmode);
197 tmode.sg_flags = setflags(1);
198 prompt();
b3afc78c 199 if (PF > 0) {
f0628629 200 oflush();
b3afc78c
SL
201 sleep(PF);
202 PF = 0;
203 }
21017259
SL
204 ioctl(0, TIOCSETP, &tmode);
205 crmod = 0;
206 upper = 0;
207 lower = 0;
208 digit = 0;
209 np = name;
210 for (;;) {
14f797c6 211 oflush();
21017259
SL
212 if (read(0, &cs, 1) <= 0)
213 exit(0);
214 if ((c = cs&0177) == 0)
215 return (0);
76ba6586 216 if (c == EOT)
21017259 217 exit(1);
76ba6586 218 if (c == '\r' || c == '\n' || np >= &name[16])
21017259
SL
219 break;
220
76ba6586 221 if (c >= 'a' && c <= 'z')
21017259 222 lower++;
76ba6586 223 else if (c >= 'A' && c <= 'Z') {
21017259 224 upper++;
76ba6586 225 } else if (c == ERASE || c == '#' || c == '\b') {
21017259
SL
226 if (np > name) {
227 np--;
228 if (tmode.sg_ospeed >= B1200)
229 puts("\b \b");
230 else
231 putchr(cs);
232 }
233 continue;
76ba6586 234 } else if (c == KILL || c == '@') {
21017259
SL
235 putchr(cs);
236 putchr('\r');
237 if (tmode.sg_ospeed < B1200)
238 putchr('\n');
239 /* this is the way they do it down under ... */
240 else if (np > name)
241 puts(" \r");
242 prompt();
243 np = name;
244 continue;
245 } else if (c == ' ')
246 c = '_';
247 else if (c >= '0' && c <= '9')
248 digit++;
249 if (IG && (c < ' ' || c > 0176))
250 continue;
251 *np++ = c;
252 putchr(cs);
253 }
14f797c6 254 signal(SIGINT, SIG_IGN);
21017259
SL
255 *np = 0;
256 if (c == '\r')
257 crmod++;
258 if (upper && !lower && !LC || UC)
259 for (np = name; *np; np++)
260 if (isupper(*np))
261 *np = tolower(*np);
262 return (1);
263}
264
265static
266short tmspc10[] = {
267 0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15
268};
269
270putpad(s)
271 register char *s;
272{
273 register pad = 0;
274 register mspc10;
275
276 if (isdigit(*s)) {
277 while (isdigit(*s)) {
278 pad *= 10;
279 pad += *s++ - '0';
280 }
281 pad *= 10;
282 if (*s == '.' && isdigit(s[1])) {
283 pad += s[1] - '0';
284 s += 2;
285 }
286 }
287
288 puts(s);
289 /*
290 * If no delay needed, or output speed is
291 * not comprehensible, then don't try to delay.
292 */
293 if (pad == 0)
294 return;
295 if (tmode.sg_ospeed <= 0 ||
296 tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0]))
297 return;
298
299 /*
300 * Round up by a half a character frame,
301 * and then do the delay.
302 * Too bad there are no user program accessible programmed delays.
303 * Transmitting pad characters slows many
304 * terminals down and also loads the system.
305 */
306 mspc10 = tmspc10[tmode.sg_ospeed];
307 pad += mspc10 / 2;
308 for (pad /= mspc10; pad > 0; pad--)
309 putchr(*PC);
310}
311
312puts(s)
313 register char *s;
314{
315
316 while (*s)
317 putchr(*s++);
318}
319
14f797c6
RE
320char outbuf[OBUFSIZ];
321int obufcnt = 0;
322
21017259
SL
323putchr(cc)
324{
325 char c;
326
327 c = cc;
328 c |= partab[c&0177] & 0200;
329 if (OP)
330 c ^= 0200;
14f797c6
RE
331 if (!UB) {
332 outbuf[obufcnt++] = c;
333 if (obufcnt >= OBUFSIZ)
334 oflush();
335 } else
336 write(1, &c, 1);
337}
338
339oflush()
340{
341 if (obufcnt)
342 write(1, outbuf, obufcnt);
343 obufcnt = 0;
21017259
SL
344}
345
346prompt()
347{
348
349 putf(LM);
350 if (CO)
351 putchr('\n');
352}
353
354putf(cp)
355 register char *cp;
356{
357 extern char editedhost[];
358
359 while (*cp) {
360 if (*cp != '%') {
361 putchr(*cp++);
362 continue;
363 }
364 switch (*++cp) {
365
366 case 'h':
367 puts(editedhost);
368 break;
369
370 case '%':
371 putchr('%');
372 break;
373 }
374 cp++;
375 }
376}