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