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