This commit was generated by cvs2svn to track changes on a CVS vendor
[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;
110963ec
DG
189 if (NP)
190 f |= PASS8;
15637ed4
RG
191
192 if (UC)
193 f |= LCASE;
194
195 if (NL)
196 f |= CRMOD;
197
198 f |= delaybits();
199
200 if (n == 1) { /* read mode flags */
201 if (RW)
202 f |= RAW;
203 else
204 f |= CBREAK;
205 return (f);
206 }
207
208 if (!HT)
209 f |= XTABS;
210
211 if (n == 0)
212 return (f);
213
214 if (CB)
215 f |= CRTBS;
216
217 if (CE)
218 f |= CRTERA;
219
220 if (CK)
221 f |= CRTKIL;
222
223 if (PE)
224 f |= PRTERA;
225
226 if (EC)
227 f |= ECHO;
228
229 if (XC)
230 f |= CTLECH;
231
232 if (DX)
233 f |= DECCTQ;
234
235 return (f);
236}
237
238struct delayval {
239 unsigned delay; /* delay in ms */
240 int bits;
241};
242
243/*
244 * below are random guesses, I can't be bothered checking
245 */
246
247struct delayval crdelay[] = {
248 1, CR1,
249 2, CR2,
250 3, CR3,
251 83, CR1,
252 166, CR2,
253 0, CR3,
254};
255
256struct delayval nldelay[] = {
257 1, NL1, /* special, calculated */
258 2, NL2,
259 3, NL3,
260 100, NL2,
261 0, NL3,
262};
263
264struct delayval bsdelay[] = {
265 1, BS1,
266 0, 0,
267};
268
269struct delayval ffdelay[] = {
270 1, FF1,
271 1750, FF1,
272 0, FF1,
273};
274
275struct delayval tbdelay[] = {
276 1, TAB1,
277 2, TAB2,
278 3, XTABS, /* this is expand tabs */
279 100, TAB1,
280 0, TAB2,
281};
282
283delaybits()
284{
285 register f;
286
287 f = adelay(CD, crdelay);
288 f |= adelay(ND, nldelay);
289 f |= adelay(FD, ffdelay);
290 f |= adelay(TD, tbdelay);
291 f |= adelay(BD, bsdelay);
292 return (f);
293}
294
295adelay(ms, dp)
296 register ms;
297 register struct delayval *dp;
298{
299 if (ms == 0)
300 return (0);
301 while (dp->delay && ms > dp->delay)
302 dp++;
303 return (dp->bits);
304}
305
306char editedhost[32];
307
308edithost(pat)
309 register char *pat;
310{
311 register char *host = HN;
312 register char *res = editedhost;
313
314 if (!pat)
315 pat = "";
316 while (*pat) {
317 switch (*pat) {
318
319 case '#':
320 if (*host)
321 host++;
322 break;
323
324 case '@':
325 if (*host)
326 *res++ = *host++;
327 break;
328
329 default:
330 *res++ = *pat;
331 break;
332
333 }
334 if (res == &editedhost[sizeof editedhost - 1]) {
335 *res = '\0';
336 return;
337 }
338 pat++;
339 }
340 if (*host)
341 strncpy(res, host, sizeof editedhost - (res - editedhost) - 1);
342 else
343 *res = '\0';
344 editedhost[sizeof editedhost - 1] = '\0';
345}
346
347struct speedtab {
348 int speed;
349 int uxname;
350} speedtab[] = {
351 50, B50,
352 75, B75,
353 110, B110,
354 134, B134,
355 150, B150,
356 200, B200,
357 300, B300,
358 600, B600,
359 1200, B1200,
360 1800, B1800,
361 2400, B2400,
362 4800, B4800,
363 9600, B9600,
364 19200, EXTA,
365 19, EXTA, /* for people who say 19.2K */
366 38400, EXTB,
367 38, EXTB,
368 7200, EXTB, /* alternative */
369 57600, B57600,
370 115200, B115200,
371 0
372};
373
374speed(val)
375{
376 register struct speedtab *sp;
377
378 if (val <= 15)
379 return (val);
380
381 for (sp = speedtab; sp->speed; sp++)
382 if (sp->speed == val)
383 return (sp->uxname);
384
385 return (B300); /* default in impossible cases */
386}
387
388makeenv(env)
389 char *env[];
390{
391 static char termbuf[128] = "TERM=";
392 register char *p, *q;
393 register char **ep;
394 char *index();
395
396 ep = env;
397 if (TT && *TT) {
398 strcat(termbuf, TT);
399 *ep++ = termbuf;
400 }
401 if (p = EV) {
402 q = p;
403 while (q = index(q, ',')) {
404 *q++ = '\0';
405 *ep++ = p;
406 p = q;
407 }
408 if (*p)
409 *ep++ = p;
410 }
411 *ep = (char *)0;
412}
413
414/*
415 * This speed select mechanism is written for the Develcon DATASWITCH.
416 * The Develcon sends a string of the form "B{speed}\n" at a predefined
417 * baud rate. This string indicates the user's actual speed.
418 * The routine below returns the terminal type mapped from derived speed.
419 */
420struct portselect {
421 char *ps_baud;
422 char *ps_type;
423} portspeeds[] = {
424 { "B110", "std.110" },
425 { "B134", "std.134" },
426 { "B150", "std.150" },
427 { "B300", "std.300" },
428 { "B600", "std.600" },
429 { "B1200", "std.1200" },
430 { "B2400", "std.2400" },
431 { "B4800", "std.4800" },
432 { "B9600", "std.9600" },
433 { "B19200", "std.19200" },
434 { 0 }
435};
436
437char *
438portselector()
439{
440 char c, baud[20], *type = "default";
441 register struct portselect *ps;
442 int len;
443
444 alarm(5*60);
445 for (len = 0; len < sizeof (baud) - 1; len++) {
446 if (read(STDIN_FILENO, &c, 1) <= 0)
447 break;
448 c &= 0177;
449 if (c == '\n' || c == '\r')
450 break;
451 if (c == 'B')
452 len = 0; /* in case of leading garbage */
453 baud[len] = c;
454 }
455 baud[len] = '\0';
456 for (ps = portspeeds; ps->ps_baud; ps++)
457 if (strcmp(ps->ps_baud, baud) == 0) {
458 type = ps->ps_type;
459 break;
460 }
461 sleep(2); /* wait for connection to complete */
462 return (type);
463}
464
465/*
466 * This auto-baud speed select mechanism is written for the Micom 600
467 * portselector. Selection is done by looking at how the character '\r'
468 * is garbled at the different speeds.
469 */
470#include <sys/time.h>
471
472char *
473autobaud()
474{
475 int rfds;
476 struct timeval timeout;
477 char c, *type = "9600-baud";
478 int null = 0;
479
480 ioctl(0, TIOCFLUSH, &null);
481 rfds = 1 << 0;
482 timeout.tv_sec = 5;
483 timeout.tv_usec = 0;
484 if (select(32, (fd_set *)&rfds, (fd_set *)NULL,
485 (fd_set *)NULL, &timeout) <= 0)
486 return (type);
487 if (read(STDIN_FILENO, &c, sizeof(char)) != sizeof(char))
488 return (type);
489 timeout.tv_sec = 0;
490 timeout.tv_usec = 20;
491 (void) select(32, (fd_set *)NULL, (fd_set *)NULL,
492 (fd_set *)NULL, &timeout);
493 ioctl(0, TIOCFLUSH, &null);
494 switch (c & 0377) {
495
496 case 0200: /* 300-baud */
497 type = "300-baud";
498 break;
499
500 case 0346: /* 1200-baud */
501 type = "1200-baud";
502 break;
503
504 case 015: /* 2400-baud */
505 case 0215:
506 type = "2400-baud";
507 break;
508
509 default: /* 4800-baud */
510 type = "4800-baud";
511 break;
512
513 case 0377: /* 9600-baud */
514 type = "9600-baud";
515 break;
516 }
517 return (type);
518}