Initial import, 0.1 + pk 0.2.4-B1
[unix-history] / libexec / getty / subr.c
CommitLineData
15637ed4
RG
1/*
2 * Copyright (c) 1983 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
34 * -------------------- ----- ----------------------
35 * CURRENT PATCH LEVEL: 1 00150
36 * -------------------- ----- ----------------------
37 *
38 * 22 Apr 93 Rodney W. Grimes support for 57600 and 115200 baud
39 *
40 */
41
42#ifndef lint
43static char sccsid[] = "@(#)subr.c 5.10 (Berkeley) 2/26/91";
44#endif /* not lint */
45
46/*
47 * Melbourne getty.
48 */
49#define USE_OLD_TTY
50#include <sgtty.h>
51#include <unistd.h>
52#include <string.h>
53#include "gettytab.h"
54
55extern struct sgttyb tmode;
56extern struct tchars tc;
57extern struct ltchars ltc;
58
59/*
60 * Get a table entry.
61 */
62gettable(name, buf, area)
63 char *name, *buf, *area;
64{
65 register struct gettystrs *sp;
66 register struct gettynums *np;
67 register struct gettyflags *fp;
68 register n;
69
70 hopcount = 0; /* new lookup, start fresh */
71 if (getent(buf, name) != 1)
72 return;
73
74 for (sp = gettystrs; sp->field; sp++)
75 sp->value = getstr(sp->field, &area);
76 for (np = gettynums; np->field; np++) {
77 n = getnum(np->field);
78 if (n == -1)
79 np->set = 0;
80 else {
81 np->set = 1;
82 np->value = n;
83 }
84 }
85 for (fp = gettyflags; fp->field; fp++) {
86 n = getflag(fp->field);
87 if (n == -1)
88 fp->set = 0;
89 else {
90 fp->set = 1;
91 fp->value = n ^ fp->invrt;
92 }
93 }
94}
95
96gendefaults()
97{
98 register struct gettystrs *sp;
99 register struct gettynums *np;
100 register struct gettyflags *fp;
101
102 for (sp = gettystrs; sp->field; sp++)
103 if (sp->value)
104 sp->defalt = sp->value;
105 for (np = gettynums; np->field; np++)
106 if (np->set)
107 np->defalt = np->value;
108 for (fp = gettyflags; fp->field; fp++)
109 if (fp->set)
110 fp->defalt = fp->value;
111 else
112 fp->defalt = fp->invrt;
113}
114
115setdefaults()
116{
117 register struct gettystrs *sp;
118 register struct gettynums *np;
119 register struct gettyflags *fp;
120
121 for (sp = gettystrs; sp->field; sp++)
122 if (!sp->value)
123 sp->value = sp->defalt;
124 for (np = gettynums; np->field; np++)
125 if (!np->set)
126 np->value = np->defalt;
127 for (fp = gettyflags; fp->field; fp++)
128 if (!fp->set)
129 fp->value = fp->defalt;
130}
131
132static char **
133charnames[] = {
134 &ER, &KL, &IN, &QU, &XN, &XF, &ET, &BK,
135 &SU, &DS, &RP, &FL, &WE, &LN, 0
136};
137
138static char *
139charvars[] = {
140 &tmode.sg_erase, &tmode.sg_kill, &tc.t_intrc,
141 &tc.t_quitc, &tc.t_startc, &tc.t_stopc,
142 &tc.t_eofc, &tc.t_brkc, &ltc.t_suspc,
143 &ltc.t_dsuspc, &ltc.t_rprntc, &ltc.t_flushc,
144 &ltc.t_werasc, &ltc.t_lnextc, 0
145};
146
147setchars()
148{
149 register int i;
150 register char *p;
151
152 for (i = 0; charnames[i]; i++) {
153 p = *charnames[i];
154 if (p && *p)
155 *charvars[i] = *p;
156 else
157 *charvars[i] = '\377';
158 }
159}
160
161long
162setflags(n)
163{
164 register long f;
165
166 switch (n) {
167 case 0:
168 if (F0set)
169 return(F0);
170 break;
171 case 1:
172 if (F1set)
173 return(F1);
174 break;
175 default:
176 if (F2set)
177 return(F2);
178 break;
179 }
180
181 f = 0;
182
183 if (AP)
184 f |= ANYP;
185 else if (OP)
186 f |= ODDP;
187 else if (EP)
188 f |= EVENP;
189
190 if (UC)
191 f |= LCASE;
192
193 if (NL)
194 f |= CRMOD;
195
196 f |= delaybits();
197
198 if (n == 1) { /* read mode flags */
199 if (RW)
200 f |= RAW;
201 else
202 f |= CBREAK;
203 return (f);
204 }
205
206 if (!HT)
207 f |= XTABS;
208
209 if (n == 0)
210 return (f);
211
212 if (CB)
213 f |= CRTBS;
214
215 if (CE)
216 f |= CRTERA;
217
218 if (CK)
219 f |= CRTKIL;
220
221 if (PE)
222 f |= PRTERA;
223
224 if (EC)
225 f |= ECHO;
226
227 if (XC)
228 f |= CTLECH;
229
230 if (DX)
231 f |= DECCTQ;
232
233 return (f);
234}
235
236struct delayval {
237 unsigned delay; /* delay in ms */
238 int bits;
239};
240
241/*
242 * below are random guesses, I can't be bothered checking
243 */
244
245struct delayval crdelay[] = {
246 1, CR1,
247 2, CR2,
248 3, CR3,
249 83, CR1,
250 166, CR2,
251 0, CR3,
252};
253
254struct delayval nldelay[] = {
255 1, NL1, /* special, calculated */
256 2, NL2,
257 3, NL3,
258 100, NL2,
259 0, NL3,
260};
261
262struct delayval bsdelay[] = {
263 1, BS1,
264 0, 0,
265};
266
267struct delayval ffdelay[] = {
268 1, FF1,
269 1750, FF1,
270 0, FF1,
271};
272
273struct delayval tbdelay[] = {
274 1, TAB1,
275 2, TAB2,
276 3, XTABS, /* this is expand tabs */
277 100, TAB1,
278 0, TAB2,
279};
280
281delaybits()
282{
283 register f;
284
285 f = adelay(CD, crdelay);
286 f |= adelay(ND, nldelay);
287 f |= adelay(FD, ffdelay);
288 f |= adelay(TD, tbdelay);
289 f |= adelay(BD, bsdelay);
290 return (f);
291}
292
293adelay(ms, dp)
294 register ms;
295 register struct delayval *dp;
296{
297 if (ms == 0)
298 return (0);
299 while (dp->delay && ms > dp->delay)
300 dp++;
301 return (dp->bits);
302}
303
304char editedhost[32];
305
306edithost(pat)
307 register char *pat;
308{
309 register char *host = HN;
310 register char *res = editedhost;
311
312 if (!pat)
313 pat = "";
314 while (*pat) {
315 switch (*pat) {
316
317 case '#':
318 if (*host)
319 host++;
320 break;
321
322 case '@':
323 if (*host)
324 *res++ = *host++;
325 break;
326
327 default:
328 *res++ = *pat;
329 break;
330
331 }
332 if (res == &editedhost[sizeof editedhost - 1]) {
333 *res = '\0';
334 return;
335 }
336 pat++;
337 }
338 if (*host)
339 strncpy(res, host, sizeof editedhost - (res - editedhost) - 1);
340 else
341 *res = '\0';
342 editedhost[sizeof editedhost - 1] = '\0';
343}
344
345struct speedtab {
346 int speed;
347 int uxname;
348} speedtab[] = {
349 50, B50,
350 75, B75,
351 110, B110,
352 134, B134,
353 150, B150,
354 200, B200,
355 300, B300,
356 600, B600,
357 1200, B1200,
358 1800, B1800,
359 2400, B2400,
360 4800, B4800,
361 9600, B9600,
362 19200, EXTA,
363 19, EXTA, /* for people who say 19.2K */
364 38400, EXTB,
365 38, EXTB,
366 7200, EXTB, /* alternative */
367 57600, B57600,
368 115200, B115200,
369 0
370};
371
372speed(val)
373{
374 register struct speedtab *sp;
375
376 if (val <= 15)
377 return (val);
378
379 for (sp = speedtab; sp->speed; sp++)
380 if (sp->speed == val)
381 return (sp->uxname);
382
383 return (B300); /* default in impossible cases */
384}
385
386makeenv(env)
387 char *env[];
388{
389 static char termbuf[128] = "TERM=";
390 register char *p, *q;
391 register char **ep;
392 char *index();
393
394 ep = env;
395 if (TT && *TT) {
396 strcat(termbuf, TT);
397 *ep++ = termbuf;
398 }
399 if (p = EV) {
400 q = p;
401 while (q = index(q, ',')) {
402 *q++ = '\0';
403 *ep++ = p;
404 p = q;
405 }
406 if (*p)
407 *ep++ = p;
408 }
409 *ep = (char *)0;
410}
411
412/*
413 * This speed select mechanism is written for the Develcon DATASWITCH.
414 * The Develcon sends a string of the form "B{speed}\n" at a predefined
415 * baud rate. This string indicates the user's actual speed.
416 * The routine below returns the terminal type mapped from derived speed.
417 */
418struct portselect {
419 char *ps_baud;
420 char *ps_type;
421} portspeeds[] = {
422 { "B110", "std.110" },
423 { "B134", "std.134" },
424 { "B150", "std.150" },
425 { "B300", "std.300" },
426 { "B600", "std.600" },
427 { "B1200", "std.1200" },
428 { "B2400", "std.2400" },
429 { "B4800", "std.4800" },
430 { "B9600", "std.9600" },
431 { "B19200", "std.19200" },
432 { 0 }
433};
434
435char *
436portselector()
437{
438 char c, baud[20], *type = "default";
439 register struct portselect *ps;
440 int len;
441
442 alarm(5*60);
443 for (len = 0; len < sizeof (baud) - 1; len++) {
444 if (read(STDIN_FILENO, &c, 1) <= 0)
445 break;
446 c &= 0177;
447 if (c == '\n' || c == '\r')
448 break;
449 if (c == 'B')
450 len = 0; /* in case of leading garbage */
451 baud[len] = c;
452 }
453 baud[len] = '\0';
454 for (ps = portspeeds; ps->ps_baud; ps++)
455 if (strcmp(ps->ps_baud, baud) == 0) {
456 type = ps->ps_type;
457 break;
458 }
459 sleep(2); /* wait for connection to complete */
460 return (type);
461}
462
463/*
464 * This auto-baud speed select mechanism is written for the Micom 600
465 * portselector. Selection is done by looking at how the character '\r'
466 * is garbled at the different speeds.
467 */
468#include <sys/time.h>
469
470char *
471autobaud()
472{
473 int rfds;
474 struct timeval timeout;
475 char c, *type = "9600-baud";
476 int null = 0;
477
478 ioctl(0, TIOCFLUSH, &null);
479 rfds = 1 << 0;
480 timeout.tv_sec = 5;
481 timeout.tv_usec = 0;
482 if (select(32, (fd_set *)&rfds, (fd_set *)NULL,
483 (fd_set *)NULL, &timeout) <= 0)
484 return (type);
485 if (read(STDIN_FILENO, &c, sizeof(char)) != sizeof(char))
486 return (type);
487 timeout.tv_sec = 0;
488 timeout.tv_usec = 20;
489 (void) select(32, (fd_set *)NULL, (fd_set *)NULL,
490 (fd_set *)NULL, &timeout);
491 ioctl(0, TIOCFLUSH, &null);
492 switch (c & 0377) {
493
494 case 0200: /* 300-baud */
495 type = "300-baud";
496 break;
497
498 case 0346: /* 1200-baud */
499 type = "1200-baud";
500 break;
501
502 case 015: /* 2400-baud */
503 case 0215:
504 type = "2400-baud";
505 break;
506
507 default: /* 4800-baud */
508 type = "4800-baud";
509 break;
510
511 case 0377: /* 9600-baud */
512 type = "9600-baud";
513 break;
514 }
515 return (type);
516}