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