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