4.4BSD snapshot (revision 8.1); add 1993 to copyright
[unix-history] / usr / src / libexec / getty / subr.c
CommitLineData
8a3f4fd4 1/*
7e93bfe3
KB
2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
9d72a529 4 *
836fe169 5 * %sccs.include.redist.c%
8a3f4fd4
DF
6 */
7
3eea9327 8#ifndef lint
7e93bfe3 9static char sccsid[] = "@(#)subr.c 8.1 (Berkeley) %G%";
9d72a529 10#endif /* not lint */
3eea9327
SL
11
12/*
13 * Melbourne getty.
14 */
244691fc 15#define USE_OLD_TTY
69494ff4 16#include <stdlib.h>
3eea9327 17#include <sgtty.h>
2de7ea86 18#include <string.h>
34129485
KB
19#include <unistd.h>
20
3eea9327 21#include "gettytab.h"
34129485 22#include "extern.h"
69494ff4 23#include "pathnames.h"
3eea9327
SL
24
25extern struct sgttyb tmode;
26extern struct tchars tc;
27extern struct ltchars ltc;
28
29/*
30 * Get a table entry.
31 */
34129485 32void
69494ff4
EA
33gettable(name, buf)
34 char *name, *buf;
3eea9327
SL
35{
36 register struct gettystrs *sp;
37 register struct gettynums *np;
38 register struct gettyflags *fp;
69494ff4
EA
39 long n;
40 char *dba[2];
41 dba[0] = _PATH_GETTYTAB;
42 dba[1] = 0;
3eea9327 43
69494ff4 44 if (cgetent(&buf, dba, name) != 0)
3eea9327
SL
45 return;
46
69494ff4
EA
47 for (sp = gettystrs; sp->field; sp++)
48 cgetstr(buf, sp->field, &sp->value);
3eea9327 49 for (np = gettynums; np->field; np++) {
69494ff4 50 if (cgetnum(buf, np->field, &n) == -1)
3eea9327
SL
51 np->set = 0;
52 else {
53 np->set = 1;
54 np->value = n;
55 }
56 }
57 for (fp = gettyflags; fp->field; fp++) {
69494ff4 58 if (cgetcap(buf, fp->field, ':') == NULL)
3eea9327
SL
59 fp->set = 0;
60 else {
61 fp->set = 1;
69494ff4 62 fp->value = 1 ^ fp->invrt;
3eea9327
SL
63 }
64 }
69494ff4
EA
65#ifdef DEBUG
66 printf("name=\"%s\", buf=\"%s\"\n", name, buf);
67 for (sp = gettystrs; sp->field; sp++)
68 printf("cgetstr: %s=%s\n", sp->field, sp->value);
69 for (np = gettynums; np->field; np++)
70 printf("cgetnum: %s=%d\n", np->field, np->value);
71 for (fp = gettyflags; fp->field; fp++)
72 printf("cgetflags: %s='%c' set='%c'\n", fp->field,
73 fp->value + '0', fp->set + '0');
74 exit(1);
75#endif /* DEBUG */
3eea9327
SL
76}
77
34129485 78void
3eea9327
SL
79gendefaults()
80{
81 register struct gettystrs *sp;
82 register struct gettynums *np;
83 register struct gettyflags *fp;
84
85 for (sp = gettystrs; sp->field; sp++)
86 if (sp->value)
87 sp->defalt = sp->value;
88 for (np = gettynums; np->field; np++)
89 if (np->set)
90 np->defalt = np->value;
91 for (fp = gettyflags; fp->field; fp++)
92 if (fp->set)
93 fp->defalt = fp->value;
94 else
95 fp->defalt = fp->invrt;
96}
97
34129485 98void
3eea9327
SL
99setdefaults()
100{
101 register struct gettystrs *sp;
102 register struct gettynums *np;
103 register struct gettyflags *fp;
104
105 for (sp = gettystrs; sp->field; sp++)
106 if (!sp->value)
107 sp->value = sp->defalt;
108 for (np = gettynums; np->field; np++)
109 if (!np->set)
110 np->value = np->defalt;
111 for (fp = gettyflags; fp->field; fp++)
112 if (!fp->set)
113 fp->value = fp->defalt;
114}
115
116static char **
117charnames[] = {
118 &ER, &KL, &IN, &QU, &XN, &XF, &ET, &BK,
119 &SU, &DS, &RP, &FL, &WE, &LN, 0
120};
121
122static char *
123charvars[] = {
124 &tmode.sg_erase, &tmode.sg_kill, &tc.t_intrc,
125 &tc.t_quitc, &tc.t_startc, &tc.t_stopc,
126 &tc.t_eofc, &tc.t_brkc, &ltc.t_suspc,
127 &ltc.t_dsuspc, &ltc.t_rprntc, &ltc.t_flushc,
128 &ltc.t_werasc, &ltc.t_lnextc, 0
129};
130
34129485 131void
3eea9327
SL
132setchars()
133{
134 register int i;
135 register char *p;
136
137 for (i = 0; charnames[i]; i++) {
138 p = *charnames[i];
139 if (p && *p)
140 *charvars[i] = *p;
141 else
4eaf53e2 142 *charvars[i] = '\377';
3eea9327
SL
143 }
144}
145
146long
147setflags(n)
34129485 148 int n;
3eea9327
SL
149{
150 register long f;
151
152 switch (n) {
153 case 0:
154 if (F0set)
155 return(F0);
156 break;
157 case 1:
158 if (F1set)
159 return(F1);
160 break;
161 default:
162 if (F2set)
163 return(F2);
164 break;
165 }
166
167 f = 0;
168
169 if (AP)
170 f |= ANYP;
171 else if (OP)
172 f |= ODDP;
173 else if (EP)
174 f |= EVENP;
175
176 if (UC)
177 f |= LCASE;
178
179 if (NL)
180 f |= CRMOD;
181
182 f |= delaybits();
183
184 if (n == 1) { /* read mode flags */
185 if (RW)
186 f |= RAW;
187 else
188 f |= CBREAK;
189 return (f);
190 }
191
192 if (!HT)
193 f |= XTABS;
194
195 if (n == 0)
196 return (f);
197
198 if (CB)
199 f |= CRTBS;
200
201 if (CE)
202 f |= CRTERA;
203
7f170415
RC
204 if (CK)
205 f |= CRTKIL;
206
3eea9327
SL
207 if (PE)
208 f |= PRTERA;
209
210 if (EC)
211 f |= ECHO;
212
213 if (XC)
214 f |= CTLECH;
215
e5943133
KM
216 if (DX)
217 f |= DECCTQ;
218
3eea9327
SL
219 return (f);
220}
221
222struct delayval {
223 unsigned delay; /* delay in ms */
224 int bits;
225};
226
227/*
228 * below are random guesses, I can't be bothered checking
229 */
230
231struct delayval crdelay[] = {
34129485
KB
232 { 1, CR1 },
233 { 2, CR2 },
234 { 3, CR3 },
235 { 83, CR1 },
236 { 166, CR2 },
237 { 0, CR3 },
3eea9327
SL
238};
239
240struct delayval nldelay[] = {
34129485
KB
241 { 1, NL1 }, /* special, calculated */
242 { 2, NL2 },
243 { 3, NL3 },
244 { 100, NL2 },
245 { 0, NL3 },
3eea9327
SL
246};
247
248struct delayval bsdelay[] = {
34129485
KB
249 { 1, BS1 },
250 { 0, 0 },
3eea9327
SL
251};
252
253struct delayval ffdelay[] = {
34129485
KB
254 { 1, FF1 },
255 { 1750, FF1 },
256 { 0, FF1 },
3eea9327
SL
257};
258
259struct delayval tbdelay[] = {
34129485
KB
260 { 1, TAB1 },
261 { 2, TAB2 },
262 { 3, XTABS }, /* this is expand tabs */
263 { 100, TAB1 },
264 { 0, TAB2 },
3eea9327
SL
265};
266
34129485 267int
3eea9327
SL
268delaybits()
269{
34129485 270 register int f;
3eea9327
SL
271
272 f = adelay(CD, crdelay);
273 f |= adelay(ND, nldelay);
274 f |= adelay(FD, ffdelay);
275 f |= adelay(TD, tbdelay);
276 f |= adelay(BD, bsdelay);
277 return (f);
278}
279
34129485 280int
3eea9327
SL
281adelay(ms, dp)
282 register ms;
283 register struct delayval *dp;
284{
285 if (ms == 0)
286 return (0);
287 while (dp->delay && ms > dp->delay)
288 dp++;
289 return (dp->bits);
290}
291
292char editedhost[32];
293
34129485 294void
3eea9327
SL
295edithost(pat)
296 register char *pat;
297{
298 register char *host = HN;
299 register char *res = editedhost;
300
301 if (!pat)
302 pat = "";
303 while (*pat) {
304 switch (*pat) {
305
306 case '#':
307 if (*host)
308 host++;
309 break;
310
311 case '@':
312 if (*host)
313 *res++ = *host++;
314 break;
315
316 default:
317 *res++ = *pat;
318 break;
319
320 }
321 if (res == &editedhost[sizeof editedhost - 1]) {
322 *res = '\0';
323 return;
324 }
325 pat++;
326 }
327 if (*host)
328 strncpy(res, host, sizeof editedhost - (res - editedhost) - 1);
329 else
330 *res = '\0';
331 editedhost[sizeof editedhost - 1] = '\0';
332}
333
334struct speedtab {
335 int speed;
336 int uxname;
337} speedtab[] = {
34129485
KB
338 { 50, B50 },
339 { 75, B75 },
340 { 110, B110 },
341 { 134, B134 },
342 { 150, B150 },
343 { 200, B200 },
344 { 300, B300 },
345 { 600, B600 },
346 { 1200, B1200 },
347 { 1800, B1800 },
348 { 2400, B2400 },
349 { 4800, B4800 },
350 { 9600, B9600 },
351 { 19200, EXTA },
352 { 19, EXTA }, /* for people who say 19.2K */
353 { 38400, EXTB },
354 { 38, EXTB },
355 { 7200, EXTB }, /* alternative */
356 { 0 }
3eea9327
SL
357};
358
34129485 359int
3eea9327 360speed(val)
34129485 361 int val;
3eea9327
SL
362{
363 register struct speedtab *sp;
364
365 if (val <= 15)
ec2b493d 366 return (val);
3eea9327
SL
367
368 for (sp = speedtab; sp->speed; sp++)
369 if (sp->speed == val)
370 return (sp->uxname);
371
372 return (B300); /* default in impossible cases */
373}
374
34129485 375void
3eea9327
SL
376makeenv(env)
377 char *env[];
378{
379 static char termbuf[128] = "TERM=";
380 register char *p, *q;
381 register char **ep;
3eea9327
SL
382
383 ep = env;
384 if (TT && *TT) {
385 strcat(termbuf, TT);
386 *ep++ = termbuf;
387 }
388 if (p = EV) {
389 q = p;
34129485 390 while (q = strchr(q, ',')) {
3eea9327
SL
391 *q++ = '\0';
392 *ep++ = p;
393 p = q;
394 }
395 if (*p)
396 *ep++ = p;
397 }
398 *ep = (char *)0;
399}
400
401/*
402 * This speed select mechanism is written for the Develcon DATASWITCH.
403 * The Develcon sends a string of the form "B{speed}\n" at a predefined
404 * baud rate. This string indicates the user's actual speed.
405 * The routine below returns the terminal type mapped from derived speed.
406 */
407struct portselect {
408 char *ps_baud;
409 char *ps_type;
410} portspeeds[] = {
411 { "B110", "std.110" },
412 { "B134", "std.134" },
413 { "B150", "std.150" },
414 { "B300", "std.300" },
415 { "B600", "std.600" },
416 { "B1200", "std.1200" },
417 { "B2400", "std.2400" },
418 { "B4800", "std.4800" },
419 { "B9600", "std.9600" },
84e05cce 420 { "B19200", "std.19200" },
3eea9327
SL
421 { 0 }
422};
423
424char *
425portselector()
426{
427 char c, baud[20], *type = "default";
428 register struct portselect *ps;
429 int len;
430
431 alarm(5*60);
432 for (len = 0; len < sizeof (baud) - 1; len++) {
897c1d4e 433 if (read(STDIN_FILENO, &c, 1) <= 0)
3eea9327
SL
434 break;
435 c &= 0177;
436 if (c == '\n' || c == '\r')
437 break;
438 if (c == 'B')
439 len = 0; /* in case of leading garbage */
440 baud[len] = c;
441 }
442 baud[len] = '\0';
443 for (ps = portspeeds; ps->ps_baud; ps++)
444 if (strcmp(ps->ps_baud, baud) == 0) {
445 type = ps->ps_type;
446 break;
447 }
448 sleep(2); /* wait for connection to complete */
449 return (type);
450}
ec2b493d
RC
451
452/*
453 * This auto-baud speed select mechanism is written for the Micom 600
454 * portselector. Selection is done by looking at how the character '\r'
455 * is garbled at the different speeds.
456 */
457#include <sys/time.h>
458
459char *
460autobaud()
461{
462 int rfds;
463 struct timeval timeout;
464 char c, *type = "9600-baud";
465 int null = 0;
466
467 ioctl(0, TIOCFLUSH, &null);
468 rfds = 1 << 0;
469 timeout.tv_sec = 5;
470 timeout.tv_usec = 0;
3d35c7ff
KB
471 if (select(32, (fd_set *)&rfds, (fd_set *)NULL,
472 (fd_set *)NULL, &timeout) <= 0)
ec2b493d 473 return (type);
897c1d4e 474 if (read(STDIN_FILENO, &c, sizeof(char)) != sizeof(char))
ec2b493d
RC
475 return (type);
476 timeout.tv_sec = 0;
477 timeout.tv_usec = 20;
3d35c7ff
KB
478 (void) select(32, (fd_set *)NULL, (fd_set *)NULL,
479 (fd_set *)NULL, &timeout);
ec2b493d
RC
480 ioctl(0, TIOCFLUSH, &null);
481 switch (c & 0377) {
482
483 case 0200: /* 300-baud */
484 type = "300-baud";
485 break;
486
487 case 0346: /* 1200-baud */
488 type = "1200-baud";
489 break;
490
491 case 015: /* 2400-baud */
492 case 0215:
493 type = "2400-baud";
494 break;
495
496 default: /* 4800-baud */
497 type = "4800-baud";
498 break;
499
500 case 0377: /* 9600-baud */
501 type = "9600-baud";
502 break;
503 }
504 return (type);
505}